Skip to content

Commit cd34ab6

Browse files
committed
[CIR] Upstream initial function call support
1 parent 8fddef8 commit cd34ab6

File tree

18 files changed

+580
-1
lines changed

18 files changed

+580
-1
lines changed

clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,19 @@ class CIRBaseBuilderTy : public mlir::OpBuilder {
201201
return create<cir::PtrStrideOp>(loc, base.getType(), base, stride);
202202
}
203203

204+
//===--------------------------------------------------------------------===//
205+
// Call operators
206+
//===--------------------------------------------------------------------===//
207+
208+
cir::CallOp createCallOp(mlir::Location loc, mlir::SymbolRefAttr callee) {
209+
auto op = create<cir::CallOp>(loc, callee);
210+
return op;
211+
}
212+
213+
cir::CallOp createCallOp(mlir::Location loc, cir::FuncOp callee) {
214+
return createCallOp(loc, mlir::SymbolRefAttr::get(callee));
215+
}
216+
204217
//===--------------------------------------------------------------------===//
205218
// Cast/Conversion Operators
206219
//===--------------------------------------------------------------------===//

clang/include/clang/CIR/Dialect/IR/CIROps.td

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1242,6 +1242,47 @@ def FuncOp : CIR_Op<"func", [
12421242
let hasVerifier = 1;
12431243
}
12441244

1245+
//===----------------------------------------------------------------------===//
1246+
// CallOp
1247+
//===----------------------------------------------------------------------===//
1248+
1249+
class CIR_CallOpBase<string mnemonic, list<Trait> extra_traits = []>
1250+
: Op<CIR_Dialect, mnemonic,
1251+
!listconcat(extra_traits,
1252+
[DeclareOpInterfaceMethods<CIRCallOpInterface>,
1253+
DeclareOpInterfaceMethods<SymbolUserOpInterface>])> {
1254+
let hasCustomAssemblyFormat = 1;
1255+
let skipDefaultBuilders = 1;
1256+
let hasVerifier = 0;
1257+
1258+
// TODO(cir): for now cir.call is just a tiny shell of what it will become.
1259+
// More attributes, arguments, and properties will be added in the future as
1260+
// the upstreaming process moves on.
1261+
1262+
dag commonArgs = (ins FlatSymbolRefAttr:$callee);
1263+
}
1264+
1265+
def CallOp : CIR_CallOpBase<"call", [NoRegionArguments]> {
1266+
let summary = "call a function";
1267+
let description = [{
1268+
The `cir.call` operation represents a direct call to a function that is
1269+
within the same symbol scope as the call. The callee is encoded as a symbol
1270+
reference attribute named `callee`.
1271+
1272+
Example:
1273+
1274+
```mlir
1275+
%0 = cir.call @foo()
1276+
```
1277+
}];
1278+
1279+
let arguments = commonArgs;
1280+
1281+
let builders = [OpBuilder<(ins "mlir::SymbolRefAttr":$callee), [{
1282+
$_state.addAttribute("callee", callee);
1283+
}]>];
1284+
}
1285+
12451286
//===----------------------------------------------------------------------===//
12461287
// UnreachableOp
12471288
//===----------------------------------------------------------------------===//

clang/include/clang/CIR/Interfaces/CIROpInterfaces.td

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,17 @@
1515

1616
include "mlir/IR/OpBase.td"
1717
include "mlir/IR/SymbolInterfaces.td"
18+
include "mlir/Interfaces/CallInterfaces.td"
1819

1920
let cppNamespace = "::cir" in {
21+
// The CIRCallOpInterface must be used instead of CallOpInterface when looking
22+
// at arguments and other bits of CallOp. This creates a level of abstraction
23+
// that's useful for handling indirect calls and other details.
24+
def CIRCallOpInterface : OpInterface<"CIRCallOpInterface", []> {
25+
// Currently we don't have any methods defined in CIRCallOpInterface. We'll
26+
// add more methods as the upstreaming proceeds.
27+
}
28+
2029
def CIRGlobalValueInterface
2130
: OpInterface<"CIRGlobalValueInterface", [Symbol]> {
2231

clang/include/clang/CIR/MissingFeatures.h

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,24 @@ struct MissingFeatures {
7272
static bool opFuncLinkage() { return false; }
7373
static bool opFuncVisibility() { return false; }
7474

75+
// CallOp handling
76+
static bool opCallBuiltinFunc() { return false; }
77+
static bool opCallPseudoDtor() { return false; }
78+
static bool opCallArgs() { return false; }
79+
static bool opCallReturn() { return false; }
80+
static bool opCallArgEvaluationOrder() { return false; }
81+
static bool opCallCallConv() { return false; }
82+
static bool opCallSideEffect() { return false; }
83+
static bool opCallChainCall() { return false; }
84+
static bool opCallNoPrototypeFunc() { return false; }
85+
static bool opCallMustTail() { return false; }
86+
static bool opCallIndirect() { return false; }
87+
static bool opCallVirtual() { return false; }
88+
static bool opCallInAlloca() { return false; }
89+
static bool opCallAttrs() { return false; }
90+
static bool opCallSurroundingTry() { return false; }
91+
static bool opCallASTAttr() { return false; }
92+
7593
// ScopeOp handling
7694
static bool opScopeCleanupRegion() { return false; }
7795

@@ -90,7 +108,10 @@ struct MissingFeatures {
90108
static bool opTBAA() { return false; }
91109
static bool opCmp() { return false; }
92110
static bool objCLifetime() { return false; }
111+
static bool objCBlocks() { return false; }
93112
static bool emitNullabilityCheck() { return false; }
113+
static bool emitLValueAlignmentAssumption() { return false; }
114+
static bool emitLifetimeMarkers() { return false; }
94115
static bool astVarDeclInterface() { return false; }
95116
static bool stackSaveOp() { return false; }
96117
static bool aggValueSlot() { return false; }
@@ -108,6 +129,8 @@ struct MissingFeatures {
108129
static bool cgFPOptionsRAII() { return false; }
109130
static bool metaDataNode() { return false; }
110131
static bool fastMathFlags() { return false; }
132+
static bool weakRefReference() { return false; }
133+
static bool hip() { return false; }
111134

112135
// Missing types
113136
static bool dataMemberType() { return false; }
@@ -127,6 +150,7 @@ struct MissingFeatures {
127150
static bool complexImagOp() { return false; }
128151
static bool complexRealOp() { return false; }
129152
static bool ifOp() { return false; }
153+
static bool invokeOp() { return false; }
130154
static bool labelOp() { return false; }
131155
static bool ptrDiffOp() { return false; }
132156
static bool ptrStrideOp() { return false; }

clang/lib/CIR/CodeGen/CIRGenCall.cpp

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
//===--- CIRGenCall.cpp - Encapsulate calling convention details ----------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
//
9+
// These classes wrap the information about a call or function definition used
10+
// to handle ABI compliancy.
11+
//
12+
//===----------------------------------------------------------------------===//
13+
14+
#include "CIRGenCall.h"
15+
#include "CIRGenFunction.h"
16+
#include "clang/CIR/MissingFeatures.h"
17+
18+
using namespace clang;
19+
using namespace clang::CIRGen;
20+
21+
CIRGenFunctionInfo *CIRGenFunctionInfo::create() {
22+
// For now we just create an empty CIRGenFunctionInfo.
23+
CIRGenFunctionInfo *fi = new CIRGenFunctionInfo();
24+
return fi;
25+
}
26+
27+
CIRGenCallee CIRGenCallee::prepareConcreteCallee(CIRGenFunction &cgf) const {
28+
assert(!cir::MissingFeatures::opCallVirtual());
29+
return *this;
30+
}
31+
32+
static const CIRGenFunctionInfo &arrangeFreeFunctionLikeCall(CIRGenTypes &cgt) {
33+
assert(!cir::MissingFeatures::opCallArgs());
34+
return cgt.arrangeCIRFunctionInfo();
35+
}
36+
37+
const CIRGenFunctionInfo &CIRGenTypes::arrangeFreeFunctionCall() {
38+
return arrangeFreeFunctionLikeCall(*this);
39+
}
40+
41+
static cir::CIRCallOpInterface emitCallLikeOp(CIRGenFunction &cgf,
42+
mlir::Location callLoc,
43+
cir::FuncOp directFuncOp) {
44+
CIRGenBuilderTy &builder = cgf.getBuilder();
45+
46+
assert(!cir::MissingFeatures::opCallSurroundingTry());
47+
assert(!cir::MissingFeatures::invokeOp());
48+
49+
assert(builder.getInsertionBlock() && "expected valid basic block");
50+
assert(!cir::MissingFeatures::opCallIndirect());
51+
52+
return builder.createCallOp(callLoc, directFuncOp);
53+
}
54+
55+
RValue CIRGenFunction::emitCall(const CIRGenFunctionInfo &funcInfo,
56+
const CIRGenCallee &callee,
57+
cir::CIRCallOpInterface *callOp,
58+
mlir::Location loc) {
59+
assert(!cir::MissingFeatures::opCallArgs());
60+
assert(!cir::MissingFeatures::emitLifetimeMarkers());
61+
62+
const CIRGenCallee &concreteCallee = callee.prepareConcreteCallee(*this);
63+
mlir::Operation *calleePtr = concreteCallee.getFunctionPointer();
64+
65+
assert(!cir::MissingFeatures::opCallInAlloca());
66+
67+
mlir::NamedAttrList attrs;
68+
StringRef funcName;
69+
if (auto calleeFuncOp = dyn_cast<cir::FuncOp>(calleePtr))
70+
funcName = calleeFuncOp.getName();
71+
72+
assert(!cir::MissingFeatures::opCallCallConv());
73+
assert(!cir::MissingFeatures::opCallSideEffect());
74+
assert(!cir::MissingFeatures::opCallAttrs());
75+
76+
assert(!cir::MissingFeatures::invokeOp());
77+
78+
auto directFuncOp = dyn_cast<cir::FuncOp>(calleePtr);
79+
assert(!cir::MissingFeatures::opCallIndirect());
80+
assert(!cir::MissingFeatures::opCallAttrs());
81+
82+
cir::CIRCallOpInterface theCall = emitCallLikeOp(*this, loc, directFuncOp);
83+
84+
if (callOp)
85+
*callOp = theCall;
86+
87+
assert(!cir::MissingFeatures::opCallMustTail());
88+
assert(!cir::MissingFeatures::opCallReturn());
89+
90+
// For now we just return nothing because we don't have support for return
91+
// values yet.
92+
RValue ret = RValue::get(nullptr);
93+
94+
return ret;
95+
}

clang/lib/CIR/CodeGen/CIRGenCall.h

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,15 +14,73 @@
1414
#ifndef CLANG_LIB_CODEGEN_CIRGENCALL_H
1515
#define CLANG_LIB_CODEGEN_CIRGENCALL_H
1616

17+
#include "mlir/IR/Operation.h"
1718
#include "clang/AST/GlobalDecl.h"
1819
#include "llvm/ADT/SmallVector.h"
1920

2021
namespace clang::CIRGen {
2122

23+
class CIRGenFunction;
24+
25+
/// Abstract information about a function or function prototype.
26+
class CIRGenCalleeInfo {
27+
clang::GlobalDecl calleeDecl;
28+
29+
public:
30+
explicit CIRGenCalleeInfo() : calleeDecl() {}
31+
CIRGenCalleeInfo(clang::GlobalDecl calleeDecl) : calleeDecl(calleeDecl) {}
32+
};
33+
34+
class CIRGenCallee {
35+
enum class SpecialKind : uintptr_t {
36+
Invalid,
37+
38+
Last = Invalid,
39+
};
40+
41+
SpecialKind kindOrFunctionPtr;
42+
43+
union {
44+
CIRGenCalleeInfo abstractInfo;
45+
};
46+
47+
public:
48+
CIRGenCallee() : kindOrFunctionPtr(SpecialKind::Invalid) {}
49+
50+
CIRGenCallee(const CIRGenCalleeInfo &abstractInfo, mlir::Operation *funcPtr)
51+
: kindOrFunctionPtr(SpecialKind(reinterpret_cast<uintptr_t>(funcPtr))),
52+
abstractInfo(abstractInfo) {
53+
assert(funcPtr && "configuring callee without function pointer");
54+
}
55+
56+
static CIRGenCallee
57+
forDirect(mlir::Operation *funcPtr,
58+
const CIRGenCalleeInfo &abstractInfo = CIRGenCalleeInfo()) {
59+
return CIRGenCallee(abstractInfo, funcPtr);
60+
}
61+
62+
bool isOrdinary() const {
63+
return uintptr_t(kindOrFunctionPtr) > uintptr_t(SpecialKind::Last);
64+
}
65+
66+
/// If this is a delayed callee computation of some sort, prepare a concrete
67+
/// callee
68+
CIRGenCallee prepareConcreteCallee(CIRGenFunction &cgf) const;
69+
70+
mlir::Operation *getFunctionPointer() const {
71+
assert(isOrdinary());
72+
return reinterpret_cast<mlir::Operation *>(kindOrFunctionPtr);
73+
}
74+
};
75+
2276
/// Type for representing both the decl and type of parameters to a function.
2377
/// The decl must be either a ParmVarDecl or ImplicitParamDecl.
2478
class FunctionArgList : public llvm::SmallVector<const clang::VarDecl *, 16> {};
2579

80+
struct CallArg {};
81+
82+
class CallArgList : public llvm::SmallVector<CallArg, 8> {};
83+
2684
} // namespace clang::CIRGen
2785

2886
#endif // CLANG_LIB_CODEGEN_CIRGENCALL_H

0 commit comments

Comments
 (0)