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