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
22namespace llvm {
23  class raw_ostream;
24}
25
26namespace 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.
43class MangleContext {
44public:
45  enum ManglerKind {
46    MK_Itanium,
47    MK_Microsoft
48  };
49
50private:
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
61public:
62  ManglerKind getKind() const { return Kind; }
63
64  explicit MangleContext(ASTContext &Context,
65                         DiagnosticsEngine &Diags,
66                         ManglerKind Kind)
67      : Context(Context), Diags(Diags), Kind(Kind) {}
68
69  virtual ~MangleContext() { }
70
71  ASTContext &getASTContext() const { return Context; }
72
73  DiagnosticsEngine &getDiags() const { return Diags; }
74
75  virtual void startNewFunction() { LocalBlockIds.clear(); }
76
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
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
153class ItaniumMangleContext : public MangleContext {
154public:
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
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
183class MicrosoftMangleContext : public MangleContext {
184public:
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
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
249class ASTNameGenerator {
250public:
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
265private:
266  class Implementation;
267  std::unique_ptr<Implementation> Impl;
268};
269}
270
271#endif
272