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