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