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