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