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(P: reinterpret_cast<void*>(-1)); |
216 | } |
217 | |
218 | static unsigned getHashValue(clang::GlobalDecl GD) { |
219 | return DenseMapInfo<void*>::getHashValue(PtrVal: 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 |
231 | |