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 |