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