1 //===- GlobalDecl.h - Global declaration holder -----------------*- C++ -*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // A GlobalDecl can hold either a regular variable/function or a C++ ctor/dtor 10 // together with its type. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #ifndef LLVM_CLANG_AST_GLOBALDECL_H 15 #define LLVM_CLANG_AST_GLOBALDECL_H 16 17 #include "clang/AST/Attr.h" 18 #include "clang/AST/DeclCXX.h" 19 #include "clang/AST/DeclObjC.h" 20 #include "clang/AST/DeclOpenACC.h" 21 #include "clang/AST/DeclOpenMP.h" 22 #include "clang/AST/DeclTemplate.h" 23 #include "clang/Basic/ABI.h" 24 #include "clang/Basic/LLVM.h" 25 #include "llvm/ADT/DenseMapInfo.h" 26 #include "llvm/ADT/PointerIntPair.h" 27 #include "llvm/Support/Casting.h" 28 #include "llvm/Support/type_traits.h" 29 #include <cassert> 30 31 namespace clang { 32 33 enum class DynamicInitKind : unsigned { 34 NoStub = 0, 35 Initializer, 36 AtExit, 37 GlobalArrayDestructor 38 }; 39 40 enum class KernelReferenceKind : unsigned { 41 Kernel = 0, 42 Stub = 1, 43 }; 44 45 /// GlobalDecl - represents a global declaration. This can either be a 46 /// CXXConstructorDecl and the constructor type (Base, Complete). 47 /// a CXXDestructorDecl and the destructor type (Base, Complete), 48 /// a FunctionDecl and the kernel reference type (Kernel, Stub), or 49 /// a VarDecl, a FunctionDecl or a BlockDecl. 50 /// 51 /// When a new type of GlobalDecl is added, the following places should 52 /// be updated to convert a Decl* to a GlobalDecl: 53 /// PredefinedExpr::ComputeName() in lib/AST/Expr.cpp. 54 /// getParentOfLocalEntity() in lib/AST/ItaniumMangle.cpp 55 /// ASTNameGenerator::Implementation::writeFuncOrVarName in lib/AST/Mangle.cpp 56 /// 57 class GlobalDecl { 58 llvm::PointerIntPair<const Decl *, 3> Value; 59 unsigned MultiVersionIndex = 0; 60 Init(const Decl * D)61 void Init(const Decl *D) { 62 assert(!isa<CXXConstructorDecl>(D) && "Use other ctor with ctor decls!"); 63 assert(!isa<CXXDestructorDecl>(D) && "Use other ctor with dtor decls!"); 64 assert(!D->hasAttr<CUDAGlobalAttr>() && "Use other ctor with GPU kernels!"); 65 66 Value.setPointer(D); 67 } 68 69 public: 70 GlobalDecl() = default; GlobalDecl(const VarDecl * D)71 GlobalDecl(const VarDecl *D) { Init(D);} 72 GlobalDecl(const FunctionDecl *D, unsigned MVIndex = 0) MultiVersionIndex(MVIndex)73 : MultiVersionIndex(MVIndex) { 74 if (D->isReferenceableKernel()) { 75 Value.setPointerAndInt(D, unsigned(getDefaultKernelReference(D))); 76 return; 77 } 78 Init(D); 79 } GlobalDecl(const FunctionDecl * D,KernelReferenceKind Kind)80 GlobalDecl(const FunctionDecl *D, KernelReferenceKind Kind) 81 : Value(D, unsigned(Kind)) { 82 assert(D->isReferenceableKernel() && "Decl is not a GPU kernel!"); 83 } GlobalDecl(const NamedDecl * D)84 GlobalDecl(const NamedDecl *D) { Init(D); } GlobalDecl(const BlockDecl * D)85 GlobalDecl(const BlockDecl *D) { Init(D); } GlobalDecl(const CapturedDecl * D)86 GlobalDecl(const CapturedDecl *D) { Init(D); } GlobalDecl(const ObjCMethodDecl * D)87 GlobalDecl(const ObjCMethodDecl *D) { Init(D); } GlobalDecl(const OMPDeclareReductionDecl * D)88 GlobalDecl(const OMPDeclareReductionDecl *D) { Init(D); } GlobalDecl(const OMPDeclareMapperDecl * D)89 GlobalDecl(const OMPDeclareMapperDecl *D) { Init(D); } GlobalDecl(const OpenACCRoutineDecl * D)90 GlobalDecl(const OpenACCRoutineDecl *D) { Init(D); } GlobalDecl(const OpenACCDeclareDecl * D)91 GlobalDecl(const OpenACCDeclareDecl *D) { Init(D); } GlobalDecl(const CXXConstructorDecl * D,CXXCtorType Type)92 GlobalDecl(const CXXConstructorDecl *D, CXXCtorType Type) : Value(D, Type) {} GlobalDecl(const CXXDestructorDecl * D,CXXDtorType Type)93 GlobalDecl(const CXXDestructorDecl *D, CXXDtorType Type) : Value(D, Type) {} GlobalDecl(const VarDecl * D,DynamicInitKind StubKind)94 GlobalDecl(const VarDecl *D, DynamicInitKind StubKind) 95 : Value(D, unsigned(StubKind)) {} 96 getCanonicalDecl()97 GlobalDecl getCanonicalDecl() const { 98 GlobalDecl CanonGD; 99 CanonGD.Value.setPointer(Value.getPointer()->getCanonicalDecl()); 100 CanonGD.Value.setInt(Value.getInt()); 101 CanonGD.MultiVersionIndex = MultiVersionIndex; 102 103 return CanonGD; 104 } 105 getDecl()106 const Decl *getDecl() const { return Value.getPointer(); } 107 getCtorType()108 CXXCtorType getCtorType() const { 109 assert(isa<CXXConstructorDecl>(getDecl()) && "Decl is not a ctor!"); 110 return static_cast<CXXCtorType>(Value.getInt()); 111 } 112 getDtorType()113 CXXDtorType getDtorType() const { 114 assert(isa<CXXDestructorDecl>(getDecl()) && "Decl is not a dtor!"); 115 return static_cast<CXXDtorType>(Value.getInt()); 116 } 117 getDynamicInitKind()118 DynamicInitKind getDynamicInitKind() const { 119 assert(isa<VarDecl>(getDecl()) && 120 cast<VarDecl>(getDecl())->hasGlobalStorage() && 121 "Decl is not a global variable!"); 122 return static_cast<DynamicInitKind>(Value.getInt()); 123 } 124 getMultiVersionIndex()125 unsigned getMultiVersionIndex() const { 126 assert(isa<FunctionDecl>( 127 getDecl()) && 128 !cast<FunctionDecl>(getDecl())->hasAttr<CUDAGlobalAttr>() && 129 !isa<CXXConstructorDecl>(getDecl()) && 130 !isa<CXXDestructorDecl>(getDecl()) && 131 "Decl is not a plain FunctionDecl!"); 132 return MultiVersionIndex; 133 } 134 getKernelReferenceKind()135 KernelReferenceKind getKernelReferenceKind() const { 136 assert(((isa<FunctionDecl>(getDecl()) && 137 cast<FunctionDecl>(getDecl())->isReferenceableKernel()) || 138 (isa<FunctionTemplateDecl>(getDecl()) && 139 cast<FunctionTemplateDecl>(getDecl()) 140 ->getTemplatedDecl() 141 ->hasAttr<CUDAGlobalAttr>())) && 142 "Decl is not a GPU kernel!"); 143 144 return static_cast<KernelReferenceKind>(Value.getInt()); 145 } 146 147 friend bool operator==(const GlobalDecl &LHS, const GlobalDecl &RHS) { 148 return LHS.Value == RHS.Value && 149 LHS.MultiVersionIndex == RHS.MultiVersionIndex; 150 } 151 152 bool operator!=(const GlobalDecl &Other) const { 153 return !(*this == Other); 154 } 155 getAsOpaquePtr()156 void *getAsOpaquePtr() const { return Value.getOpaqueValue(); } 157 158 explicit operator bool() const { return getAsOpaquePtr(); } 159 getFromOpaquePtr(void * P)160 static GlobalDecl getFromOpaquePtr(void *P) { 161 GlobalDecl GD; 162 GD.Value.setFromOpaqueValue(P); 163 return GD; 164 } 165 getDefaultKernelReference(const FunctionDecl * D)166 static KernelReferenceKind getDefaultKernelReference(const FunctionDecl *D) { 167 return (D->hasAttr<DeviceKernelAttr>() || D->getLangOpts().CUDAIsDevice) 168 ? KernelReferenceKind::Kernel 169 : KernelReferenceKind::Stub; 170 } 171 getWithDecl(const Decl * D)172 GlobalDecl getWithDecl(const Decl *D) { 173 GlobalDecl Result(*this); 174 Result.Value.setPointer(D); 175 return Result; 176 } 177 getWithCtorType(CXXCtorType Type)178 GlobalDecl getWithCtorType(CXXCtorType Type) { 179 assert(isa<CXXConstructorDecl>(getDecl())); 180 GlobalDecl Result(*this); 181 Result.Value.setInt(Type); 182 return Result; 183 } 184 getWithDtorType(CXXDtorType Type)185 GlobalDecl getWithDtorType(CXXDtorType Type) { 186 assert(isa<CXXDestructorDecl>(getDecl())); 187 GlobalDecl Result(*this); 188 Result.Value.setInt(Type); 189 return Result; 190 } 191 getWithMultiVersionIndex(unsigned Index)192 GlobalDecl getWithMultiVersionIndex(unsigned Index) { 193 assert(isa<FunctionDecl>(getDecl()) && 194 !cast<FunctionDecl>(getDecl())->hasAttr<CUDAGlobalAttr>() && 195 !isa<CXXConstructorDecl>(getDecl()) && 196 !isa<CXXDestructorDecl>(getDecl()) && 197 "Decl is not a plain FunctionDecl!"); 198 GlobalDecl Result(*this); 199 Result.MultiVersionIndex = Index; 200 return Result; 201 } 202 getWithKernelReferenceKind(KernelReferenceKind Kind)203 GlobalDecl getWithKernelReferenceKind(KernelReferenceKind Kind) { 204 assert(isa<FunctionDecl>(getDecl()) && 205 cast<FunctionDecl>(getDecl())->isReferenceableKernel() && 206 "Decl is not a GPU kernel!"); 207 GlobalDecl Result(*this); 208 Result.Value.setInt(unsigned(Kind)); 209 return Result; 210 } 211 }; 212 213 } // namespace clang 214 215 namespace llvm { 216 217 template<> struct DenseMapInfo<clang::GlobalDecl> { 218 static inline clang::GlobalDecl getEmptyKey() { 219 return clang::GlobalDecl(); 220 } 221 222 static inline clang::GlobalDecl getTombstoneKey() { 223 return clang::GlobalDecl:: 224 getFromOpaquePtr(reinterpret_cast<void*>(-1)); 225 } 226 227 static unsigned getHashValue(clang::GlobalDecl GD) { 228 return DenseMapInfo<void*>::getHashValue(GD.getAsOpaquePtr()); 229 } 230 231 static bool isEqual(clang::GlobalDecl LHS, 232 clang::GlobalDecl RHS) { 233 return LHS == RHS; 234 } 235 }; 236 237 } // namespace llvm 238 239 #endif // LLVM_CLANG_AST_GLOBALDECL_H 240