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