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