@@ -542,7 +542,9 @@ def LLVM_InvokeOp : LLVM_Op<"invoke", [
542
542
DeclareOpInterfaceMethods<CallOpInterface>,
543
543
DeclareOpInterfaceMethods<BranchWeightOpInterface>,
544
544
Terminator]> {
545
- let arguments = (ins OptionalAttr<FlatSymbolRefAttr>:$callee,
545
+ let arguments = (ins
546
+ OptionalAttr<TypeAttrOf<LLVM_FunctionType>>:$callee_type,
547
+ OptionalAttr<FlatSymbolRefAttr>:$callee,
546
548
Variadic<LLVM_Type>:$callee_operands,
547
549
Variadic<LLVM_Type>:$normalDestOperands,
548
550
Variadic<LLVM_Type>:$unwindDestOperands,
@@ -552,21 +554,21 @@ def LLVM_InvokeOp : LLVM_Op<"invoke", [
552
554
AnySuccessor:$unwindDest);
553
555
554
556
let builders = [
557
+ OpBuilder<(ins "LLVMFuncOp":$func,
558
+ "ValueRange":$ops, "Block*":$normal, "ValueRange":$normalOps,
559
+ "Block*":$unwind, "ValueRange":$unwindOps)>,
555
560
OpBuilder<(ins "TypeRange":$tys, "FlatSymbolRefAttr":$callee,
556
561
"ValueRange":$ops, "Block*":$normal, "ValueRange":$normalOps,
557
- "Block*":$unwind, "ValueRange":$unwindOps),
558
- [{
559
- $_state.addAttribute("callee", callee);
560
- build($_builder, $_state, tys, ops, normal, normalOps, unwind, unwindOps);
561
- }]>,
562
- OpBuilder<(ins "TypeRange":$tys, "ValueRange":$ops, "Block*":$normal,
563
- "ValueRange":$normalOps, "Block*":$unwind, "ValueRange":$unwindOps),
564
- [{
565
- build($_builder, $_state, tys, /*callee=*/FlatSymbolRefAttr(), ops, normalOps,
566
- unwindOps, nullptr, normal, unwind);
567
- }]>];
562
+ "Block*":$unwind, "ValueRange":$unwindOps)>,
563
+ OpBuilder<(ins "LLVMFunctionType":$calleeType, "FlatSymbolRefAttr":$callee,
564
+ "ValueRange":$ops, "Block*":$normal, "ValueRange":$normalOps,
565
+ "Block*":$unwind, "ValueRange":$unwindOps)>];
568
566
let hasCustomAssemblyFormat = 1;
569
567
let hasVerifier = 1;
568
+ let extraClassDeclaration = [{
569
+ /// Returns the callee function type.
570
+ LLVMFunctionType getCalleeFunctionType();
571
+ }];
570
572
}
571
573
572
574
def LLVM_LandingpadOp : LLVM_Op<"landingpad"> {
@@ -581,9 +583,6 @@ def LLVM_LandingpadOp : LLVM_Op<"landingpad"> {
581
583
// CallOp
582
584
//===----------------------------------------------------------------------===//
583
585
584
- // FIXME: Add a type attribute that carries the LLVM function type to support
585
- // indirect calls to variadic functions. The type attribute is necessary to
586
- // distinguish normal and variadic arguments.
587
586
def LLVM_CallOp : LLVM_MemAccessOpBase<"call",
588
587
[DeclareOpInterfaceMethods<FastmathFlagsInterface>,
589
588
DeclareOpInterfaceMethods<CallOpInterface>,
@@ -599,10 +598,11 @@ def LLVM_CallOp : LLVM_MemAccessOpBase<"call",
599
598
The `call` instruction supports both direct and indirect calls. Direct calls
600
599
start with a function name (`@`-prefixed) and indirect calls start with an
601
600
SSA value (`%`-prefixed). The direct callee, if present, is stored as a
602
- function attribute `callee`. The trailing type list contains the optional
603
- indirect callee type and the MLIR function type, which differs from the
604
- LLVM function type that uses a explicit void type to model functions that do
605
- not return a value.
601
+ function attribute `callee`. If the callee is a variadic function, then the
602
+ `callee_type` attribute must carry the function type. The trailing type list
603
+ contains the optional indirect callee type and the MLIR function type, which
604
+ differs from the LLVM function type that uses a explicit void type to model
605
+ functions that do not return a value.
606
606
607
607
Examples:
608
608
@@ -615,10 +615,17 @@ def LLVM_CallOp : LLVM_MemAccessOpBase<"call",
615
615
616
616
// Indirect call with an argument and without a result.
617
617
llvm.call %1(%0) : !llvm.ptr, (f32) -> ()
618
+
619
+ // Direct variadic call.
620
+ llvm.call @printf(%0, %1) vararg(!llvm.func<i32 (ptr, ...)>) : (!llvm.ptr, i32) -> i32
621
+
622
+ // Indirect variadic call
623
+ llvm.call %1(%0) vararg(!llvm.func<void (...)>) : !llvm.ptr, (i32) -> ()
618
624
```
619
625
}];
620
626
621
- dag args = (ins OptionalAttr<FlatSymbolRefAttr>:$callee,
627
+ dag args = (ins OptionalAttr<TypeAttrOf<LLVM_FunctionType>>:$callee_type,
628
+ OptionalAttr<FlatSymbolRefAttr>:$callee,
622
629
Variadic<LLVM_Type>:$callee_operands,
623
630
DefaultValuedAttr<LLVM_FastmathFlagsAttr,
624
631
"{}">:$fastmathFlags,
@@ -628,14 +635,25 @@ def LLVM_CallOp : LLVM_MemAccessOpBase<"call",
628
635
let results = (outs Optional<LLVM_Type>:$result);
629
636
let builders = [
630
637
OpBuilder<(ins "LLVMFuncOp":$func, "ValueRange":$args)>,
638
+ OpBuilder<(ins "LLVMFunctionType":$calleeType, "ValueRange":$args)>,
631
639
OpBuilder<(ins "TypeRange":$results, "StringAttr":$callee,
632
640
CArg<"ValueRange", "{}">:$args)>,
633
641
OpBuilder<(ins "TypeRange":$results, "FlatSymbolRefAttr":$callee,
634
642
CArg<"ValueRange", "{}">:$args)>,
635
643
OpBuilder<(ins "TypeRange":$results, "StringRef":$callee,
644
+ CArg<"ValueRange", "{}">:$args)>,
645
+ OpBuilder<(ins "LLVMFunctionType":$calleeType, "StringAttr":$callee,
646
+ CArg<"ValueRange", "{}">:$args)>,
647
+ OpBuilder<(ins "LLVMFunctionType":$calleeType, "FlatSymbolRefAttr":$callee,
648
+ CArg<"ValueRange", "{}">:$args)>,
649
+ OpBuilder<(ins "LLVMFunctionType":$calleeType, "StringRef":$callee,
636
650
CArg<"ValueRange", "{}">:$args)>
637
651
];
638
652
let hasCustomAssemblyFormat = 1;
653
+ let extraClassDeclaration = [{
654
+ /// Returns the callee function type.
655
+ LLVMFunctionType getCalleeFunctionType();
656
+ }];
639
657
}
640
658
641
659
//===----------------------------------------------------------------------===//
0 commit comments