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