@@ -1798,13 +1798,8 @@ class CIR_CallOpBase<string mnemonic, list<Trait> extra_traits = []>
17981798 DeclareOpInterfaceMethods<SymbolUserOpInterface>])> {
17991799 let extraClassDeclaration = [{
18001800 /// Get the argument operands to the called function.
1801- mlir::OperandRange getArgOperands() {
1802- return getArgs();
1803- }
1804-
1805- mlir::MutableOperandRange getArgOperandsMutable() {
1806- return getArgsMutable();
1807- }
1801+ mlir::OperandRange getArgOperands();
1802+ mlir::MutableOperandRange getArgOperandsMutable();
18081803
18091804 /// Return the callee of this operation
18101805 mlir::CallInterfaceCallable getCallableForCallee() {
@@ -1826,8 +1821,17 @@ class CIR_CallOpBase<string mnemonic, list<Trait> extra_traits = []>
18261821 ::mlir::Attribute removeArgAttrsAttr() { return {}; }
18271822 ::mlir::Attribute removeResAttrsAttr() { return {}; }
18281823
1824+ bool isIndirect() { return !getCallee(); }
1825+ mlir::Value getIndirectCall();
1826+
18291827 void setArg(unsigned index, mlir::Value value) {
1830- setOperand(index, value);
1828+ if (!isIndirect()) {
1829+ setOperand(index, value);
1830+ return;
1831+ }
1832+
1833+ // For indirect call, the operand list is shifted by one.
1834+ setOperand(index + 1, value);
18311835 }
18321836 }];
18331837
@@ -1839,16 +1843,24 @@ class CIR_CallOpBase<string mnemonic, list<Trait> extra_traits = []>
18391843 // the upstreaming process moves on. The verifiers is also missing for now,
18401844 // will add in the future.
18411845
1842- dag commonArgs = (ins FlatSymbolRefAttr:$callee,
1843- Variadic<CIR_AnyType>:$args);
1846+ dag commonArgs = (ins OptionalAttr< FlatSymbolRefAttr> :$callee,
1847+ Variadic<CIR_AnyType>:$args);
18441848}
18451849
18461850def CallOp : CIR_CallOpBase<"call", [NoRegionArguments]> {
18471851 let summary = "call a function";
18481852 let description = [{
1849- The `cir.call` operation represents a direct call to a function that is
1850- within the same symbol scope as the call. The callee is encoded as a symbol
1851- reference attribute named `callee`.
1853+ The `cir.call` operation represents a function call. It could represent
1854+ either a direct call or an indirect call.
1855+
1856+ If the operation represents a direct call, the callee should be defined
1857+ within the same symbol scope as the call. The `callee` attribute contains a
1858+ symbol reference to the callee function. All operands of this operation are
1859+ arguments to the callee function.
1860+
1861+ If the operation represents an indirect call, the `callee` attribute is
1862+ empty. The first operand of this operation must be a pointer to the callee
1863+ function. The rest operands are arguments to the callee function.
18521864
18531865 Example:
18541866
@@ -1860,14 +1872,25 @@ def CallOp : CIR_CallOpBase<"call", [NoRegionArguments]> {
18601872 let results = (outs Optional<CIR_AnyType>:$result);
18611873 let arguments = commonArgs;
18621874
1863- let builders = [OpBuilder<(ins "mlir::SymbolRefAttr":$callee,
1864- "mlir::Type":$resType,
1865- "mlir::ValueRange":$operands), [{
1875+ let builders = [
1876+ // Build a call op for a direct call
1877+ OpBuilder<(ins "mlir::SymbolRefAttr":$callee, "mlir::Type":$resType,
1878+ "mlir::ValueRange":$operands), [{
1879+ assert(callee && "callee attribute is required for direct call");
18661880 $_state.addOperands(operands);
18671881 $_state.addAttribute("callee", callee);
18681882 if (resType && !isa<VoidType>(resType))
18691883 $_state.addTypes(resType);
1870- }]>];
1884+ }]>,
1885+ // Build a call op for an indirect call
1886+ OpBuilder<(ins "mlir::Value":$calleePtr, "mlir::Type":$resType,
1887+ "mlir::ValueRange":$operands), [{
1888+ $_state.addOperands(calleePtr);
1889+ $_state.addOperands(operands);
1890+ if (resType && !isa<VoidType>(resType))
1891+ $_state.addTypes(resType);
1892+ }]>,
1893+ ];
18711894}
18721895
18731896//===----------------------------------------------------------------------===//
0 commit comments