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