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:
getKind()63   ManglerKind getKind() const { return Kind; }
64 
MangleContext(ASTContext & Context,DiagnosticsEngine & Diags,ManglerKind Kind)65   explicit MangleContext(ASTContext &Context,
66                          DiagnosticsEngine &Diags,
67                          ManglerKind Kind)
68       : Context(Context), Diags(Diags), Kind(Kind) {}
69 
~MangleContext()70   virtual ~MangleContext() { }
71 
getASTContext()72   ASTContext &getASTContext() const { return Context; }
73 
getDiags()74   DiagnosticsEngine &getDiags() const { return Diags; }
75 
startNewFunction()76   virtual void startNewFunction() { LocalBlockIds.clear(); }
77 
getBlockId(const BlockDecl * BD,bool Local)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 
getAnonymousStructId(const NamedDecl * D)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 
getAnonymousStructIdForDebugInfo(const NamedDecl * D)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 
isUniqueInternalLinkageDecl(const NamedDecl * ND)110   virtual bool isUniqueInternalLinkageDecl(const NamedDecl *ND) {
111     return false;
112   }
113 
needsUniqueInternalLinkageNames()114   virtual void needsUniqueInternalLinkageNames() { }
115 
116   // FIXME: consider replacing raw_ostream & with something like SmallString &.
117   void mangleName(GlobalDecl GD, raw_ostream &);
118   virtual void mangleCXXName(GlobalDecl GD, raw_ostream &) = 0;
119   virtual void mangleThunk(const CXXMethodDecl *MD,
120                           const ThunkInfo &Thunk,
121                           raw_ostream &) = 0;
122   virtual void mangleCXXDtorThunk(const CXXDestructorDecl *DD, CXXDtorType Type,
123                                   const ThisAdjustment &ThisAdjustment,
124                                   raw_ostream &) = 0;
125   virtual void mangleReferenceTemporary(const VarDecl *D,
126                                         unsigned ManglingNumber,
127                                         raw_ostream &) = 0;
128   virtual void mangleCXXRTTI(QualType T, raw_ostream &) = 0;
129   virtual void mangleCXXRTTIName(QualType T, raw_ostream &) = 0;
130   virtual void mangleStringLiteral(const StringLiteral *SL, raw_ostream &) = 0;
131   virtual void mangleMSGuidDecl(const MSGuidDecl *GD, raw_ostream&);
132 
133   void mangleGlobalBlock(const BlockDecl *BD,
134                          const NamedDecl *ID,
135                          raw_ostream &Out);
136   void mangleCtorBlock(const CXXConstructorDecl *CD, CXXCtorType CT,
137                        const BlockDecl *BD, raw_ostream &Out);
138   void mangleDtorBlock(const CXXDestructorDecl *CD, CXXDtorType DT,
139                        const BlockDecl *BD, raw_ostream &Out);
140   void mangleBlock(const DeclContext *DC, const BlockDecl *BD,
141                    raw_ostream &Out);
142 
143   void mangleObjCMethodName(const ObjCMethodDecl *MD, raw_ostream &OS,
144                             bool includePrefixByte = true,
145                             bool includeCategoryNamespace = true);
146   void mangleObjCMethodNameAsSourceName(const ObjCMethodDecl *MD,
147                                         raw_ostream &);
148 
149   virtual void mangleStaticGuardVariable(const VarDecl *D, raw_ostream &) = 0;
150 
151   virtual void mangleDynamicInitializer(const VarDecl *D, raw_ostream &) = 0;
152 
153   virtual void mangleDynamicAtExitDestructor(const VarDecl *D,
154                                              raw_ostream &) = 0;
155 
156   virtual void mangleSEHFilterExpression(const NamedDecl *EnclosingDecl,
157                                          raw_ostream &Out) = 0;
158 
159   virtual void mangleSEHFinallyBlock(const NamedDecl *EnclosingDecl,
160                                      raw_ostream &Out) = 0;
161 
162   /// Generates a unique string for an externally visible type for use with TBAA
163   /// or type uniquing.
164   /// TODO: Extend this to internal types by generating names that are unique
165   /// across translation units so it can be used with LTO.
166   virtual void mangleTypeName(QualType T, raw_ostream &) = 0;
167 
168   /// @}
169 };
170 
171 class ItaniumMangleContext : public MangleContext {
172 public:
173   using DiscriminatorOverrideTy =
174       llvm::Optional<unsigned> (*)(ASTContext &, const NamedDecl *);
ItaniumMangleContext(ASTContext & C,DiagnosticsEngine & D)175   explicit ItaniumMangleContext(ASTContext &C, DiagnosticsEngine &D)
176       : MangleContext(C, D, MK_Itanium) {}
177 
178   virtual void mangleCXXVTable(const CXXRecordDecl *RD, raw_ostream &) = 0;
179   virtual void mangleCXXVTT(const CXXRecordDecl *RD, raw_ostream &) = 0;
180   virtual void mangleCXXCtorVTable(const CXXRecordDecl *RD, int64_t Offset,
181                                    const CXXRecordDecl *Type,
182                                    raw_ostream &) = 0;
183   virtual void mangleItaniumThreadLocalInit(const VarDecl *D,
184                                             raw_ostream &) = 0;
185   virtual void mangleItaniumThreadLocalWrapper(const VarDecl *D,
186                                                raw_ostream &) = 0;
187 
188   virtual void mangleCXXCtorComdat(const CXXConstructorDecl *D,
189                                    raw_ostream &) = 0;
190   virtual void mangleCXXDtorComdat(const CXXDestructorDecl *D,
191                                    raw_ostream &) = 0;
192 
193   virtual void mangleLambdaSig(const CXXRecordDecl *Lambda, raw_ostream &) = 0;
194 
195   virtual void mangleDynamicStermFinalizer(const VarDecl *D, raw_ostream &) = 0;
196 
197   // This has to live here, otherwise the CXXNameMangler won't have access to
198   // it.
199   virtual DiscriminatorOverrideTy getDiscriminatorOverride() const = 0;
classof(const MangleContext * C)200   static bool classof(const MangleContext *C) {
201     return C->getKind() == MK_Itanium;
202   }
203 
204   static ItaniumMangleContext *create(ASTContext &Context,
205                                       DiagnosticsEngine &Diags);
206   static ItaniumMangleContext *create(ASTContext &Context,
207                                       DiagnosticsEngine &Diags,
208                                       DiscriminatorOverrideTy Discriminator);
209 };
210 
211 class MicrosoftMangleContext : public MangleContext {
212 public:
MicrosoftMangleContext(ASTContext & C,DiagnosticsEngine & D)213   explicit MicrosoftMangleContext(ASTContext &C, DiagnosticsEngine &D)
214       : MangleContext(C, D, MK_Microsoft) {}
215 
216   /// Mangle vftable symbols.  Only a subset of the bases along the path
217   /// to the vftable are included in the name.  It's up to the caller to pick
218   /// them correctly.
219   virtual void mangleCXXVFTable(const CXXRecordDecl *Derived,
220                                 ArrayRef<const CXXRecordDecl *> BasePath,
221                                 raw_ostream &Out) = 0;
222 
223   /// Mangle vbtable symbols.  Only a subset of the bases along the path
224   /// to the vbtable are included in the name.  It's up to the caller to pick
225   /// them correctly.
226   virtual void mangleCXXVBTable(const CXXRecordDecl *Derived,
227                                 ArrayRef<const CXXRecordDecl *> BasePath,
228                                 raw_ostream &Out) = 0;
229 
230   virtual void mangleThreadSafeStaticGuardVariable(const VarDecl *VD,
231                                                    unsigned GuardNum,
232                                                    raw_ostream &Out) = 0;
233 
234   virtual void mangleVirtualMemPtrThunk(const CXXMethodDecl *MD,
235                                         const MethodVFTableLocation &ML,
236                                         raw_ostream &Out) = 0;
237 
238   virtual void mangleCXXVirtualDisplacementMap(const CXXRecordDecl *SrcRD,
239                                                const CXXRecordDecl *DstRD,
240                                                raw_ostream &Out) = 0;
241 
242   virtual void mangleCXXThrowInfo(QualType T, bool IsConst, bool IsVolatile,
243                                   bool IsUnaligned, uint32_t NumEntries,
244                                   raw_ostream &Out) = 0;
245 
246   virtual void mangleCXXCatchableTypeArray(QualType T, uint32_t NumEntries,
247                                            raw_ostream &Out) = 0;
248 
249   virtual void mangleCXXCatchableType(QualType T, const CXXConstructorDecl *CD,
250                                       CXXCtorType CT, uint32_t Size,
251                                       uint32_t NVOffset, int32_t VBPtrOffset,
252                                       uint32_t VBIndex, raw_ostream &Out) = 0;
253 
254   virtual void mangleCXXRTTIBaseClassDescriptor(
255       const CXXRecordDecl *Derived, uint32_t NVOffset, int32_t VBPtrOffset,
256       uint32_t VBTableOffset, uint32_t Flags, raw_ostream &Out) = 0;
257 
258   virtual void mangleCXXRTTIBaseClassArray(const CXXRecordDecl *Derived,
259                                            raw_ostream &Out) = 0;
260   virtual void
261   mangleCXXRTTIClassHierarchyDescriptor(const CXXRecordDecl *Derived,
262                                         raw_ostream &Out) = 0;
263 
264   virtual void
265   mangleCXXRTTICompleteObjectLocator(const CXXRecordDecl *Derived,
266                                      ArrayRef<const CXXRecordDecl *> BasePath,
267                                      raw_ostream &Out) = 0;
268 
classof(const MangleContext * C)269   static bool classof(const MangleContext *C) {
270     return C->getKind() == MK_Microsoft;
271   }
272 
273   static MicrosoftMangleContext *create(ASTContext &Context,
274                                         DiagnosticsEngine &Diags);
275 };
276 
277 class ASTNameGenerator {
278 public:
279   explicit ASTNameGenerator(ASTContext &Ctx);
280   ~ASTNameGenerator();
281 
282   /// Writes name for \p D to \p OS.
283   /// \returns true on failure, false on success.
284   bool writeName(const Decl *D, raw_ostream &OS);
285 
286   /// \returns name for \p D
287   std::string getName(const Decl *D);
288 
289   /// \returns all applicable mangled names.
290   /// For example C++ constructors/destructors can have multiple.
291   std::vector<std::string> getAllManglings(const Decl *D);
292 
293 private:
294   class Implementation;
295   std::unique_ptr<Implementation> Impl;
296 };
297 }
298 
299 #endif
300