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