1 //===- GlobalDecl.h - Global declaration holder -----------------*- C++ -*-===//
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
7 //===----------------------------------------------------------------------===//
9 // A GlobalDecl can hold either a regular variable/function or a C++ ctor/dtor
10 // together with its type.
12 //===----------------------------------------------------------------------===//
14 #ifndef LLVM_CLANG_AST_GLOBALDECL_H
15 #define LLVM_CLANG_AST_GLOBALDECL_H
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/Basic/ABI.h"
22 #include "clang/Basic/LLVM.h"
23 #include "llvm/ADT/DenseMapInfo.h"
24 #include "llvm/ADT/PointerIntPair.h"
25 #include "llvm/Support/Casting.h"
26 #include "llvm/Support/type_traits.h"
31 enum class DynamicInitKind : unsigned {
37 enum class KernelReferenceKind : unsigned {
42 /// GlobalDecl - represents a global declaration. This can either be a
43 /// CXXConstructorDecl and the constructor type (Base, Complete).
44 /// a CXXDestructorDecl and the destructor type (Base, Complete),
45 /// a FunctionDecl and the kernel reference type (Kernel, Stub), or
46 /// a VarDecl, a FunctionDecl or a BlockDecl.
48 /// When a new type of GlobalDecl is added, the following places should
49 /// be updated to convert a Decl* to a GlobalDecl:
50 /// PredefinedExpr::ComputeName() in lib/AST/Expr.cpp.
51 /// getParentOfLocalEntity() in lib/AST/ItaniumMangle.cpp
52 /// ASTNameGenerator::Implementation::writeFuncOrVarName in lib/AST/Mangle.cpp
55 llvm::PointerIntPair<const Decl *, 3> Value;
56 unsigned MultiVersionIndex = 0;
58 void Init(const Decl *D) {
59 assert(!isa<CXXConstructorDecl>(D) && "Use other ctor with ctor decls!");
60 assert(!isa<CXXDestructorDecl>(D) && "Use other ctor with dtor decls!");
61 assert(!D->hasAttr<CUDAGlobalAttr>() && "Use other ctor with GPU kernels!");
67 GlobalDecl() = default;
68 GlobalDecl(const VarDecl *D) { Init(D);}
69 GlobalDecl(const FunctionDecl *D, unsigned MVIndex = 0)
70 : MultiVersionIndex(MVIndex) {
71 if (!D->hasAttr<CUDAGlobalAttr>()) {
75 Value.setPointerAndInt(D, unsigned(getDefaultKernelReference(D)));
77 GlobalDecl(const FunctionDecl *D, KernelReferenceKind Kind)
78 : Value(D, unsigned(Kind)) {
79 assert(D->hasAttr<CUDAGlobalAttr>() && "Decl is not a GPU kernel!");
81 GlobalDecl(const NamedDecl *D) { Init(D); }
82 GlobalDecl(const BlockDecl *D) { Init(D); }
83 GlobalDecl(const CapturedDecl *D) { Init(D); }
84 GlobalDecl(const ObjCMethodDecl *D) { Init(D); }
85 GlobalDecl(const OMPDeclareReductionDecl *D) { Init(D); }
86 GlobalDecl(const OMPDeclareMapperDecl *D) { Init(D); }
87 GlobalDecl(const CXXConstructorDecl *D, CXXCtorType Type) : Value(D, Type) {}
88 GlobalDecl(const CXXDestructorDecl *D, CXXDtorType Type) : Value(D, Type) {}
89 GlobalDecl(const VarDecl *D, DynamicInitKind StubKind)
90 : Value(D, unsigned(StubKind)) {}
92 GlobalDecl getCanonicalDecl() const {
94 CanonGD.Value.setPointer(Value.getPointer()->getCanonicalDecl());
95 CanonGD.Value.setInt(Value.getInt());
96 CanonGD.MultiVersionIndex = MultiVersionIndex;
101 const Decl *getDecl() const { return Value.getPointer(); }
103 CXXCtorType getCtorType() const {
104 assert(isa<CXXConstructorDecl>(getDecl()) && "Decl is not a ctor!");
105 return static_cast<CXXCtorType>(Value.getInt());
108 CXXDtorType getDtorType() const {
109 assert(isa<CXXDestructorDecl>(getDecl()) && "Decl is not a dtor!");
110 return static_cast<CXXDtorType>(Value.getInt());
113 DynamicInitKind getDynamicInitKind() const {
114 assert(isa<VarDecl>(getDecl()) &&
115 cast<VarDecl>(getDecl())->hasGlobalStorage() &&
116 "Decl is not a global variable!");
117 return static_cast<DynamicInitKind>(Value.getInt());
120 unsigned getMultiVersionIndex() const {
121 assert(isa<FunctionDecl>(
123 !cast<FunctionDecl>(getDecl())->hasAttr<CUDAGlobalAttr>() &&
124 !isa<CXXConstructorDecl>(getDecl()) &&
125 !isa<CXXDestructorDecl>(getDecl()) &&
126 "Decl is not a plain FunctionDecl!");
127 return MultiVersionIndex;
130 KernelReferenceKind getKernelReferenceKind() const {
131 assert(isa<FunctionDecl>(getDecl()) &&
132 cast<FunctionDecl>(getDecl())->hasAttr<CUDAGlobalAttr>() &&
133 "Decl is not a GPU kernel!");
134 return static_cast<KernelReferenceKind>(Value.getInt());
137 friend bool operator==(const GlobalDecl &LHS, const GlobalDecl &RHS) {
138 return LHS.Value == RHS.Value &&
139 LHS.MultiVersionIndex == RHS.MultiVersionIndex;
142 void *getAsOpaquePtr() const { return Value.getOpaqueValue(); }
144 explicit operator bool() const { return getAsOpaquePtr(); }
146 static GlobalDecl getFromOpaquePtr(void *P) {
148 GD.Value.setFromOpaqueValue(P);
152 static KernelReferenceKind getDefaultKernelReference(const FunctionDecl *D) {
153 return D->getLangOpts().CUDAIsDevice ? KernelReferenceKind::Kernel
154 : KernelReferenceKind::Stub;
157 GlobalDecl getWithDecl(const Decl *D) {
158 GlobalDecl Result(*this);
159 Result.Value.setPointer(D);
163 GlobalDecl getWithCtorType(CXXCtorType Type) {
164 assert(isa<CXXConstructorDecl>(getDecl()));
165 GlobalDecl Result(*this);
166 Result.Value.setInt(Type);
170 GlobalDecl getWithDtorType(CXXDtorType Type) {
171 assert(isa<CXXDestructorDecl>(getDecl()));
172 GlobalDecl Result(*this);
173 Result.Value.setInt(Type);
177 GlobalDecl getWithMultiVersionIndex(unsigned Index) {
178 assert(isa<FunctionDecl>(getDecl()) &&
179 !cast<FunctionDecl>(getDecl())->hasAttr<CUDAGlobalAttr>() &&
180 !isa<CXXConstructorDecl>(getDecl()) &&
181 !isa<CXXDestructorDecl>(getDecl()) &&
182 "Decl is not a plain FunctionDecl!");
183 GlobalDecl Result(*this);
184 Result.MultiVersionIndex = Index;
188 GlobalDecl getWithKernelReferenceKind(KernelReferenceKind Kind) {
189 assert(isa<FunctionDecl>(getDecl()) &&
190 cast<FunctionDecl>(getDecl())->hasAttr<CUDAGlobalAttr>() &&
191 "Decl is not a GPU kernel!");
192 GlobalDecl Result(*this);
193 Result.Value.setInt(unsigned(Kind));
202 template<> struct DenseMapInfo<clang::GlobalDecl> {
203 static inline clang::GlobalDecl getEmptyKey() {
204 return clang::GlobalDecl();
207 static inline clang::GlobalDecl getTombstoneKey() {
208 return clang::GlobalDecl::
209 getFromOpaquePtr(reinterpret_cast<void*>(-1));
212 static unsigned getHashValue(clang::GlobalDecl GD) {
213 return DenseMapInfo<void*>::getHashValue(GD.getAsOpaquePtr());
216 static bool isEqual(clang::GlobalDecl LHS,
217 clang::GlobalDecl RHS) {
224 #endif // LLVM_CLANG_AST_GLOBALDECL_H