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