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