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 |