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