@@ -1843,13 +1843,8 @@ class CIR_CallOpBase<string mnemonic, list<Trait> extra_traits = []>
18431843 DeclareOpInterfaceMethods<SymbolUserOpInterface>])> {
18441844 let extraClassDeclaration = [{
18451845 /// Get the argument operands to the called function.
1846- mlir::OperandRange getArgOperands() {
1847- return getArgs();
1848- }
1849-
1850- mlir::MutableOperandRange getArgOperandsMutable() {
1851- return getArgsMutable();
1852- }
1846+ mlir::OperandRange getArgOperands();
1847+ mlir::MutableOperandRange getArgOperandsMutable();
18531848
18541849 /// Return the callee of this operation
18551850 mlir::CallInterfaceCallable getCallableForCallee() {
@@ -1871,8 +1866,17 @@ class CIR_CallOpBase<string mnemonic, list<Trait> extra_traits = []>
18711866 ::mlir::Attribute removeArgAttrsAttr() { return {}; }
18721867 ::mlir::Attribute removeResAttrsAttr() { return {}; }
18731868
1869+ bool isIndirect() { return !getCallee(); }
1870+ mlir::Value getIndirectCall();
1871+
18741872 void setArg(unsigned index, mlir::Value value) {
1875- setOperand(index, value);
1873+ if (!isIndirect()) {
1874+ setOperand(index, value);
1875+ return;
1876+ }
1877+
1878+ // For indirect call, the operand list is shifted by one.
1879+ setOperand(index + 1, value);
18761880 }
18771881 }];
18781882
@@ -1884,16 +1888,24 @@ class CIR_CallOpBase<string mnemonic, list<Trait> extra_traits = []>
18841888 // the upstreaming process moves on. The verifiers is also missing for now,
18851889 // will add in the future.
18861890
1887- dag commonArgs = (ins FlatSymbolRefAttr:$callee,
1888- Variadic<CIR_AnyType>:$args);
1891+ dag commonArgs = (ins OptionalAttr< FlatSymbolRefAttr> :$callee,
1892+ Variadic<CIR_AnyType>:$args);
18891893}
18901894
18911895def CallOp : CIR_CallOpBase<"call", [NoRegionArguments]> {
18921896 let summary = "call a function";
18931897 let description = [{
1894- The `cir.call` operation represents a direct call to a function that is
1895- within the same symbol scope as the call. The callee is encoded as a symbol
1896- reference attribute named `callee`.
1898+ The `cir.call` operation represents a function call. It could represent
1899+ either a direct call or an indirect call.
1900+
1901+ If the operation represents a direct call, the callee should be defined
1902+ within the same symbol scope as the call. The `callee` attribute contains a
1903+ symbol reference to the callee function. All operands of this operation are
1904+ arguments to the callee function.
1905+
1906+ If the operation represents an indirect call, the `callee` attribute is
1907+ empty. The first operand of this operation must be a pointer to the callee
1908+ function. The rest operands are arguments to the callee function.
18971909
18981910 Example:
18991911
@@ -1905,14 +1917,25 @@ def CallOp : CIR_CallOpBase<"call", [NoRegionArguments]> {
19051917 let results = (outs Optional<CIR_AnyType>:$result);
19061918 let arguments = commonArgs;
19071919
1908- let builders = [OpBuilder<(ins "mlir::SymbolRefAttr":$callee,
1909- "mlir::Type":$resType,
1910- "mlir::ValueRange":$operands), [{
1920+ let builders = [
1921+ // Build a call op for a direct call
1922+ OpBuilder<(ins "mlir::SymbolRefAttr":$callee, "mlir::Type":$resType,
1923+ "mlir::ValueRange":$operands), [{
1924+ assert(callee && "callee attribute is required for direct call");
19111925 $_state.addOperands(operands);
19121926 $_state.addAttribute("callee", callee);
19131927 if (resType && !isa<VoidType>(resType))
19141928 $_state.addTypes(resType);
1915- }]>];
1929+ }]>,
1930+ // Build a call op for an indirect call
1931+ OpBuilder<(ins "mlir::Value":$calleePtr, "mlir::Type":$resType,
1932+ "mlir::ValueRange":$operands), [{
1933+ $_state.addOperands(calleePtr);
1934+ $_state.addOperands(operands);
1935+ if (resType && !isa<VoidType>(resType))
1936+ $_state.addTypes(resType);
1937+ }]>,
1938+ ];
19161939}
19171940
19181941//===----------------------------------------------------------------------===//
0 commit comments