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