Details | Last modification | View Log | RSS feed
| Rev | Author | Line No. | Line | 
|---|---|---|---|
| 14 | pmbaty | 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 | |||
| 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; | ||
| 70 | GlobalDecl(const VarDecl *D) { Init(D);} | ||
| 71 | GlobalDecl(const FunctionDecl *D, unsigned MVIndex = 0) | ||
| 72 | : MultiVersionIndex(MVIndex) { | ||
| 73 | if (!D->hasAttr<CUDAGlobalAttr>()) { | ||
| 74 | Init(D); | ||
| 75 | return; | ||
| 76 |     } | ||
| 77 | Value.setPointerAndInt(D, unsigned(getDefaultKernelReference(D))); | ||
| 78 |   } | ||
| 79 | GlobalDecl(const FunctionDecl *D, KernelReferenceKind Kind) | ||
| 80 | : Value(D, unsigned(Kind)) { | ||
| 81 | assert(D->hasAttr<CUDAGlobalAttr>() && "Decl is not a GPU kernel!"); | ||
| 82 |   } | ||
| 83 | GlobalDecl(const NamedDecl *D) { Init(D); } | ||
| 84 | GlobalDecl(const BlockDecl *D) { Init(D); } | ||
| 85 | GlobalDecl(const CapturedDecl *D) { Init(D); } | ||
| 86 | GlobalDecl(const ObjCMethodDecl *D) { Init(D); } | ||
| 87 | GlobalDecl(const OMPDeclareReductionDecl *D) { Init(D); } | ||
| 88 | GlobalDecl(const OMPDeclareMapperDecl *D) { Init(D); } | ||
| 89 | GlobalDecl(const CXXConstructorDecl *D, CXXCtorType Type) : Value(D, Type) {} | ||
| 90 | GlobalDecl(const CXXDestructorDecl *D, CXXDtorType Type) : Value(D, Type) {} | ||
| 91 | GlobalDecl(const VarDecl *D, DynamicInitKind StubKind) | ||
| 92 | : Value(D, unsigned(StubKind)) {} | ||
| 93 | |||
| 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 | |||
| 103 | const Decl *getDecl() const { return Value.getPointer(); } | ||
| 104 | |||
| 105 | CXXCtorType getCtorType() const { | ||
| 106 | assert(isa<CXXConstructorDecl>(getDecl()) && "Decl is not a ctor!"); | ||
| 107 | return static_cast<CXXCtorType>(Value.getInt()); | ||
| 108 |   } | ||
| 109 | |||
| 110 | CXXDtorType getDtorType() const { | ||
| 111 | assert(isa<CXXDestructorDecl>(getDecl()) && "Decl is not a dtor!"); | ||
| 112 | return static_cast<CXXDtorType>(Value.getInt()); | ||
| 113 |   } | ||
| 114 | |||
| 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 | |||
| 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 | |||
| 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 | void *getAsOpaquePtr() const { return Value.getOpaqueValue(); } | ||
| 149 | |||
| 150 | explicit operator bool() const { return getAsOpaquePtr(); } | ||
| 151 | |||
| 152 | static GlobalDecl getFromOpaquePtr(void *P) { | ||
| 153 |     GlobalDecl GD; | ||
| 154 | GD.Value.setFromOpaqueValue(P); | ||
| 155 | return GD; | ||
| 156 |   } | ||
| 157 | |||
| 158 | static KernelReferenceKind getDefaultKernelReference(const FunctionDecl *D) { | ||
| 159 | return D->getLangOpts().CUDAIsDevice ? KernelReferenceKind::Kernel | ||
| 160 | : KernelReferenceKind::Stub; | ||
| 161 |   } | ||
| 162 | |||
| 163 | GlobalDecl getWithDecl(const Decl *D) { | ||
| 164 | GlobalDecl Result(*this); | ||
| 165 | Result.Value.setPointer(D); | ||
| 166 | return Result; | ||
| 167 |   } | ||
| 168 | |||
| 169 | GlobalDecl getWithCtorType(CXXCtorType Type) { | ||
| 170 | assert(isa<CXXConstructorDecl>(getDecl())); | ||
| 171 | GlobalDecl Result(*this); | ||
| 172 | Result.Value.setInt(Type); | ||
| 173 | return Result; | ||
| 174 |   } | ||
| 175 | |||
| 176 | GlobalDecl getWithDtorType(CXXDtorType Type) { | ||
| 177 | assert(isa<CXXDestructorDecl>(getDecl())); | ||
| 178 | GlobalDecl Result(*this); | ||
| 179 | Result.Value.setInt(Type); | ||
| 180 | return Result; | ||
| 181 |   } | ||
| 182 | |||
| 183 | GlobalDecl getWithMultiVersionIndex(unsigned Index) { | ||
| 184 | assert(isa<FunctionDecl>(getDecl()) && | ||
| 185 | !cast<FunctionDecl>(getDecl())->hasAttr<CUDAGlobalAttr>() && | ||
| 186 | !isa<CXXConstructorDecl>(getDecl()) && | ||
| 187 | !isa<CXXDestructorDecl>(getDecl()) && | ||
| 188 | "Decl is not a plain FunctionDecl!"); | ||
| 189 | GlobalDecl Result(*this); | ||
| 190 | Result.MultiVersionIndex = Index; | ||
| 191 | return Result; | ||
| 192 |   } | ||
| 193 | |||
| 194 | GlobalDecl getWithKernelReferenceKind(KernelReferenceKind Kind) { | ||
| 195 | assert(isa<FunctionDecl>(getDecl()) && | ||
| 196 | cast<FunctionDecl>(getDecl())->hasAttr<CUDAGlobalAttr>() && | ||
| 197 | "Decl is not a GPU kernel!"); | ||
| 198 | GlobalDecl Result(*this); | ||
| 199 | Result.Value.setInt(unsigned(Kind)); | ||
| 200 | return Result; | ||
| 201 |   } | ||
| 202 | }; | ||
| 203 | |||
| 204 | } // namespace clang | ||
| 205 | |||
| 206 | namespace llvm { | ||
| 207 | |||
| 208 | template<> struct DenseMapInfo<clang::GlobalDecl> { | ||
| 209 | static inline clang::GlobalDecl getEmptyKey() { | ||
| 210 | return clang::GlobalDecl(); | ||
| 211 |     } | ||
| 212 | |||
| 213 | static inline clang::GlobalDecl getTombstoneKey() { | ||
| 214 | return clang::GlobalDecl:: | ||
| 215 | getFromOpaquePtr(reinterpret_cast<void*>(-1)); | ||
| 216 |     } | ||
| 217 | |||
| 218 | static unsigned getHashValue(clang::GlobalDecl GD) { | ||
| 219 | return DenseMapInfo<void*>::getHashValue(GD.getAsOpaquePtr()); | ||
| 220 |     } | ||
| 221 | |||
| 222 | static bool isEqual(clang::GlobalDecl LHS, | ||
| 223 | clang::GlobalDecl RHS) { | ||
| 224 | return LHS == RHS; | ||
| 225 |     } | ||
| 226 | }; | ||
| 227 | |||
| 228 | } // namespace llvm | ||
| 229 | |||
| 230 | #endif // LLVM_CLANG_AST_GLOBALDECL_H |