Home | History | Annotate | Line # | Download | only in AST
      1 //===--- Mangle.h - Mangle C++ Names ----------------------------*- 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 // Defines the C++ name mangling interface.
     10 //
     11 //===----------------------------------------------------------------------===//
     12 
     13 #ifndef LLVM_CLANG_AST_MANGLE_H
     14 #define LLVM_CLANG_AST_MANGLE_H
     15 
     16 #include "clang/AST/Decl.h"
     17 #include "clang/AST/GlobalDecl.h"
     18 #include "clang/AST/Type.h"
     19 #include "clang/Basic/ABI.h"
     20 #include "llvm/ADT/DenseMap.h"
     21 #include "llvm/Support/Casting.h"
     22 
     23 namespace llvm {
     24   class raw_ostream;
     25 }
     26 
     27 namespace clang {
     28   class ASTContext;
     29   class BlockDecl;
     30   class CXXConstructorDecl;
     31   class CXXDestructorDecl;
     32   class CXXMethodDecl;
     33   class FunctionDecl;
     34   struct MethodVFTableLocation;
     35   class NamedDecl;
     36   class ObjCMethodDecl;
     37   class StringLiteral;
     38   struct ThisAdjustment;
     39   struct ThunkInfo;
     40   class VarDecl;
     41 
     42 /// MangleContext - Context for tracking state which persists across multiple
     43 /// calls to the C++ name mangler.
     44 class MangleContext {
     45 public:
     46   enum ManglerKind {
     47     MK_Itanium,
     48     MK_Microsoft
     49   };
     50 
     51 private:
     52   virtual void anchor();
     53 
     54   ASTContext &Context;
     55   DiagnosticsEngine &Diags;
     56   const ManglerKind Kind;
     57 
     58   llvm::DenseMap<const BlockDecl*, unsigned> GlobalBlockIds;
     59   llvm::DenseMap<const BlockDecl*, unsigned> LocalBlockIds;
     60   llvm::DenseMap<const NamedDecl*, uint64_t> AnonStructIds;
     61 
     62 public:
     63   ManglerKind getKind() const { return Kind; }
     64 
     65   explicit MangleContext(ASTContext &Context,
     66                          DiagnosticsEngine &Diags,
     67                          ManglerKind Kind)
     68       : Context(Context), Diags(Diags), Kind(Kind) {}
     69 
     70   virtual ~MangleContext() { }
     71 
     72   ASTContext &getASTContext() const { return Context; }
     73 
     74   DiagnosticsEngine &getDiags() const { return Diags; }
     75 
     76   virtual void startNewFunction() { LocalBlockIds.clear(); }
     77 
     78   unsigned getBlockId(const BlockDecl *BD, bool Local) {
     79     llvm::DenseMap<const BlockDecl *, unsigned> &BlockIds
     80       = Local? LocalBlockIds : GlobalBlockIds;
     81     std::pair<llvm::DenseMap<const BlockDecl *, unsigned>::iterator, bool>
     82       Result = BlockIds.insert(std::make_pair(BD, BlockIds.size()));
     83     return Result.first->second;
     84   }
     85 
     86   uint64_t getAnonymousStructId(const NamedDecl *D) {
     87     std::pair<llvm::DenseMap<const NamedDecl *, uint64_t>::iterator, bool>
     88         Result = AnonStructIds.insert(std::make_pair(D, AnonStructIds.size()));
     89     return Result.first->second;
     90   }
     91 
     92   uint64_t getAnonymousStructIdForDebugInfo(const NamedDecl *D) {
     93     llvm::DenseMap<const NamedDecl *, uint64_t>::iterator Result =
     94         AnonStructIds.find(D);
     95     // The decl should already be inserted, but return 0 in case it is not.
     96     if (Result == AnonStructIds.end())
     97       return 0;
     98     return Result->second;
     99   }
    100 
    101   virtual std::string getLambdaString(const CXXRecordDecl *Lambda) = 0;
    102 
    103   /// @name Mangler Entry Points
    104   /// @{
    105 
    106   bool shouldMangleDeclName(const NamedDecl *D);
    107   virtual bool shouldMangleCXXName(const NamedDecl *D) = 0;
    108   virtual bool shouldMangleStringLiteral(const StringLiteral *SL) = 0;
    109 
    110   virtual bool isDeviceMangleContext() const { return false; }
    111   virtual void setDeviceMangleContext(bool) {}
    112 
    113   virtual bool isUniqueInternalLinkageDecl(const NamedDecl *ND) {
    114     return false;
    115   }
    116 
    117   virtual void needsUniqueInternalLinkageNames() { }
    118 
    119   // FIXME: consider replacing raw_ostream & with something like SmallString &.
    120   void mangleName(GlobalDecl GD, raw_ostream &);
    121   virtual void mangleCXXName(GlobalDecl GD, raw_ostream &) = 0;
    122   virtual void mangleThunk(const CXXMethodDecl *MD,
    123                           const ThunkInfo &Thunk,
    124                           raw_ostream &) = 0;
    125   virtual void mangleCXXDtorThunk(const CXXDestructorDecl *DD, CXXDtorType Type,
    126                                   const ThisAdjustment &ThisAdjustment,
    127                                   raw_ostream &) = 0;
    128   virtual void mangleReferenceTemporary(const VarDecl *D,
    129                                         unsigned ManglingNumber,
    130                                         raw_ostream &) = 0;
    131   virtual void mangleCXXRTTI(QualType T, raw_ostream &) = 0;
    132   virtual void mangleCXXRTTIName(QualType T, raw_ostream &) = 0;
    133   virtual void mangleStringLiteral(const StringLiteral *SL, raw_ostream &) = 0;
    134   virtual void mangleMSGuidDecl(const MSGuidDecl *GD, raw_ostream&);
    135 
    136   void mangleGlobalBlock(const BlockDecl *BD,
    137                          const NamedDecl *ID,
    138                          raw_ostream &Out);
    139   void mangleCtorBlock(const CXXConstructorDecl *CD, CXXCtorType CT,
    140                        const BlockDecl *BD, raw_ostream &Out);
    141   void mangleDtorBlock(const CXXDestructorDecl *CD, CXXDtorType DT,
    142                        const BlockDecl *BD, raw_ostream &Out);
    143   void mangleBlock(const DeclContext *DC, const BlockDecl *BD,
    144                    raw_ostream &Out);
    145 
    146   void mangleObjCMethodName(const ObjCMethodDecl *MD, raw_ostream &OS,
    147                             bool includePrefixByte = true,
    148                             bool includeCategoryNamespace = true);
    149   void mangleObjCMethodNameAsSourceName(const ObjCMethodDecl *MD,
    150                                         raw_ostream &);
    151 
    152   virtual void mangleStaticGuardVariable(const VarDecl *D, raw_ostream &) = 0;
    153 
    154   virtual void mangleDynamicInitializer(const VarDecl *D, raw_ostream &) = 0;
    155 
    156   virtual void mangleDynamicAtExitDestructor(const VarDecl *D,
    157                                              raw_ostream &) = 0;
    158 
    159   virtual void mangleSEHFilterExpression(const NamedDecl *EnclosingDecl,
    160                                          raw_ostream &Out) = 0;
    161 
    162   virtual void mangleSEHFinallyBlock(const NamedDecl *EnclosingDecl,
    163                                      raw_ostream &Out) = 0;
    164 
    165   /// Generates a unique string for an externally visible type for use with TBAA
    166   /// or type uniquing.
    167   /// TODO: Extend this to internal types by generating names that are unique
    168   /// across translation units so it can be used with LTO.
    169   virtual void mangleTypeName(QualType T, raw_ostream &) = 0;
    170 
    171   /// @}
    172 };
    173 
    174 class ItaniumMangleContext : public MangleContext {
    175 public:
    176   explicit ItaniumMangleContext(ASTContext &C, DiagnosticsEngine &D)
    177       : MangleContext(C, D, MK_Itanium) {}
    178 
    179   virtual void mangleCXXVTable(const CXXRecordDecl *RD, raw_ostream &) = 0;
    180   virtual void mangleCXXVTT(const CXXRecordDecl *RD, raw_ostream &) = 0;
    181   virtual void mangleCXXCtorVTable(const CXXRecordDecl *RD, int64_t Offset,
    182                                    const CXXRecordDecl *Type,
    183                                    raw_ostream &) = 0;
    184   virtual void mangleItaniumThreadLocalInit(const VarDecl *D,
    185                                             raw_ostream &) = 0;
    186   virtual void mangleItaniumThreadLocalWrapper(const VarDecl *D,
    187                                                raw_ostream &) = 0;
    188 
    189   virtual void mangleCXXCtorComdat(const CXXConstructorDecl *D,
    190                                    raw_ostream &) = 0;
    191   virtual void mangleCXXDtorComdat(const CXXDestructorDecl *D,
    192                                    raw_ostream &) = 0;
    193 
    194   virtual void mangleLambdaSig(const CXXRecordDecl *Lambda, raw_ostream &) = 0;
    195 
    196   virtual void mangleDynamicStermFinalizer(const VarDecl *D, raw_ostream &) = 0;
    197 
    198   static bool classof(const MangleContext *C) {
    199     return C->getKind() == MK_Itanium;
    200   }
    201 
    202   static ItaniumMangleContext *create(ASTContext &Context,
    203                                       DiagnosticsEngine &Diags);
    204 };
    205 
    206 class MicrosoftMangleContext : public MangleContext {
    207 public:
    208   explicit MicrosoftMangleContext(ASTContext &C, DiagnosticsEngine &D)
    209       : MangleContext(C, D, MK_Microsoft) {}
    210 
    211   /// Mangle vftable symbols.  Only a subset of the bases along the path
    212   /// to the vftable are included in the name.  It's up to the caller to pick
    213   /// them correctly.
    214   virtual void mangleCXXVFTable(const CXXRecordDecl *Derived,
    215                                 ArrayRef<const CXXRecordDecl *> BasePath,
    216                                 raw_ostream &Out) = 0;
    217 
    218   /// Mangle vbtable symbols.  Only a subset of the bases along the path
    219   /// to the vbtable are included in the name.  It's up to the caller to pick
    220   /// them correctly.
    221   virtual void mangleCXXVBTable(const CXXRecordDecl *Derived,
    222                                 ArrayRef<const CXXRecordDecl *> BasePath,
    223                                 raw_ostream &Out) = 0;
    224 
    225   virtual void mangleThreadSafeStaticGuardVariable(const VarDecl *VD,
    226                                                    unsigned GuardNum,
    227                                                    raw_ostream &Out) = 0;
    228 
    229   virtual void mangleVirtualMemPtrThunk(const CXXMethodDecl *MD,
    230                                         const MethodVFTableLocation &ML,
    231                                         raw_ostream &Out) = 0;
    232 
    233   virtual void mangleCXXVirtualDisplacementMap(const CXXRecordDecl *SrcRD,
    234                                                const CXXRecordDecl *DstRD,
    235                                                raw_ostream &Out) = 0;
    236 
    237   virtual void mangleCXXThrowInfo(QualType T, bool IsConst, bool IsVolatile,
    238                                   bool IsUnaligned, uint32_t NumEntries,
    239                                   raw_ostream &Out) = 0;
    240 
    241   virtual void mangleCXXCatchableTypeArray(QualType T, uint32_t NumEntries,
    242                                            raw_ostream &Out) = 0;
    243 
    244   virtual void mangleCXXCatchableType(QualType T, const CXXConstructorDecl *CD,
    245                                       CXXCtorType CT, uint32_t Size,
    246                                       uint32_t NVOffset, int32_t VBPtrOffset,
    247                                       uint32_t VBIndex, raw_ostream &Out) = 0;
    248 
    249   virtual void mangleCXXRTTIBaseClassDescriptor(
    250       const CXXRecordDecl *Derived, uint32_t NVOffset, int32_t VBPtrOffset,
    251       uint32_t VBTableOffset, uint32_t Flags, raw_ostream &Out) = 0;
    252 
    253   virtual void mangleCXXRTTIBaseClassArray(const CXXRecordDecl *Derived,
    254                                            raw_ostream &Out) = 0;
    255   virtual void
    256   mangleCXXRTTIClassHierarchyDescriptor(const CXXRecordDecl *Derived,
    257                                         raw_ostream &Out) = 0;
    258 
    259   virtual void
    260   mangleCXXRTTICompleteObjectLocator(const CXXRecordDecl *Derived,
    261                                      ArrayRef<const CXXRecordDecl *> BasePath,
    262                                      raw_ostream &Out) = 0;
    263 
    264   static bool classof(const MangleContext *C) {
    265     return C->getKind() == MK_Microsoft;
    266   }
    267 
    268   static MicrosoftMangleContext *create(ASTContext &Context,
    269                                         DiagnosticsEngine &Diags);
    270 };
    271 
    272 class ASTNameGenerator {
    273 public:
    274   explicit ASTNameGenerator(ASTContext &Ctx);
    275   ~ASTNameGenerator();
    276 
    277   /// Writes name for \p D to \p OS.
    278   /// \returns true on failure, false on success.
    279   bool writeName(const Decl *D, raw_ostream &OS);
    280 
    281   /// \returns name for \p D
    282   std::string getName(const Decl *D);
    283 
    284   /// \returns all applicable mangled names.
    285   /// For example C++ constructors/destructors can have multiple.
    286   std::vector<std::string> getAllManglings(const Decl *D);
    287 
    288 private:
    289   class Implementation;
    290   std::unique_ptr<Implementation> Impl;
    291 };
    292 }
    293 
    294 #endif
    295