xref: /freebsd/contrib/llvm-project/clang/lib/CodeGen/CGCall.h (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
10b57cec5SDimitry Andric //===----- CGCall.h - Encapsulate calling convention details ----*- C++ -*-===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // These classes wrap the information about a call or function
100b57cec5SDimitry Andric // definition used to handle ABI compliancy.
110b57cec5SDimitry Andric //
120b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
130b57cec5SDimitry Andric 
140b57cec5SDimitry Andric #ifndef LLVM_CLANG_LIB_CODEGEN_CGCALL_H
150b57cec5SDimitry Andric #define LLVM_CLANG_LIB_CODEGEN_CGCALL_H
160b57cec5SDimitry Andric 
17*0fca6ea1SDimitry Andric #include "CGPointerAuthInfo.h"
180b57cec5SDimitry Andric #include "CGValue.h"
190b57cec5SDimitry Andric #include "EHScopeStack.h"
205ffd83dbSDimitry Andric #include "clang/AST/ASTFwd.h"
210b57cec5SDimitry Andric #include "clang/AST/CanonicalType.h"
220b57cec5SDimitry Andric #include "clang/AST/GlobalDecl.h"
230b57cec5SDimitry Andric #include "clang/AST/Type.h"
245f757f3fSDimitry Andric #include "llvm/ADT/STLForwardCompat.h"
250b57cec5SDimitry Andric #include "llvm/IR/Value.h"
260b57cec5SDimitry Andric 
270b57cec5SDimitry Andric namespace llvm {
280b57cec5SDimitry Andric class Type;
290b57cec5SDimitry Andric class Value;
30480093f4SDimitry Andric } // namespace llvm
310b57cec5SDimitry Andric 
320b57cec5SDimitry Andric namespace clang {
330b57cec5SDimitry Andric class Decl;
340b57cec5SDimitry Andric class FunctionDecl;
3506c3fb27SDimitry Andric class TargetOptions;
360b57cec5SDimitry Andric class VarDecl;
370b57cec5SDimitry Andric 
380b57cec5SDimitry Andric namespace CodeGen {
390b57cec5SDimitry Andric 
400b57cec5SDimitry Andric /// Abstract information about a function or function prototype.
410b57cec5SDimitry Andric class CGCalleeInfo {
420b57cec5SDimitry Andric   /// The function prototype of the callee.
430b57cec5SDimitry Andric   const FunctionProtoType *CalleeProtoTy;
440b57cec5SDimitry Andric   /// The function declaration of the callee.
450b57cec5SDimitry Andric   GlobalDecl CalleeDecl;
460b57cec5SDimitry Andric 
470b57cec5SDimitry Andric public:
CGCalleeInfo()4804eeddc0SDimitry Andric   explicit CGCalleeInfo() : CalleeProtoTy(nullptr) {}
CGCalleeInfo(const FunctionProtoType * calleeProtoTy,GlobalDecl calleeDecl)490b57cec5SDimitry Andric   CGCalleeInfo(const FunctionProtoType *calleeProtoTy, GlobalDecl calleeDecl)
500b57cec5SDimitry Andric       : CalleeProtoTy(calleeProtoTy), CalleeDecl(calleeDecl) {}
CGCalleeInfo(const FunctionProtoType * calleeProtoTy)510b57cec5SDimitry Andric   CGCalleeInfo(const FunctionProtoType *calleeProtoTy)
5204eeddc0SDimitry Andric       : CalleeProtoTy(calleeProtoTy) {}
CGCalleeInfo(GlobalDecl calleeDecl)530b57cec5SDimitry Andric   CGCalleeInfo(GlobalDecl calleeDecl)
540b57cec5SDimitry Andric       : CalleeProtoTy(nullptr), CalleeDecl(calleeDecl) {}
550b57cec5SDimitry Andric 
getCalleeFunctionProtoType()560b57cec5SDimitry Andric   const FunctionProtoType *getCalleeFunctionProtoType() const {
570b57cec5SDimitry Andric     return CalleeProtoTy;
580b57cec5SDimitry Andric   }
getCalleeDecl()590b57cec5SDimitry Andric   const GlobalDecl getCalleeDecl() const { return CalleeDecl; }
600b57cec5SDimitry Andric };
610b57cec5SDimitry Andric 
620b57cec5SDimitry Andric /// All available information about a concrete callee.
630b57cec5SDimitry Andric class CGCallee {
640b57cec5SDimitry Andric   enum class SpecialKind : uintptr_t {
650b57cec5SDimitry Andric     Invalid,
660b57cec5SDimitry Andric     Builtin,
670b57cec5SDimitry Andric     PseudoDestructor,
680b57cec5SDimitry Andric     Virtual,
690b57cec5SDimitry Andric 
700b57cec5SDimitry Andric     Last = Virtual
710b57cec5SDimitry Andric   };
720b57cec5SDimitry Andric 
73*0fca6ea1SDimitry Andric   struct OrdinaryInfoStorage {
74*0fca6ea1SDimitry Andric     CGCalleeInfo AbstractInfo;
75*0fca6ea1SDimitry Andric     CGPointerAuthInfo PointerAuthInfo;
76*0fca6ea1SDimitry Andric   };
770b57cec5SDimitry Andric   struct BuiltinInfoStorage {
780b57cec5SDimitry Andric     const FunctionDecl *Decl;
790b57cec5SDimitry Andric     unsigned ID;
800b57cec5SDimitry Andric   };
810b57cec5SDimitry Andric   struct PseudoDestructorInfoStorage {
820b57cec5SDimitry Andric     const CXXPseudoDestructorExpr *Expr;
830b57cec5SDimitry Andric   };
840b57cec5SDimitry Andric   struct VirtualInfoStorage {
850b57cec5SDimitry Andric     const CallExpr *CE;
860b57cec5SDimitry Andric     GlobalDecl MD;
870b57cec5SDimitry Andric     Address Addr;
880b57cec5SDimitry Andric     llvm::FunctionType *FTy;
890b57cec5SDimitry Andric   };
900b57cec5SDimitry Andric 
910b57cec5SDimitry Andric   SpecialKind KindOrFunctionPointer;
920b57cec5SDimitry Andric   union {
93*0fca6ea1SDimitry Andric     OrdinaryInfoStorage OrdinaryInfo;
940b57cec5SDimitry Andric     BuiltinInfoStorage BuiltinInfo;
950b57cec5SDimitry Andric     PseudoDestructorInfoStorage PseudoDestructorInfo;
960b57cec5SDimitry Andric     VirtualInfoStorage VirtualInfo;
970b57cec5SDimitry Andric   };
980b57cec5SDimitry Andric 
CGCallee(SpecialKind kind)990b57cec5SDimitry Andric   explicit CGCallee(SpecialKind kind) : KindOrFunctionPointer(kind) {}
1000b57cec5SDimitry Andric 
CGCallee(const FunctionDecl * builtinDecl,unsigned builtinID)1010b57cec5SDimitry Andric   CGCallee(const FunctionDecl *builtinDecl, unsigned builtinID)
1020b57cec5SDimitry Andric       : KindOrFunctionPointer(SpecialKind::Builtin) {
1030b57cec5SDimitry Andric     BuiltinInfo.Decl = builtinDecl;
1040b57cec5SDimitry Andric     BuiltinInfo.ID = builtinID;
1050b57cec5SDimitry Andric   }
1060b57cec5SDimitry Andric 
1070b57cec5SDimitry Andric public:
CGCallee()1080b57cec5SDimitry Andric   CGCallee() : KindOrFunctionPointer(SpecialKind::Invalid) {}
1090b57cec5SDimitry Andric 
1100b57cec5SDimitry Andric   /// Construct a callee.  Call this constructor directly when this
1110b57cec5SDimitry Andric   /// isn't a direct call.
112*0fca6ea1SDimitry Andric   CGCallee(const CGCalleeInfo &abstractInfo, llvm::Value *functionPtr,
113*0fca6ea1SDimitry Andric            /* FIXME: make parameter pointerAuthInfo mandatory */
114*0fca6ea1SDimitry Andric            const CGPointerAuthInfo &pointerAuthInfo = CGPointerAuthInfo())
KindOrFunctionPointer(SpecialKind (reinterpret_cast<uintptr_t> (functionPtr)))115e8d8bef9SDimitry Andric       : KindOrFunctionPointer(
116e8d8bef9SDimitry Andric             SpecialKind(reinterpret_cast<uintptr_t>(functionPtr))) {
117*0fca6ea1SDimitry Andric     OrdinaryInfo.AbstractInfo = abstractInfo;
118*0fca6ea1SDimitry Andric     OrdinaryInfo.PointerAuthInfo = pointerAuthInfo;
1190b57cec5SDimitry Andric     assert(functionPtr && "configuring callee without function pointer");
1200b57cec5SDimitry Andric     assert(functionPtr->getType()->isPointerTy());
1210b57cec5SDimitry Andric   }
1220b57cec5SDimitry Andric 
forBuiltin(unsigned builtinID,const FunctionDecl * builtinDecl)1230b57cec5SDimitry Andric   static CGCallee forBuiltin(unsigned builtinID,
1240b57cec5SDimitry Andric                              const FunctionDecl *builtinDecl) {
1250b57cec5SDimitry Andric     CGCallee result(SpecialKind::Builtin);
1260b57cec5SDimitry Andric     result.BuiltinInfo.Decl = builtinDecl;
1270b57cec5SDimitry Andric     result.BuiltinInfo.ID = builtinID;
1280b57cec5SDimitry Andric     return result;
1290b57cec5SDimitry Andric   }
1300b57cec5SDimitry Andric 
forPseudoDestructor(const CXXPseudoDestructorExpr * E)1310b57cec5SDimitry Andric   static CGCallee forPseudoDestructor(const CXXPseudoDestructorExpr *E) {
1320b57cec5SDimitry Andric     CGCallee result(SpecialKind::PseudoDestructor);
1330b57cec5SDimitry Andric     result.PseudoDestructorInfo.Expr = E;
1340b57cec5SDimitry Andric     return result;
1350b57cec5SDimitry Andric   }
1360b57cec5SDimitry Andric 
1370b57cec5SDimitry Andric   static CGCallee forDirect(llvm::Constant *functionPtr,
1380b57cec5SDimitry Andric                             const CGCalleeInfo &abstractInfo = CGCalleeInfo()) {
1390b57cec5SDimitry Andric     return CGCallee(abstractInfo, functionPtr);
1400b57cec5SDimitry Andric   }
1410b57cec5SDimitry Andric 
142480093f4SDimitry Andric   static CGCallee forDirect(llvm::FunctionCallee functionPtr,
1430b57cec5SDimitry Andric                             const CGCalleeInfo &abstractInfo = CGCalleeInfo()) {
1440b57cec5SDimitry Andric     return CGCallee(abstractInfo, functionPtr.getCallee());
1450b57cec5SDimitry Andric   }
1460b57cec5SDimitry Andric 
forVirtual(const CallExpr * CE,GlobalDecl MD,Address Addr,llvm::FunctionType * FTy)1470b57cec5SDimitry Andric   static CGCallee forVirtual(const CallExpr *CE, GlobalDecl MD, Address Addr,
1480b57cec5SDimitry Andric                              llvm::FunctionType *FTy) {
1490b57cec5SDimitry Andric     CGCallee result(SpecialKind::Virtual);
1500b57cec5SDimitry Andric     result.VirtualInfo.CE = CE;
1510b57cec5SDimitry Andric     result.VirtualInfo.MD = MD;
1520b57cec5SDimitry Andric     result.VirtualInfo.Addr = Addr;
1530b57cec5SDimitry Andric     result.VirtualInfo.FTy = FTy;
1540b57cec5SDimitry Andric     return result;
1550b57cec5SDimitry Andric   }
1560b57cec5SDimitry Andric 
isBuiltin()1570b57cec5SDimitry Andric   bool isBuiltin() const {
1580b57cec5SDimitry Andric     return KindOrFunctionPointer == SpecialKind::Builtin;
1590b57cec5SDimitry Andric   }
getBuiltinDecl()1600b57cec5SDimitry Andric   const FunctionDecl *getBuiltinDecl() const {
1610b57cec5SDimitry Andric     assert(isBuiltin());
1620b57cec5SDimitry Andric     return BuiltinInfo.Decl;
1630b57cec5SDimitry Andric   }
getBuiltinID()1640b57cec5SDimitry Andric   unsigned getBuiltinID() const {
1650b57cec5SDimitry Andric     assert(isBuiltin());
1660b57cec5SDimitry Andric     return BuiltinInfo.ID;
1670b57cec5SDimitry Andric   }
1680b57cec5SDimitry Andric 
isPseudoDestructor()1690b57cec5SDimitry Andric   bool isPseudoDestructor() const {
1700b57cec5SDimitry Andric     return KindOrFunctionPointer == SpecialKind::PseudoDestructor;
1710b57cec5SDimitry Andric   }
getPseudoDestructorExpr()1720b57cec5SDimitry Andric   const CXXPseudoDestructorExpr *getPseudoDestructorExpr() const {
1730b57cec5SDimitry Andric     assert(isPseudoDestructor());
1740b57cec5SDimitry Andric     return PseudoDestructorInfo.Expr;
1750b57cec5SDimitry Andric   }
1760b57cec5SDimitry Andric 
isOrdinary()1770b57cec5SDimitry Andric   bool isOrdinary() const {
1780b57cec5SDimitry Andric     return uintptr_t(KindOrFunctionPointer) > uintptr_t(SpecialKind::Last);
1790b57cec5SDimitry Andric   }
getAbstractInfo()1800b57cec5SDimitry Andric   CGCalleeInfo getAbstractInfo() const {
1810b57cec5SDimitry Andric     if (isVirtual())
1820b57cec5SDimitry Andric       return VirtualInfo.MD;
1830b57cec5SDimitry Andric     assert(isOrdinary());
184*0fca6ea1SDimitry Andric     return OrdinaryInfo.AbstractInfo;
185*0fca6ea1SDimitry Andric   }
getPointerAuthInfo()186*0fca6ea1SDimitry Andric   const CGPointerAuthInfo &getPointerAuthInfo() const {
187*0fca6ea1SDimitry Andric     assert(isOrdinary());
188*0fca6ea1SDimitry Andric     return OrdinaryInfo.PointerAuthInfo;
1890b57cec5SDimitry Andric   }
getFunctionPointer()1900b57cec5SDimitry Andric   llvm::Value *getFunctionPointer() const {
1910b57cec5SDimitry Andric     assert(isOrdinary());
1920b57cec5SDimitry Andric     return reinterpret_cast<llvm::Value *>(uintptr_t(KindOrFunctionPointer));
1930b57cec5SDimitry Andric   }
setFunctionPointer(llvm::Value * functionPtr)1940b57cec5SDimitry Andric   void setFunctionPointer(llvm::Value *functionPtr) {
1950b57cec5SDimitry Andric     assert(isOrdinary());
196e8d8bef9SDimitry Andric     KindOrFunctionPointer =
197e8d8bef9SDimitry Andric         SpecialKind(reinterpret_cast<uintptr_t>(functionPtr));
1980b57cec5SDimitry Andric   }
setPointerAuthInfo(CGPointerAuthInfo PointerAuth)199*0fca6ea1SDimitry Andric   void setPointerAuthInfo(CGPointerAuthInfo PointerAuth) {
200*0fca6ea1SDimitry Andric     assert(isOrdinary());
201*0fca6ea1SDimitry Andric     OrdinaryInfo.PointerAuthInfo = PointerAuth;
202*0fca6ea1SDimitry Andric   }
2030b57cec5SDimitry Andric 
isVirtual()2040b57cec5SDimitry Andric   bool isVirtual() const {
2050b57cec5SDimitry Andric     return KindOrFunctionPointer == SpecialKind::Virtual;
2060b57cec5SDimitry Andric   }
getVirtualCallExpr()2070b57cec5SDimitry Andric   const CallExpr *getVirtualCallExpr() const {
2080b57cec5SDimitry Andric     assert(isVirtual());
2090b57cec5SDimitry Andric     return VirtualInfo.CE;
2100b57cec5SDimitry Andric   }
getVirtualMethodDecl()2110b57cec5SDimitry Andric   GlobalDecl getVirtualMethodDecl() const {
2120b57cec5SDimitry Andric     assert(isVirtual());
2130b57cec5SDimitry Andric     return VirtualInfo.MD;
2140b57cec5SDimitry Andric   }
getThisAddress()2150b57cec5SDimitry Andric   Address getThisAddress() const {
2160b57cec5SDimitry Andric     assert(isVirtual());
2170b57cec5SDimitry Andric     return VirtualInfo.Addr;
2180b57cec5SDimitry Andric   }
getVirtualFunctionType()2190b57cec5SDimitry Andric   llvm::FunctionType *getVirtualFunctionType() const {
2200b57cec5SDimitry Andric     assert(isVirtual());
2210b57cec5SDimitry Andric     return VirtualInfo.FTy;
2220b57cec5SDimitry Andric   }
2230b57cec5SDimitry Andric 
2240b57cec5SDimitry Andric   /// If this is a delayed callee computation of some sort, prepare
2250b57cec5SDimitry Andric   /// a concrete callee.
2260b57cec5SDimitry Andric   CGCallee prepareConcreteCallee(CodeGenFunction &CGF) const;
2270b57cec5SDimitry Andric };
2280b57cec5SDimitry Andric 
2290b57cec5SDimitry Andric struct CallArg {
2300b57cec5SDimitry Andric private:
2310b57cec5SDimitry Andric   union {
2320b57cec5SDimitry Andric     RValue RV;
2330b57cec5SDimitry Andric     LValue LV; /// The argument is semantically a load from this l-value.
2340b57cec5SDimitry Andric   };
2350b57cec5SDimitry Andric   bool HasLV;
2360b57cec5SDimitry Andric 
2370b57cec5SDimitry Andric   /// A data-flow flag to make sure getRValue and/or copyInto are not
2380b57cec5SDimitry Andric   /// called twice for duplicated IR emission.
2390b57cec5SDimitry Andric   mutable bool IsUsed;
2400b57cec5SDimitry Andric 
2410b57cec5SDimitry Andric public:
2420b57cec5SDimitry Andric   QualType Ty;
CallArgCallArg2430b57cec5SDimitry Andric   CallArg(RValue rv, QualType ty)
2440b57cec5SDimitry Andric       : RV(rv), HasLV(false), IsUsed(false), Ty(ty) {}
CallArgCallArg2450b57cec5SDimitry Andric   CallArg(LValue lv, QualType ty)
2460b57cec5SDimitry Andric       : LV(lv), HasLV(true), IsUsed(false), Ty(ty) {}
hasLValueCallArg2470b57cec5SDimitry Andric   bool hasLValue() const { return HasLV; }
getTypeCallArg2480b57cec5SDimitry Andric   QualType getType() const { return Ty; }
2490b57cec5SDimitry Andric 
2500b57cec5SDimitry Andric   /// \returns an independent RValue. If the CallArg contains an LValue,
2510b57cec5SDimitry Andric   /// a temporary copy is returned.
2520b57cec5SDimitry Andric   RValue getRValue(CodeGenFunction &CGF) const;
2530b57cec5SDimitry Andric 
getKnownLValueCallArg2540b57cec5SDimitry Andric   LValue getKnownLValue() const {
2550b57cec5SDimitry Andric     assert(HasLV && !IsUsed);
2560b57cec5SDimitry Andric     return LV;
2570b57cec5SDimitry Andric   }
getKnownRValueCallArg2580b57cec5SDimitry Andric   RValue getKnownRValue() const {
2590b57cec5SDimitry Andric     assert(!HasLV && !IsUsed);
2600b57cec5SDimitry Andric     return RV;
2610b57cec5SDimitry Andric   }
setRValueCallArg2620b57cec5SDimitry Andric   void setRValue(RValue _RV) {
2630b57cec5SDimitry Andric     assert(!HasLV);
2640b57cec5SDimitry Andric     RV = _RV;
2650b57cec5SDimitry Andric   }
2660b57cec5SDimitry Andric 
isAggregateCallArg2670b57cec5SDimitry Andric   bool isAggregate() const { return HasLV || RV.isAggregate(); }
2680b57cec5SDimitry Andric 
2690b57cec5SDimitry Andric   void copyInto(CodeGenFunction &CGF, Address A) const;
2700b57cec5SDimitry Andric };
2710b57cec5SDimitry Andric 
2720b57cec5SDimitry Andric /// CallArgList - Type for representing both the value and type of
2730b57cec5SDimitry Andric /// arguments in a call.
274480093f4SDimitry Andric class CallArgList : public SmallVector<CallArg, 8> {
2750b57cec5SDimitry Andric public:
2765f757f3fSDimitry Andric   CallArgList() = default;
2770b57cec5SDimitry Andric 
2780b57cec5SDimitry Andric   struct Writeback {
2790b57cec5SDimitry Andric     /// The original argument.  Note that the argument l-value
2800b57cec5SDimitry Andric     /// is potentially null.
2810b57cec5SDimitry Andric     LValue Source;
2820b57cec5SDimitry Andric 
2830b57cec5SDimitry Andric     /// The temporary alloca.
2840b57cec5SDimitry Andric     Address Temporary;
2850b57cec5SDimitry Andric 
2860b57cec5SDimitry Andric     /// A value to "use" after the writeback, or null.
2870b57cec5SDimitry Andric     llvm::Value *ToUse;
2880b57cec5SDimitry Andric   };
2890b57cec5SDimitry Andric 
2900b57cec5SDimitry Andric   struct CallArgCleanup {
2910b57cec5SDimitry Andric     EHScopeStack::stable_iterator Cleanup;
2920b57cec5SDimitry Andric 
2930b57cec5SDimitry Andric     /// The "is active" insertion point.  This instruction is temporary and
2940b57cec5SDimitry Andric     /// will be removed after insertion.
2950b57cec5SDimitry Andric     llvm::Instruction *IsActiveIP;
2960b57cec5SDimitry Andric   };
2970b57cec5SDimitry Andric 
add(RValue rvalue,QualType type)2980b57cec5SDimitry Andric   void add(RValue rvalue, QualType type) { push_back(CallArg(rvalue, type)); }
2990b57cec5SDimitry Andric 
addUncopiedAggregate(LValue LV,QualType type)3000b57cec5SDimitry Andric   void addUncopiedAggregate(LValue LV, QualType type) {
3010b57cec5SDimitry Andric     push_back(CallArg(LV, type));
3020b57cec5SDimitry Andric   }
3030b57cec5SDimitry Andric 
3040b57cec5SDimitry Andric   /// Add all the arguments from another CallArgList to this one. After doing
3050b57cec5SDimitry Andric   /// this, the old CallArgList retains its list of arguments, but must not
3060b57cec5SDimitry Andric   /// be used to emit a call.
addFrom(const CallArgList & other)3070b57cec5SDimitry Andric   void addFrom(const CallArgList &other) {
3080b57cec5SDimitry Andric     insert(end(), other.begin(), other.end());
309480093f4SDimitry Andric     Writebacks.insert(Writebacks.end(), other.Writebacks.begin(),
310480093f4SDimitry Andric                       other.Writebacks.end());
3110b57cec5SDimitry Andric     CleanupsToDeactivate.insert(CleanupsToDeactivate.end(),
3120b57cec5SDimitry Andric                                 other.CleanupsToDeactivate.begin(),
3130b57cec5SDimitry Andric                                 other.CleanupsToDeactivate.end());
3140b57cec5SDimitry Andric     assert(!(StackBase && other.StackBase) && "can't merge stackbases");
3150b57cec5SDimitry Andric     if (!StackBase)
3160b57cec5SDimitry Andric       StackBase = other.StackBase;
3170b57cec5SDimitry Andric   }
3180b57cec5SDimitry Andric 
addWriteback(LValue srcLV,Address temporary,llvm::Value * toUse)319480093f4SDimitry Andric   void addWriteback(LValue srcLV, Address temporary, llvm::Value *toUse) {
3200b57cec5SDimitry Andric     Writeback writeback = {srcLV, temporary, toUse};
3210b57cec5SDimitry Andric     Writebacks.push_back(writeback);
3220b57cec5SDimitry Andric   }
3230b57cec5SDimitry Andric 
hasWritebacks()3240b57cec5SDimitry Andric   bool hasWritebacks() const { return !Writebacks.empty(); }
3250b57cec5SDimitry Andric 
3260b57cec5SDimitry Andric   typedef llvm::iterator_range<SmallVectorImpl<Writeback>::const_iterator>
3270b57cec5SDimitry Andric       writeback_const_range;
3280b57cec5SDimitry Andric 
writebacks()3290b57cec5SDimitry Andric   writeback_const_range writebacks() const {
3300b57cec5SDimitry Andric     return writeback_const_range(Writebacks.begin(), Writebacks.end());
3310b57cec5SDimitry Andric   }
3320b57cec5SDimitry Andric 
addArgCleanupDeactivation(EHScopeStack::stable_iterator Cleanup,llvm::Instruction * IsActiveIP)3330b57cec5SDimitry Andric   void addArgCleanupDeactivation(EHScopeStack::stable_iterator Cleanup,
3340b57cec5SDimitry Andric                                  llvm::Instruction *IsActiveIP) {
3350b57cec5SDimitry Andric     CallArgCleanup ArgCleanup;
3360b57cec5SDimitry Andric     ArgCleanup.Cleanup = Cleanup;
3370b57cec5SDimitry Andric     ArgCleanup.IsActiveIP = IsActiveIP;
3380b57cec5SDimitry Andric     CleanupsToDeactivate.push_back(ArgCleanup);
3390b57cec5SDimitry Andric   }
3400b57cec5SDimitry Andric 
getCleanupsToDeactivate()3410b57cec5SDimitry Andric   ArrayRef<CallArgCleanup> getCleanupsToDeactivate() const {
3420b57cec5SDimitry Andric     return CleanupsToDeactivate;
3430b57cec5SDimitry Andric   }
3440b57cec5SDimitry Andric 
3450b57cec5SDimitry Andric   void allocateArgumentMemory(CodeGenFunction &CGF);
getStackBase()3460b57cec5SDimitry Andric   llvm::Instruction *getStackBase() const { return StackBase; }
3470b57cec5SDimitry Andric   void freeArgumentMemory(CodeGenFunction &CGF) const;
3480b57cec5SDimitry Andric 
3490b57cec5SDimitry Andric   /// Returns if we're using an inalloca struct to pass arguments in
3500b57cec5SDimitry Andric   /// memory.
isUsingInAlloca()3510b57cec5SDimitry Andric   bool isUsingInAlloca() const { return StackBase; }
3520b57cec5SDimitry Andric 
3530b57cec5SDimitry Andric private:
3540b57cec5SDimitry Andric   SmallVector<Writeback, 1> Writebacks;
3550b57cec5SDimitry Andric 
3560b57cec5SDimitry Andric   /// Deactivate these cleanups immediately before making the call.  This
3570b57cec5SDimitry Andric   /// is used to cleanup objects that are owned by the callee once the call
3580b57cec5SDimitry Andric   /// occurs.
3590b57cec5SDimitry Andric   SmallVector<CallArgCleanup, 1> CleanupsToDeactivate;
3600b57cec5SDimitry Andric 
3610b57cec5SDimitry Andric   /// The stacksave call.  It dominates all of the argument evaluation.
3625f757f3fSDimitry Andric   llvm::CallInst *StackBase = nullptr;
3630b57cec5SDimitry Andric };
3640b57cec5SDimitry Andric 
3650b57cec5SDimitry Andric /// FunctionArgList - Type for representing both the decl and type
3660b57cec5SDimitry Andric /// of parameters to a function. The decl must be either a
3670b57cec5SDimitry Andric /// ParmVarDecl or ImplicitParamDecl.
368480093f4SDimitry Andric class FunctionArgList : public SmallVector<const VarDecl *, 16> {};
3690b57cec5SDimitry Andric 
3700b57cec5SDimitry Andric /// ReturnValueSlot - Contains the address where the return value of a
3710b57cec5SDimitry Andric /// function can be stored, and whether the address is volatile or not.
3720b57cec5SDimitry Andric class ReturnValueSlot {
3735ffd83dbSDimitry Andric   Address Addr = Address::invalid();
3740b57cec5SDimitry Andric 
3750b57cec5SDimitry Andric   // Return value slot flags
376*0fca6ea1SDimitry Andric   LLVM_PREFERRED_TYPE(bool)
3775ffd83dbSDimitry Andric   unsigned IsVolatile : 1;
378*0fca6ea1SDimitry Andric   LLVM_PREFERRED_TYPE(bool)
3795ffd83dbSDimitry Andric   unsigned IsUnused : 1;
380*0fca6ea1SDimitry Andric   LLVM_PREFERRED_TYPE(bool)
3815ffd83dbSDimitry Andric   unsigned IsExternallyDestructed : 1;
3820b57cec5SDimitry Andric 
3830b57cec5SDimitry Andric public:
ReturnValueSlot()3845ffd83dbSDimitry Andric   ReturnValueSlot()
3855ffd83dbSDimitry Andric       : IsVolatile(false), IsUnused(false), IsExternallyDestructed(false) {}
3865ffd83dbSDimitry Andric   ReturnValueSlot(Address Addr, bool IsVolatile, bool IsUnused = false,
3875ffd83dbSDimitry Andric                   bool IsExternallyDestructed = false)
Addr(Addr)3885ffd83dbSDimitry Andric       : Addr(Addr), IsVolatile(IsVolatile), IsUnused(IsUnused),
3895ffd83dbSDimitry Andric         IsExternallyDestructed(IsExternallyDestructed) {}
3900b57cec5SDimitry Andric 
isNull()3915ffd83dbSDimitry Andric   bool isNull() const { return !Addr.isValid(); }
isVolatile()3925ffd83dbSDimitry Andric   bool isVolatile() const { return IsVolatile; }
getValue()3935ffd83dbSDimitry Andric   Address getValue() const { return Addr; }
isUnused()3945ffd83dbSDimitry Andric   bool isUnused() const { return IsUnused; }
isExternallyDestructed()3955ffd83dbSDimitry Andric   bool isExternallyDestructed() const { return IsExternallyDestructed; }
getAddress()396*0fca6ea1SDimitry Andric   Address getAddress() const { return Addr; }
3970b57cec5SDimitry Andric };
3980b57cec5SDimitry Andric 
3995f757f3fSDimitry Andric /// Adds attributes to \p F according to our \p CodeGenOpts and \p LangOpts, as
4005f757f3fSDimitry Andric /// though we had emitted it ourselves. We remove any attributes on F that
4015f757f3fSDimitry Andric /// conflict with the attributes we add here.
4025f757f3fSDimitry Andric ///
4035f757f3fSDimitry Andric /// This is useful for adding attrs to bitcode modules that you want to link
4045f757f3fSDimitry Andric /// with but don't control, such as CUDA's libdevice.  When linking with such
4055f757f3fSDimitry Andric /// a bitcode library, you might want to set e.g. its functions'
4065f757f3fSDimitry Andric /// "unsafe-fp-math" attribute to match the attr of the functions you're
4075f757f3fSDimitry Andric /// codegen'ing.  Otherwise, LLVM will interpret the bitcode module's lack of
4085f757f3fSDimitry Andric /// unsafe-fp-math attrs as tantamount to unsafe-fp-math=false, and then LLVM
4095f757f3fSDimitry Andric /// will propagate unsafe-fp-math=false up to every transitive caller of a
4105f757f3fSDimitry Andric /// function in the bitcode library!
4115f757f3fSDimitry Andric ///
4125f757f3fSDimitry Andric /// With the exception of fast-math attrs, this will only make the attributes
4135f757f3fSDimitry Andric /// on the function more conservative.  But it's unsafe to call this on a
4145f757f3fSDimitry Andric /// function which relies on particular fast-math attributes for correctness.
4155f757f3fSDimitry Andric /// It's up to you to ensure that this is safe.
41606c3fb27SDimitry Andric void mergeDefaultFunctionDefinitionAttributes(llvm::Function &F,
4175f757f3fSDimitry Andric                                               const CodeGenOptions &CodeGenOpts,
41806c3fb27SDimitry Andric                                               const LangOptions &LangOpts,
41906c3fb27SDimitry Andric                                               const TargetOptions &TargetOpts,
42006c3fb27SDimitry Andric                                               bool WillInternalize);
42106c3fb27SDimitry Andric 
4228a4dda33SDimitry Andric enum class FnInfoOpts {
4238a4dda33SDimitry Andric   None = 0,
4248a4dda33SDimitry Andric   IsInstanceMethod = 1 << 0,
4258a4dda33SDimitry Andric   IsChainCall = 1 << 1,
4268a4dda33SDimitry Andric   IsDelegateCall = 1 << 2,
4278a4dda33SDimitry Andric };
4288a4dda33SDimitry Andric 
4298a4dda33SDimitry Andric inline FnInfoOpts operator|(FnInfoOpts A, FnInfoOpts B) {
4305f757f3fSDimitry Andric   return static_cast<FnInfoOpts>(llvm::to_underlying(A) |
4315f757f3fSDimitry Andric                                  llvm::to_underlying(B));
4328a4dda33SDimitry Andric }
4338a4dda33SDimitry Andric 
4348a4dda33SDimitry Andric inline FnInfoOpts operator&(FnInfoOpts A, FnInfoOpts B) {
4355f757f3fSDimitry Andric   return static_cast<FnInfoOpts>(llvm::to_underlying(A) &
4365f757f3fSDimitry Andric                                  llvm::to_underlying(B));
4378a4dda33SDimitry Andric }
4388a4dda33SDimitry Andric 
4398a4dda33SDimitry Andric inline FnInfoOpts operator|=(FnInfoOpts A, FnInfoOpts B) {
4408a4dda33SDimitry Andric   A = A | B;
4418a4dda33SDimitry Andric   return A;
4428a4dda33SDimitry Andric }
4438a4dda33SDimitry Andric 
4448a4dda33SDimitry Andric inline FnInfoOpts operator&=(FnInfoOpts A, FnInfoOpts B) {
4458a4dda33SDimitry Andric   A = A & B;
4468a4dda33SDimitry Andric   return A;
4478a4dda33SDimitry Andric }
4488a4dda33SDimitry Andric 
4490b57cec5SDimitry Andric } // end namespace CodeGen
4500b57cec5SDimitry Andric } // end namespace clang
4510b57cec5SDimitry Andric 
4520b57cec5SDimitry Andric #endif
453