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