1//===----------------------------------------------------------------------===//
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
10// definition used to handle ABI compliancy.
11//
12//===----------------------------------------------------------------------===//
13
14#ifndef CLANG_LIB_CODEGEN_CIRGENCALL_H
15#define CLANG_LIB_CODEGEN_CIRGENCALL_H
16
17#include "CIRGenValue.h"
18#include "mlir/IR/Operation.h"
19#include "clang/AST/GlobalDecl.h"
20#include "llvm/ADT/SmallVector.h"
21
22namespace clang::CIRGen {
23
24class CIRGenFunction;
25
26/// Abstract information about a function or function prototype.
27class CIRGenCalleeInfo {
28 const clang::FunctionProtoType *calleeProtoTy;
29 clang::GlobalDecl calleeDecl;
30
31public:
32 explicit CIRGenCalleeInfo() : calleeProtoTy(nullptr), calleeDecl() {}
33 CIRGenCalleeInfo(const clang::FunctionProtoType *calleeProtoTy,
34 clang::GlobalDecl calleeDecl)
35 : calleeProtoTy(calleeProtoTy), calleeDecl(calleeDecl) {}
36 CIRGenCalleeInfo(clang::GlobalDecl calleeDecl)
37 : calleeProtoTy(nullptr), calleeDecl(calleeDecl) {}
38
39 const clang::FunctionProtoType *getCalleeFunctionProtoType() const {
40 return calleeProtoTy;
41 }
42 clang::GlobalDecl getCalleeDecl() const { return calleeDecl; }
43};
44
45class CIRGenCallee {
46 enum class SpecialKind : uintptr_t {
47 Invalid,
48 Builtin,
49
50 Last = Builtin,
51 };
52
53 struct BuiltinInfoStorage {
54 const clang::FunctionDecl *decl;
55 unsigned id;
56 };
57
58 SpecialKind kindOrFunctionPtr;
59
60 union {
61 CIRGenCalleeInfo abstractInfo;
62 BuiltinInfoStorage builtinInfo;
63 };
64
65 explicit CIRGenCallee(SpecialKind kind) : kindOrFunctionPtr(kind) {}
66
67public:
68 CIRGenCallee() : kindOrFunctionPtr(SpecialKind::Invalid) {}
69
70 CIRGenCallee(const CIRGenCalleeInfo &abstractInfo, mlir::Operation *funcPtr)
71 : kindOrFunctionPtr(SpecialKind(reinterpret_cast<uintptr_t>(funcPtr))),
72 abstractInfo(abstractInfo) {
73 assert(funcPtr && "configuring callee without function pointer");
74 }
75
76 static CIRGenCallee
77 forDirect(mlir::Operation *funcPtr,
78 const CIRGenCalleeInfo &abstractInfo = CIRGenCalleeInfo()) {
79 return CIRGenCallee(abstractInfo, funcPtr);
80 }
81
82 bool isBuiltin() const { return kindOrFunctionPtr == SpecialKind::Builtin; }
83
84 const clang::FunctionDecl *getBuiltinDecl() const {
85 assert(isBuiltin());
86 return builtinInfo.decl;
87 }
88 unsigned getBuiltinID() const {
89 assert(isBuiltin());
90 return builtinInfo.id;
91 }
92
93 static CIRGenCallee forBuiltin(unsigned builtinID,
94 const clang::FunctionDecl *builtinDecl) {
95 CIRGenCallee result(SpecialKind::Builtin);
96 result.builtinInfo.decl = builtinDecl;
97 result.builtinInfo.id = builtinID;
98 return result;
99 }
100
101 bool isOrdinary() const {
102 return uintptr_t(kindOrFunctionPtr) > uintptr_t(SpecialKind::Last);
103 }
104
105 /// If this is a delayed callee computation of some sort, prepare a concrete
106 /// callee
107 CIRGenCallee prepareConcreteCallee(CIRGenFunction &cgf) const;
108
109 CIRGenCalleeInfo getAbstractInfo() const {
110 assert(!cir::MissingFeatures::opCallVirtual());
111 assert(isOrdinary());
112 return abstractInfo;
113 }
114
115 mlir::Operation *getFunctionPointer() const {
116 assert(isOrdinary());
117 return reinterpret_cast<mlir::Operation *>(kindOrFunctionPtr);
118 }
119};
120
121/// Type for representing both the decl and type of parameters to a function.
122/// The decl must be either a ParmVarDecl or ImplicitParamDecl.
123class FunctionArgList : public llvm::SmallVector<const clang::VarDecl *, 16> {};
124
125struct CallArg {
126private:
127 union {
128 RValue rv;
129 LValue lv; // This argument is semantically a load from this l-value
130 };
131 bool hasLV;
132
133 /// A data-flow flag to make sure getRValue and/or copyInto are not
134 /// called twice for duplicated IR emission.
135 mutable bool isUsed;
136
137public:
138 clang::QualType ty;
139
140 CallArg(RValue rv, clang::QualType ty)
141 : rv(rv), hasLV(false), isUsed(false), ty(ty) {}
142
143 CallArg(LValue lv, clang::QualType ty)
144 : lv(lv), hasLV(true), isUsed(false), ty(ty) {}
145
146 bool hasLValue() const { return hasLV; }
147
148 LValue getKnownLValue() const {
149 assert(hasLV && !isUsed);
150 return lv;
151 }
152
153 RValue getKnownRValue() const {
154 assert(!hasLV && !isUsed);
155 return rv;
156 }
157
158 bool isAggregate() const { return hasLV || rv.isAggregate(); }
159};
160
161class CallArgList : public llvm::SmallVector<CallArg, 8> {
162public:
163 void add(RValue rvalue, clang::QualType type) { emplace_back(Args&: rvalue, Args&: type); }
164
165 void addUncopiedAggregate(LValue lvalue, clang::QualType type) {
166 emplace_back(Args&: lvalue, Args&: type);
167 }
168
169 /// Add all the arguments from another CallArgList to this one. After doing
170 /// this, the old CallArgList retains its list of arguments, but must not
171 /// be used to emit a call.
172 void addFrom(const CallArgList &other) {
173 insert(I: end(), From: other.begin(), To: other.end());
174 // Classic codegen has handling for these here. We may not need it here for
175 // CIR, but if not we should implement equivalent handling in lowering.
176 assert(!cir::MissingFeatures::writebacks());
177 assert(!cir::MissingFeatures::cleanupsToDeactivate());
178 assert(!cir::MissingFeatures::stackBase());
179 }
180};
181
182/// Contains the address where the return value of a function can be stored, and
183/// whether the address is volatile or not.
184class ReturnValueSlot {
185 Address addr = Address::invalid();
186
187public:
188 ReturnValueSlot() = default;
189 ReturnValueSlot(Address addr) : addr(addr) {}
190
191 Address getValue() const { return addr; }
192};
193
194} // namespace clang::CIRGen
195
196#endif // CLANG_LIB_CODEGEN_CIRGENCALL_H
197

source code of clang/lib/CIR/CodeGen/CIRGenCall.h