1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | |
14 | #ifndef LLVM_CLANG_LIB_CODEGEN_CGCALL_H |
15 | #define LLVM_CLANG_LIB_CODEGEN_CGCALL_H |
16 | |
17 | #include "CGValue.h" |
18 | #include "EHScopeStack.h" |
19 | #include "clang/AST/CanonicalType.h" |
20 | #include "clang/AST/GlobalDecl.h" |
21 | #include "clang/AST/Type.h" |
22 | #include "llvm/IR/Value.h" |
23 | |
24 | |
25 | #include "ABIInfo.h" |
26 | |
27 | namespace llvm { |
28 | class AttributeList; |
29 | class Function; |
30 | class Type; |
31 | class Value; |
32 | } |
33 | |
34 | namespace clang { |
35 | class ASTContext; |
36 | class Decl; |
37 | class FunctionDecl; |
38 | class ObjCMethodDecl; |
39 | class VarDecl; |
40 | |
41 | namespace CodeGen { |
42 | |
43 | |
44 | class CGCalleeInfo { |
45 | |
46 | const FunctionProtoType *CalleeProtoTy; |
47 | |
48 | GlobalDecl CalleeDecl; |
49 | |
50 | public: |
51 | explicit CGCalleeInfo() : CalleeProtoTy(nullptr), CalleeDecl() {} |
52 | CGCalleeInfo(const FunctionProtoType *calleeProtoTy, GlobalDecl calleeDecl) |
53 | : CalleeProtoTy(calleeProtoTy), CalleeDecl(calleeDecl) {} |
54 | CGCalleeInfo(const FunctionProtoType *calleeProtoTy) |
55 | : CalleeProtoTy(calleeProtoTy), CalleeDecl() {} |
56 | CGCalleeInfo(GlobalDecl calleeDecl) |
57 | : CalleeProtoTy(nullptr), CalleeDecl(calleeDecl) {} |
58 | |
59 | const FunctionProtoType *getCalleeFunctionProtoType() const { |
60 | return CalleeProtoTy; |
61 | } |
62 | const GlobalDecl getCalleeDecl() const { return CalleeDecl; } |
63 | }; |
64 | |
65 | |
66 | class CGCallee { |
67 | enum class SpecialKind : uintptr_t { |
68 | Invalid, |
69 | Builtin, |
70 | PseudoDestructor, |
71 | Virtual, |
72 | |
73 | Last = Virtual |
74 | }; |
75 | |
76 | struct BuiltinInfoStorage { |
77 | const FunctionDecl *Decl; |
78 | unsigned ID; |
79 | }; |
80 | struct PseudoDestructorInfoStorage { |
81 | const CXXPseudoDestructorExpr *Expr; |
82 | }; |
83 | struct VirtualInfoStorage { |
84 | const CallExpr *CE; |
85 | GlobalDecl MD; |
86 | Address Addr; |
87 | llvm::FunctionType *FTy; |
88 | }; |
89 | |
90 | SpecialKind KindOrFunctionPointer; |
91 | union { |
92 | CGCalleeInfo AbstractInfo; |
93 | BuiltinInfoStorage BuiltinInfo; |
94 | PseudoDestructorInfoStorage PseudoDestructorInfo; |
95 | VirtualInfoStorage VirtualInfo; |
96 | }; |
97 | |
98 | explicit CGCallee(SpecialKind kind) : KindOrFunctionPointer(kind) {} |
99 | |
100 | CGCallee(const FunctionDecl *builtinDecl, unsigned builtinID) |
101 | : KindOrFunctionPointer(SpecialKind::Builtin) { |
102 | BuiltinInfo.Decl = builtinDecl; |
103 | BuiltinInfo.ID = builtinID; |
104 | } |
105 | |
106 | public: |
107 | CGCallee() : KindOrFunctionPointer(SpecialKind::Invalid) {} |
108 | |
109 | |
110 | |
111 | CGCallee(const CGCalleeInfo &abstractInfo, llvm::Value *functionPtr) |
112 | : KindOrFunctionPointer(SpecialKind(uintptr_t(functionPtr))) { |
113 | AbstractInfo = abstractInfo; |
114 | (0) . __assert_fail ("functionPtr && \"configuring callee without function pointer\"", "/home/seafit/code_projects/clang_source/clang/lib/CodeGen/CGCall.h", 114, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(functionPtr && "configuring callee without function pointer"); |
115 | getType()->isPointerTy()", "/home/seafit/code_projects/clang_source/clang/lib/CodeGen/CGCall.h", 115, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(functionPtr->getType()->isPointerTy()); |
116 | getType()->getPointerElementType()->isFunctionTy()", "/home/seafit/code_projects/clang_source/clang/lib/CodeGen/CGCall.h", 116, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(functionPtr->getType()->getPointerElementType()->isFunctionTy()); |
117 | } |
118 | |
119 | static CGCallee forBuiltin(unsigned builtinID, |
120 | const FunctionDecl *builtinDecl) { |
121 | CGCallee result(SpecialKind::Builtin); |
122 | result.BuiltinInfo.Decl = builtinDecl; |
123 | result.BuiltinInfo.ID = builtinID; |
124 | return result; |
125 | } |
126 | |
127 | static CGCallee forPseudoDestructor(const CXXPseudoDestructorExpr *E) { |
128 | CGCallee result(SpecialKind::PseudoDestructor); |
129 | result.PseudoDestructorInfo.Expr = E; |
130 | return result; |
131 | } |
132 | |
133 | static CGCallee forDirect(llvm::Constant *functionPtr, |
134 | const CGCalleeInfo &abstractInfo = CGCalleeInfo()) { |
135 | return CGCallee(abstractInfo, functionPtr); |
136 | } |
137 | |
138 | static CGCallee |
139 | forDirect(llvm::FunctionCallee functionPtr, |
140 | const CGCalleeInfo &abstractInfo = CGCalleeInfo()) { |
141 | return CGCallee(abstractInfo, functionPtr.getCallee()); |
142 | } |
143 | |
144 | static CGCallee forVirtual(const CallExpr *CE, GlobalDecl MD, Address Addr, |
145 | llvm::FunctionType *FTy) { |
146 | CGCallee result(SpecialKind::Virtual); |
147 | result.VirtualInfo.CE = CE; |
148 | result.VirtualInfo.MD = MD; |
149 | result.VirtualInfo.Addr = Addr; |
150 | result.VirtualInfo.FTy = FTy; |
151 | return result; |
152 | } |
153 | |
154 | bool isBuiltin() const { |
155 | return KindOrFunctionPointer == SpecialKind::Builtin; |
156 | } |
157 | const FunctionDecl *getBuiltinDecl() const { |
158 | assert(isBuiltin()); |
159 | return BuiltinInfo.Decl; |
160 | } |
161 | unsigned getBuiltinID() const { |
162 | assert(isBuiltin()); |
163 | return BuiltinInfo.ID; |
164 | } |
165 | |
166 | bool isPseudoDestructor() const { |
167 | return KindOrFunctionPointer == SpecialKind::PseudoDestructor; |
168 | } |
169 | const CXXPseudoDestructorExpr *getPseudoDestructorExpr() const { |
170 | assert(isPseudoDestructor()); |
171 | return PseudoDestructorInfo.Expr; |
172 | } |
173 | |
174 | bool isOrdinary() const { |
175 | return uintptr_t(KindOrFunctionPointer) > uintptr_t(SpecialKind::Last); |
176 | } |
177 | CGCalleeInfo getAbstractInfo() const { |
178 | if (isVirtual()) |
179 | return VirtualInfo.MD; |
180 | assert(isOrdinary()); |
181 | return AbstractInfo; |
182 | } |
183 | llvm::Value *getFunctionPointer() const { |
184 | assert(isOrdinary()); |
185 | return reinterpret_cast<llvm::Value*>(uintptr_t(KindOrFunctionPointer)); |
186 | } |
187 | void setFunctionPointer(llvm::Value *functionPtr) { |
188 | assert(isOrdinary()); |
189 | KindOrFunctionPointer = SpecialKind(uintptr_t(functionPtr)); |
190 | } |
191 | |
192 | bool isVirtual() const { |
193 | return KindOrFunctionPointer == SpecialKind::Virtual; |
194 | } |
195 | const CallExpr *getVirtualCallExpr() const { |
196 | assert(isVirtual()); |
197 | return VirtualInfo.CE; |
198 | } |
199 | GlobalDecl getVirtualMethodDecl() const { |
200 | assert(isVirtual()); |
201 | return VirtualInfo.MD; |
202 | } |
203 | Address getThisAddress() const { |
204 | assert(isVirtual()); |
205 | return VirtualInfo.Addr; |
206 | } |
207 | llvm::FunctionType *getVirtualFunctionType() const { |
208 | assert(isVirtual()); |
209 | return VirtualInfo.FTy; |
210 | } |
211 | |
212 | |
213 | |
214 | CGCallee prepareConcreteCallee(CodeGenFunction &CGF) const; |
215 | }; |
216 | |
217 | struct CallArg { |
218 | private: |
219 | union { |
220 | RValue RV; |
221 | LValue LV; |
222 | }; |
223 | bool HasLV; |
224 | |
225 | |
226 | |
227 | mutable bool IsUsed; |
228 | |
229 | public: |
230 | QualType Ty; |
231 | CallArg(RValue rv, QualType ty) |
232 | : RV(rv), HasLV(false), IsUsed(false), Ty(ty) {} |
233 | CallArg(LValue lv, QualType ty) |
234 | : LV(lv), HasLV(true), IsUsed(false), Ty(ty) {} |
235 | bool hasLValue() const { return HasLV; } |
236 | QualType getType() const { return Ty; } |
237 | |
238 | |
239 | |
240 | RValue getRValue(CodeGenFunction &CGF) const; |
241 | |
242 | LValue getKnownLValue() const { |
243 | assert(HasLV && !IsUsed); |
244 | return LV; |
245 | } |
246 | RValue getKnownRValue() const { |
247 | assert(!HasLV && !IsUsed); |
248 | return RV; |
249 | } |
250 | void setRValue(RValue _RV) { |
251 | assert(!HasLV); |
252 | RV = _RV; |
253 | } |
254 | |
255 | bool isAggregate() const { return HasLV || RV.isAggregate(); } |
256 | |
257 | void copyInto(CodeGenFunction &CGF, Address A) const; |
258 | }; |
259 | |
260 | |
261 | |
262 | class CallArgList : |
263 | public SmallVector<CallArg, 8> { |
264 | public: |
265 | CallArgList() : StackBase(nullptr) {} |
266 | |
267 | struct Writeback { |
268 | |
269 | |
270 | LValue Source; |
271 | |
272 | |
273 | Address Temporary; |
274 | |
275 | |
276 | llvm::Value *ToUse; |
277 | }; |
278 | |
279 | struct CallArgCleanup { |
280 | EHScopeStack::stable_iterator Cleanup; |
281 | |
282 | |
283 | |
284 | llvm::Instruction *IsActiveIP; |
285 | }; |
286 | |
287 | void add(RValue rvalue, QualType type) { push_back(CallArg(rvalue, type)); } |
288 | |
289 | void addUncopiedAggregate(LValue LV, QualType type) { |
290 | push_back(CallArg(LV, type)); |
291 | } |
292 | |
293 | |
294 | |
295 | |
296 | void addFrom(const CallArgList &other) { |
297 | insert(end(), other.begin(), other.end()); |
298 | Writebacks.insert(Writebacks.end(), |
299 | other.Writebacks.begin(), other.Writebacks.end()); |
300 | CleanupsToDeactivate.insert(CleanupsToDeactivate.end(), |
301 | other.CleanupsToDeactivate.begin(), |
302 | other.CleanupsToDeactivate.end()); |
303 | (0) . __assert_fail ("!(StackBase && other.StackBase) && \"can't merge stackbases\"", "/home/seafit/code_projects/clang_source/clang/lib/CodeGen/CGCall.h", 303, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(!(StackBase && other.StackBase) && "can't merge stackbases"); |
304 | if (!StackBase) |
305 | StackBase = other.StackBase; |
306 | } |
307 | |
308 | void addWriteback(LValue srcLV, Address temporary, |
309 | llvm::Value *toUse) { |
310 | Writeback writeback = { srcLV, temporary, toUse }; |
311 | Writebacks.push_back(writeback); |
312 | } |
313 | |
314 | bool hasWritebacks() const { return !Writebacks.empty(); } |
315 | |
316 | typedef llvm::iterator_range<SmallVectorImpl<Writeback>::const_iterator> |
317 | writeback_const_range; |
318 | |
319 | writeback_const_range writebacks() const { |
320 | return writeback_const_range(Writebacks.begin(), Writebacks.end()); |
321 | } |
322 | |
323 | void addArgCleanupDeactivation(EHScopeStack::stable_iterator Cleanup, |
324 | llvm::Instruction *IsActiveIP) { |
325 | CallArgCleanup ArgCleanup; |
326 | ArgCleanup.Cleanup = Cleanup; |
327 | ArgCleanup.IsActiveIP = IsActiveIP; |
328 | CleanupsToDeactivate.push_back(ArgCleanup); |
329 | } |
330 | |
331 | ArrayRef<CallArgCleanup> getCleanupsToDeactivate() const { |
332 | return CleanupsToDeactivate; |
333 | } |
334 | |
335 | void allocateArgumentMemory(CodeGenFunction &CGF); |
336 | llvm::Instruction *getStackBase() const { return StackBase; } |
337 | void freeArgumentMemory(CodeGenFunction &CGF) const; |
338 | |
339 | |
340 | |
341 | bool isUsingInAlloca() const { return StackBase; } |
342 | |
343 | private: |
344 | SmallVector<Writeback, 1> Writebacks; |
345 | |
346 | |
347 | |
348 | |
349 | SmallVector<CallArgCleanup, 1> CleanupsToDeactivate; |
350 | |
351 | |
352 | llvm::CallInst *StackBase; |
353 | }; |
354 | |
355 | |
356 | |
357 | |
358 | class FunctionArgList : public SmallVector<const VarDecl*, 16> { |
359 | }; |
360 | |
361 | |
362 | |
363 | class ReturnValueSlot { |
364 | llvm::PointerIntPair<llvm::Value *, 2, unsigned int> Value; |
365 | CharUnits Alignment; |
366 | |
367 | |
368 | enum Flags { |
369 | IS_VOLATILE = 0x1, |
370 | IS_UNUSED = 0x2, |
371 | }; |
372 | |
373 | public: |
374 | ReturnValueSlot() {} |
375 | ReturnValueSlot(Address Addr, bool IsVolatile, bool IsUnused = false) |
376 | : Value(Addr.isValid() ? Addr.getPointer() : nullptr, |
377 | (IsVolatile ? IS_VOLATILE : 0) | (IsUnused ? IS_UNUSED : 0)), |
378 | Alignment(Addr.isValid() ? Addr.getAlignment() : CharUnits::Zero()) {} |
379 | |
380 | bool isNull() const { return !getValue().isValid(); } |
381 | |
382 | bool isVolatile() const { return Value.getInt() & IS_VOLATILE; } |
383 | Address getValue() const { return Address(Value.getPointer(), Alignment); } |
384 | bool isUnused() const { return Value.getInt() & IS_UNUSED; } |
385 | }; |
386 | |
387 | } |
388 | } |
389 | |
390 | #endif |
391 | |