aboutsummaryrefslogtreecommitdiffstats
path: root/include/clang/AST/Mangle.h
blob: 5db5c5b977da567adb6cc8a41acdf33d02cda6ed (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
//===--- Mangle.h - Mangle C++ Names ----------------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// Defines the C++ name mangling interface.
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_CLANG_AST_MANGLE_H
#define LLVM_CLANG_AST_MANGLE_H

#include "clang/AST/Decl.h"
#include "clang/AST/Type.h"
#include "clang/Basic/ABI.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/Support/Casting.h"

namespace llvm {
  class raw_ostream;
}

namespace clang {
  class ASTContext;
  class BlockDecl;
  class CXXConstructorDecl;
  class CXXDestructorDecl;
  class CXXMethodDecl;
  class FunctionDecl;
  struct MethodVFTableLocation;
  class NamedDecl;
  class ObjCMethodDecl;
  class StringLiteral;
  struct ThisAdjustment;
  struct ThunkInfo;
  class VarDecl;

/// MangleContext - Context for tracking state which persists across multiple
/// calls to the C++ name mangler.
class MangleContext {
public:
  enum ManglerKind {
    MK_Itanium,
    MK_Microsoft
  };

private:
  virtual void anchor();

  ASTContext &Context;
  DiagnosticsEngine &Diags;
  const ManglerKind Kind;

  llvm::DenseMap<const BlockDecl*, unsigned> GlobalBlockIds;
  llvm::DenseMap<const BlockDecl*, unsigned> LocalBlockIds;
  llvm::DenseMap<const NamedDecl*, uint64_t> AnonStructIds;

public:
  ManglerKind getKind() const { return Kind; }

  explicit MangleContext(ASTContext &Context,
                         DiagnosticsEngine &Diags,
                         ManglerKind Kind)
      : Context(Context), Diags(Diags), Kind(Kind) {}

  virtual ~MangleContext() { }

  ASTContext &getASTContext() const { return Context; }

  DiagnosticsEngine &getDiags() const { return Diags; }

  virtual void startNewFunction() { LocalBlockIds.clear(); }

  unsigned getBlockId(const BlockDecl *BD, bool Local) {
    llvm::DenseMap<const BlockDecl *, unsigned> &BlockIds
      = Local? LocalBlockIds : GlobalBlockIds;
    std::pair<llvm::DenseMap<const BlockDecl *, unsigned>::iterator, bool>
      Result = BlockIds.insert(std::make_pair(BD, BlockIds.size()));
    return Result.first->second;
  }

  uint64_t getAnonymousStructId(const NamedDecl *D) {
    std::pair<llvm::DenseMap<const NamedDecl *, uint64_t>::iterator, bool>
        Result = AnonStructIds.insert(std::make_pair(D, AnonStructIds.size()));
    return Result.first->second;
  }

  /// @name Mangler Entry Points
  /// @{

  bool shouldMangleDeclName(const NamedDecl *D);
  virtual bool shouldMangleCXXName(const NamedDecl *D) = 0;
  virtual bool shouldMangleStringLiteral(const StringLiteral *SL) = 0;

  // FIXME: consider replacing raw_ostream & with something like SmallString &.
  void mangleName(const NamedDecl *D, raw_ostream &);
  virtual void mangleCXXName(const NamedDecl *D, raw_ostream &) = 0;
  virtual void mangleThunk(const CXXMethodDecl *MD,
                          const ThunkInfo &Thunk,
                          raw_ostream &) = 0;
  virtual void mangleCXXDtorThunk(const CXXDestructorDecl *DD, CXXDtorType Type,
                                  const ThisAdjustment &ThisAdjustment,
                                  raw_ostream &) = 0;
  virtual void mangleReferenceTemporary(const VarDecl *D,
                                        unsigned ManglingNumber,
                                        raw_ostream &) = 0;
  virtual void mangleCXXRTTI(QualType T, raw_ostream &) = 0;
  virtual void mangleCXXRTTIName(QualType T, raw_ostream &) = 0;
  virtual void mangleCXXCtor(const CXXConstructorDecl *D, CXXCtorType Type,
                             raw_ostream &) = 0;
  virtual void mangleCXXDtor(const CXXDestructorDecl *D, CXXDtorType Type,
                             raw_ostream &) = 0;
  virtual void mangleStringLiteral(const StringLiteral *SL, raw_ostream &) = 0;

  void mangleGlobalBlock(const BlockDecl *BD,
                         const NamedDecl *ID,
                         raw_ostream &Out);
  void mangleCtorBlock(const CXXConstructorDecl *CD, CXXCtorType CT,
                       const BlockDecl *BD, raw_ostream &Out);
  void mangleDtorBlock(const CXXDestructorDecl *CD, CXXDtorType DT,
                       const BlockDecl *BD, raw_ostream &Out);
  void mangleBlock(const DeclContext *DC, const BlockDecl *BD,
                   raw_ostream &Out);

  void mangleObjCMethodNameWithoutSize(const ObjCMethodDecl *MD, raw_ostream &);
  void mangleObjCMethodName(const ObjCMethodDecl *MD, raw_ostream &);

  virtual void mangleStaticGuardVariable(const VarDecl *D, raw_ostream &) = 0;

  virtual void mangleDynamicInitializer(const VarDecl *D, raw_ostream &) = 0;

  virtual void mangleDynamicAtExitDestructor(const VarDecl *D,
                                             raw_ostream &) = 0;

  virtual void mangleSEHFilterExpression(const NamedDecl *EnclosingDecl,
                                         raw_ostream &Out) = 0;

  virtual void mangleSEHFinallyBlock(const NamedDecl *EnclosingDecl,
                                     raw_ostream &Out) = 0;

  /// Generates a unique string for an externally visible type for use with TBAA
  /// or type uniquing.
  /// TODO: Extend this to internal types by generating names that are unique
  /// across translation units so it can be used with LTO.
  virtual void mangleTypeName(QualType T, raw_ostream &) = 0;

  /// @}
};

class ItaniumMangleContext : public MangleContext {
public:
  explicit ItaniumMangleContext(ASTContext &C, DiagnosticsEngine &D)
      : MangleContext(C, D, MK_Itanium) {}

  virtual void mangleCXXVTable(const CXXRecordDecl *RD, raw_ostream &) = 0;
  virtual void mangleCXXVTT(const CXXRecordDecl *RD, raw_ostream &) = 0;
  virtual void mangleCXXCtorVTable(const CXXRecordDecl *RD, int64_t Offset,
                                   const CXXRecordDecl *Type,
                                   raw_ostream &) = 0;
  virtual void mangleItaniumThreadLocalInit(const VarDecl *D,
                                            raw_ostream &) = 0;
  virtual void mangleItaniumThreadLocalWrapper(const VarDecl *D,
                                               raw_ostream &) = 0;

  virtual void mangleCXXCtorComdat(const CXXConstructorDecl *D,
                                   raw_ostream &) = 0;
  virtual void mangleCXXDtorComdat(const CXXDestructorDecl *D,
                                   raw_ostream &) = 0;

  virtual void mangleLambdaSig(const CXXRecordDecl *Lambda, raw_ostream &) = 0;

  static bool classof(const MangleContext *C) {
    return C->getKind() == MK_Itanium;
  }

  static ItaniumMangleContext *create(ASTContext &Context,
                                      DiagnosticsEngine &Diags);
};

class MicrosoftMangleContext : public MangleContext {
public:
  explicit MicrosoftMangleContext(ASTContext &C, DiagnosticsEngine &D)
      : MangleContext(C, D, MK_Microsoft) {}

  /// Mangle vftable symbols.  Only a subset of the bases along the path
  /// to the vftable are included in the name.  It's up to the caller to pick
  /// them correctly.
  virtual void mangleCXXVFTable(const CXXRecordDecl *Derived,
                                ArrayRef<const CXXRecordDecl *> BasePath,
                                raw_ostream &Out) = 0;

  /// Mangle vbtable symbols.  Only a subset of the bases along the path
  /// to the vbtable are included in the name.  It's up to the caller to pick
  /// them correctly.
  virtual void mangleCXXVBTable(const CXXRecordDecl *Derived,
                                ArrayRef<const CXXRecordDecl *> BasePath,
                                raw_ostream &Out) = 0;

  virtual void mangleThreadSafeStaticGuardVariable(const VarDecl *VD,
                                                   unsigned GuardNum,
                                                   raw_ostream &Out) = 0;

  virtual void mangleVirtualMemPtrThunk(const CXXMethodDecl *MD,
                                        const MethodVFTableLocation &ML,
                                        raw_ostream &Out) = 0;

  virtual void mangleCXXVirtualDisplacementMap(const CXXRecordDecl *SrcRD,
                                               const CXXRecordDecl *DstRD,
                                               raw_ostream &Out) = 0;

  virtual void mangleCXXThrowInfo(QualType T, bool IsConst, bool IsVolatile,
                                  bool IsUnaligned, uint32_t NumEntries,
                                  raw_ostream &Out) = 0;

  virtual void mangleCXXCatchableTypeArray(QualType T, uint32_t NumEntries,
                                           raw_ostream &Out) = 0;

  virtual void mangleCXXCatchableType(QualType T, const CXXConstructorDecl *CD,
                                      CXXCtorType CT, uint32_t Size,
                                      uint32_t NVOffset, int32_t VBPtrOffset,
                                      uint32_t VBIndex, raw_ostream &Out) = 0;

  virtual void mangleCXXRTTIBaseClassDescriptor(
      const CXXRecordDecl *Derived, uint32_t NVOffset, int32_t VBPtrOffset,
      uint32_t VBTableOffset, uint32_t Flags, raw_ostream &Out) = 0;

  virtual void mangleCXXRTTIBaseClassArray(const CXXRecordDecl *Derived,
                                           raw_ostream &Out) = 0;
  virtual void
  mangleCXXRTTIClassHierarchyDescriptor(const CXXRecordDecl *Derived,
                                        raw_ostream &Out) = 0;

  virtual void
  mangleCXXRTTICompleteObjectLocator(const CXXRecordDecl *Derived,
                                     ArrayRef<const CXXRecordDecl *> BasePath,
                                     raw_ostream &Out) = 0;

  static bool classof(const MangleContext *C) {
    return C->getKind() == MK_Microsoft;
  }

  static MicrosoftMangleContext *create(ASTContext &Context,
                                        DiagnosticsEngine &Diags);
};

class ASTNameGenerator {
public:
  explicit ASTNameGenerator(ASTContext &Ctx);
  ~ASTNameGenerator();

  /// Writes name for \p D to \p OS.
  /// \returns true on failure, false on success.
  bool writeName(const Decl *D, raw_ostream &OS);

  /// \returns name for \p D
  std::string getName(const Decl *D);

  /// \returns all applicable mangled names.
  /// For example C++ constructors/destructors can have multiple.
  std::vector<std::string> getAllManglings(const Decl *D);

private:
  class Implementation;
  std::unique_ptr<Implementation> Impl;
};
}

#endif