xref: /freebsd/contrib/llvm-project/clang/include/clang/AST/GlobalDecl.h (revision 700637cbb5e582861067a11aaca4d053546871d2)
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/DeclOpenACC.h"
21 #include "clang/AST/DeclOpenMP.h"
22 #include "clang/AST/DeclTemplate.h"
23 #include "clang/Basic/ABI.h"
24 #include "clang/Basic/LLVM.h"
25 #include "llvm/ADT/DenseMapInfo.h"
26 #include "llvm/ADT/PointerIntPair.h"
27 #include "llvm/Support/Casting.h"
28 #include "llvm/Support/type_traits.h"
29 #include <cassert>
30 
31 namespace clang {
32 
33 enum class DynamicInitKind : unsigned {
34   NoStub = 0,
35   Initializer,
36   AtExit,
37   GlobalArrayDestructor
38 };
39 
40 enum class KernelReferenceKind : unsigned {
41   Kernel = 0,
42   Stub = 1,
43 };
44 
45 /// GlobalDecl - represents a global declaration. This can either be a
46 /// CXXConstructorDecl and the constructor type (Base, Complete).
47 /// a CXXDestructorDecl and the destructor type (Base, Complete),
48 /// a FunctionDecl and the kernel reference type (Kernel, Stub), or
49 /// a VarDecl, a FunctionDecl or a BlockDecl.
50 ///
51 /// When a new type of GlobalDecl is added, the following places should
52 /// be updated to convert a Decl* to a GlobalDecl:
53 /// PredefinedExpr::ComputeName() in lib/AST/Expr.cpp.
54 /// getParentOfLocalEntity() in lib/AST/ItaniumMangle.cpp
55 /// ASTNameGenerator::Implementation::writeFuncOrVarName in lib/AST/Mangle.cpp
56 ///
57 class GlobalDecl {
58   llvm::PointerIntPair<const Decl *, 3> Value;
59   unsigned MultiVersionIndex = 0;
60 
Init(const Decl * D)61   void Init(const Decl *D) {
62     assert(!isa<CXXConstructorDecl>(D) && "Use other ctor with ctor decls!");
63     assert(!isa<CXXDestructorDecl>(D) && "Use other ctor with dtor decls!");
64     assert(!D->hasAttr<CUDAGlobalAttr>() && "Use other ctor with GPU kernels!");
65 
66     Value.setPointer(D);
67   }
68 
69 public:
70   GlobalDecl() = default;
GlobalDecl(const VarDecl * D)71   GlobalDecl(const VarDecl *D) { Init(D);}
72   GlobalDecl(const FunctionDecl *D, unsigned MVIndex = 0)
MultiVersionIndex(MVIndex)73       : MultiVersionIndex(MVIndex) {
74     if (D->isReferenceableKernel()) {
75       Value.setPointerAndInt(D, unsigned(getDefaultKernelReference(D)));
76       return;
77     }
78     Init(D);
79   }
GlobalDecl(const FunctionDecl * D,KernelReferenceKind Kind)80   GlobalDecl(const FunctionDecl *D, KernelReferenceKind Kind)
81       : Value(D, unsigned(Kind)) {
82     assert(D->isReferenceableKernel() && "Decl is not a GPU kernel!");
83   }
GlobalDecl(const NamedDecl * D)84   GlobalDecl(const NamedDecl *D) { Init(D); }
GlobalDecl(const BlockDecl * D)85   GlobalDecl(const BlockDecl *D) { Init(D); }
GlobalDecl(const CapturedDecl * D)86   GlobalDecl(const CapturedDecl *D) { Init(D); }
GlobalDecl(const ObjCMethodDecl * D)87   GlobalDecl(const ObjCMethodDecl *D) { Init(D); }
GlobalDecl(const OMPDeclareReductionDecl * D)88   GlobalDecl(const OMPDeclareReductionDecl *D) { Init(D); }
GlobalDecl(const OMPDeclareMapperDecl * D)89   GlobalDecl(const OMPDeclareMapperDecl *D) { Init(D); }
GlobalDecl(const OpenACCRoutineDecl * D)90   GlobalDecl(const OpenACCRoutineDecl *D) { Init(D); }
GlobalDecl(const OpenACCDeclareDecl * D)91   GlobalDecl(const OpenACCDeclareDecl *D) { Init(D); }
GlobalDecl(const CXXConstructorDecl * D,CXXCtorType Type)92   GlobalDecl(const CXXConstructorDecl *D, CXXCtorType Type) : Value(D, Type) {}
GlobalDecl(const CXXDestructorDecl * D,CXXDtorType Type)93   GlobalDecl(const CXXDestructorDecl *D, CXXDtorType Type) : Value(D, Type) {}
GlobalDecl(const VarDecl * D,DynamicInitKind StubKind)94   GlobalDecl(const VarDecl *D, DynamicInitKind StubKind)
95       : Value(D, unsigned(StubKind)) {}
96 
getCanonicalDecl()97   GlobalDecl getCanonicalDecl() const {
98     GlobalDecl CanonGD;
99     CanonGD.Value.setPointer(Value.getPointer()->getCanonicalDecl());
100     CanonGD.Value.setInt(Value.getInt());
101     CanonGD.MultiVersionIndex = MultiVersionIndex;
102 
103     return CanonGD;
104   }
105 
getDecl()106   const Decl *getDecl() const { return Value.getPointer(); }
107 
getCtorType()108   CXXCtorType getCtorType() const {
109     assert(isa<CXXConstructorDecl>(getDecl()) && "Decl is not a ctor!");
110     return static_cast<CXXCtorType>(Value.getInt());
111   }
112 
getDtorType()113   CXXDtorType getDtorType() const {
114     assert(isa<CXXDestructorDecl>(getDecl()) && "Decl is not a dtor!");
115     return static_cast<CXXDtorType>(Value.getInt());
116   }
117 
getDynamicInitKind()118   DynamicInitKind getDynamicInitKind() const {
119     assert(isa<VarDecl>(getDecl()) &&
120            cast<VarDecl>(getDecl())->hasGlobalStorage() &&
121            "Decl is not a global variable!");
122     return static_cast<DynamicInitKind>(Value.getInt());
123   }
124 
getMultiVersionIndex()125   unsigned getMultiVersionIndex() const {
126     assert(isa<FunctionDecl>(
127                getDecl()) &&
128                !cast<FunctionDecl>(getDecl())->hasAttr<CUDAGlobalAttr>() &&
129            !isa<CXXConstructorDecl>(getDecl()) &&
130            !isa<CXXDestructorDecl>(getDecl()) &&
131            "Decl is not a plain FunctionDecl!");
132     return MultiVersionIndex;
133   }
134 
getKernelReferenceKind()135   KernelReferenceKind getKernelReferenceKind() const {
136     assert(((isa<FunctionDecl>(getDecl()) &&
137              cast<FunctionDecl>(getDecl())->isReferenceableKernel()) ||
138             (isa<FunctionTemplateDecl>(getDecl()) &&
139              cast<FunctionTemplateDecl>(getDecl())
140                  ->getTemplatedDecl()
141                  ->hasAttr<CUDAGlobalAttr>())) &&
142            "Decl is not a GPU kernel!");
143 
144     return static_cast<KernelReferenceKind>(Value.getInt());
145   }
146 
147   friend bool operator==(const GlobalDecl &LHS, const GlobalDecl &RHS) {
148     return LHS.Value == RHS.Value &&
149            LHS.MultiVersionIndex == RHS.MultiVersionIndex;
150   }
151 
152   bool operator!=(const GlobalDecl &Other) const {
153     return !(*this == Other);
154   }
155 
getAsOpaquePtr()156   void *getAsOpaquePtr() const { return Value.getOpaqueValue(); }
157 
158   explicit operator bool() const { return getAsOpaquePtr(); }
159 
getFromOpaquePtr(void * P)160   static GlobalDecl getFromOpaquePtr(void *P) {
161     GlobalDecl GD;
162     GD.Value.setFromOpaqueValue(P);
163     return GD;
164   }
165 
getDefaultKernelReference(const FunctionDecl * D)166   static KernelReferenceKind getDefaultKernelReference(const FunctionDecl *D) {
167     return (D->hasAttr<DeviceKernelAttr>() || D->getLangOpts().CUDAIsDevice)
168                ? KernelReferenceKind::Kernel
169                : KernelReferenceKind::Stub;
170   }
171 
getWithDecl(const Decl * D)172   GlobalDecl getWithDecl(const Decl *D) {
173     GlobalDecl Result(*this);
174     Result.Value.setPointer(D);
175     return Result;
176   }
177 
getWithCtorType(CXXCtorType Type)178   GlobalDecl getWithCtorType(CXXCtorType Type) {
179     assert(isa<CXXConstructorDecl>(getDecl()));
180     GlobalDecl Result(*this);
181     Result.Value.setInt(Type);
182     return Result;
183   }
184 
getWithDtorType(CXXDtorType Type)185   GlobalDecl getWithDtorType(CXXDtorType Type) {
186     assert(isa<CXXDestructorDecl>(getDecl()));
187     GlobalDecl Result(*this);
188     Result.Value.setInt(Type);
189     return Result;
190   }
191 
getWithMultiVersionIndex(unsigned Index)192   GlobalDecl getWithMultiVersionIndex(unsigned Index) {
193     assert(isa<FunctionDecl>(getDecl()) &&
194            !cast<FunctionDecl>(getDecl())->hasAttr<CUDAGlobalAttr>() &&
195            !isa<CXXConstructorDecl>(getDecl()) &&
196            !isa<CXXDestructorDecl>(getDecl()) &&
197            "Decl is not a plain FunctionDecl!");
198     GlobalDecl Result(*this);
199     Result.MultiVersionIndex = Index;
200     return Result;
201   }
202 
getWithKernelReferenceKind(KernelReferenceKind Kind)203   GlobalDecl getWithKernelReferenceKind(KernelReferenceKind Kind) {
204     assert(isa<FunctionDecl>(getDecl()) &&
205            cast<FunctionDecl>(getDecl())->isReferenceableKernel() &&
206            "Decl is not a GPU kernel!");
207     GlobalDecl Result(*this);
208     Result.Value.setInt(unsigned(Kind));
209     return Result;
210   }
211 };
212 
213 } // namespace clang
214 
215 namespace llvm {
216 
217   template<> struct DenseMapInfo<clang::GlobalDecl> {
218     static inline clang::GlobalDecl getEmptyKey() {
219       return clang::GlobalDecl();
220     }
221 
222     static inline clang::GlobalDecl getTombstoneKey() {
223       return clang::GlobalDecl::
224         getFromOpaquePtr(reinterpret_cast<void*>(-1));
225     }
226 
227     static unsigned getHashValue(clang::GlobalDecl GD) {
228       return DenseMapInfo<void*>::getHashValue(GD.getAsOpaquePtr());
229     }
230 
231     static bool isEqual(clang::GlobalDecl LHS,
232                         clang::GlobalDecl RHS) {
233       return LHS == RHS;
234     }
235   };
236 
237 } // namespace llvm
238 
239 #endif // LLVM_CLANG_AST_GLOBALDECL_H
240