1//===----- CGCall.h - Encapsulate calling convention details ----*- C++ -*-===//
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 LLVM_CLANG_LIB_CODEGEN_CGCALL_H
15#define LLVM_CLANG_LIB_CODEGEN_CGCALL_H
16
17#include "CGPointerAuthInfo.h"
18#include "CGValue.h"
19#include "EHScopeStack.h"
20#include "clang/AST/ASTFwd.h"
21#include "clang/AST/CanonicalType.h"
22#include "clang/AST/GlobalDecl.h"
23#include "clang/AST/Type.h"
24#include "clang/Basic/BitmaskEnum.h"
25#include "clang/CodeGen/ModuleLinker.h"
26#include "llvm/ADT/STLForwardCompat.h"
27#include "llvm/IR/Value.h"
28
29namespace llvm {
30class Type;
31class Value;
32} // namespace llvm
33
34namespace clang {
35class Decl;
36class FunctionDecl;
37class TargetOptions;
38class VarDecl;
39
40namespace CodeGen {
41
42/// Abstract information about a function or function prototype.
43class CGCalleeInfo {
44 /// The function prototype of the callee.
45 const FunctionProtoType *CalleeProtoTy;
46 /// The function declaration of the callee.
47 GlobalDecl CalleeDecl;
48
49public:
50 explicit CGCalleeInfo() : CalleeProtoTy(nullptr) {}
51 CGCalleeInfo(const FunctionProtoType *calleeProtoTy, GlobalDecl calleeDecl)
52 : CalleeProtoTy(calleeProtoTy), CalleeDecl(calleeDecl) {}
53 CGCalleeInfo(const FunctionProtoType *calleeProtoTy)
54 : CalleeProtoTy(calleeProtoTy) {}
55 CGCalleeInfo(GlobalDecl calleeDecl)
56 : CalleeProtoTy(nullptr), CalleeDecl(calleeDecl) {}
57
58 const FunctionProtoType *getCalleeFunctionProtoType() const {
59 return CalleeProtoTy;
60 }
61 const GlobalDecl getCalleeDecl() const { return CalleeDecl; }
62};
63
64/// All available information about a concrete callee.
65class CGCallee {
66 enum class SpecialKind : uintptr_t {
67 Invalid,
68 Builtin,
69 PseudoDestructor,
70 Virtual,
71
72 Last = Virtual
73 };
74
75 struct OrdinaryInfoStorage {
76 CGCalleeInfo AbstractInfo;
77 CGPointerAuthInfo PointerAuthInfo;
78 };
79 struct BuiltinInfoStorage {
80 const FunctionDecl *Decl;
81 unsigned ID;
82 };
83 struct PseudoDestructorInfoStorage {
84 const CXXPseudoDestructorExpr *Expr;
85 };
86 struct VirtualInfoStorage {
87 const CallExpr *CE;
88 GlobalDecl MD;
89 Address Addr;
90 llvm::FunctionType *FTy;
91 };
92
93 SpecialKind KindOrFunctionPointer;
94 union {
95 OrdinaryInfoStorage OrdinaryInfo;
96 BuiltinInfoStorage BuiltinInfo;
97 PseudoDestructorInfoStorage PseudoDestructorInfo;
98 VirtualInfoStorage VirtualInfo;
99 };
100
101 explicit CGCallee(SpecialKind kind) : KindOrFunctionPointer(kind) {}
102
103 CGCallee(const FunctionDecl *builtinDecl, unsigned builtinID)
104 : KindOrFunctionPointer(SpecialKind::Builtin) {
105 BuiltinInfo.Decl = builtinDecl;
106 BuiltinInfo.ID = builtinID;
107 }
108
109public:
110 CGCallee() : KindOrFunctionPointer(SpecialKind::Invalid) {}
111
112 /// Construct a callee. Call this constructor directly when this
113 /// isn't a direct call.
114 CGCallee(const CGCalleeInfo &abstractInfo, llvm::Value *functionPtr,
115 /* FIXME: make parameter pointerAuthInfo mandatory */
116 const CGPointerAuthInfo &pointerAuthInfo = CGPointerAuthInfo())
117 : KindOrFunctionPointer(
118 SpecialKind(reinterpret_cast<uintptr_t>(functionPtr))) {
119 OrdinaryInfo.AbstractInfo = abstractInfo;
120 OrdinaryInfo.PointerAuthInfo = pointerAuthInfo;
121 assert(functionPtr && "configuring callee without function pointer");
122 assert(functionPtr->getType()->isPointerTy());
123 }
124
125 static CGCallee forBuiltin(unsigned builtinID,
126 const FunctionDecl *builtinDecl) {
127 CGCallee result(SpecialKind::Builtin);
128 result.BuiltinInfo.Decl = builtinDecl;
129 result.BuiltinInfo.ID = builtinID;
130 return result;
131 }
132
133 static CGCallee forPseudoDestructor(const CXXPseudoDestructorExpr *E) {
134 CGCallee result(SpecialKind::PseudoDestructor);
135 result.PseudoDestructorInfo.Expr = E;
136 return result;
137 }
138
139 static CGCallee forDirect(llvm::Constant *functionPtr,
140 const CGCalleeInfo &abstractInfo = CGCalleeInfo()) {
141 return CGCallee(abstractInfo, functionPtr);
142 }
143
144 static CGCallee forDirect(llvm::FunctionCallee functionPtr,
145 const CGCalleeInfo &abstractInfo = CGCalleeInfo()) {
146 return CGCallee(abstractInfo, functionPtr.getCallee());
147 }
148
149 static CGCallee forVirtual(const CallExpr *CE, GlobalDecl MD, Address Addr,
150 llvm::FunctionType *FTy) {
151 CGCallee result(SpecialKind::Virtual);
152 result.VirtualInfo.CE = CE;
153 result.VirtualInfo.MD = MD;
154 result.VirtualInfo.Addr = Addr;
155 result.VirtualInfo.FTy = FTy;
156 return result;
157 }
158
159 bool isBuiltin() const {
160 return KindOrFunctionPointer == SpecialKind::Builtin;
161 }
162 const FunctionDecl *getBuiltinDecl() const {
163 assert(isBuiltin());
164 return BuiltinInfo.Decl;
165 }
166 unsigned getBuiltinID() const {
167 assert(isBuiltin());
168 return BuiltinInfo.ID;
169 }
170
171 bool isPseudoDestructor() const {
172 return KindOrFunctionPointer == SpecialKind::PseudoDestructor;
173 }
174 const CXXPseudoDestructorExpr *getPseudoDestructorExpr() const {
175 assert(isPseudoDestructor());
176 return PseudoDestructorInfo.Expr;
177 }
178
179 bool isOrdinary() const {
180 return uintptr_t(KindOrFunctionPointer) > uintptr_t(SpecialKind::Last);
181 }
182 CGCalleeInfo getAbstractInfo() const {
183 if (isVirtual())
184 return VirtualInfo.MD;
185 assert(isOrdinary());
186 return OrdinaryInfo.AbstractInfo;
187 }
188 const CGPointerAuthInfo &getPointerAuthInfo() const {
189 assert(isOrdinary());
190 return OrdinaryInfo.PointerAuthInfo;
191 }
192 llvm::Value *getFunctionPointer() const {
193 assert(isOrdinary());
194 return reinterpret_cast<llvm::Value *>(uintptr_t(KindOrFunctionPointer));
195 }
196 void setFunctionPointer(llvm::Value *functionPtr) {
197 assert(isOrdinary());
198 KindOrFunctionPointer =
199 SpecialKind(reinterpret_cast<uintptr_t>(functionPtr));
200 }
201 void setPointerAuthInfo(CGPointerAuthInfo PointerAuth) {
202 assert(isOrdinary());
203 OrdinaryInfo.PointerAuthInfo = PointerAuth;
204 }
205
206 bool isVirtual() const {
207 return KindOrFunctionPointer == SpecialKind::Virtual;
208 }
209 const CallExpr *getVirtualCallExpr() const {
210 assert(isVirtual());
211 return VirtualInfo.CE;
212 }
213 GlobalDecl getVirtualMethodDecl() const {
214 assert(isVirtual());
215 return VirtualInfo.MD;
216 }
217 Address getThisAddress() const {
218 assert(isVirtual());
219 return VirtualInfo.Addr;
220 }
221 llvm::FunctionType *getVirtualFunctionType() const {
222 assert(isVirtual());
223 return VirtualInfo.FTy;
224 }
225
226 /// If this is a delayed callee computation of some sort, prepare
227 /// a concrete callee.
228 CGCallee prepareConcreteCallee(CodeGenFunction &CGF) const;
229};
230
231struct CallArg {
232private:
233 union {
234 RValue RV;
235 LValue LV; /// The argument is semantically a load from this l-value.
236 };
237 bool HasLV;
238
239 /// A data-flow flag to make sure getRValue and/or copyInto are not
240 /// called twice for duplicated IR emission.
241 mutable bool IsUsed;
242
243public:
244 QualType Ty;
245 CallArg(RValue rv, QualType ty)
246 : RV(rv), HasLV(false), IsUsed(false), Ty(ty) {}
247 CallArg(LValue lv, QualType ty)
248 : LV(lv), HasLV(true), IsUsed(false), Ty(ty) {}
249 bool hasLValue() const { return HasLV; }
250 QualType getType() const { return Ty; }
251
252 /// \returns an independent RValue. If the CallArg contains an LValue,
253 /// a temporary copy is returned.
254 RValue getRValue(CodeGenFunction &CGF) const;
255
256 LValue getKnownLValue() const {
257 assert(HasLV && !IsUsed);
258 return LV;
259 }
260 RValue getKnownRValue() const {
261 assert(!HasLV && !IsUsed);
262 return RV;
263 }
264 void setRValue(RValue _RV) {
265 assert(!HasLV);
266 RV = _RV;
267 }
268
269 bool isAggregate() const { return HasLV || RV.isAggregate(); }
270
271 void copyInto(CodeGenFunction &CGF, Address A) const;
272};
273
274/// CallArgList - Type for representing both the value and type of
275/// arguments in a call.
276class CallArgList : public SmallVector<CallArg, 8> {
277public:
278 CallArgList() = default;
279
280 struct Writeback {
281 /// The original argument. Note that the argument l-value
282 /// is potentially null.
283 LValue Source;
284
285 /// The temporary alloca.
286 Address Temporary;
287
288 /// A value to "use" after the writeback, or null.
289 llvm::Value *ToUse;
290
291 /// An Expression (optional) that performs the writeback with any required
292 /// casting.
293 const Expr *WritebackExpr;
294 };
295
296 struct CallArgCleanup {
297 EHScopeStack::stable_iterator Cleanup;
298
299 /// The "is active" insertion point. This instruction is temporary and
300 /// will be removed after insertion.
301 llvm::Instruction *IsActiveIP;
302 };
303
304 void add(RValue rvalue, QualType type) { push_back(Elt: CallArg(rvalue, type)); }
305
306 void addUncopiedAggregate(LValue LV, QualType type) {
307 push_back(Elt: CallArg(LV, type));
308 }
309
310 /// Add all the arguments from another CallArgList to this one. After doing
311 /// this, the old CallArgList retains its list of arguments, but must not
312 /// be used to emit a call.
313 void addFrom(const CallArgList &other) {
314 llvm::append_range(C&: *this, R: other);
315 llvm::append_range(C&: Writebacks, R: other.Writebacks);
316 llvm::append_range(C&: CleanupsToDeactivate, R: other.CleanupsToDeactivate);
317 assert(!(StackBase && other.StackBase) && "can't merge stackbases");
318 if (!StackBase)
319 StackBase = other.StackBase;
320 }
321
322 void addWriteback(LValue srcLV, Address temporary, llvm::Value *toUse,
323 const Expr *writebackExpr = nullptr) {
324 Writeback writeback = {.Source: srcLV, .Temporary: temporary, .ToUse: toUse, .WritebackExpr: writebackExpr};
325 Writebacks.push_back(Elt: writeback);
326 }
327
328 bool hasWritebacks() const { return !Writebacks.empty(); }
329
330 typedef llvm::iterator_range<SmallVectorImpl<Writeback>::const_iterator>
331 writeback_const_range;
332
333 writeback_const_range writebacks() const {
334 return writeback_const_range(Writebacks.begin(), Writebacks.end());
335 }
336
337 void addArgCleanupDeactivation(EHScopeStack::stable_iterator Cleanup,
338 llvm::Instruction *IsActiveIP) {
339 CallArgCleanup ArgCleanup;
340 ArgCleanup.Cleanup = Cleanup;
341 ArgCleanup.IsActiveIP = IsActiveIP;
342 CleanupsToDeactivate.push_back(Elt: ArgCleanup);
343 }
344
345 ArrayRef<CallArgCleanup> getCleanupsToDeactivate() const {
346 return CleanupsToDeactivate;
347 }
348
349 void allocateArgumentMemory(CodeGenFunction &CGF);
350 llvm::Instruction *getStackBase() const { return StackBase; }
351 void freeArgumentMemory(CodeGenFunction &CGF) const;
352
353 /// Returns if we're using an inalloca struct to pass arguments in
354 /// memory.
355 bool isUsingInAlloca() const { return StackBase; }
356
357 // Support reversing writebacks for MSVC ABI.
358 void reverseWritebacks() {
359 std::reverse(first: Writebacks.begin(), last: Writebacks.end());
360 }
361
362private:
363 SmallVector<Writeback, 1> Writebacks;
364
365 /// Deactivate these cleanups immediately before making the call. This
366 /// is used to cleanup objects that are owned by the callee once the call
367 /// occurs.
368 SmallVector<CallArgCleanup, 1> CleanupsToDeactivate;
369
370 /// The stacksave call. It dominates all of the argument evaluation.
371 llvm::CallInst *StackBase = nullptr;
372};
373
374/// FunctionArgList - Type for representing both the decl and type
375/// of parameters to a function. The decl must be either a
376/// ParmVarDecl or ImplicitParamDecl.
377class FunctionArgList : public SmallVector<const VarDecl *, 16> {
378 using SmallVector::SmallVector;
379};
380
381/// ReturnValueSlot - Contains the address where the return value of a
382/// function can be stored, and whether the address is volatile or not.
383class ReturnValueSlot {
384 Address Addr = Address::invalid();
385
386 // Return value slot flags
387 LLVM_PREFERRED_TYPE(bool)
388 unsigned IsVolatile : 1;
389 LLVM_PREFERRED_TYPE(bool)
390 unsigned IsUnused : 1;
391 LLVM_PREFERRED_TYPE(bool)
392 unsigned IsExternallyDestructed : 1;
393
394public:
395 ReturnValueSlot()
396 : IsVolatile(false), IsUnused(false), IsExternallyDestructed(false) {}
397 ReturnValueSlot(Address Addr, bool IsVolatile, bool IsUnused = false,
398 bool IsExternallyDestructed = false)
399 : Addr(Addr), IsVolatile(IsVolatile), IsUnused(IsUnused),
400 IsExternallyDestructed(IsExternallyDestructed) {}
401
402 bool isNull() const { return !Addr.isValid(); }
403 bool isVolatile() const { return IsVolatile; }
404 Address getValue() const { return Addr; }
405 bool isUnused() const { return IsUnused; }
406 bool isExternallyDestructed() const { return IsExternallyDestructed; }
407 Address getAddress() const { return Addr; }
408};
409
410enum class FnInfoOpts {
411 None = 0,
412 IsInstanceMethod = 1 << 0,
413 IsChainCall = 1 << 1,
414 IsDelegateCall = 1 << 2,
415 LLVM_MARK_AS_BITMASK_ENUM(/*LargestValue=*/IsDelegateCall)
416};
417
418struct DisableDebugLocationUpdates {
419 CodeGenFunction &CGF;
420 DisableDebugLocationUpdates(CodeGenFunction &CGF);
421 ~DisableDebugLocationUpdates();
422 DisableDebugLocationUpdates(const DisableDebugLocationUpdates &) = delete;
423 DisableDebugLocationUpdates &
424 operator=(const DisableDebugLocationUpdates &) = delete;
425};
426
427} // end namespace CodeGen
428} // end namespace clang
429
430#endif
431