File: | llvm/include/llvm/Demangle/MicrosoftDemangle.h |
Warning: | line 88, column 12 4096 bytes is possibly not enough for array allocation which requires 16 bytes. Current overhead requires the size of 4080 bytes |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | //===- MicrosoftDemangle.cpp ----------------------------------------------===// | ||||||||
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 | // This file defines a demangler for MSVC-style mangled symbols. | ||||||||
10 | // | ||||||||
11 | // This file has no dependencies on the rest of LLVM so that it can be | ||||||||
12 | // easily reused in other programs such as libcxxabi. | ||||||||
13 | // | ||||||||
14 | //===----------------------------------------------------------------------===// | ||||||||
15 | |||||||||
16 | #include "llvm/Demangle/MicrosoftDemangle.h" | ||||||||
17 | #include "llvm/Demangle/Demangle.h" | ||||||||
18 | #include "llvm/Demangle/MicrosoftDemangleNodes.h" | ||||||||
19 | |||||||||
20 | #include "llvm/Demangle/DemangleConfig.h" | ||||||||
21 | #include "llvm/Demangle/StringView.h" | ||||||||
22 | #include "llvm/Demangle/Utility.h" | ||||||||
23 | |||||||||
24 | #include <array> | ||||||||
25 | #include <cctype> | ||||||||
26 | #include <cstdio> | ||||||||
27 | #include <tuple> | ||||||||
28 | |||||||||
29 | using namespace llvm; | ||||||||
30 | using namespace ms_demangle; | ||||||||
31 | |||||||||
32 | static bool startsWithDigit(StringView S) { | ||||||||
33 | return !S.empty() && std::isdigit(S.front()); | ||||||||
34 | } | ||||||||
35 | |||||||||
36 | |||||||||
37 | struct NodeList { | ||||||||
38 | Node *N = nullptr; | ||||||||
39 | NodeList *Next = nullptr; | ||||||||
40 | }; | ||||||||
41 | |||||||||
42 | static bool isMemberPointer(StringView MangledName, bool &Error) { | ||||||||
43 | Error = false; | ||||||||
44 | switch (MangledName.popFront()) { | ||||||||
45 | case '$': | ||||||||
46 | // This is probably an rvalue reference (e.g. $$Q), and you cannot have an | ||||||||
47 | // rvalue reference to a member. | ||||||||
48 | return false; | ||||||||
49 | case 'A': | ||||||||
50 | // 'A' indicates a reference, and you cannot have a reference to a member | ||||||||
51 | // function or member. | ||||||||
52 | return false; | ||||||||
53 | case 'P': | ||||||||
54 | case 'Q': | ||||||||
55 | case 'R': | ||||||||
56 | case 'S': | ||||||||
57 | // These 4 values indicate some kind of pointer, but we still don't know | ||||||||
58 | // what. | ||||||||
59 | break; | ||||||||
60 | default: | ||||||||
61 | // isMemberPointer() is called only if isPointerType() returns true, | ||||||||
62 | // and it rejects other prefixes. | ||||||||
63 | DEMANGLE_UNREACHABLE__builtin_unreachable(); | ||||||||
64 | } | ||||||||
65 | |||||||||
66 | // If it starts with a number, then 6 indicates a non-member function | ||||||||
67 | // pointer, and 8 indicates a member function pointer. | ||||||||
68 | if (startsWithDigit(MangledName)) { | ||||||||
69 | if (MangledName[0] != '6' && MangledName[0] != '8') { | ||||||||
70 | Error = true; | ||||||||
71 | return false; | ||||||||
72 | } | ||||||||
73 | return (MangledName[0] == '8'); | ||||||||
74 | } | ||||||||
75 | |||||||||
76 | // Remove ext qualifiers since those can appear on either type and are | ||||||||
77 | // therefore not indicative. | ||||||||
78 | MangledName.consumeFront('E'); // 64-bit | ||||||||
79 | MangledName.consumeFront('I'); // restrict | ||||||||
80 | MangledName.consumeFront('F'); // unaligned | ||||||||
81 | |||||||||
82 | if (MangledName.empty()) { | ||||||||
83 | Error = true; | ||||||||
84 | return false; | ||||||||
85 | } | ||||||||
86 | |||||||||
87 | // The next value should be either ABCD (non-member) or QRST (member). | ||||||||
88 | switch (MangledName.front()) { | ||||||||
89 | case 'A': | ||||||||
90 | case 'B': | ||||||||
91 | case 'C': | ||||||||
92 | case 'D': | ||||||||
93 | return false; | ||||||||
94 | case 'Q': | ||||||||
95 | case 'R': | ||||||||
96 | case 'S': | ||||||||
97 | case 'T': | ||||||||
98 | return true; | ||||||||
99 | default: | ||||||||
100 | Error = true; | ||||||||
101 | return false; | ||||||||
102 | } | ||||||||
103 | } | ||||||||
104 | |||||||||
105 | static SpecialIntrinsicKind | ||||||||
106 | consumeSpecialIntrinsicKind(StringView &MangledName) { | ||||||||
107 | if (MangledName.consumeFront("?_7")) | ||||||||
108 | return SpecialIntrinsicKind::Vftable; | ||||||||
109 | if (MangledName.consumeFront("?_8")) | ||||||||
110 | return SpecialIntrinsicKind::Vbtable; | ||||||||
111 | if (MangledName.consumeFront("?_9")) | ||||||||
112 | return SpecialIntrinsicKind::VcallThunk; | ||||||||
113 | if (MangledName.consumeFront("?_A")) | ||||||||
114 | return SpecialIntrinsicKind::Typeof; | ||||||||
115 | if (MangledName.consumeFront("?_B")) | ||||||||
116 | return SpecialIntrinsicKind::LocalStaticGuard; | ||||||||
117 | if (MangledName.consumeFront("?_C")) | ||||||||
118 | return SpecialIntrinsicKind::StringLiteralSymbol; | ||||||||
119 | if (MangledName.consumeFront("?_P")) | ||||||||
120 | return SpecialIntrinsicKind::UdtReturning; | ||||||||
121 | if (MangledName.consumeFront("?_R0")) | ||||||||
122 | return SpecialIntrinsicKind::RttiTypeDescriptor; | ||||||||
123 | if (MangledName.consumeFront("?_R1")) | ||||||||
124 | return SpecialIntrinsicKind::RttiBaseClassDescriptor; | ||||||||
125 | if (MangledName.consumeFront("?_R2")) | ||||||||
126 | return SpecialIntrinsicKind::RttiBaseClassArray; | ||||||||
127 | if (MangledName.consumeFront("?_R3")) | ||||||||
128 | return SpecialIntrinsicKind::RttiClassHierarchyDescriptor; | ||||||||
129 | if (MangledName.consumeFront("?_R4")) | ||||||||
130 | return SpecialIntrinsicKind::RttiCompleteObjLocator; | ||||||||
131 | if (MangledName.consumeFront("?_S")) | ||||||||
132 | return SpecialIntrinsicKind::LocalVftable; | ||||||||
133 | if (MangledName.consumeFront("?__E")) | ||||||||
134 | return SpecialIntrinsicKind::DynamicInitializer; | ||||||||
135 | if (MangledName.consumeFront("?__F")) | ||||||||
136 | return SpecialIntrinsicKind::DynamicAtexitDestructor; | ||||||||
137 | if (MangledName.consumeFront("?__J")) | ||||||||
138 | return SpecialIntrinsicKind::LocalStaticThreadGuard; | ||||||||
139 | return SpecialIntrinsicKind::None; | ||||||||
140 | } | ||||||||
141 | |||||||||
142 | static bool startsWithLocalScopePattern(StringView S) { | ||||||||
143 | if (!S.consumeFront('?')) | ||||||||
144 | return false; | ||||||||
145 | |||||||||
146 | size_t End = S.find('?'); | ||||||||
147 | if (End == StringView::npos) | ||||||||
148 | return false; | ||||||||
149 | StringView Candidate = S.substr(0, End); | ||||||||
150 | if (Candidate.empty()) | ||||||||
151 | return false; | ||||||||
152 | |||||||||
153 | // \?[0-9]\? | ||||||||
154 | // ?@? is the discriminator 0. | ||||||||
155 | if (Candidate.size() == 1) | ||||||||
156 | return Candidate[0] == '@' || (Candidate[0] >= '0' && Candidate[0] <= '9'); | ||||||||
157 | |||||||||
158 | // If it's not 0-9, then it's an encoded number terminated with an @ | ||||||||
159 | if (Candidate.back() != '@') | ||||||||
160 | return false; | ||||||||
161 | Candidate = Candidate.dropBack(); | ||||||||
162 | |||||||||
163 | // An encoded number starts with B-P and all subsequent digits are in A-P. | ||||||||
164 | // Note that the reason the first digit cannot be A is two fold. First, it | ||||||||
165 | // would create an ambiguity with ?A which delimits the beginning of an | ||||||||
166 | // anonymous namespace. Second, A represents 0, and you don't start a multi | ||||||||
167 | // digit number with a leading 0. Presumably the anonymous namespace | ||||||||
168 | // ambiguity is also why single digit encoded numbers use 0-9 rather than A-J. | ||||||||
169 | if (Candidate[0] < 'B' || Candidate[0] > 'P') | ||||||||
170 | return false; | ||||||||
171 | Candidate = Candidate.dropFront(); | ||||||||
172 | while (!Candidate.empty()) { | ||||||||
173 | if (Candidate[0] < 'A' || Candidate[0] > 'P') | ||||||||
174 | return false; | ||||||||
175 | Candidate = Candidate.dropFront(); | ||||||||
176 | } | ||||||||
177 | |||||||||
178 | return true; | ||||||||
179 | } | ||||||||
180 | |||||||||
181 | static bool isTagType(StringView S) { | ||||||||
182 | switch (S.front()) { | ||||||||
183 | case 'T': // union | ||||||||
184 | case 'U': // struct | ||||||||
185 | case 'V': // class | ||||||||
186 | case 'W': // enum | ||||||||
187 | return true; | ||||||||
188 | } | ||||||||
189 | return false; | ||||||||
190 | } | ||||||||
191 | |||||||||
192 | static bool isCustomType(StringView S) { return S[0] == '?'; } | ||||||||
193 | |||||||||
194 | static bool isPointerType(StringView S) { | ||||||||
195 | if (S.startsWith("$$Q")) // foo && | ||||||||
196 | return true; | ||||||||
197 | |||||||||
198 | switch (S.front()) { | ||||||||
199 | case 'A': // foo & | ||||||||
200 | case 'P': // foo * | ||||||||
201 | case 'Q': // foo *const | ||||||||
202 | case 'R': // foo *volatile | ||||||||
203 | case 'S': // foo *const volatile | ||||||||
204 | return true; | ||||||||
205 | } | ||||||||
206 | return false; | ||||||||
207 | } | ||||||||
208 | |||||||||
209 | static bool isArrayType(StringView S) { return S[0] == 'Y'; } | ||||||||
210 | |||||||||
211 | static bool isFunctionType(StringView S) { | ||||||||
212 | return S.startsWith("$$A8@@") || S.startsWith("$$A6"); | ||||||||
213 | } | ||||||||
214 | |||||||||
215 | static FunctionRefQualifier | ||||||||
216 | demangleFunctionRefQualifier(StringView &MangledName) { | ||||||||
217 | if (MangledName.consumeFront('G')) | ||||||||
218 | return FunctionRefQualifier::Reference; | ||||||||
219 | else if (MangledName.consumeFront('H')) | ||||||||
220 | return FunctionRefQualifier::RValueReference; | ||||||||
221 | return FunctionRefQualifier::None; | ||||||||
222 | } | ||||||||
223 | |||||||||
224 | static std::pair<Qualifiers, PointerAffinity> | ||||||||
225 | demanglePointerCVQualifiers(StringView &MangledName) { | ||||||||
226 | if (MangledName.consumeFront("$$Q")) | ||||||||
227 | return std::make_pair(Q_None, PointerAffinity::RValueReference); | ||||||||
228 | |||||||||
229 | switch (MangledName.popFront()) { | ||||||||
230 | case 'A': | ||||||||
231 | return std::make_pair(Q_None, PointerAffinity::Reference); | ||||||||
232 | case 'P': | ||||||||
233 | return std::make_pair(Q_None, PointerAffinity::Pointer); | ||||||||
234 | case 'Q': | ||||||||
235 | return std::make_pair(Q_Const, PointerAffinity::Pointer); | ||||||||
236 | case 'R': | ||||||||
237 | return std::make_pair(Q_Volatile, PointerAffinity::Pointer); | ||||||||
238 | case 'S': | ||||||||
239 | return std::make_pair(Qualifiers(Q_Const | Q_Volatile), | ||||||||
240 | PointerAffinity::Pointer); | ||||||||
241 | } | ||||||||
242 | // This function is only called if isPointerType() returns true, | ||||||||
243 | // and it only returns true for the six cases listed above. | ||||||||
244 | DEMANGLE_UNREACHABLE__builtin_unreachable(); | ||||||||
245 | } | ||||||||
246 | |||||||||
247 | StringView Demangler::copyString(StringView Borrowed) { | ||||||||
248 | char *Stable = Arena.allocUnalignedBuffer(Borrowed.size() + 1); | ||||||||
249 | std::strcpy(Stable, Borrowed.begin()); | ||||||||
250 | |||||||||
251 | return {Stable, Borrowed.size()}; | ||||||||
252 | } | ||||||||
253 | |||||||||
254 | SpecialTableSymbolNode * | ||||||||
255 | Demangler::demangleSpecialTableSymbolNode(StringView &MangledName, | ||||||||
256 | SpecialIntrinsicKind K) { | ||||||||
257 | NamedIdentifierNode *NI = Arena.alloc<NamedIdentifierNode>(); | ||||||||
258 | switch (K) { | ||||||||
259 | case SpecialIntrinsicKind::Vftable: | ||||||||
260 | NI->Name = "`vftable'"; | ||||||||
261 | break; | ||||||||
262 | case SpecialIntrinsicKind::Vbtable: | ||||||||
263 | NI->Name = "`vbtable'"; | ||||||||
264 | break; | ||||||||
265 | case SpecialIntrinsicKind::LocalVftable: | ||||||||
266 | NI->Name = "`local vftable'"; | ||||||||
267 | break; | ||||||||
268 | case SpecialIntrinsicKind::RttiCompleteObjLocator: | ||||||||
269 | NI->Name = "`RTTI Complete Object Locator'"; | ||||||||
270 | break; | ||||||||
271 | default: | ||||||||
272 | DEMANGLE_UNREACHABLE__builtin_unreachable(); | ||||||||
273 | } | ||||||||
274 | QualifiedNameNode *QN = demangleNameScopeChain(MangledName, NI); | ||||||||
275 | SpecialTableSymbolNode *STSN = Arena.alloc<SpecialTableSymbolNode>(); | ||||||||
276 | STSN->Name = QN; | ||||||||
277 | bool IsMember = false; | ||||||||
278 | if (MangledName.empty()) { | ||||||||
279 | Error = true; | ||||||||
280 | return nullptr; | ||||||||
281 | } | ||||||||
282 | char Front = MangledName.popFront(); | ||||||||
283 | if (Front != '6' && Front != '7') { | ||||||||
284 | Error = true; | ||||||||
285 | return nullptr; | ||||||||
286 | } | ||||||||
287 | |||||||||
288 | std::tie(STSN->Quals, IsMember) = demangleQualifiers(MangledName); | ||||||||
289 | if (!MangledName.consumeFront('@')) | ||||||||
290 | STSN->TargetName = demangleFullyQualifiedTypeName(MangledName); | ||||||||
291 | return STSN; | ||||||||
292 | } | ||||||||
293 | |||||||||
294 | LocalStaticGuardVariableNode * | ||||||||
295 | Demangler::demangleLocalStaticGuard(StringView &MangledName, bool IsThread) { | ||||||||
296 | LocalStaticGuardIdentifierNode *LSGI = | ||||||||
297 | Arena.alloc<LocalStaticGuardIdentifierNode>(); | ||||||||
298 | LSGI->IsThread = IsThread; | ||||||||
299 | QualifiedNameNode *QN = demangleNameScopeChain(MangledName, LSGI); | ||||||||
300 | LocalStaticGuardVariableNode *LSGVN = | ||||||||
301 | Arena.alloc<LocalStaticGuardVariableNode>(); | ||||||||
302 | LSGVN->Name = QN; | ||||||||
303 | |||||||||
304 | if (MangledName.consumeFront("4IA")) | ||||||||
305 | LSGVN->IsVisible = false; | ||||||||
306 | else if (MangledName.consumeFront("5")) | ||||||||
307 | LSGVN->IsVisible = true; | ||||||||
308 | else { | ||||||||
309 | Error = true; | ||||||||
310 | return nullptr; | ||||||||
311 | } | ||||||||
312 | |||||||||
313 | if (!MangledName.empty()) | ||||||||
314 | LSGI->ScopeIndex = demangleUnsigned(MangledName); | ||||||||
315 | return LSGVN; | ||||||||
316 | } | ||||||||
317 | |||||||||
318 | static NamedIdentifierNode *synthesizeNamedIdentifier(ArenaAllocator &Arena, | ||||||||
319 | StringView Name) { | ||||||||
320 | NamedIdentifierNode *Id = Arena.alloc<NamedIdentifierNode>(); | ||||||||
321 | Id->Name = Name; | ||||||||
322 | return Id; | ||||||||
323 | } | ||||||||
324 | |||||||||
325 | static QualifiedNameNode *synthesizeQualifiedName(ArenaAllocator &Arena, | ||||||||
326 | IdentifierNode *Identifier) { | ||||||||
327 | QualifiedNameNode *QN = Arena.alloc<QualifiedNameNode>(); | ||||||||
328 | QN->Components = Arena.alloc<NodeArrayNode>(); | ||||||||
329 | QN->Components->Count = 1; | ||||||||
330 | QN->Components->Nodes = Arena.allocArray<Node *>(1); | ||||||||
331 | QN->Components->Nodes[0] = Identifier; | ||||||||
332 | return QN; | ||||||||
333 | } | ||||||||
334 | |||||||||
335 | static QualifiedNameNode *synthesizeQualifiedName(ArenaAllocator &Arena, | ||||||||
336 | StringView Name) { | ||||||||
337 | NamedIdentifierNode *Id = synthesizeNamedIdentifier(Arena, Name); | ||||||||
338 | return synthesizeQualifiedName(Arena, Id); | ||||||||
339 | } | ||||||||
340 | |||||||||
341 | static VariableSymbolNode *synthesizeVariable(ArenaAllocator &Arena, | ||||||||
342 | TypeNode *Type, | ||||||||
343 | StringView VariableName) { | ||||||||
344 | VariableSymbolNode *VSN = Arena.alloc<VariableSymbolNode>(); | ||||||||
345 | VSN->Type = Type; | ||||||||
346 | VSN->Name = synthesizeQualifiedName(Arena, VariableName); | ||||||||
347 | return VSN; | ||||||||
348 | } | ||||||||
349 | |||||||||
350 | VariableSymbolNode *Demangler::demangleUntypedVariable( | ||||||||
351 | ArenaAllocator &Arena, StringView &MangledName, StringView VariableName) { | ||||||||
352 | NamedIdentifierNode *NI = synthesizeNamedIdentifier(Arena, VariableName); | ||||||||
353 | QualifiedNameNode *QN = demangleNameScopeChain(MangledName, NI); | ||||||||
354 | VariableSymbolNode *VSN = Arena.alloc<VariableSymbolNode>(); | ||||||||
355 | VSN->Name = QN; | ||||||||
356 | if (MangledName.consumeFront("8")) | ||||||||
357 | return VSN; | ||||||||
358 | |||||||||
359 | Error = true; | ||||||||
360 | return nullptr; | ||||||||
361 | } | ||||||||
362 | |||||||||
363 | VariableSymbolNode * | ||||||||
364 | Demangler::demangleRttiBaseClassDescriptorNode(ArenaAllocator &Arena, | ||||||||
365 | StringView &MangledName) { | ||||||||
366 | RttiBaseClassDescriptorNode *RBCDN = | ||||||||
367 | Arena.alloc<RttiBaseClassDescriptorNode>(); | ||||||||
368 | RBCDN->NVOffset = demangleUnsigned(MangledName); | ||||||||
369 | RBCDN->VBPtrOffset = demangleSigned(MangledName); | ||||||||
370 | RBCDN->VBTableOffset = demangleUnsigned(MangledName); | ||||||||
371 | RBCDN->Flags = demangleUnsigned(MangledName); | ||||||||
372 | if (Error) | ||||||||
373 | return nullptr; | ||||||||
374 | |||||||||
375 | VariableSymbolNode *VSN = Arena.alloc<VariableSymbolNode>(); | ||||||||
376 | VSN->Name = demangleNameScopeChain(MangledName, RBCDN); | ||||||||
377 | MangledName.consumeFront('8'); | ||||||||
378 | return VSN; | ||||||||
379 | } | ||||||||
380 | |||||||||
381 | FunctionSymbolNode *Demangler::demangleInitFiniStub(StringView &MangledName, | ||||||||
382 | bool IsDestructor) { | ||||||||
383 | DynamicStructorIdentifierNode *DSIN = | ||||||||
384 | Arena.alloc<DynamicStructorIdentifierNode>(); | ||||||||
385 | DSIN->IsDestructor = IsDestructor; | ||||||||
386 | |||||||||
387 | bool IsKnownStaticDataMember = false; | ||||||||
388 | if (MangledName.consumeFront('?')) | ||||||||
389 | IsKnownStaticDataMember = true; | ||||||||
390 | |||||||||
391 | SymbolNode *Symbol = demangleDeclarator(MangledName); | ||||||||
392 | if (Error) | ||||||||
393 | return nullptr; | ||||||||
394 | |||||||||
395 | FunctionSymbolNode *FSN = nullptr; | ||||||||
396 | |||||||||
397 | if (Symbol->kind() == NodeKind::VariableSymbol) { | ||||||||
398 | DSIN->Variable = static_cast<VariableSymbolNode *>(Symbol); | ||||||||
399 | |||||||||
400 | // Older versions of clang mangled this type of symbol incorrectly. They | ||||||||
401 | // would omit the leading ? and they would only emit a single @ at the end. | ||||||||
402 | // The correct mangling is a leading ? and 2 trailing @ signs. Handle | ||||||||
403 | // both cases. | ||||||||
404 | int AtCount = IsKnownStaticDataMember ? 2 : 1; | ||||||||
405 | for (int I = 0; I < AtCount; ++I) { | ||||||||
406 | if (MangledName.consumeFront('@')) | ||||||||
407 | continue; | ||||||||
408 | Error = true; | ||||||||
409 | return nullptr; | ||||||||
410 | } | ||||||||
411 | |||||||||
412 | FSN = demangleFunctionEncoding(MangledName); | ||||||||
413 | if (FSN) | ||||||||
414 | FSN->Name = synthesizeQualifiedName(Arena, DSIN); | ||||||||
415 | } else { | ||||||||
416 | if (IsKnownStaticDataMember) { | ||||||||
417 | // This was supposed to be a static data member, but we got a function. | ||||||||
418 | Error = true; | ||||||||
419 | return nullptr; | ||||||||
420 | } | ||||||||
421 | |||||||||
422 | FSN = static_cast<FunctionSymbolNode *>(Symbol); | ||||||||
423 | DSIN->Name = Symbol->Name; | ||||||||
424 | FSN->Name = synthesizeQualifiedName(Arena, DSIN); | ||||||||
425 | } | ||||||||
426 | |||||||||
427 | return FSN; | ||||||||
428 | } | ||||||||
429 | |||||||||
430 | SymbolNode *Demangler::demangleSpecialIntrinsic(StringView &MangledName) { | ||||||||
431 | SpecialIntrinsicKind SIK = consumeSpecialIntrinsicKind(MangledName); | ||||||||
432 | |||||||||
433 | switch (SIK) { | ||||||||
434 | case SpecialIntrinsicKind::None: | ||||||||
435 | return nullptr; | ||||||||
436 | case SpecialIntrinsicKind::StringLiteralSymbol: | ||||||||
437 | return demangleStringLiteral(MangledName); | ||||||||
438 | case SpecialIntrinsicKind::Vftable: | ||||||||
439 | case SpecialIntrinsicKind::Vbtable: | ||||||||
440 | case SpecialIntrinsicKind::LocalVftable: | ||||||||
441 | case SpecialIntrinsicKind::RttiCompleteObjLocator: | ||||||||
442 | return demangleSpecialTableSymbolNode(MangledName, SIK); | ||||||||
443 | case SpecialIntrinsicKind::VcallThunk: | ||||||||
444 | return demangleVcallThunkNode(MangledName); | ||||||||
445 | case SpecialIntrinsicKind::LocalStaticGuard: | ||||||||
446 | return demangleLocalStaticGuard(MangledName, /*IsThread=*/false); | ||||||||
447 | case SpecialIntrinsicKind::LocalStaticThreadGuard: | ||||||||
448 | return demangleLocalStaticGuard(MangledName, /*IsThread=*/true); | ||||||||
449 | case SpecialIntrinsicKind::RttiTypeDescriptor: { | ||||||||
450 | TypeNode *T = demangleType(MangledName, QualifierMangleMode::Result); | ||||||||
451 | if (Error) | ||||||||
452 | break; | ||||||||
453 | if (!MangledName.consumeFront("@8")) | ||||||||
454 | break; | ||||||||
455 | if (!MangledName.empty()) | ||||||||
456 | break; | ||||||||
457 | return synthesizeVariable(Arena, T, "`RTTI Type Descriptor'"); | ||||||||
458 | } | ||||||||
459 | case SpecialIntrinsicKind::RttiBaseClassArray: | ||||||||
460 | return demangleUntypedVariable(Arena, MangledName, | ||||||||
461 | "`RTTI Base Class Array'"); | ||||||||
462 | case SpecialIntrinsicKind::RttiClassHierarchyDescriptor: | ||||||||
463 | return demangleUntypedVariable(Arena, MangledName, | ||||||||
464 | "`RTTI Class Hierarchy Descriptor'"); | ||||||||
465 | case SpecialIntrinsicKind::RttiBaseClassDescriptor: | ||||||||
466 | return demangleRttiBaseClassDescriptorNode(Arena, MangledName); | ||||||||
467 | case SpecialIntrinsicKind::DynamicInitializer: | ||||||||
468 | return demangleInitFiniStub(MangledName, /*IsDestructor=*/false); | ||||||||
469 | case SpecialIntrinsicKind::DynamicAtexitDestructor: | ||||||||
470 | return demangleInitFiniStub(MangledName, /*IsDestructor=*/true); | ||||||||
471 | case SpecialIntrinsicKind::Typeof: | ||||||||
472 | case SpecialIntrinsicKind::UdtReturning: | ||||||||
473 | // It's unclear which tools produces these manglings, so demangling | ||||||||
474 | // support is not (yet?) implemented. | ||||||||
475 | break; | ||||||||
476 | case SpecialIntrinsicKind::Unknown: | ||||||||
477 | DEMANGLE_UNREACHABLE__builtin_unreachable(); // Never returned by consumeSpecialIntrinsicKind. | ||||||||
478 | } | ||||||||
479 | Error = true; | ||||||||
480 | return nullptr; | ||||||||
481 | } | ||||||||
482 | |||||||||
483 | IdentifierNode * | ||||||||
484 | Demangler::demangleFunctionIdentifierCode(StringView &MangledName) { | ||||||||
485 | assert(MangledName.startsWith('?'))(static_cast <bool> (MangledName.startsWith('?')) ? void (0) : __assert_fail ("MangledName.startsWith('?')", "/build/llvm-toolchain-snapshot-13~++20210726100616+dead50d4427c/llvm/lib/Demangle/MicrosoftDemangle.cpp" , 485, __extension__ __PRETTY_FUNCTION__)); | ||||||||
486 | MangledName = MangledName.dropFront(); | ||||||||
487 | if (MangledName.empty()) { | ||||||||
488 | Error = true; | ||||||||
489 | return nullptr; | ||||||||
490 | } | ||||||||
491 | |||||||||
492 | if (MangledName.consumeFront("__")) | ||||||||
493 | return demangleFunctionIdentifierCode( | ||||||||
494 | MangledName, FunctionIdentifierCodeGroup::DoubleUnder); | ||||||||
495 | if (MangledName.consumeFront("_")) | ||||||||
496 | return demangleFunctionIdentifierCode(MangledName, | ||||||||
497 | FunctionIdentifierCodeGroup::Under); | ||||||||
498 | return demangleFunctionIdentifierCode(MangledName, | ||||||||
499 | FunctionIdentifierCodeGroup::Basic); | ||||||||
500 | } | ||||||||
501 | |||||||||
502 | StructorIdentifierNode * | ||||||||
503 | Demangler::demangleStructorIdentifier(StringView &MangledName, | ||||||||
504 | bool IsDestructor) { | ||||||||
505 | StructorIdentifierNode *N = Arena.alloc<StructorIdentifierNode>(); | ||||||||
506 | N->IsDestructor = IsDestructor; | ||||||||
507 | return N; | ||||||||
508 | } | ||||||||
509 | |||||||||
510 | ConversionOperatorIdentifierNode * | ||||||||
511 | Demangler::demangleConversionOperatorIdentifier(StringView &MangledName) { | ||||||||
512 | ConversionOperatorIdentifierNode *N = | ||||||||
513 | Arena.alloc<ConversionOperatorIdentifierNode>(); | ||||||||
514 | return N; | ||||||||
515 | } | ||||||||
516 | |||||||||
517 | LiteralOperatorIdentifierNode * | ||||||||
518 | Demangler::demangleLiteralOperatorIdentifier(StringView &MangledName) { | ||||||||
519 | LiteralOperatorIdentifierNode *N = | ||||||||
520 | Arena.alloc<LiteralOperatorIdentifierNode>(); | ||||||||
521 | N->Name = demangleSimpleString(MangledName, /*Memorize=*/false); | ||||||||
522 | return N; | ||||||||
523 | } | ||||||||
524 | |||||||||
525 | IntrinsicFunctionKind | ||||||||
526 | Demangler::translateIntrinsicFunctionCode(char CH, | ||||||||
527 | FunctionIdentifierCodeGroup Group) { | ||||||||
528 | using IFK = IntrinsicFunctionKind; | ||||||||
529 | if (!(CH >= '0' && CH <= '9') && !(CH >= 'A' && CH <= 'Z')) { | ||||||||
530 | Error = true; | ||||||||
531 | return IFK::None; | ||||||||
532 | } | ||||||||
533 | |||||||||
534 | // Not all ? identifiers are intrinsics *functions*. This function only maps | ||||||||
535 | // operator codes for the special functions, all others are handled elsewhere, | ||||||||
536 | // hence the IFK::None entries in the table. | ||||||||
537 | static IFK Basic[36] = { | ||||||||
538 | IFK::None, // ?0 # Foo::Foo() | ||||||||
539 | IFK::None, // ?1 # Foo::~Foo() | ||||||||
540 | IFK::New, // ?2 # operator new | ||||||||
541 | IFK::Delete, // ?3 # operator delete | ||||||||
542 | IFK::Assign, // ?4 # operator= | ||||||||
543 | IFK::RightShift, // ?5 # operator>> | ||||||||
544 | IFK::LeftShift, // ?6 # operator<< | ||||||||
545 | IFK::LogicalNot, // ?7 # operator! | ||||||||
546 | IFK::Equals, // ?8 # operator== | ||||||||
547 | IFK::NotEquals, // ?9 # operator!= | ||||||||
548 | IFK::ArraySubscript, // ?A # operator[] | ||||||||
549 | IFK::None, // ?B # Foo::operator <type>() | ||||||||
550 | IFK::Pointer, // ?C # operator-> | ||||||||
551 | IFK::Dereference, // ?D # operator* | ||||||||
552 | IFK::Increment, // ?E # operator++ | ||||||||
553 | IFK::Decrement, // ?F # operator-- | ||||||||
554 | IFK::Minus, // ?G # operator- | ||||||||
555 | IFK::Plus, // ?H # operator+ | ||||||||
556 | IFK::BitwiseAnd, // ?I # operator& | ||||||||
557 | IFK::MemberPointer, // ?J # operator->* | ||||||||
558 | IFK::Divide, // ?K # operator/ | ||||||||
559 | IFK::Modulus, // ?L # operator% | ||||||||
560 | IFK::LessThan, // ?M operator< | ||||||||
561 | IFK::LessThanEqual, // ?N operator<= | ||||||||
562 | IFK::GreaterThan, // ?O operator> | ||||||||
563 | IFK::GreaterThanEqual, // ?P operator>= | ||||||||
564 | IFK::Comma, // ?Q operator, | ||||||||
565 | IFK::Parens, // ?R operator() | ||||||||
566 | IFK::BitwiseNot, // ?S operator~ | ||||||||
567 | IFK::BitwiseXor, // ?T operator^ | ||||||||
568 | IFK::BitwiseOr, // ?U operator| | ||||||||
569 | IFK::LogicalAnd, // ?V operator&& | ||||||||
570 | IFK::LogicalOr, // ?W operator|| | ||||||||
571 | IFK::TimesEqual, // ?X operator*= | ||||||||
572 | IFK::PlusEqual, // ?Y operator+= | ||||||||
573 | IFK::MinusEqual, // ?Z operator-= | ||||||||
574 | }; | ||||||||
575 | static IFK Under[36] = { | ||||||||
576 | IFK::DivEqual, // ?_0 operator/= | ||||||||
577 | IFK::ModEqual, // ?_1 operator%= | ||||||||
578 | IFK::RshEqual, // ?_2 operator>>= | ||||||||
579 | IFK::LshEqual, // ?_3 operator<<= | ||||||||
580 | IFK::BitwiseAndEqual, // ?_4 operator&= | ||||||||
581 | IFK::BitwiseOrEqual, // ?_5 operator|= | ||||||||
582 | IFK::BitwiseXorEqual, // ?_6 operator^= | ||||||||
583 | IFK::None, // ?_7 # vftable | ||||||||
584 | IFK::None, // ?_8 # vbtable | ||||||||
585 | IFK::None, // ?_9 # vcall | ||||||||
586 | IFK::None, // ?_A # typeof | ||||||||
587 | IFK::None, // ?_B # local static guard | ||||||||
588 | IFK::None, // ?_C # string literal | ||||||||
589 | IFK::VbaseDtor, // ?_D # vbase destructor | ||||||||
590 | IFK::VecDelDtor, // ?_E # vector deleting destructor | ||||||||
591 | IFK::DefaultCtorClosure, // ?_F # default constructor closure | ||||||||
592 | IFK::ScalarDelDtor, // ?_G # scalar deleting destructor | ||||||||
593 | IFK::VecCtorIter, // ?_H # vector constructor iterator | ||||||||
594 | IFK::VecDtorIter, // ?_I # vector destructor iterator | ||||||||
595 | IFK::VecVbaseCtorIter, // ?_J # vector vbase constructor iterator | ||||||||
596 | IFK::VdispMap, // ?_K # virtual displacement map | ||||||||
597 | IFK::EHVecCtorIter, // ?_L # eh vector constructor iterator | ||||||||
598 | IFK::EHVecDtorIter, // ?_M # eh vector destructor iterator | ||||||||
599 | IFK::EHVecVbaseCtorIter, // ?_N # eh vector vbase constructor iterator | ||||||||
600 | IFK::CopyCtorClosure, // ?_O # copy constructor closure | ||||||||
601 | IFK::None, // ?_P<name> # udt returning <name> | ||||||||
602 | IFK::None, // ?_Q # <unknown> | ||||||||
603 | IFK::None, // ?_R0 - ?_R4 # RTTI Codes | ||||||||
604 | IFK::None, // ?_S # local vftable | ||||||||
605 | IFK::LocalVftableCtorClosure, // ?_T # local vftable constructor closure | ||||||||
606 | IFK::ArrayNew, // ?_U operator new[] | ||||||||
607 | IFK::ArrayDelete, // ?_V operator delete[] | ||||||||
608 | IFK::None, // ?_W <unused> | ||||||||
609 | IFK::None, // ?_X <unused> | ||||||||
610 | IFK::None, // ?_Y <unused> | ||||||||
611 | IFK::None, // ?_Z <unused> | ||||||||
612 | }; | ||||||||
613 | static IFK DoubleUnder[36] = { | ||||||||
614 | IFK::None, // ?__0 <unused> | ||||||||
615 | IFK::None, // ?__1 <unused> | ||||||||
616 | IFK::None, // ?__2 <unused> | ||||||||
617 | IFK::None, // ?__3 <unused> | ||||||||
618 | IFK::None, // ?__4 <unused> | ||||||||
619 | IFK::None, // ?__5 <unused> | ||||||||
620 | IFK::None, // ?__6 <unused> | ||||||||
621 | IFK::None, // ?__7 <unused> | ||||||||
622 | IFK::None, // ?__8 <unused> | ||||||||
623 | IFK::None, // ?__9 <unused> | ||||||||
624 | IFK::ManVectorCtorIter, // ?__A managed vector ctor iterator | ||||||||
625 | IFK::ManVectorDtorIter, // ?__B managed vector dtor iterator | ||||||||
626 | IFK::EHVectorCopyCtorIter, // ?__C EH vector copy ctor iterator | ||||||||
627 | IFK::EHVectorVbaseCopyCtorIter, // ?__D EH vector vbase copy ctor iter | ||||||||
628 | IFK::None, // ?__E dynamic initializer for `T' | ||||||||
629 | IFK::None, // ?__F dynamic atexit destructor for `T' | ||||||||
630 | IFK::VectorCopyCtorIter, // ?__G vector copy constructor iter | ||||||||
631 | IFK::VectorVbaseCopyCtorIter, // ?__H vector vbase copy ctor iter | ||||||||
632 | IFK::ManVectorVbaseCopyCtorIter, // ?__I managed vector vbase copy ctor | ||||||||
633 | // iter | ||||||||
634 | IFK::None, // ?__J local static thread guard | ||||||||
635 | IFK::None, // ?__K operator ""_name | ||||||||
636 | IFK::CoAwait, // ?__L operator co_await | ||||||||
637 | IFK::Spaceship, // ?__M operator<=> | ||||||||
638 | IFK::None, // ?__N <unused> | ||||||||
639 | IFK::None, // ?__O <unused> | ||||||||
640 | IFK::None, // ?__P <unused> | ||||||||
641 | IFK::None, // ?__Q <unused> | ||||||||
642 | IFK::None, // ?__R <unused> | ||||||||
643 | IFK::None, // ?__S <unused> | ||||||||
644 | IFK::None, // ?__T <unused> | ||||||||
645 | IFK::None, // ?__U <unused> | ||||||||
646 | IFK::None, // ?__V <unused> | ||||||||
647 | IFK::None, // ?__W <unused> | ||||||||
648 | IFK::None, // ?__X <unused> | ||||||||
649 | IFK::None, // ?__Y <unused> | ||||||||
650 | IFK::None, // ?__Z <unused> | ||||||||
651 | }; | ||||||||
652 | |||||||||
653 | int Index = (CH >= '0' && CH <= '9') ? (CH - '0') : (CH - 'A' + 10); | ||||||||
654 | switch (Group) { | ||||||||
655 | case FunctionIdentifierCodeGroup::Basic: | ||||||||
656 | return Basic[Index]; | ||||||||
657 | case FunctionIdentifierCodeGroup::Under: | ||||||||
658 | return Under[Index]; | ||||||||
659 | case FunctionIdentifierCodeGroup::DoubleUnder: | ||||||||
660 | return DoubleUnder[Index]; | ||||||||
661 | } | ||||||||
662 | DEMANGLE_UNREACHABLE__builtin_unreachable(); | ||||||||
663 | } | ||||||||
664 | |||||||||
665 | IdentifierNode * | ||||||||
666 | Demangler::demangleFunctionIdentifierCode(StringView &MangledName, | ||||||||
667 | FunctionIdentifierCodeGroup Group) { | ||||||||
668 | if (MangledName.empty()) { | ||||||||
669 | Error = true; | ||||||||
670 | return nullptr; | ||||||||
671 | } | ||||||||
672 | switch (Group) { | ||||||||
673 | case FunctionIdentifierCodeGroup::Basic: | ||||||||
674 | switch (char CH = MangledName.popFront()) { | ||||||||
675 | case '0': | ||||||||
676 | case '1': | ||||||||
677 | return demangleStructorIdentifier(MangledName, CH == '1'); | ||||||||
678 | case 'B': | ||||||||
679 | return demangleConversionOperatorIdentifier(MangledName); | ||||||||
680 | default: | ||||||||
681 | return Arena.alloc<IntrinsicFunctionIdentifierNode>( | ||||||||
682 | translateIntrinsicFunctionCode(CH, Group)); | ||||||||
683 | } | ||||||||
684 | case FunctionIdentifierCodeGroup::Under: | ||||||||
685 | return Arena.alloc<IntrinsicFunctionIdentifierNode>( | ||||||||
686 | translateIntrinsicFunctionCode(MangledName.popFront(), Group)); | ||||||||
687 | case FunctionIdentifierCodeGroup::DoubleUnder: | ||||||||
688 | switch (char CH = MangledName.popFront()) { | ||||||||
689 | case 'K': | ||||||||
690 | return demangleLiteralOperatorIdentifier(MangledName); | ||||||||
691 | default: | ||||||||
692 | return Arena.alloc<IntrinsicFunctionIdentifierNode>( | ||||||||
693 | translateIntrinsicFunctionCode(CH, Group)); | ||||||||
694 | } | ||||||||
695 | } | ||||||||
696 | |||||||||
697 | DEMANGLE_UNREACHABLE__builtin_unreachable(); | ||||||||
698 | } | ||||||||
699 | |||||||||
700 | SymbolNode *Demangler::demangleEncodedSymbol(StringView &MangledName, | ||||||||
701 | QualifiedNameNode *Name) { | ||||||||
702 | if (MangledName.empty()) { | ||||||||
703 | Error = true; | ||||||||
704 | return nullptr; | ||||||||
705 | } | ||||||||
706 | |||||||||
707 | // Read a variable. | ||||||||
708 | switch (MangledName.front()) { | ||||||||
709 | case '0': | ||||||||
710 | case '1': | ||||||||
711 | case '2': | ||||||||
712 | case '3': | ||||||||
713 | case '4': { | ||||||||
714 | StorageClass SC = demangleVariableStorageClass(MangledName); | ||||||||
715 | return demangleVariableEncoding(MangledName, SC); | ||||||||
716 | } | ||||||||
717 | } | ||||||||
718 | FunctionSymbolNode *FSN = demangleFunctionEncoding(MangledName); | ||||||||
719 | |||||||||
720 | IdentifierNode *UQN = Name->getUnqualifiedIdentifier(); | ||||||||
721 | if (UQN->kind() == NodeKind::ConversionOperatorIdentifier) { | ||||||||
722 | ConversionOperatorIdentifierNode *COIN = | ||||||||
723 | static_cast<ConversionOperatorIdentifierNode *>(UQN); | ||||||||
724 | if (FSN) | ||||||||
725 | COIN->TargetType = FSN->Signature->ReturnType; | ||||||||
726 | } | ||||||||
727 | return FSN; | ||||||||
728 | } | ||||||||
729 | |||||||||
730 | SymbolNode *Demangler::demangleDeclarator(StringView &MangledName) { | ||||||||
731 | // What follows is a main symbol name. This may include namespaces or class | ||||||||
732 | // back references. | ||||||||
733 | QualifiedNameNode *QN = demangleFullyQualifiedSymbolName(MangledName); | ||||||||
734 | if (Error) | ||||||||
735 | return nullptr; | ||||||||
736 | |||||||||
737 | SymbolNode *Symbol = demangleEncodedSymbol(MangledName, QN); | ||||||||
738 | if (Error) | ||||||||
739 | return nullptr; | ||||||||
740 | Symbol->Name = QN; | ||||||||
741 | |||||||||
742 | IdentifierNode *UQN = QN->getUnqualifiedIdentifier(); | ||||||||
743 | if (UQN->kind() == NodeKind::ConversionOperatorIdentifier) { | ||||||||
744 | ConversionOperatorIdentifierNode *COIN = | ||||||||
745 | static_cast<ConversionOperatorIdentifierNode *>(UQN); | ||||||||
746 | if (!COIN->TargetType) { | ||||||||
747 | Error = true; | ||||||||
748 | return nullptr; | ||||||||
749 | } | ||||||||
750 | } | ||||||||
751 | return Symbol; | ||||||||
752 | } | ||||||||
753 | |||||||||
754 | SymbolNode *Demangler::demangleMD5Name(StringView &MangledName) { | ||||||||
755 | assert(MangledName.startsWith("??@"))(static_cast <bool> (MangledName.startsWith("??@")) ? void (0) : __assert_fail ("MangledName.startsWith(\"??@\")", "/build/llvm-toolchain-snapshot-13~++20210726100616+dead50d4427c/llvm/lib/Demangle/MicrosoftDemangle.cpp" , 755, __extension__ __PRETTY_FUNCTION__)); | ||||||||
756 | // This is an MD5 mangled name. We can't demangle it, just return the | ||||||||
757 | // mangled name. | ||||||||
758 | // An MD5 mangled name is ??@ followed by 32 characters and a terminating @. | ||||||||
759 | size_t MD5Last = MangledName.find('@', strlen("??@")); | ||||||||
760 | if (MD5Last == StringView::npos) { | ||||||||
761 | Error = true; | ||||||||
762 | return nullptr; | ||||||||
763 | } | ||||||||
764 | const char *Start = MangledName.begin(); | ||||||||
765 | MangledName = MangledName.dropFront(MD5Last + 1); | ||||||||
766 | |||||||||
767 | // There are two additional special cases for MD5 names: | ||||||||
768 | // 1. For complete object locators where the object name is long enough | ||||||||
769 | // for the object to have an MD5 name, the complete object locator is | ||||||||
770 | // called ??@...@??_R4@ (with a trailing "??_R4@" instead of the usual | ||||||||
771 | // leading "??_R4". This is handled here. | ||||||||
772 | // 2. For catchable types, in versions of MSVC before 2015 (<1900) or after | ||||||||
773 | // 2017.2 (>= 1914), the catchable type mangling is _CT??@...@??@...@8 | ||||||||
774 | // instead of_CT??@...@8 with just one MD5 name. Since we don't yet | ||||||||
775 | // demangle catchable types anywhere, this isn't handled for MD5 names | ||||||||
776 | // either. | ||||||||
777 | MangledName.consumeFront("??_R4@"); | ||||||||
778 | |||||||||
779 | StringView MD5(Start, MangledName.begin()); | ||||||||
780 | SymbolNode *S = Arena.alloc<SymbolNode>(NodeKind::Md5Symbol); | ||||||||
781 | S->Name = synthesizeQualifiedName(Arena, MD5); | ||||||||
782 | |||||||||
783 | return S; | ||||||||
784 | } | ||||||||
785 | |||||||||
786 | SymbolNode *Demangler::demangleTypeinfoName(StringView &MangledName) { | ||||||||
787 | assert(MangledName.startsWith('.'))(static_cast <bool> (MangledName.startsWith('.')) ? void (0) : __assert_fail ("MangledName.startsWith('.')", "/build/llvm-toolchain-snapshot-13~++20210726100616+dead50d4427c/llvm/lib/Demangle/MicrosoftDemangle.cpp" , 787, __extension__ __PRETTY_FUNCTION__)); | ||||||||
788 | MangledName.consumeFront('.'); | ||||||||
789 | |||||||||
790 | TypeNode *T = demangleType(MangledName, QualifierMangleMode::Result); | ||||||||
791 | if (Error || !MangledName.empty()) { | ||||||||
792 | Error = true; | ||||||||
793 | return nullptr; | ||||||||
794 | } | ||||||||
795 | return synthesizeVariable(Arena, T, "`RTTI Type Descriptor Name'"); | ||||||||
796 | } | ||||||||
797 | |||||||||
798 | // Parser entry point. | ||||||||
799 | SymbolNode *Demangler::parse(StringView &MangledName) { | ||||||||
800 | // Typeinfo names are strings stored in RTTI data. They're not symbol names. | ||||||||
801 | // It's still useful to demangle them. They're the only demangled entity | ||||||||
802 | // that doesn't start with a "?" but a ".". | ||||||||
803 | if (MangledName.startsWith('.')) | ||||||||
804 | return demangleTypeinfoName(MangledName); | ||||||||
805 | |||||||||
806 | if (MangledName.startsWith("??@")) | ||||||||
807 | return demangleMD5Name(MangledName); | ||||||||
808 | |||||||||
809 | // MSVC-style mangled symbols must start with '?'. | ||||||||
810 | if (!MangledName.startsWith('?')) { | ||||||||
811 | Error = true; | ||||||||
812 | return nullptr; | ||||||||
813 | } | ||||||||
814 | |||||||||
815 | MangledName.consumeFront('?'); | ||||||||
816 | |||||||||
817 | // ?$ is a template instantiation, but all other names that start with ? are | ||||||||
818 | // operators / special names. | ||||||||
819 | if (SymbolNode *SI = demangleSpecialIntrinsic(MangledName)) | ||||||||
820 | return SI; | ||||||||
821 | |||||||||
822 | return demangleDeclarator(MangledName); | ||||||||
823 | } | ||||||||
824 | |||||||||
825 | TagTypeNode *Demangler::parseTagUniqueName(StringView &MangledName) { | ||||||||
826 | if (!MangledName.consumeFront(".?A")) | ||||||||
827 | return nullptr; | ||||||||
828 | MangledName.consumeFront(".?A"); | ||||||||
829 | if (MangledName.empty()) | ||||||||
830 | return nullptr; | ||||||||
831 | |||||||||
832 | return demangleClassType(MangledName); | ||||||||
833 | } | ||||||||
834 | |||||||||
835 | // <type-encoding> ::= <storage-class> <variable-type> | ||||||||
836 | // <storage-class> ::= 0 # private static member | ||||||||
837 | // ::= 1 # protected static member | ||||||||
838 | // ::= 2 # public static member | ||||||||
839 | // ::= 3 # global | ||||||||
840 | // ::= 4 # static local | ||||||||
841 | |||||||||
842 | VariableSymbolNode *Demangler::demangleVariableEncoding(StringView &MangledName, | ||||||||
843 | StorageClass SC) { | ||||||||
844 | VariableSymbolNode *VSN = Arena.alloc<VariableSymbolNode>(); | ||||||||
845 | |||||||||
846 | VSN->Type = demangleType(MangledName, QualifierMangleMode::Drop); | ||||||||
847 | VSN->SC = SC; | ||||||||
848 | |||||||||
849 | if (Error) | ||||||||
850 | return nullptr; | ||||||||
851 | |||||||||
852 | // <variable-type> ::= <type> <cvr-qualifiers> | ||||||||
853 | // ::= <type> <pointee-cvr-qualifiers> # pointers, references | ||||||||
854 | switch (VSN->Type->kind()) { | ||||||||
855 | case NodeKind::PointerType: { | ||||||||
856 | PointerTypeNode *PTN = static_cast<PointerTypeNode *>(VSN->Type); | ||||||||
857 | |||||||||
858 | Qualifiers ExtraChildQuals = Q_None; | ||||||||
859 | PTN->Quals = Qualifiers(VSN->Type->Quals | | ||||||||
860 | demanglePointerExtQualifiers(MangledName)); | ||||||||
861 | |||||||||
862 | bool IsMember = false; | ||||||||
863 | std::tie(ExtraChildQuals, IsMember) = demangleQualifiers(MangledName); | ||||||||
864 | |||||||||
865 | if (PTN->ClassParent) { | ||||||||
866 | QualifiedNameNode *BackRefName = | ||||||||
867 | demangleFullyQualifiedTypeName(MangledName); | ||||||||
868 | (void)BackRefName; | ||||||||
869 | } | ||||||||
870 | PTN->Pointee->Quals = Qualifiers(PTN->Pointee->Quals | ExtraChildQuals); | ||||||||
871 | |||||||||
872 | break; | ||||||||
873 | } | ||||||||
874 | default: | ||||||||
875 | VSN->Type->Quals = demangleQualifiers(MangledName).first; | ||||||||
876 | break; | ||||||||
877 | } | ||||||||
878 | |||||||||
879 | return VSN; | ||||||||
880 | } | ||||||||
881 | |||||||||
882 | // Sometimes numbers are encoded in mangled symbols. For example, | ||||||||
883 | // "int (*x)[20]" is a valid C type (x is a pointer to an array of | ||||||||
884 | // length 20), so we need some way to embed numbers as part of symbols. | ||||||||
885 | // This function parses it. | ||||||||
886 | // | ||||||||
887 | // <number> ::= [?] <non-negative integer> | ||||||||
888 | // | ||||||||
889 | // <non-negative integer> ::= <decimal digit> # when 1 <= Number <= 10 | ||||||||
890 | // ::= <hex digit>+ @ # when Number == 0 or >= 10 | ||||||||
891 | // | ||||||||
892 | // <hex-digit> ::= [A-P] # A = 0, B = 1, ... | ||||||||
893 | std::pair<uint64_t, bool> Demangler::demangleNumber(StringView &MangledName) { | ||||||||
894 | bool IsNegative = MangledName.consumeFront('?'); | ||||||||
895 | |||||||||
896 | if (startsWithDigit(MangledName)) { | ||||||||
897 | uint64_t Ret = MangledName[0] - '0' + 1; | ||||||||
898 | MangledName = MangledName.dropFront(1); | ||||||||
899 | return {Ret, IsNegative}; | ||||||||
900 | } | ||||||||
901 | |||||||||
902 | uint64_t Ret = 0; | ||||||||
903 | for (size_t i = 0; i < MangledName.size(); ++i) { | ||||||||
904 | char C = MangledName[i]; | ||||||||
905 | if (C == '@') { | ||||||||
906 | MangledName = MangledName.dropFront(i + 1); | ||||||||
907 | return {Ret, IsNegative}; | ||||||||
908 | } | ||||||||
909 | if ('A' <= C && C <= 'P') { | ||||||||
910 | Ret = (Ret << 4) + (C - 'A'); | ||||||||
911 | continue; | ||||||||
912 | } | ||||||||
913 | break; | ||||||||
914 | } | ||||||||
915 | |||||||||
916 | Error = true; | ||||||||
917 | return {0ULL, false}; | ||||||||
918 | } | ||||||||
919 | |||||||||
920 | uint64_t Demangler::demangleUnsigned(StringView &MangledName) { | ||||||||
921 | bool IsNegative = false; | ||||||||
922 | uint64_t Number = 0; | ||||||||
923 | std::tie(Number, IsNegative) = demangleNumber(MangledName); | ||||||||
924 | if (IsNegative) | ||||||||
925 | Error = true; | ||||||||
926 | return Number; | ||||||||
927 | } | ||||||||
928 | |||||||||
929 | int64_t Demangler::demangleSigned(StringView &MangledName) { | ||||||||
930 | bool IsNegative = false; | ||||||||
931 | uint64_t Number = 0; | ||||||||
932 | std::tie(Number, IsNegative) = demangleNumber(MangledName); | ||||||||
933 | if (Number > INT64_MAX(9223372036854775807L)) | ||||||||
934 | Error = true; | ||||||||
935 | int64_t I = static_cast<int64_t>(Number); | ||||||||
936 | return IsNegative ? -I : I; | ||||||||
937 | } | ||||||||
938 | |||||||||
939 | // First 10 strings can be referenced by special BackReferences ?0, ?1, ..., ?9. | ||||||||
940 | // Memorize it. | ||||||||
941 | void Demangler::memorizeString(StringView S) { | ||||||||
942 | if (Backrefs.NamesCount >= BackrefContext::Max) | ||||||||
943 | return; | ||||||||
944 | for (size_t i = 0; i < Backrefs.NamesCount; ++i) | ||||||||
945 | if (S == Backrefs.Names[i]->Name) | ||||||||
946 | return; | ||||||||
947 | NamedIdentifierNode *N = Arena.alloc<NamedIdentifierNode>(); | ||||||||
948 | N->Name = S; | ||||||||
949 | Backrefs.Names[Backrefs.NamesCount++] = N; | ||||||||
950 | } | ||||||||
951 | |||||||||
952 | NamedIdentifierNode *Demangler::demangleBackRefName(StringView &MangledName) { | ||||||||
953 | assert(startsWithDigit(MangledName))(static_cast <bool> (startsWithDigit(MangledName)) ? void (0) : __assert_fail ("startsWithDigit(MangledName)", "/build/llvm-toolchain-snapshot-13~++20210726100616+dead50d4427c/llvm/lib/Demangle/MicrosoftDemangle.cpp" , 953, __extension__ __PRETTY_FUNCTION__)); | ||||||||
954 | |||||||||
955 | size_t I = MangledName[0] - '0'; | ||||||||
956 | if (I >= Backrefs.NamesCount) { | ||||||||
957 | Error = true; | ||||||||
958 | return nullptr; | ||||||||
959 | } | ||||||||
960 | |||||||||
961 | MangledName = MangledName.dropFront(); | ||||||||
962 | return Backrefs.Names[I]; | ||||||||
963 | } | ||||||||
964 | |||||||||
965 | void Demangler::memorizeIdentifier(IdentifierNode *Identifier) { | ||||||||
966 | // Render this class template name into a string buffer so that we can | ||||||||
967 | // memorize it for the purpose of back-referencing. | ||||||||
968 | OutputStream OS; | ||||||||
969 | if (!initializeOutputStream(nullptr, nullptr, OS, 1024)) | ||||||||
970 | // FIXME: Propagate out-of-memory as an error? | ||||||||
971 | std::terminate(); | ||||||||
972 | Identifier->output(OS, OF_Default); | ||||||||
973 | OS << '\0'; | ||||||||
974 | char *Name = OS.getBuffer(); | ||||||||
975 | |||||||||
976 | StringView Owned = copyString(Name); | ||||||||
977 | memorizeString(Owned); | ||||||||
978 | std::free(Name); | ||||||||
979 | } | ||||||||
980 | |||||||||
981 | IdentifierNode * | ||||||||
982 | Demangler::demangleTemplateInstantiationName(StringView &MangledName, | ||||||||
983 | NameBackrefBehavior NBB) { | ||||||||
984 | assert(MangledName.startsWith("?$"))(static_cast <bool> (MangledName.startsWith("?$")) ? void (0) : __assert_fail ("MangledName.startsWith(\"?$\")", "/build/llvm-toolchain-snapshot-13~++20210726100616+dead50d4427c/llvm/lib/Demangle/MicrosoftDemangle.cpp" , 984, __extension__ __PRETTY_FUNCTION__)); | ||||||||
985 | MangledName.consumeFront("?$"); | ||||||||
986 | |||||||||
987 | BackrefContext OuterContext; | ||||||||
988 | std::swap(OuterContext, Backrefs); | ||||||||
989 | |||||||||
990 | IdentifierNode *Identifier = | ||||||||
991 | demangleUnqualifiedSymbolName(MangledName, NBB_Simple); | ||||||||
992 | if (!Error) | ||||||||
993 | Identifier->TemplateParams = demangleTemplateParameterList(MangledName); | ||||||||
994 | |||||||||
995 | std::swap(OuterContext, Backrefs); | ||||||||
996 | if (Error) | ||||||||
997 | return nullptr; | ||||||||
998 | |||||||||
999 | if (NBB & NBB_Template) { | ||||||||
1000 | // NBB_Template is only set for types and non-leaf names ("a::" in "a::b"). | ||||||||
1001 | // Structors and conversion operators only makes sense in a leaf name, so | ||||||||
1002 | // reject them in NBB_Template contexts. | ||||||||
1003 | if (Identifier->kind() == NodeKind::ConversionOperatorIdentifier || | ||||||||
1004 | Identifier->kind() == NodeKind::StructorIdentifier) { | ||||||||
1005 | Error = true; | ||||||||
1006 | return nullptr; | ||||||||
1007 | } | ||||||||
1008 | |||||||||
1009 | memorizeIdentifier(Identifier); | ||||||||
1010 | } | ||||||||
1011 | |||||||||
1012 | return Identifier; | ||||||||
1013 | } | ||||||||
1014 | |||||||||
1015 | NamedIdentifierNode *Demangler::demangleSimpleName(StringView &MangledName, | ||||||||
1016 | bool Memorize) { | ||||||||
1017 | StringView S = demangleSimpleString(MangledName, Memorize); | ||||||||
1018 | if (Error) | ||||||||
1019 | return nullptr; | ||||||||
1020 | |||||||||
1021 | NamedIdentifierNode *Name = Arena.alloc<NamedIdentifierNode>(); | ||||||||
1022 | Name->Name = S; | ||||||||
1023 | return Name; | ||||||||
1024 | } | ||||||||
1025 | |||||||||
1026 | static bool isRebasedHexDigit(char C) { return (C >= 'A' && C <= 'P'); } | ||||||||
1027 | |||||||||
1028 | static uint8_t rebasedHexDigitToNumber(char C) { | ||||||||
1029 | assert(isRebasedHexDigit(C))(static_cast <bool> (isRebasedHexDigit(C)) ? void (0) : __assert_fail ("isRebasedHexDigit(C)", "/build/llvm-toolchain-snapshot-13~++20210726100616+dead50d4427c/llvm/lib/Demangle/MicrosoftDemangle.cpp" , 1029, __extension__ __PRETTY_FUNCTION__)); | ||||||||
1030 | return (C <= 'J') ? (C - 'A') : (10 + C - 'K'); | ||||||||
1031 | } | ||||||||
1032 | |||||||||
1033 | uint8_t Demangler::demangleCharLiteral(StringView &MangledName) { | ||||||||
1034 | assert(!MangledName.empty())(static_cast <bool> (!MangledName.empty()) ? void (0) : __assert_fail ("!MangledName.empty()", "/build/llvm-toolchain-snapshot-13~++20210726100616+dead50d4427c/llvm/lib/Demangle/MicrosoftDemangle.cpp" , 1034, __extension__ __PRETTY_FUNCTION__)); | ||||||||
1035 | if (!MangledName.startsWith('?')) | ||||||||
1036 | return MangledName.popFront(); | ||||||||
1037 | |||||||||
1038 | MangledName = MangledName.dropFront(); | ||||||||
1039 | if (MangledName.empty()) | ||||||||
1040 | goto CharLiteralError; | ||||||||
1041 | |||||||||
1042 | if (MangledName.consumeFront('$')) { | ||||||||
1043 | // Two hex digits | ||||||||
1044 | if (MangledName.size() < 2) | ||||||||
1045 | goto CharLiteralError; | ||||||||
1046 | StringView Nibbles = MangledName.substr(0, 2); | ||||||||
1047 | if (!isRebasedHexDigit(Nibbles[0]) || !isRebasedHexDigit(Nibbles[1])) | ||||||||
1048 | goto CharLiteralError; | ||||||||
1049 | // Don't append the null terminator. | ||||||||
1050 | uint8_t C1 = rebasedHexDigitToNumber(Nibbles[0]); | ||||||||
1051 | uint8_t C2 = rebasedHexDigitToNumber(Nibbles[1]); | ||||||||
1052 | MangledName = MangledName.dropFront(2); | ||||||||
1053 | return (C1 << 4) | C2; | ||||||||
1054 | } | ||||||||
1055 | |||||||||
1056 | if (startsWithDigit(MangledName)) { | ||||||||
1057 | const char *Lookup = ",/\\:. \n\t'-"; | ||||||||
1058 | char C = Lookup[MangledName[0] - '0']; | ||||||||
1059 | MangledName = MangledName.dropFront(); | ||||||||
1060 | return C; | ||||||||
1061 | } | ||||||||
1062 | |||||||||
1063 | if (MangledName[0] >= 'a' && MangledName[0] <= 'z') { | ||||||||
1064 | char Lookup[26] = {'\xE1', '\xE2', '\xE3', '\xE4', '\xE5', '\xE6', '\xE7', | ||||||||
1065 | '\xE8', '\xE9', '\xEA', '\xEB', '\xEC', '\xED', '\xEE', | ||||||||
1066 | '\xEF', '\xF0', '\xF1', '\xF2', '\xF3', '\xF4', '\xF5', | ||||||||
1067 | '\xF6', '\xF7', '\xF8', '\xF9', '\xFA'}; | ||||||||
1068 | char C = Lookup[MangledName[0] - 'a']; | ||||||||
1069 | MangledName = MangledName.dropFront(); | ||||||||
1070 | return C; | ||||||||
1071 | } | ||||||||
1072 | |||||||||
1073 | if (MangledName[0] >= 'A' && MangledName[0] <= 'Z') { | ||||||||
1074 | char Lookup[26] = {'\xC1', '\xC2', '\xC3', '\xC4', '\xC5', '\xC6', '\xC7', | ||||||||
1075 | '\xC8', '\xC9', '\xCA', '\xCB', '\xCC', '\xCD', '\xCE', | ||||||||
1076 | '\xCF', '\xD0', '\xD1', '\xD2', '\xD3', '\xD4', '\xD5', | ||||||||
1077 | '\xD6', '\xD7', '\xD8', '\xD9', '\xDA'}; | ||||||||
1078 | char C = Lookup[MangledName[0] - 'A']; | ||||||||
1079 | MangledName = MangledName.dropFront(); | ||||||||
1080 | return C; | ||||||||
1081 | } | ||||||||
1082 | |||||||||
1083 | CharLiteralError: | ||||||||
1084 | Error = true; | ||||||||
1085 | return '\0'; | ||||||||
1086 | } | ||||||||
1087 | |||||||||
1088 | wchar_t Demangler::demangleWcharLiteral(StringView &MangledName) { | ||||||||
1089 | uint8_t C1, C2; | ||||||||
1090 | |||||||||
1091 | C1 = demangleCharLiteral(MangledName); | ||||||||
1092 | if (Error || MangledName.empty()) | ||||||||
1093 | goto WCharLiteralError; | ||||||||
1094 | C2 = demangleCharLiteral(MangledName); | ||||||||
1095 | if (Error) | ||||||||
1096 | goto WCharLiteralError; | ||||||||
1097 | |||||||||
1098 | return ((wchar_t)C1 << 8) | (wchar_t)C2; | ||||||||
1099 | |||||||||
1100 | WCharLiteralError: | ||||||||
1101 | Error = true; | ||||||||
1102 | return L'\0'; | ||||||||
1103 | } | ||||||||
1104 | |||||||||
1105 | static void writeHexDigit(char *Buffer, uint8_t Digit) { | ||||||||
1106 | assert(Digit <= 15)(static_cast <bool> (Digit <= 15) ? void (0) : __assert_fail ("Digit <= 15", "/build/llvm-toolchain-snapshot-13~++20210726100616+dead50d4427c/llvm/lib/Demangle/MicrosoftDemangle.cpp" , 1106, __extension__ __PRETTY_FUNCTION__)); | ||||||||
1107 | *Buffer = (Digit < 10) ? ('0' + Digit) : ('A' + Digit - 10); | ||||||||
1108 | } | ||||||||
1109 | |||||||||
1110 | static void outputHex(OutputStream &OS, unsigned C) { | ||||||||
1111 | assert (C != 0)(static_cast <bool> (C != 0) ? void (0) : __assert_fail ("C != 0", "/build/llvm-toolchain-snapshot-13~++20210726100616+dead50d4427c/llvm/lib/Demangle/MicrosoftDemangle.cpp" , 1111, __extension__ __PRETTY_FUNCTION__)); | ||||||||
1112 | |||||||||
1113 | // It's easier to do the math if we can work from right to left, but we need | ||||||||
1114 | // to print the numbers from left to right. So render this into a temporary | ||||||||
1115 | // buffer first, then output the temporary buffer. Each byte is of the form | ||||||||
1116 | // \xAB, which means that each byte needs 4 characters. Since there are at | ||||||||
1117 | // most 4 bytes, we need a 4*4+1 = 17 character temporary buffer. | ||||||||
1118 | char TempBuffer[17]; | ||||||||
1119 | |||||||||
1120 | ::memset(TempBuffer, 0, sizeof(TempBuffer)); | ||||||||
1121 | constexpr int MaxPos = sizeof(TempBuffer) - 1; | ||||||||
1122 | |||||||||
1123 | int Pos = MaxPos - 1; // TempBuffer[MaxPos] is the terminating \0. | ||||||||
1124 | while (C != 0) { | ||||||||
1125 | for (int I = 0; I < 2; ++I) { | ||||||||
1126 | writeHexDigit(&TempBuffer[Pos--], C % 16); | ||||||||
1127 | C /= 16; | ||||||||
1128 | } | ||||||||
1129 | } | ||||||||
1130 | TempBuffer[Pos--] = 'x'; | ||||||||
1131 | assert(Pos >= 0)(static_cast <bool> (Pos >= 0) ? void (0) : __assert_fail ("Pos >= 0", "/build/llvm-toolchain-snapshot-13~++20210726100616+dead50d4427c/llvm/lib/Demangle/MicrosoftDemangle.cpp" , 1131, __extension__ __PRETTY_FUNCTION__)); | ||||||||
1132 | TempBuffer[Pos--] = '\\'; | ||||||||
1133 | OS << StringView(&TempBuffer[Pos + 1]); | ||||||||
1134 | } | ||||||||
1135 | |||||||||
1136 | static void outputEscapedChar(OutputStream &OS, unsigned C) { | ||||||||
1137 | switch (C) { | ||||||||
1138 | case '\0': // nul | ||||||||
1139 | OS << "\\0"; | ||||||||
1140 | return; | ||||||||
1141 | case '\'': // single quote | ||||||||
1142 | OS << "\\\'"; | ||||||||
1143 | return; | ||||||||
1144 | case '\"': // double quote | ||||||||
1145 | OS << "\\\""; | ||||||||
1146 | return; | ||||||||
1147 | case '\\': // backslash | ||||||||
1148 | OS << "\\\\"; | ||||||||
1149 | return; | ||||||||
1150 | case '\a': // bell | ||||||||
1151 | OS << "\\a"; | ||||||||
1152 | return; | ||||||||
1153 | case '\b': // backspace | ||||||||
1154 | OS << "\\b"; | ||||||||
1155 | return; | ||||||||
1156 | case '\f': // form feed | ||||||||
1157 | OS << "\\f"; | ||||||||
1158 | return; | ||||||||
1159 | case '\n': // new line | ||||||||
1160 | OS << "\\n"; | ||||||||
1161 | return; | ||||||||
1162 | case '\r': // carriage return | ||||||||
1163 | OS << "\\r"; | ||||||||
1164 | return; | ||||||||
1165 | case '\t': // tab | ||||||||
1166 | OS << "\\t"; | ||||||||
1167 | return; | ||||||||
1168 | case '\v': // vertical tab | ||||||||
1169 | OS << "\\v"; | ||||||||
1170 | return; | ||||||||
1171 | default: | ||||||||
1172 | break; | ||||||||
1173 | } | ||||||||
1174 | |||||||||
1175 | if (C > 0x1F && C < 0x7F) { | ||||||||
1176 | // Standard ascii char. | ||||||||
1177 | OS << (char)C; | ||||||||
1178 | return; | ||||||||
1179 | } | ||||||||
1180 | |||||||||
1181 | outputHex(OS, C); | ||||||||
1182 | } | ||||||||
1183 | |||||||||
1184 | static unsigned countTrailingNullBytes(const uint8_t *StringBytes, int Length) { | ||||||||
1185 | const uint8_t *End = StringBytes + Length - 1; | ||||||||
1186 | unsigned Count = 0; | ||||||||
1187 | while (Length > 0 && *End == 0) { | ||||||||
1188 | --Length; | ||||||||
1189 | --End; | ||||||||
1190 | ++Count; | ||||||||
1191 | } | ||||||||
1192 | return Count; | ||||||||
1193 | } | ||||||||
1194 | |||||||||
1195 | static unsigned countEmbeddedNulls(const uint8_t *StringBytes, | ||||||||
1196 | unsigned Length) { | ||||||||
1197 | unsigned Result = 0; | ||||||||
1198 | for (unsigned I = 0; I < Length; ++I) { | ||||||||
1199 | if (*StringBytes++ == 0) | ||||||||
1200 | ++Result; | ||||||||
1201 | } | ||||||||
1202 | return Result; | ||||||||
1203 | } | ||||||||
1204 | |||||||||
1205 | // A mangled (non-wide) string literal stores the total length of the string it | ||||||||
1206 | // refers to (passed in NumBytes), and it contains up to 32 bytes of actual text | ||||||||
1207 | // (passed in StringBytes, NumChars). | ||||||||
1208 | static unsigned guessCharByteSize(const uint8_t *StringBytes, unsigned NumChars, | ||||||||
1209 | uint64_t NumBytes) { | ||||||||
1210 | assert(NumBytes > 0)(static_cast <bool> (NumBytes > 0) ? void (0) : __assert_fail ("NumBytes > 0", "/build/llvm-toolchain-snapshot-13~++20210726100616+dead50d4427c/llvm/lib/Demangle/MicrosoftDemangle.cpp" , 1210, __extension__ __PRETTY_FUNCTION__)); | ||||||||
1211 | |||||||||
1212 | // If the number of bytes is odd, this is guaranteed to be a char string. | ||||||||
1213 | if (NumBytes % 2 == 1) | ||||||||
1214 | return 1; | ||||||||
1215 | |||||||||
1216 | // All strings can encode at most 32 bytes of data. If it's less than that, | ||||||||
1217 | // then we encoded the entire string. In this case we check for a 1-byte, | ||||||||
1218 | // 2-byte, or 4-byte null terminator. | ||||||||
1219 | if (NumBytes < 32) { | ||||||||
1220 | unsigned TrailingNulls = countTrailingNullBytes(StringBytes, NumChars); | ||||||||
1221 | if (TrailingNulls >= 4 && NumBytes % 4 == 0) | ||||||||
1222 | return 4; | ||||||||
1223 | if (TrailingNulls >= 2) | ||||||||
1224 | return 2; | ||||||||
1225 | return 1; | ||||||||
1226 | } | ||||||||
1227 | |||||||||
1228 | // The whole string was not able to be encoded. Try to look at embedded null | ||||||||
1229 | // terminators to guess. The heuristic is that we count all embedded null | ||||||||
1230 | // terminators. If more than 2/3 are null, it's a char32. If more than 1/3 | ||||||||
1231 | // are null, it's a char16. Otherwise it's a char8. This obviously isn't | ||||||||
1232 | // perfect and is biased towards languages that have ascii alphabets, but this | ||||||||
1233 | // was always going to be best effort since the encoding is lossy. | ||||||||
1234 | unsigned Nulls = countEmbeddedNulls(StringBytes, NumChars); | ||||||||
1235 | if (Nulls >= 2 * NumChars / 3 && NumBytes % 4 == 0) | ||||||||
1236 | return 4; | ||||||||
1237 | if (Nulls >= NumChars / 3) | ||||||||
1238 | return 2; | ||||||||
1239 | return 1; | ||||||||
1240 | } | ||||||||
1241 | |||||||||
1242 | static unsigned decodeMultiByteChar(const uint8_t *StringBytes, | ||||||||
1243 | unsigned CharIndex, unsigned CharBytes) { | ||||||||
1244 | assert(CharBytes == 1 || CharBytes == 2 || CharBytes == 4)(static_cast <bool> (CharBytes == 1 || CharBytes == 2 || CharBytes == 4) ? void (0) : __assert_fail ("CharBytes == 1 || CharBytes == 2 || CharBytes == 4" , "/build/llvm-toolchain-snapshot-13~++20210726100616+dead50d4427c/llvm/lib/Demangle/MicrosoftDemangle.cpp" , 1244, __extension__ __PRETTY_FUNCTION__)); | ||||||||
1245 | unsigned Offset = CharIndex * CharBytes; | ||||||||
1246 | unsigned Result = 0; | ||||||||
1247 | StringBytes = StringBytes + Offset; | ||||||||
1248 | for (unsigned I = 0; I < CharBytes; ++I) { | ||||||||
1249 | unsigned C = static_cast<unsigned>(StringBytes[I]); | ||||||||
1250 | Result |= C << (8 * I); | ||||||||
1251 | } | ||||||||
1252 | return Result; | ||||||||
1253 | } | ||||||||
1254 | |||||||||
1255 | FunctionSymbolNode *Demangler::demangleVcallThunkNode(StringView &MangledName) { | ||||||||
1256 | FunctionSymbolNode *FSN = Arena.alloc<FunctionSymbolNode>(); | ||||||||
1257 | VcallThunkIdentifierNode *VTIN = Arena.alloc<VcallThunkIdentifierNode>(); | ||||||||
1258 | FSN->Signature = Arena.alloc<ThunkSignatureNode>(); | ||||||||
1259 | FSN->Signature->FunctionClass = FC_NoParameterList; | ||||||||
1260 | |||||||||
1261 | FSN->Name = demangleNameScopeChain(MangledName, VTIN); | ||||||||
1262 | if (!Error) | ||||||||
1263 | Error = !MangledName.consumeFront("$B"); | ||||||||
1264 | if (!Error) | ||||||||
1265 | VTIN->OffsetInVTable = demangleUnsigned(MangledName); | ||||||||
1266 | if (!Error) | ||||||||
1267 | Error = !MangledName.consumeFront('A'); | ||||||||
1268 | if (!Error) | ||||||||
1269 | FSN->Signature->CallConvention = demangleCallingConvention(MangledName); | ||||||||
1270 | return (Error) ? nullptr : FSN; | ||||||||
1271 | } | ||||||||
1272 | |||||||||
1273 | EncodedStringLiteralNode * | ||||||||
1274 | Demangler::demangleStringLiteral(StringView &MangledName) { | ||||||||
1275 | // This function uses goto, so declare all variables up front. | ||||||||
1276 | OutputStream OS; | ||||||||
1277 | StringView CRC; | ||||||||
1278 | uint64_t StringByteSize; | ||||||||
1279 | bool IsWcharT = false; | ||||||||
1280 | bool IsNegative = false; | ||||||||
1281 | size_t CrcEndPos = 0; | ||||||||
1282 | char *ResultBuffer = nullptr; | ||||||||
1283 | |||||||||
1284 | EncodedStringLiteralNode *Result = Arena.alloc<EncodedStringLiteralNode>(); | ||||||||
1285 | |||||||||
1286 | // Must happen before the first `goto StringLiteralError`. | ||||||||
1287 | if (!initializeOutputStream(nullptr, nullptr, OS, 1024)) | ||||||||
1288 | // FIXME: Propagate out-of-memory as an error? | ||||||||
1289 | std::terminate(); | ||||||||
1290 | |||||||||
1291 | // Prefix indicating the beginning of a string literal | ||||||||
1292 | if (!MangledName.consumeFront("@_")) | ||||||||
1293 | goto StringLiteralError; | ||||||||
1294 | if (MangledName.empty()) | ||||||||
1295 | goto StringLiteralError; | ||||||||
1296 | |||||||||
1297 | // Char Type (regular or wchar_t) | ||||||||
1298 | switch (MangledName.popFront()) { | ||||||||
1299 | case '1': | ||||||||
1300 | IsWcharT = true; | ||||||||
1301 | DEMANGLE_FALLTHROUGH[[gnu::fallthrough]]; | ||||||||
1302 | case '0': | ||||||||
1303 | break; | ||||||||
1304 | default: | ||||||||
1305 | goto StringLiteralError; | ||||||||
1306 | } | ||||||||
1307 | |||||||||
1308 | // Encoded Length | ||||||||
1309 | std::tie(StringByteSize, IsNegative) = demangleNumber(MangledName); | ||||||||
1310 | if (Error || IsNegative || StringByteSize < (IsWcharT ? 2 : 1)) | ||||||||
1311 | goto StringLiteralError; | ||||||||
1312 | |||||||||
1313 | // CRC 32 (always 8 characters plus a terminator) | ||||||||
1314 | CrcEndPos = MangledName.find('@'); | ||||||||
1315 | if (CrcEndPos == StringView::npos) | ||||||||
1316 | goto StringLiteralError; | ||||||||
1317 | CRC = MangledName.substr(0, CrcEndPos); | ||||||||
1318 | MangledName = MangledName.dropFront(CrcEndPos + 1); | ||||||||
1319 | if (MangledName.empty()) | ||||||||
1320 | goto StringLiteralError; | ||||||||
1321 | |||||||||
1322 | if (IsWcharT) { | ||||||||
1323 | Result->Char = CharKind::Wchar; | ||||||||
1324 | if (StringByteSize > 64) | ||||||||
1325 | Result->IsTruncated = true; | ||||||||
1326 | |||||||||
1327 | while (!MangledName.consumeFront('@')) { | ||||||||
1328 | if (MangledName.size() < 2) | ||||||||
1329 | goto StringLiteralError; | ||||||||
1330 | wchar_t W = demangleWcharLiteral(MangledName); | ||||||||
1331 | if (StringByteSize != 2 || Result->IsTruncated) | ||||||||
1332 | outputEscapedChar(OS, W); | ||||||||
1333 | StringByteSize -= 2; | ||||||||
1334 | if (Error) | ||||||||
1335 | goto StringLiteralError; | ||||||||
1336 | } | ||||||||
1337 | } else { | ||||||||
1338 | // The max byte length is actually 32, but some compilers mangled strings | ||||||||
1339 | // incorrectly, so we have to assume it can go higher. | ||||||||
1340 | constexpr unsigned MaxStringByteLength = 32 * 4; | ||||||||
1341 | uint8_t StringBytes[MaxStringByteLength]; | ||||||||
1342 | |||||||||
1343 | unsigned BytesDecoded = 0; | ||||||||
1344 | while (!MangledName.consumeFront('@')) { | ||||||||
1345 | if (MangledName.size() < 1 || BytesDecoded >= MaxStringByteLength) | ||||||||
1346 | goto StringLiteralError; | ||||||||
1347 | StringBytes[BytesDecoded++] = demangleCharLiteral(MangledName); | ||||||||
1348 | } | ||||||||
1349 | |||||||||
1350 | if (StringByteSize > BytesDecoded) | ||||||||
1351 | Result->IsTruncated = true; | ||||||||
1352 | |||||||||
1353 | unsigned CharBytes = | ||||||||
1354 | guessCharByteSize(StringBytes, BytesDecoded, StringByteSize); | ||||||||
1355 | assert(StringByteSize % CharBytes == 0)(static_cast <bool> (StringByteSize % CharBytes == 0) ? void (0) : __assert_fail ("StringByteSize % CharBytes == 0", "/build/llvm-toolchain-snapshot-13~++20210726100616+dead50d4427c/llvm/lib/Demangle/MicrosoftDemangle.cpp" , 1355, __extension__ __PRETTY_FUNCTION__)); | ||||||||
1356 | switch (CharBytes) { | ||||||||
1357 | case 1: | ||||||||
1358 | Result->Char = CharKind::Char; | ||||||||
1359 | break; | ||||||||
1360 | case 2: | ||||||||
1361 | Result->Char = CharKind::Char16; | ||||||||
1362 | break; | ||||||||
1363 | case 4: | ||||||||
1364 | Result->Char = CharKind::Char32; | ||||||||
1365 | break; | ||||||||
1366 | default: | ||||||||
1367 | DEMANGLE_UNREACHABLE__builtin_unreachable(); | ||||||||
1368 | } | ||||||||
1369 | const unsigned NumChars = BytesDecoded / CharBytes; | ||||||||
1370 | for (unsigned CharIndex = 0; CharIndex < NumChars; ++CharIndex) { | ||||||||
1371 | unsigned NextChar = | ||||||||
1372 | decodeMultiByteChar(StringBytes, CharIndex, CharBytes); | ||||||||
1373 | if (CharIndex + 1 < NumChars || Result->IsTruncated) | ||||||||
1374 | outputEscapedChar(OS, NextChar); | ||||||||
1375 | } | ||||||||
1376 | } | ||||||||
1377 | |||||||||
1378 | OS << '\0'; | ||||||||
1379 | ResultBuffer = OS.getBuffer(); | ||||||||
1380 | Result->DecodedString = copyString(ResultBuffer); | ||||||||
1381 | std::free(ResultBuffer); | ||||||||
1382 | return Result; | ||||||||
1383 | |||||||||
1384 | StringLiteralError: | ||||||||
1385 | Error = true; | ||||||||
1386 | std::free(OS.getBuffer()); | ||||||||
1387 | return nullptr; | ||||||||
1388 | } | ||||||||
1389 | |||||||||
1390 | // Returns MangledName's prefix before the first '@', or an error if | ||||||||
1391 | // MangledName contains no '@' or the prefix has length 0. | ||||||||
1392 | StringView Demangler::demangleSimpleString(StringView &MangledName, | ||||||||
1393 | bool Memorize) { | ||||||||
1394 | StringView S; | ||||||||
1395 | for (size_t i = 0; i < MangledName.size(); ++i) { | ||||||||
1396 | if (MangledName[i] != '@') | ||||||||
1397 | continue; | ||||||||
1398 | if (i == 0) | ||||||||
1399 | break; | ||||||||
1400 | S = MangledName.substr(0, i); | ||||||||
1401 | MangledName = MangledName.dropFront(i + 1); | ||||||||
1402 | |||||||||
1403 | if (Memorize) | ||||||||
1404 | memorizeString(S); | ||||||||
1405 | return S; | ||||||||
1406 | } | ||||||||
1407 | |||||||||
1408 | Error = true; | ||||||||
1409 | return {}; | ||||||||
1410 | } | ||||||||
1411 | |||||||||
1412 | NamedIdentifierNode * | ||||||||
1413 | Demangler::demangleAnonymousNamespaceName(StringView &MangledName) { | ||||||||
1414 | assert(MangledName.startsWith("?A"))(static_cast <bool> (MangledName.startsWith("?A")) ? void (0) : __assert_fail ("MangledName.startsWith(\"?A\")", "/build/llvm-toolchain-snapshot-13~++20210726100616+dead50d4427c/llvm/lib/Demangle/MicrosoftDemangle.cpp" , 1414, __extension__ __PRETTY_FUNCTION__)); | ||||||||
1415 | MangledName.consumeFront("?A"); | ||||||||
1416 | |||||||||
1417 | NamedIdentifierNode *Node = Arena.alloc<NamedIdentifierNode>(); | ||||||||
1418 | Node->Name = "`anonymous namespace'"; | ||||||||
1419 | size_t EndPos = MangledName.find('@'); | ||||||||
1420 | if (EndPos == StringView::npos) { | ||||||||
1421 | Error = true; | ||||||||
1422 | return nullptr; | ||||||||
1423 | } | ||||||||
1424 | StringView NamespaceKey = MangledName.substr(0, EndPos); | ||||||||
1425 | memorizeString(NamespaceKey); | ||||||||
1426 | MangledName = MangledName.substr(EndPos + 1); | ||||||||
1427 | return Node; | ||||||||
1428 | } | ||||||||
1429 | |||||||||
1430 | NamedIdentifierNode * | ||||||||
1431 | Demangler::demangleLocallyScopedNamePiece(StringView &MangledName) { | ||||||||
1432 | assert(startsWithLocalScopePattern(MangledName))(static_cast <bool> (startsWithLocalScopePattern(MangledName )) ? void (0) : __assert_fail ("startsWithLocalScopePattern(MangledName)" , "/build/llvm-toolchain-snapshot-13~++20210726100616+dead50d4427c/llvm/lib/Demangle/MicrosoftDemangle.cpp" , 1432, __extension__ __PRETTY_FUNCTION__)); | ||||||||
1433 | |||||||||
1434 | NamedIdentifierNode *Identifier = Arena.alloc<NamedIdentifierNode>(); | ||||||||
1435 | MangledName.consumeFront('?'); | ||||||||
1436 | uint64_t Number = 0; | ||||||||
1437 | bool IsNegative = false; | ||||||||
1438 | std::tie(Number, IsNegative) = demangleNumber(MangledName); | ||||||||
1439 | assert(!IsNegative)(static_cast <bool> (!IsNegative) ? void (0) : __assert_fail ("!IsNegative", "/build/llvm-toolchain-snapshot-13~++20210726100616+dead50d4427c/llvm/lib/Demangle/MicrosoftDemangle.cpp" , 1439, __extension__ __PRETTY_FUNCTION__)); | ||||||||
1440 | |||||||||
1441 | // One ? to terminate the number | ||||||||
1442 | MangledName.consumeFront('?'); | ||||||||
1443 | |||||||||
1444 | assert(!Error)(static_cast <bool> (!Error) ? void (0) : __assert_fail ("!Error", "/build/llvm-toolchain-snapshot-13~++20210726100616+dead50d4427c/llvm/lib/Demangle/MicrosoftDemangle.cpp" , 1444, __extension__ __PRETTY_FUNCTION__)); | ||||||||
1445 | Node *Scope = parse(MangledName); | ||||||||
1446 | if (Error) | ||||||||
1447 | return nullptr; | ||||||||
1448 | |||||||||
1449 | // Render the parent symbol's name into a buffer. | ||||||||
1450 | OutputStream OS; | ||||||||
1451 | if (!initializeOutputStream(nullptr, nullptr, OS, 1024)) | ||||||||
1452 | // FIXME: Propagate out-of-memory as an error? | ||||||||
1453 | std::terminate(); | ||||||||
1454 | OS << '`'; | ||||||||
1455 | Scope->output(OS, OF_Default); | ||||||||
1456 | OS << '\''; | ||||||||
1457 | OS << "::`" << Number << "'"; | ||||||||
1458 | OS << '\0'; | ||||||||
1459 | char *Result = OS.getBuffer(); | ||||||||
1460 | Identifier->Name = copyString(Result); | ||||||||
1461 | std::free(Result); | ||||||||
1462 | return Identifier; | ||||||||
1463 | } | ||||||||
1464 | |||||||||
1465 | // Parses a type name in the form of A@B@C@@ which represents C::B::A. | ||||||||
1466 | QualifiedNameNode * | ||||||||
1467 | Demangler::demangleFullyQualifiedTypeName(StringView &MangledName) { | ||||||||
1468 | IdentifierNode *Identifier = | ||||||||
1469 | demangleUnqualifiedTypeName(MangledName, /*Memorize=*/true); | ||||||||
1470 | if (Error) | ||||||||
1471 | return nullptr; | ||||||||
1472 | assert(Identifier)(static_cast <bool> (Identifier) ? void (0) : __assert_fail ("Identifier", "/build/llvm-toolchain-snapshot-13~++20210726100616+dead50d4427c/llvm/lib/Demangle/MicrosoftDemangle.cpp" , 1472, __extension__ __PRETTY_FUNCTION__)); | ||||||||
1473 | |||||||||
1474 | QualifiedNameNode *QN = demangleNameScopeChain(MangledName, Identifier); | ||||||||
1475 | if (Error) | ||||||||
1476 | return nullptr; | ||||||||
1477 | assert(QN)(static_cast <bool> (QN) ? void (0) : __assert_fail ("QN" , "/build/llvm-toolchain-snapshot-13~++20210726100616+dead50d4427c/llvm/lib/Demangle/MicrosoftDemangle.cpp" , 1477, __extension__ __PRETTY_FUNCTION__)); | ||||||||
1478 | return QN; | ||||||||
1479 | } | ||||||||
1480 | |||||||||
1481 | // Parses a symbol name in the form of A@B@C@@ which represents C::B::A. | ||||||||
1482 | // Symbol names have slightly different rules regarding what can appear | ||||||||
1483 | // so we separate out the implementations for flexibility. | ||||||||
1484 | QualifiedNameNode * | ||||||||
1485 | Demangler::demangleFullyQualifiedSymbolName(StringView &MangledName) { | ||||||||
1486 | // This is the final component of a symbol name (i.e. the leftmost component | ||||||||
1487 | // of a mangled name. Since the only possible template instantiation that | ||||||||
1488 | // can appear in this context is a function template, and since those are | ||||||||
1489 | // not saved for the purposes of name backreferences, only backref simple | ||||||||
1490 | // names. | ||||||||
1491 | IdentifierNode *Identifier = | ||||||||
1492 | demangleUnqualifiedSymbolName(MangledName, NBB_Simple); | ||||||||
1493 | if (Error) | ||||||||
1494 | return nullptr; | ||||||||
1495 | |||||||||
1496 | QualifiedNameNode *QN = demangleNameScopeChain(MangledName, Identifier); | ||||||||
1497 | if (Error) | ||||||||
1498 | return nullptr; | ||||||||
1499 | |||||||||
1500 | if (Identifier->kind() == NodeKind::StructorIdentifier) { | ||||||||
1501 | if (QN->Components->Count < 2) { | ||||||||
1502 | Error = true; | ||||||||
1503 | return nullptr; | ||||||||
1504 | } | ||||||||
1505 | StructorIdentifierNode *SIN = | ||||||||
1506 | static_cast<StructorIdentifierNode *>(Identifier); | ||||||||
1507 | Node *ClassNode = QN->Components->Nodes[QN->Components->Count - 2]; | ||||||||
1508 | SIN->Class = static_cast<IdentifierNode *>(ClassNode); | ||||||||
1509 | } | ||||||||
1510 | assert(QN)(static_cast <bool> (QN) ? void (0) : __assert_fail ("QN" , "/build/llvm-toolchain-snapshot-13~++20210726100616+dead50d4427c/llvm/lib/Demangle/MicrosoftDemangle.cpp" , 1510, __extension__ __PRETTY_FUNCTION__)); | ||||||||
1511 | return QN; | ||||||||
1512 | } | ||||||||
1513 | |||||||||
1514 | IdentifierNode *Demangler::demangleUnqualifiedTypeName(StringView &MangledName, | ||||||||
1515 | bool Memorize) { | ||||||||
1516 | // An inner-most name can be a back-reference, because a fully-qualified name | ||||||||
1517 | // (e.g. Scope + Inner) can contain other fully qualified names inside of | ||||||||
1518 | // them (for example template parameters), and these nested parameters can | ||||||||
1519 | // refer to previously mangled types. | ||||||||
1520 | if (startsWithDigit(MangledName)) | ||||||||
1521 | return demangleBackRefName(MangledName); | ||||||||
1522 | |||||||||
1523 | if (MangledName.startsWith("?$")) | ||||||||
1524 | return demangleTemplateInstantiationName(MangledName, NBB_Template); | ||||||||
1525 | |||||||||
1526 | return demangleSimpleName(MangledName, Memorize); | ||||||||
1527 | } | ||||||||
1528 | |||||||||
1529 | IdentifierNode * | ||||||||
1530 | Demangler::demangleUnqualifiedSymbolName(StringView &MangledName, | ||||||||
1531 | NameBackrefBehavior NBB) { | ||||||||
1532 | if (startsWithDigit(MangledName)) | ||||||||
1533 | return demangleBackRefName(MangledName); | ||||||||
1534 | if (MangledName.startsWith("?$")) | ||||||||
1535 | return demangleTemplateInstantiationName(MangledName, NBB); | ||||||||
1536 | if (MangledName.startsWith('?')) | ||||||||
1537 | return demangleFunctionIdentifierCode(MangledName); | ||||||||
1538 | return demangleSimpleName(MangledName, /*Memorize=*/(NBB & NBB_Simple) != 0); | ||||||||
1539 | } | ||||||||
1540 | |||||||||
1541 | IdentifierNode *Demangler::demangleNameScopePiece(StringView &MangledName) { | ||||||||
1542 | if (startsWithDigit(MangledName)) | ||||||||
1543 | return demangleBackRefName(MangledName); | ||||||||
1544 | |||||||||
1545 | if (MangledName.startsWith("?$")) | ||||||||
1546 | return demangleTemplateInstantiationName(MangledName, NBB_Template); | ||||||||
1547 | |||||||||
1548 | if (MangledName.startsWith("?A")) | ||||||||
1549 | return demangleAnonymousNamespaceName(MangledName); | ||||||||
1550 | |||||||||
1551 | if (startsWithLocalScopePattern(MangledName)) | ||||||||
1552 | return demangleLocallyScopedNamePiece(MangledName); | ||||||||
1553 | |||||||||
1554 | return demangleSimpleName(MangledName, /*Memorize=*/true); | ||||||||
1555 | } | ||||||||
1556 | |||||||||
1557 | static NodeArrayNode *nodeListToNodeArray(ArenaAllocator &Arena, NodeList *Head, | ||||||||
1558 | size_t Count) { | ||||||||
1559 | NodeArrayNode *N = Arena.alloc<NodeArrayNode>(); | ||||||||
1560 | N->Count = Count; | ||||||||
1561 | N->Nodes = Arena.allocArray<Node *>(Count); | ||||||||
1562 | for (size_t I = 0; I < Count; ++I) { | ||||||||
1563 | N->Nodes[I] = Head->N; | ||||||||
1564 | Head = Head->Next; | ||||||||
1565 | } | ||||||||
1566 | return N; | ||||||||
1567 | } | ||||||||
1568 | |||||||||
1569 | QualifiedNameNode * | ||||||||
1570 | Demangler::demangleNameScopeChain(StringView &MangledName, | ||||||||
1571 | IdentifierNode *UnqualifiedName) { | ||||||||
1572 | NodeList *Head = Arena.alloc<NodeList>(); | ||||||||
1573 | |||||||||
1574 | Head->N = UnqualifiedName; | ||||||||
1575 | |||||||||
1576 | size_t Count = 1; | ||||||||
1577 | while (!MangledName.consumeFront("@")) { | ||||||||
1578 | ++Count; | ||||||||
1579 | NodeList *NewHead = Arena.alloc<NodeList>(); | ||||||||
1580 | NewHead->Next = Head; | ||||||||
1581 | Head = NewHead; | ||||||||
1582 | |||||||||
1583 | if (MangledName.empty()) { | ||||||||
1584 | Error = true; | ||||||||
1585 | return nullptr; | ||||||||
1586 | } | ||||||||
1587 | |||||||||
1588 | assert(!Error)(static_cast <bool> (!Error) ? void (0) : __assert_fail ("!Error", "/build/llvm-toolchain-snapshot-13~++20210726100616+dead50d4427c/llvm/lib/Demangle/MicrosoftDemangle.cpp" , 1588, __extension__ __PRETTY_FUNCTION__)); | ||||||||
1589 | IdentifierNode *Elem = demangleNameScopePiece(MangledName); | ||||||||
1590 | if (Error) | ||||||||
1591 | return nullptr; | ||||||||
1592 | |||||||||
1593 | Head->N = Elem; | ||||||||
1594 | } | ||||||||
1595 | |||||||||
1596 | QualifiedNameNode *QN = Arena.alloc<QualifiedNameNode>(); | ||||||||
1597 | QN->Components = nodeListToNodeArray(Arena, Head, Count); | ||||||||
1598 | return QN; | ||||||||
1599 | } | ||||||||
1600 | |||||||||
1601 | FuncClass Demangler::demangleFunctionClass(StringView &MangledName) { | ||||||||
1602 | switch (MangledName.popFront()) { | ||||||||
1603 | case '9': | ||||||||
1604 | return FuncClass(FC_ExternC | FC_NoParameterList); | ||||||||
1605 | case 'A': | ||||||||
1606 | return FC_Private; | ||||||||
1607 | case 'B': | ||||||||
1608 | return FuncClass(FC_Private | FC_Far); | ||||||||
1609 | case 'C': | ||||||||
1610 | return FuncClass(FC_Private | FC_Static); | ||||||||
1611 | case 'D': | ||||||||
1612 | return FuncClass(FC_Private | FC_Static | FC_Far); | ||||||||
1613 | case 'E': | ||||||||
1614 | return FuncClass(FC_Private | FC_Virtual); | ||||||||
1615 | case 'F': | ||||||||
1616 | return FuncClass(FC_Private | FC_Virtual | FC_Far); | ||||||||
1617 | case 'G': | ||||||||
1618 | return FuncClass(FC_Private | FC_StaticThisAdjust); | ||||||||
1619 | case 'H': | ||||||||
1620 | return FuncClass(FC_Private | FC_StaticThisAdjust | FC_Far); | ||||||||
1621 | case 'I': | ||||||||
1622 | return FuncClass(FC_Protected); | ||||||||
1623 | case 'J': | ||||||||
1624 | return FuncClass(FC_Protected | FC_Far); | ||||||||
1625 | case 'K': | ||||||||
1626 | return FuncClass(FC_Protected | FC_Static); | ||||||||
1627 | case 'L': | ||||||||
1628 | return FuncClass(FC_Protected | FC_Static | FC_Far); | ||||||||
1629 | case 'M': | ||||||||
1630 | return FuncClass(FC_Protected | FC_Virtual); | ||||||||
1631 | case 'N': | ||||||||
1632 | return FuncClass(FC_Protected | FC_Virtual | FC_Far); | ||||||||
1633 | case 'O': | ||||||||
1634 | return FuncClass(FC_Protected | FC_Virtual | FC_StaticThisAdjust); | ||||||||
1635 | case 'P': | ||||||||
1636 | return FuncClass(FC_Protected | FC_Virtual | FC_StaticThisAdjust | FC_Far); | ||||||||
1637 | case 'Q': | ||||||||
1638 | return FuncClass(FC_Public); | ||||||||
1639 | case 'R': | ||||||||
1640 | return FuncClass(FC_Public | FC_Far); | ||||||||
1641 | case 'S': | ||||||||
1642 | return FuncClass(FC_Public | FC_Static); | ||||||||
1643 | case 'T': | ||||||||
1644 | return FuncClass(FC_Public | FC_Static | FC_Far); | ||||||||
1645 | case 'U': | ||||||||
1646 | return FuncClass(FC_Public | FC_Virtual); | ||||||||
1647 | case 'V': | ||||||||
1648 | return FuncClass(FC_Public | FC_Virtual | FC_Far); | ||||||||
1649 | case 'W': | ||||||||
1650 | return FuncClass(FC_Public | FC_Virtual | FC_StaticThisAdjust); | ||||||||
1651 | case 'X': | ||||||||
1652 | return FuncClass(FC_Public | FC_Virtual | FC_StaticThisAdjust | FC_Far); | ||||||||
1653 | case 'Y': | ||||||||
1654 | return FuncClass(FC_Global); | ||||||||
1655 | case 'Z': | ||||||||
1656 | return FuncClass(FC_Global | FC_Far); | ||||||||
1657 | case '$': { | ||||||||
1658 | FuncClass VFlag = FC_VirtualThisAdjust; | ||||||||
1659 | if (MangledName.consumeFront('R')) | ||||||||
1660 | VFlag = FuncClass(VFlag | FC_VirtualThisAdjustEx); | ||||||||
1661 | if (MangledName.empty()) | ||||||||
1662 | break; | ||||||||
1663 | switch (MangledName.popFront()) { | ||||||||
1664 | case '0': | ||||||||
1665 | return FuncClass(FC_Private | FC_Virtual | VFlag); | ||||||||
1666 | case '1': | ||||||||
1667 | return FuncClass(FC_Private | FC_Virtual | VFlag | FC_Far); | ||||||||
1668 | case '2': | ||||||||
1669 | return FuncClass(FC_Protected | FC_Virtual | VFlag); | ||||||||
1670 | case '3': | ||||||||
1671 | return FuncClass(FC_Protected | FC_Virtual | VFlag | FC_Far); | ||||||||
1672 | case '4': | ||||||||
1673 | return FuncClass(FC_Public | FC_Virtual | VFlag); | ||||||||
1674 | case '5': | ||||||||
1675 | return FuncClass(FC_Public | FC_Virtual | VFlag | FC_Far); | ||||||||
1676 | } | ||||||||
1677 | } | ||||||||
1678 | } | ||||||||
1679 | |||||||||
1680 | Error = true; | ||||||||
1681 | return FC_Public; | ||||||||
1682 | } | ||||||||
1683 | |||||||||
1684 | CallingConv Demangler::demangleCallingConvention(StringView &MangledName) { | ||||||||
1685 | if (MangledName.empty()) { | ||||||||
1686 | Error = true; | ||||||||
1687 | return CallingConv::None; | ||||||||
1688 | } | ||||||||
1689 | |||||||||
1690 | switch (MangledName.popFront()) { | ||||||||
1691 | case 'A': | ||||||||
1692 | case 'B': | ||||||||
1693 | return CallingConv::Cdecl; | ||||||||
1694 | case 'C': | ||||||||
1695 | case 'D': | ||||||||
1696 | return CallingConv::Pascal; | ||||||||
1697 | case 'E': | ||||||||
1698 | case 'F': | ||||||||
1699 | return CallingConv::Thiscall; | ||||||||
1700 | case 'G': | ||||||||
1701 | case 'H': | ||||||||
1702 | return CallingConv::Stdcall; | ||||||||
1703 | case 'I': | ||||||||
1704 | case 'J': | ||||||||
1705 | return CallingConv::Fastcall; | ||||||||
1706 | case 'M': | ||||||||
1707 | case 'N': | ||||||||
1708 | return CallingConv::Clrcall; | ||||||||
1709 | case 'O': | ||||||||
1710 | case 'P': | ||||||||
1711 | return CallingConv::Eabi; | ||||||||
1712 | case 'Q': | ||||||||
1713 | return CallingConv::Vectorcall; | ||||||||
1714 | case 'S': | ||||||||
1715 | return CallingConv::Swift; | ||||||||
1716 | case 'W': | ||||||||
1717 | return CallingConv::SwiftAsync; | ||||||||
1718 | } | ||||||||
1719 | |||||||||
1720 | return CallingConv::None; | ||||||||
1721 | } | ||||||||
1722 | |||||||||
1723 | StorageClass Demangler::demangleVariableStorageClass(StringView &MangledName) { | ||||||||
1724 | assert(MangledName.front() >= '0' && MangledName.front() <= '4')(static_cast <bool> (MangledName.front() >= '0' && MangledName.front() <= '4') ? void (0) : __assert_fail ("MangledName.front() >= '0' && MangledName.front() <= '4'" , "/build/llvm-toolchain-snapshot-13~++20210726100616+dead50d4427c/llvm/lib/Demangle/MicrosoftDemangle.cpp" , 1724, __extension__ __PRETTY_FUNCTION__)); | ||||||||
1725 | |||||||||
1726 | switch (MangledName.popFront()) { | ||||||||
1727 | case '0': | ||||||||
1728 | return StorageClass::PrivateStatic; | ||||||||
1729 | case '1': | ||||||||
1730 | return StorageClass::ProtectedStatic; | ||||||||
1731 | case '2': | ||||||||
1732 | return StorageClass::PublicStatic; | ||||||||
1733 | case '3': | ||||||||
1734 | return StorageClass::Global; | ||||||||
1735 | case '4': | ||||||||
1736 | return StorageClass::FunctionLocalStatic; | ||||||||
1737 | } | ||||||||
1738 | DEMANGLE_UNREACHABLE__builtin_unreachable(); | ||||||||
1739 | } | ||||||||
1740 | |||||||||
1741 | std::pair<Qualifiers, bool> | ||||||||
1742 | Demangler::demangleQualifiers(StringView &MangledName) { | ||||||||
1743 | if (MangledName.empty()) { | ||||||||
1744 | Error = true; | ||||||||
1745 | return std::make_pair(Q_None, false); | ||||||||
1746 | } | ||||||||
1747 | |||||||||
1748 | switch (MangledName.popFront()) { | ||||||||
1749 | // Member qualifiers | ||||||||
1750 | case 'Q': | ||||||||
1751 | return std::make_pair(Q_None, true); | ||||||||
1752 | case 'R': | ||||||||
1753 | return std::make_pair(Q_Const, true); | ||||||||
1754 | case 'S': | ||||||||
1755 | return std::make_pair(Q_Volatile, true); | ||||||||
1756 | case 'T': | ||||||||
1757 | return std::make_pair(Qualifiers(Q_Const | Q_Volatile), true); | ||||||||
1758 | // Non-Member qualifiers | ||||||||
1759 | case 'A': | ||||||||
1760 | return std::make_pair(Q_None, false); | ||||||||
1761 | case 'B': | ||||||||
1762 | return std::make_pair(Q_Const, false); | ||||||||
1763 | case 'C': | ||||||||
1764 | return std::make_pair(Q_Volatile, false); | ||||||||
1765 | case 'D': | ||||||||
1766 | return std::make_pair(Qualifiers(Q_Const | Q_Volatile), false); | ||||||||
1767 | } | ||||||||
1768 | Error = true; | ||||||||
1769 | return std::make_pair(Q_None, false); | ||||||||
1770 | } | ||||||||
1771 | |||||||||
1772 | // <variable-type> ::= <type> <cvr-qualifiers> | ||||||||
1773 | // ::= <type> <pointee-cvr-qualifiers> # pointers, references | ||||||||
1774 | TypeNode *Demangler::demangleType(StringView &MangledName, | ||||||||
1775 | QualifierMangleMode QMM) { | ||||||||
1776 | Qualifiers Quals = Q_None; | ||||||||
1777 | bool IsMember = false; | ||||||||
1778 | if (QMM == QualifierMangleMode::Mangle) { | ||||||||
1779 | std::tie(Quals, IsMember) = demangleQualifiers(MangledName); | ||||||||
1780 | } else if (QMM == QualifierMangleMode::Result) { | ||||||||
1781 | if (MangledName.consumeFront('?')) | ||||||||
1782 | std::tie(Quals, IsMember) = demangleQualifiers(MangledName); | ||||||||
1783 | } | ||||||||
1784 | |||||||||
1785 | if (MangledName.empty()) { | ||||||||
1786 | Error = true; | ||||||||
1787 | return nullptr; | ||||||||
1788 | } | ||||||||
1789 | |||||||||
1790 | TypeNode *Ty = nullptr; | ||||||||
1791 | if (isTagType(MangledName)) | ||||||||
1792 | Ty = demangleClassType(MangledName); | ||||||||
1793 | else if (isPointerType(MangledName)) { | ||||||||
1794 | if (isMemberPointer(MangledName, Error)) | ||||||||
1795 | Ty = demangleMemberPointerType(MangledName); | ||||||||
1796 | else if (!Error) | ||||||||
1797 | Ty = demanglePointerType(MangledName); | ||||||||
1798 | else | ||||||||
1799 | return nullptr; | ||||||||
1800 | } else if (isArrayType(MangledName)) | ||||||||
1801 | Ty = demangleArrayType(MangledName); | ||||||||
1802 | else if (isFunctionType(MangledName)) { | ||||||||
1803 | if (MangledName.consumeFront("$$A8@@")) | ||||||||
1804 | Ty = demangleFunctionType(MangledName, true); | ||||||||
1805 | else { | ||||||||
1806 | assert(MangledName.startsWith("$$A6"))(static_cast <bool> (MangledName.startsWith("$$A6")) ? void (0) : __assert_fail ("MangledName.startsWith(\"$$A6\")", "/build/llvm-toolchain-snapshot-13~++20210726100616+dead50d4427c/llvm/lib/Demangle/MicrosoftDemangle.cpp" , 1806, __extension__ __PRETTY_FUNCTION__)); | ||||||||
1807 | MangledName.consumeFront("$$A6"); | ||||||||
1808 | Ty = demangleFunctionType(MangledName, false); | ||||||||
1809 | } | ||||||||
1810 | } else if (isCustomType(MangledName)) { | ||||||||
1811 | Ty = demangleCustomType(MangledName); | ||||||||
1812 | } else { | ||||||||
1813 | Ty = demanglePrimitiveType(MangledName); | ||||||||
1814 | } | ||||||||
1815 | |||||||||
1816 | if (!Ty || Error) | ||||||||
1817 | return Ty; | ||||||||
1818 | Ty->Quals = Qualifiers(Ty->Quals | Quals); | ||||||||
1819 | return Ty; | ||||||||
1820 | } | ||||||||
1821 | |||||||||
1822 | bool Demangler::demangleThrowSpecification(StringView &MangledName) { | ||||||||
1823 | if (MangledName.consumeFront("_E")) | ||||||||
1824 | return true; | ||||||||
1825 | if (MangledName.consumeFront('Z')) | ||||||||
1826 | return false; | ||||||||
1827 | |||||||||
1828 | Error = true; | ||||||||
1829 | return false; | ||||||||
1830 | } | ||||||||
1831 | |||||||||
1832 | FunctionSignatureNode *Demangler::demangleFunctionType(StringView &MangledName, | ||||||||
1833 | bool HasThisQuals) { | ||||||||
1834 | FunctionSignatureNode *FTy = Arena.alloc<FunctionSignatureNode>(); | ||||||||
1835 | |||||||||
1836 | if (HasThisQuals) { | ||||||||
1837 | FTy->Quals = demanglePointerExtQualifiers(MangledName); | ||||||||
1838 | FTy->RefQualifier = demangleFunctionRefQualifier(MangledName); | ||||||||
1839 | FTy->Quals = Qualifiers(FTy->Quals | demangleQualifiers(MangledName).first); | ||||||||
1840 | } | ||||||||
1841 | |||||||||
1842 | // Fields that appear on both member and non-member functions. | ||||||||
1843 | FTy->CallConvention = demangleCallingConvention(MangledName); | ||||||||
1844 | |||||||||
1845 | // <return-type> ::= <type> | ||||||||
1846 | // ::= @ # structors (they have no declared return type) | ||||||||
1847 | bool IsStructor = MangledName.consumeFront('@'); | ||||||||
1848 | if (!IsStructor) | ||||||||
1849 | FTy->ReturnType = demangleType(MangledName, QualifierMangleMode::Result); | ||||||||
1850 | |||||||||
1851 | FTy->Params = demangleFunctionParameterList(MangledName, FTy->IsVariadic); | ||||||||
1852 | |||||||||
1853 | FTy->IsNoexcept = demangleThrowSpecification(MangledName); | ||||||||
1854 | |||||||||
1855 | return FTy; | ||||||||
1856 | } | ||||||||
1857 | |||||||||
1858 | FunctionSymbolNode * | ||||||||
1859 | Demangler::demangleFunctionEncoding(StringView &MangledName) { | ||||||||
1860 | FuncClass ExtraFlags = FC_None; | ||||||||
1861 | if (MangledName.consumeFront("$$J0")) | ||||||||
1862 | ExtraFlags = FC_ExternC; | ||||||||
1863 | |||||||||
1864 | if (MangledName.empty()) { | ||||||||
1865 | Error = true; | ||||||||
1866 | return nullptr; | ||||||||
1867 | } | ||||||||
1868 | |||||||||
1869 | FuncClass FC = demangleFunctionClass(MangledName); | ||||||||
1870 | FC = FuncClass(ExtraFlags | FC); | ||||||||
1871 | |||||||||
1872 | FunctionSignatureNode *FSN = nullptr; | ||||||||
1873 | ThunkSignatureNode *TTN = nullptr; | ||||||||
1874 | if (FC & FC_StaticThisAdjust) { | ||||||||
1875 | TTN = Arena.alloc<ThunkSignatureNode>(); | ||||||||
1876 | TTN->ThisAdjust.StaticOffset = demangleSigned(MangledName); | ||||||||
1877 | } else if (FC & FC_VirtualThisAdjust) { | ||||||||
1878 | TTN = Arena.alloc<ThunkSignatureNode>(); | ||||||||
1879 | if (FC & FC_VirtualThisAdjustEx) { | ||||||||
1880 | TTN->ThisAdjust.VBPtrOffset = demangleSigned(MangledName); | ||||||||
1881 | TTN->ThisAdjust.VBOffsetOffset = demangleSigned(MangledName); | ||||||||
1882 | } | ||||||||
1883 | TTN->ThisAdjust.VtordispOffset = demangleSigned(MangledName); | ||||||||
1884 | TTN->ThisAdjust.StaticOffset = demangleSigned(MangledName); | ||||||||
1885 | } | ||||||||
1886 | |||||||||
1887 | if (FC & FC_NoParameterList) { | ||||||||
1888 | // This is an extern "C" function whose full signature hasn't been mangled. | ||||||||
1889 | // This happens when we need to mangle a local symbol inside of an extern | ||||||||
1890 | // "C" function. | ||||||||
1891 | FSN = Arena.alloc<FunctionSignatureNode>(); | ||||||||
1892 | } else { | ||||||||
1893 | bool HasThisQuals = !(FC & (FC_Global | FC_Static)); | ||||||||
1894 | FSN = demangleFunctionType(MangledName, HasThisQuals); | ||||||||
1895 | } | ||||||||
1896 | |||||||||
1897 | if (Error) | ||||||||
1898 | return nullptr; | ||||||||
1899 | |||||||||
1900 | if (TTN) { | ||||||||
1901 | *static_cast<FunctionSignatureNode *>(TTN) = *FSN; | ||||||||
1902 | FSN = TTN; | ||||||||
1903 | } | ||||||||
1904 | FSN->FunctionClass = FC; | ||||||||
1905 | |||||||||
1906 | FunctionSymbolNode *Symbol = Arena.alloc<FunctionSymbolNode>(); | ||||||||
1907 | Symbol->Signature = FSN; | ||||||||
1908 | return Symbol; | ||||||||
1909 | } | ||||||||
1910 | |||||||||
1911 | CustomTypeNode *Demangler::demangleCustomType(StringView &MangledName) { | ||||||||
1912 | assert(MangledName.startsWith('?'))(static_cast <bool> (MangledName.startsWith('?')) ? void (0) : __assert_fail ("MangledName.startsWith('?')", "/build/llvm-toolchain-snapshot-13~++20210726100616+dead50d4427c/llvm/lib/Demangle/MicrosoftDemangle.cpp" , 1912, __extension__ __PRETTY_FUNCTION__)); | ||||||||
1913 | MangledName.popFront(); | ||||||||
1914 | |||||||||
1915 | CustomTypeNode *CTN = Arena.alloc<CustomTypeNode>(); | ||||||||
1916 | CTN->Identifier = demangleUnqualifiedTypeName(MangledName, /*Memorize=*/true); | ||||||||
1917 | if (!MangledName.consumeFront('@')) | ||||||||
1918 | Error = true; | ||||||||
1919 | if (Error) | ||||||||
1920 | return nullptr; | ||||||||
1921 | return CTN; | ||||||||
1922 | } | ||||||||
1923 | |||||||||
1924 | // Reads a primitive type. | ||||||||
1925 | PrimitiveTypeNode *Demangler::demanglePrimitiveType(StringView &MangledName) { | ||||||||
1926 | if (MangledName.consumeFront("$$T")) | ||||||||
1927 | return Arena.alloc<PrimitiveTypeNode>(PrimitiveKind::Nullptr); | ||||||||
1928 | |||||||||
1929 | switch (MangledName.popFront()) { | ||||||||
1930 | case 'X': | ||||||||
1931 | return Arena.alloc<PrimitiveTypeNode>(PrimitiveKind::Void); | ||||||||
1932 | case 'D': | ||||||||
1933 | return Arena.alloc<PrimitiveTypeNode>(PrimitiveKind::Char); | ||||||||
1934 | case 'C': | ||||||||
1935 | return Arena.alloc<PrimitiveTypeNode>(PrimitiveKind::Schar); | ||||||||
1936 | case 'E': | ||||||||
1937 | return Arena.alloc<PrimitiveTypeNode>(PrimitiveKind::Uchar); | ||||||||
1938 | case 'F': | ||||||||
1939 | return Arena.alloc<PrimitiveTypeNode>(PrimitiveKind::Short); | ||||||||
1940 | case 'G': | ||||||||
1941 | return Arena.alloc<PrimitiveTypeNode>(PrimitiveKind::Ushort); | ||||||||
1942 | case 'H': | ||||||||
1943 | return Arena.alloc<PrimitiveTypeNode>(PrimitiveKind::Int); | ||||||||
1944 | case 'I': | ||||||||
1945 | return Arena.alloc<PrimitiveTypeNode>(PrimitiveKind::Uint); | ||||||||
1946 | case 'J': | ||||||||
1947 | return Arena.alloc<PrimitiveTypeNode>(PrimitiveKind::Long); | ||||||||
1948 | case 'K': | ||||||||
1949 | return Arena.alloc<PrimitiveTypeNode>(PrimitiveKind::Ulong); | ||||||||
1950 | case 'M': | ||||||||
1951 | return Arena.alloc<PrimitiveTypeNode>(PrimitiveKind::Float); | ||||||||
1952 | case 'N': | ||||||||
1953 | return Arena.alloc<PrimitiveTypeNode>(PrimitiveKind::Double); | ||||||||
1954 | case 'O': | ||||||||
1955 | return Arena.alloc<PrimitiveTypeNode>(PrimitiveKind::Ldouble); | ||||||||
1956 | case '_': { | ||||||||
1957 | if (MangledName.empty()) { | ||||||||
1958 | Error = true; | ||||||||
1959 | return nullptr; | ||||||||
1960 | } | ||||||||
1961 | switch (MangledName.popFront()) { | ||||||||
1962 | case 'N': | ||||||||
1963 | return Arena.alloc<PrimitiveTypeNode>(PrimitiveKind::Bool); | ||||||||
1964 | case 'J': | ||||||||
1965 | return Arena.alloc<PrimitiveTypeNode>(PrimitiveKind::Int64); | ||||||||
1966 | case 'K': | ||||||||
1967 | return Arena.alloc<PrimitiveTypeNode>(PrimitiveKind::Uint64); | ||||||||
1968 | case 'W': | ||||||||
1969 | return Arena.alloc<PrimitiveTypeNode>(PrimitiveKind::Wchar); | ||||||||
1970 | case 'Q': | ||||||||
1971 | return Arena.alloc<PrimitiveTypeNode>(PrimitiveKind::Char8); | ||||||||
1972 | case 'S': | ||||||||
1973 | return Arena.alloc<PrimitiveTypeNode>(PrimitiveKind::Char16); | ||||||||
1974 | case 'U': | ||||||||
1975 | return Arena.alloc<PrimitiveTypeNode>(PrimitiveKind::Char32); | ||||||||
1976 | } | ||||||||
1977 | break; | ||||||||
1978 | } | ||||||||
1979 | } | ||||||||
1980 | Error = true; | ||||||||
1981 | return nullptr; | ||||||||
1982 | } | ||||||||
1983 | |||||||||
1984 | TagTypeNode *Demangler::demangleClassType(StringView &MangledName) { | ||||||||
1985 | TagTypeNode *TT = nullptr; | ||||||||
1986 | |||||||||
1987 | switch (MangledName.popFront()) { | ||||||||
1988 | case 'T': | ||||||||
1989 | TT = Arena.alloc<TagTypeNode>(TagKind::Union); | ||||||||
1990 | break; | ||||||||
1991 | case 'U': | ||||||||
1992 | TT = Arena.alloc<TagTypeNode>(TagKind::Struct); | ||||||||
1993 | break; | ||||||||
1994 | case 'V': | ||||||||
1995 | TT = Arena.alloc<TagTypeNode>(TagKind::Class); | ||||||||
1996 | break; | ||||||||
1997 | case 'W': | ||||||||
1998 | if (!MangledName.consumeFront('4')) { | ||||||||
1999 | Error = true; | ||||||||
2000 | return nullptr; | ||||||||
2001 | } | ||||||||
2002 | TT = Arena.alloc<TagTypeNode>(TagKind::Enum); | ||||||||
2003 | break; | ||||||||
2004 | default: | ||||||||
2005 | assert(false)(static_cast <bool> (false) ? void (0) : __assert_fail ( "false", "/build/llvm-toolchain-snapshot-13~++20210726100616+dead50d4427c/llvm/lib/Demangle/MicrosoftDemangle.cpp" , 2005, __extension__ __PRETTY_FUNCTION__)); | ||||||||
2006 | } | ||||||||
2007 | |||||||||
2008 | TT->QualifiedName = demangleFullyQualifiedTypeName(MangledName); | ||||||||
2009 | return TT; | ||||||||
2010 | } | ||||||||
2011 | |||||||||
2012 | // <pointer-type> ::= E? <pointer-cvr-qualifiers> <ext-qualifiers> <type> | ||||||||
2013 | // # the E is required for 64-bit non-static pointers | ||||||||
2014 | PointerTypeNode *Demangler::demanglePointerType(StringView &MangledName) { | ||||||||
2015 | PointerTypeNode *Pointer = Arena.alloc<PointerTypeNode>(); | ||||||||
2016 | |||||||||
2017 | std::tie(Pointer->Quals, Pointer->Affinity) = | ||||||||
2018 | demanglePointerCVQualifiers(MangledName); | ||||||||
2019 | |||||||||
2020 | if (MangledName.consumeFront("6")) { | ||||||||
2021 | Pointer->Pointee = demangleFunctionType(MangledName, false); | ||||||||
2022 | return Pointer; | ||||||||
2023 | } | ||||||||
2024 | |||||||||
2025 | Qualifiers ExtQuals = demanglePointerExtQualifiers(MangledName); | ||||||||
2026 | Pointer->Quals = Qualifiers(Pointer->Quals | ExtQuals); | ||||||||
2027 | |||||||||
2028 | Pointer->Pointee = demangleType(MangledName, QualifierMangleMode::Mangle); | ||||||||
2029 | return Pointer; | ||||||||
2030 | } | ||||||||
2031 | |||||||||
2032 | PointerTypeNode *Demangler::demangleMemberPointerType(StringView &MangledName) { | ||||||||
2033 | PointerTypeNode *Pointer = Arena.alloc<PointerTypeNode>(); | ||||||||
2034 | |||||||||
2035 | std::tie(Pointer->Quals, Pointer->Affinity) = | ||||||||
2036 | demanglePointerCVQualifiers(MangledName); | ||||||||
2037 | assert(Pointer->Affinity == PointerAffinity::Pointer)(static_cast <bool> (Pointer->Affinity == PointerAffinity ::Pointer) ? void (0) : __assert_fail ("Pointer->Affinity == PointerAffinity::Pointer" , "/build/llvm-toolchain-snapshot-13~++20210726100616+dead50d4427c/llvm/lib/Demangle/MicrosoftDemangle.cpp" , 2037, __extension__ __PRETTY_FUNCTION__)); | ||||||||
2038 | |||||||||
2039 | Qualifiers ExtQuals = demanglePointerExtQualifiers(MangledName); | ||||||||
2040 | Pointer->Quals = Qualifiers(Pointer->Quals | ExtQuals); | ||||||||
2041 | |||||||||
2042 | // isMemberPointer() only returns true if there is at least one character | ||||||||
2043 | // after the qualifiers. | ||||||||
2044 | if (MangledName.consumeFront("8")) { | ||||||||
2045 | Pointer->ClassParent = demangleFullyQualifiedTypeName(MangledName); | ||||||||
2046 | Pointer->Pointee = demangleFunctionType(MangledName, true); | ||||||||
2047 | } else { | ||||||||
2048 | Qualifiers PointeeQuals = Q_None; | ||||||||
2049 | bool IsMember = false; | ||||||||
2050 | std::tie(PointeeQuals, IsMember) = demangleQualifiers(MangledName); | ||||||||
2051 | assert(IsMember || Error)(static_cast <bool> (IsMember || Error) ? void (0) : __assert_fail ("IsMember || Error", "/build/llvm-toolchain-snapshot-13~++20210726100616+dead50d4427c/llvm/lib/Demangle/MicrosoftDemangle.cpp" , 2051, __extension__ __PRETTY_FUNCTION__)); | ||||||||
2052 | Pointer->ClassParent = demangleFullyQualifiedTypeName(MangledName); | ||||||||
2053 | |||||||||
2054 | Pointer->Pointee = demangleType(MangledName, QualifierMangleMode::Drop); | ||||||||
2055 | if (Pointer->Pointee) | ||||||||
2056 | Pointer->Pointee->Quals = PointeeQuals; | ||||||||
2057 | } | ||||||||
2058 | |||||||||
2059 | return Pointer; | ||||||||
2060 | } | ||||||||
2061 | |||||||||
2062 | Qualifiers Demangler::demanglePointerExtQualifiers(StringView &MangledName) { | ||||||||
2063 | Qualifiers Quals = Q_None; | ||||||||
2064 | if (MangledName.consumeFront('E')) | ||||||||
2065 | Quals = Qualifiers(Quals | Q_Pointer64); | ||||||||
2066 | if (MangledName.consumeFront('I')) | ||||||||
2067 | Quals = Qualifiers(Quals | Q_Restrict); | ||||||||
2068 | if (MangledName.consumeFront('F')) | ||||||||
2069 | Quals = Qualifiers(Quals | Q_Unaligned); | ||||||||
2070 | |||||||||
2071 | return Quals; | ||||||||
2072 | } | ||||||||
2073 | |||||||||
2074 | ArrayTypeNode *Demangler::demangleArrayType(StringView &MangledName) { | ||||||||
2075 | assert(MangledName.front() == 'Y')(static_cast <bool> (MangledName.front() == 'Y') ? void (0) : __assert_fail ("MangledName.front() == 'Y'", "/build/llvm-toolchain-snapshot-13~++20210726100616+dead50d4427c/llvm/lib/Demangle/MicrosoftDemangle.cpp" , 2075, __extension__ __PRETTY_FUNCTION__)); | ||||||||
2076 | MangledName.popFront(); | ||||||||
2077 | |||||||||
2078 | uint64_t Rank = 0; | ||||||||
2079 | bool IsNegative = false; | ||||||||
2080 | std::tie(Rank, IsNegative) = demangleNumber(MangledName); | ||||||||
2081 | if (IsNegative || Rank == 0) { | ||||||||
2082 | Error = true; | ||||||||
2083 | return nullptr; | ||||||||
2084 | } | ||||||||
2085 | |||||||||
2086 | ArrayTypeNode *ATy = Arena.alloc<ArrayTypeNode>(); | ||||||||
2087 | NodeList *Head = Arena.alloc<NodeList>(); | ||||||||
2088 | NodeList *Tail = Head; | ||||||||
2089 | |||||||||
2090 | for (uint64_t I = 0; I < Rank; ++I) { | ||||||||
2091 | uint64_t D = 0; | ||||||||
2092 | std::tie(D, IsNegative) = demangleNumber(MangledName); | ||||||||
2093 | if (Error || IsNegative) { | ||||||||
2094 | Error = true; | ||||||||
2095 | return nullptr; | ||||||||
2096 | } | ||||||||
2097 | Tail->N = Arena.alloc<IntegerLiteralNode>(D, IsNegative); | ||||||||
2098 | if (I + 1 < Rank) { | ||||||||
2099 | Tail->Next = Arena.alloc<NodeList>(); | ||||||||
2100 | Tail = Tail->Next; | ||||||||
2101 | } | ||||||||
2102 | } | ||||||||
2103 | ATy->Dimensions = nodeListToNodeArray(Arena, Head, Rank); | ||||||||
2104 | |||||||||
2105 | if (MangledName.consumeFront("$$C")) { | ||||||||
2106 | bool IsMember = false; | ||||||||
2107 | std::tie(ATy->Quals, IsMember) = demangleQualifiers(MangledName); | ||||||||
2108 | if (IsMember) { | ||||||||
2109 | Error = true; | ||||||||
2110 | return nullptr; | ||||||||
2111 | } | ||||||||
2112 | } | ||||||||
2113 | |||||||||
2114 | ATy->ElementType = demangleType(MangledName, QualifierMangleMode::Drop); | ||||||||
2115 | return ATy; | ||||||||
2116 | } | ||||||||
2117 | |||||||||
2118 | // Reads a function's parameters. | ||||||||
2119 | NodeArrayNode *Demangler::demangleFunctionParameterList(StringView &MangledName, | ||||||||
2120 | bool &IsVariadic) { | ||||||||
2121 | // Empty parameter list. | ||||||||
2122 | if (MangledName.consumeFront('X')) | ||||||||
| |||||||||
2123 | return nullptr; | ||||||||
2124 | |||||||||
2125 | NodeList *Head = Arena.alloc<NodeList>(); | ||||||||
2126 | NodeList **Current = &Head; | ||||||||
2127 | size_t Count = 0; | ||||||||
2128 | while (!Error
| ||||||||
2129 | !MangledName.startsWith('Z')) { | ||||||||
2130 | ++Count; | ||||||||
2131 | |||||||||
2132 | if (startsWithDigit(MangledName)) { | ||||||||
2133 | size_t N = MangledName[0] - '0'; | ||||||||
2134 | if (N >= Backrefs.FunctionParamCount) { | ||||||||
2135 | Error = true; | ||||||||
2136 | return nullptr; | ||||||||
2137 | } | ||||||||
2138 | MangledName = MangledName.dropFront(); | ||||||||
2139 | |||||||||
2140 | *Current = Arena.alloc<NodeList>(); | ||||||||
2141 | (*Current)->N = Backrefs.FunctionParams[N]; | ||||||||
2142 | Current = &(*Current)->Next; | ||||||||
2143 | continue; | ||||||||
2144 | } | ||||||||
2145 | |||||||||
2146 | size_t OldSize = MangledName.size(); | ||||||||
2147 | |||||||||
2148 | *Current = Arena.alloc<NodeList>(); | ||||||||
2149 | TypeNode *TN = demangleType(MangledName, QualifierMangleMode::Drop); | ||||||||
2150 | if (!TN
| ||||||||
2151 | return nullptr; | ||||||||
2152 | |||||||||
2153 | (*Current)->N = TN; | ||||||||
2154 | |||||||||
2155 | size_t CharsConsumed = OldSize - MangledName.size(); | ||||||||
2156 | assert(CharsConsumed != 0)(static_cast <bool> (CharsConsumed != 0) ? void (0) : __assert_fail ("CharsConsumed != 0", "/build/llvm-toolchain-snapshot-13~++20210726100616+dead50d4427c/llvm/lib/Demangle/MicrosoftDemangle.cpp" , 2156, __extension__ __PRETTY_FUNCTION__)); | ||||||||
2157 | |||||||||
2158 | // Single-letter types are ignored for backreferences because memorizing | ||||||||
2159 | // them doesn't save anything. | ||||||||
2160 | if (Backrefs.FunctionParamCount <= 9 && CharsConsumed > 1) | ||||||||
2161 | Backrefs.FunctionParams[Backrefs.FunctionParamCount++] = TN; | ||||||||
2162 | |||||||||
2163 | Current = &(*Current)->Next; | ||||||||
2164 | } | ||||||||
2165 | |||||||||
2166 | if (Error
| ||||||||
2167 | return nullptr; | ||||||||
2168 | |||||||||
2169 | NodeArrayNode *NA = nodeListToNodeArray(Arena, Head, Count); | ||||||||
2170 | // A non-empty parameter list is terminated by either 'Z' (variadic) parameter | ||||||||
2171 | // list or '@' (non variadic). Careful not to consume "@Z", as in that case | ||||||||
2172 | // the following Z could be a throw specifier. | ||||||||
2173 | if (MangledName.consumeFront('@')) | ||||||||
2174 | return NA; | ||||||||
2175 | |||||||||
2176 | if (MangledName.consumeFront('Z')) { | ||||||||
2177 | IsVariadic = true; | ||||||||
2178 | return NA; | ||||||||
2179 | } | ||||||||
2180 | |||||||||
2181 | DEMANGLE_UNREACHABLE__builtin_unreachable(); | ||||||||
2182 | } | ||||||||
2183 | |||||||||
2184 | NodeArrayNode * | ||||||||
2185 | Demangler::demangleTemplateParameterList(StringView &MangledName) { | ||||||||
2186 | NodeList *Head = nullptr; | ||||||||
2187 | NodeList **Current = &Head; | ||||||||
2188 | size_t Count = 0; | ||||||||
2189 | |||||||||
2190 | while (!MangledName.startsWith('@')) { | ||||||||
2191 | if (MangledName.consumeFront("$S") || MangledName.consumeFront("$$V") || | ||||||||
2192 | MangledName.consumeFront("$$$V") || MangledName.consumeFront("$$Z")) { | ||||||||
2193 | // parameter pack separator | ||||||||
2194 | continue; | ||||||||
2195 | } | ||||||||
2196 | |||||||||
2197 | ++Count; | ||||||||
2198 | |||||||||
2199 | // Template parameter lists don't participate in back-referencing. | ||||||||
2200 | *Current = Arena.alloc<NodeList>(); | ||||||||
2201 | |||||||||
2202 | NodeList &TP = **Current; | ||||||||
2203 | |||||||||
2204 | TemplateParameterReferenceNode *TPRN = nullptr; | ||||||||
2205 | if (MangledName.consumeFront("$$Y")) { | ||||||||
2206 | // Template alias | ||||||||
2207 | TP.N = demangleFullyQualifiedTypeName(MangledName); | ||||||||
2208 | } else if (MangledName.consumeFront("$$B")) { | ||||||||
2209 | // Array | ||||||||
2210 | TP.N = demangleType(MangledName, QualifierMangleMode::Drop); | ||||||||
2211 | } else if (MangledName.consumeFront("$$C")) { | ||||||||
2212 | // Type has qualifiers. | ||||||||
2213 | TP.N = demangleType(MangledName, QualifierMangleMode::Mangle); | ||||||||
2214 | } else if (MangledName.startsWith("$1") || MangledName.startsWith("$H") || | ||||||||
2215 | MangledName.startsWith("$I") || MangledName.startsWith("$J")) { | ||||||||
2216 | // Pointer to member | ||||||||
2217 | TP.N = TPRN = Arena.alloc<TemplateParameterReferenceNode>(); | ||||||||
2218 | TPRN->IsMemberPointer = true; | ||||||||
2219 | |||||||||
2220 | MangledName = MangledName.dropFront(); | ||||||||
2221 | // 1 - single inheritance <name> | ||||||||
2222 | // H - multiple inheritance <name> <number> | ||||||||
2223 | // I - virtual inheritance <name> <number> <number> | ||||||||
2224 | // J - unspecified inheritance <name> <number> <number> <number> | ||||||||
2225 | char InheritanceSpecifier = MangledName.popFront(); | ||||||||
2226 | SymbolNode *S = nullptr; | ||||||||
2227 | if (MangledName.startsWith('?')) { | ||||||||
2228 | S = parse(MangledName); | ||||||||
2229 | if (Error || !S->Name) { | ||||||||
2230 | Error = true; | ||||||||
2231 | return nullptr; | ||||||||
2232 | } | ||||||||
2233 | memorizeIdentifier(S->Name->getUnqualifiedIdentifier()); | ||||||||
2234 | } | ||||||||
2235 | |||||||||
2236 | switch (InheritanceSpecifier) { | ||||||||
2237 | case 'J': | ||||||||
2238 | TPRN->ThunkOffsets[TPRN->ThunkOffsetCount++] = | ||||||||
2239 | demangleSigned(MangledName); | ||||||||
2240 | DEMANGLE_FALLTHROUGH[[gnu::fallthrough]]; | ||||||||
2241 | case 'I': | ||||||||
2242 | TPRN->ThunkOffsets[TPRN->ThunkOffsetCount++] = | ||||||||
2243 | demangleSigned(MangledName); | ||||||||
2244 | DEMANGLE_FALLTHROUGH[[gnu::fallthrough]]; | ||||||||
2245 | case 'H': | ||||||||
2246 | TPRN->ThunkOffsets[TPRN->ThunkOffsetCount++] = | ||||||||
2247 | demangleSigned(MangledName); | ||||||||
2248 | DEMANGLE_FALLTHROUGH[[gnu::fallthrough]]; | ||||||||
2249 | case '1': | ||||||||
2250 | break; | ||||||||
2251 | default: | ||||||||
2252 | DEMANGLE_UNREACHABLE__builtin_unreachable(); | ||||||||
2253 | } | ||||||||
2254 | TPRN->Affinity = PointerAffinity::Pointer; | ||||||||
2255 | TPRN->Symbol = S; | ||||||||
2256 | } else if (MangledName.startsWith("$E?")) { | ||||||||
2257 | MangledName.consumeFront("$E"); | ||||||||
2258 | // Reference to symbol | ||||||||
2259 | TP.N = TPRN = Arena.alloc<TemplateParameterReferenceNode>(); | ||||||||
2260 | TPRN->Symbol = parse(MangledName); | ||||||||
2261 | TPRN->Affinity = PointerAffinity::Reference; | ||||||||
2262 | } else if (MangledName.startsWith("$F") || MangledName.startsWith("$G")) { | ||||||||
2263 | TP.N = TPRN = Arena.alloc<TemplateParameterReferenceNode>(); | ||||||||
2264 | |||||||||
2265 | // Data member pointer. | ||||||||
2266 | MangledName = MangledName.dropFront(); | ||||||||
2267 | char InheritanceSpecifier = MangledName.popFront(); | ||||||||
2268 | |||||||||
2269 | switch (InheritanceSpecifier) { | ||||||||
2270 | case 'G': | ||||||||
2271 | TPRN->ThunkOffsets[TPRN->ThunkOffsetCount++] = | ||||||||
2272 | demangleSigned(MangledName); | ||||||||
2273 | DEMANGLE_FALLTHROUGH[[gnu::fallthrough]]; | ||||||||
2274 | case 'F': | ||||||||
2275 | TPRN->ThunkOffsets[TPRN->ThunkOffsetCount++] = | ||||||||
2276 | demangleSigned(MangledName); | ||||||||
2277 | TPRN->ThunkOffsets[TPRN->ThunkOffsetCount++] = | ||||||||
2278 | demangleSigned(MangledName); | ||||||||
2279 | break; | ||||||||
2280 | default: | ||||||||
2281 | DEMANGLE_UNREACHABLE__builtin_unreachable(); | ||||||||
2282 | } | ||||||||
2283 | TPRN->IsMemberPointer = true; | ||||||||
2284 | |||||||||
2285 | } else if (MangledName.consumeFront("$0")) { | ||||||||
2286 | // Integral non-type template parameter | ||||||||
2287 | bool IsNegative = false; | ||||||||
2288 | uint64_t Value = 0; | ||||||||
2289 | std::tie(Value, IsNegative) = demangleNumber(MangledName); | ||||||||
2290 | |||||||||
2291 | TP.N = Arena.alloc<IntegerLiteralNode>(Value, IsNegative); | ||||||||
2292 | } else { | ||||||||
2293 | TP.N = demangleType(MangledName, QualifierMangleMode::Drop); | ||||||||
2294 | } | ||||||||
2295 | if (Error) | ||||||||
2296 | return nullptr; | ||||||||
2297 | |||||||||
2298 | Current = &TP.Next; | ||||||||
2299 | } | ||||||||
2300 | |||||||||
2301 | // The loop above returns nullptr on Error. | ||||||||
2302 | assert(!Error)(static_cast <bool> (!Error) ? void (0) : __assert_fail ("!Error", "/build/llvm-toolchain-snapshot-13~++20210726100616+dead50d4427c/llvm/lib/Demangle/MicrosoftDemangle.cpp" , 2302, __extension__ __PRETTY_FUNCTION__)); | ||||||||
2303 | |||||||||
2304 | // Template parameter lists cannot be variadic, so it can only be terminated | ||||||||
2305 | // by @ (as opposed to 'Z' in the function parameter case). | ||||||||
2306 | assert(MangledName.startsWith('@'))(static_cast <bool> (MangledName.startsWith('@')) ? void (0) : __assert_fail ("MangledName.startsWith('@')", "/build/llvm-toolchain-snapshot-13~++20210726100616+dead50d4427c/llvm/lib/Demangle/MicrosoftDemangle.cpp" , 2306, __extension__ __PRETTY_FUNCTION__)); // The above loop exits only on '@'. | ||||||||
2307 | MangledName.consumeFront('@'); | ||||||||
2308 | return nodeListToNodeArray(Arena, Head, Count); | ||||||||
2309 | } | ||||||||
2310 | |||||||||
2311 | void Demangler::dumpBackReferences() { | ||||||||
2312 | std::printf("%d function parameter backreferences\n", | ||||||||
2313 | (int)Backrefs.FunctionParamCount); | ||||||||
2314 | |||||||||
2315 | // Create an output stream so we can render each type. | ||||||||
2316 | OutputStream OS; | ||||||||
2317 | if (!initializeOutputStream(nullptr, nullptr, OS, 1024)) | ||||||||
2318 | std::terminate(); | ||||||||
2319 | for (size_t I = 0; I < Backrefs.FunctionParamCount; ++I) { | ||||||||
2320 | OS.setCurrentPosition(0); | ||||||||
2321 | |||||||||
2322 | TypeNode *T = Backrefs.FunctionParams[I]; | ||||||||
2323 | T->output(OS, OF_Default); | ||||||||
2324 | |||||||||
2325 | std::printf(" [%d] - %.*s\n", (int)I, (int)OS.getCurrentPosition(), | ||||||||
2326 | OS.getBuffer()); | ||||||||
2327 | } | ||||||||
2328 | std::free(OS.getBuffer()); | ||||||||
2329 | |||||||||
2330 | if (Backrefs.FunctionParamCount > 0) | ||||||||
2331 | std::printf("\n"); | ||||||||
2332 | std::printf("%d name backreferences\n", (int)Backrefs.NamesCount); | ||||||||
2333 | for (size_t I = 0; I < Backrefs.NamesCount; ++I) { | ||||||||
2334 | std::printf(" [%d] - %.*s\n", (int)I, (int)Backrefs.Names[I]->Name.size(), | ||||||||
2335 | Backrefs.Names[I]->Name.begin()); | ||||||||
2336 | } | ||||||||
2337 | if (Backrefs.NamesCount > 0) | ||||||||
2338 | std::printf("\n"); | ||||||||
2339 | } | ||||||||
2340 | |||||||||
2341 | char *llvm::microsoftDemangle(const char *MangledName, size_t *NMangled, | ||||||||
2342 | char *Buf, size_t *N, | ||||||||
2343 | int *Status, MSDemangleFlags Flags) { | ||||||||
2344 | Demangler D; | ||||||||
2345 | OutputStream S; | ||||||||
2346 | |||||||||
2347 | StringView Name{MangledName}; | ||||||||
2348 | SymbolNode *AST = D.parse(Name); | ||||||||
2349 | if (!D.Error && NMangled) | ||||||||
2350 | *NMangled = Name.begin() - MangledName; | ||||||||
2351 | |||||||||
2352 | if (Flags & MSDF_DumpBackrefs) | ||||||||
2353 | D.dumpBackReferences(); | ||||||||
2354 | |||||||||
2355 | OutputFlags OF = OF_Default; | ||||||||
2356 | if (Flags & MSDF_NoCallingConvention) | ||||||||
2357 | OF = OutputFlags(OF | OF_NoCallingConvention); | ||||||||
2358 | if (Flags & MSDF_NoAccessSpecifier) | ||||||||
2359 | OF = OutputFlags(OF | OF_NoAccessSpecifier); | ||||||||
2360 | if (Flags & MSDF_NoReturnType) | ||||||||
2361 | OF = OutputFlags(OF | OF_NoReturnType); | ||||||||
2362 | if (Flags & MSDF_NoMemberType) | ||||||||
2363 | OF = OutputFlags(OF | OF_NoMemberType); | ||||||||
2364 | |||||||||
2365 | int InternalStatus = demangle_success; | ||||||||
2366 | if (D.Error) | ||||||||
2367 | InternalStatus = demangle_invalid_mangled_name; | ||||||||
2368 | else if (!initializeOutputStream(Buf, N, S, 1024)) | ||||||||
2369 | InternalStatus = demangle_memory_alloc_failure; | ||||||||
2370 | else { | ||||||||
2371 | AST->output(S, OF); | ||||||||
2372 | S += '\0'; | ||||||||
2373 | if (N != nullptr) | ||||||||
2374 | *N = S.getCurrentPosition(); | ||||||||
2375 | Buf = S.getBuffer(); | ||||||||
2376 | } | ||||||||
2377 | |||||||||
2378 | if (Status) | ||||||||
2379 | *Status = InternalStatus; | ||||||||
2380 | return InternalStatus == demangle_success ? Buf : nullptr; | ||||||||
2381 | } |
1 | //===------------------------- MicrosoftDemangle.h --------------*- 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 | #ifndef LLVM_DEMANGLE_MICROSOFTDEMANGLE_H | |||
10 | #define LLVM_DEMANGLE_MICROSOFTDEMANGLE_H | |||
11 | ||||
12 | #include "llvm/Demangle/DemangleConfig.h" | |||
13 | #include "llvm/Demangle/MicrosoftDemangleNodes.h" | |||
14 | #include "llvm/Demangle/StringView.h" | |||
15 | #include "llvm/Demangle/Utility.h" | |||
16 | ||||
17 | #include <utility> | |||
18 | ||||
19 | namespace llvm { | |||
20 | namespace ms_demangle { | |||
21 | // This memory allocator is extremely fast, but it doesn't call dtors | |||
22 | // for allocated objects. That means you can't use STL containers | |||
23 | // (such as std::vector) with this allocator. But it pays off -- | |||
24 | // the demangler is 3x faster with this allocator compared to one with | |||
25 | // STL containers. | |||
26 | constexpr size_t AllocUnit = 4096; | |||
27 | ||||
28 | class ArenaAllocator { | |||
29 | struct AllocatorNode { | |||
30 | uint8_t *Buf = nullptr; | |||
31 | size_t Used = 0; | |||
32 | size_t Capacity = 0; | |||
33 | AllocatorNode *Next = nullptr; | |||
34 | }; | |||
35 | ||||
36 | void addNode(size_t Capacity) { | |||
37 | AllocatorNode *NewHead = new AllocatorNode; | |||
38 | NewHead->Buf = new uint8_t[Capacity]; | |||
39 | NewHead->Next = Head; | |||
40 | NewHead->Capacity = Capacity; | |||
41 | Head = NewHead; | |||
42 | NewHead->Used = 0; | |||
43 | } | |||
44 | ||||
45 | public: | |||
46 | ArenaAllocator() { addNode(AllocUnit); } | |||
47 | ||||
48 | ~ArenaAllocator() { | |||
49 | while (Head) { | |||
50 | assert(Head->Buf)(static_cast <bool> (Head->Buf) ? void (0) : __assert_fail ("Head->Buf", "/build/llvm-toolchain-snapshot-13~++20210726100616+dead50d4427c/llvm/include/llvm/Demangle/MicrosoftDemangle.h" , 50, __extension__ __PRETTY_FUNCTION__)); | |||
51 | delete[] Head->Buf; | |||
52 | AllocatorNode *Next = Head->Next; | |||
53 | delete Head; | |||
54 | Head = Next; | |||
55 | } | |||
56 | } | |||
57 | ||||
58 | char *allocUnalignedBuffer(size_t Size) { | |||
59 | assert(Head && Head->Buf)(static_cast <bool> (Head && Head->Buf) ? void (0) : __assert_fail ("Head && Head->Buf", "/build/llvm-toolchain-snapshot-13~++20210726100616+dead50d4427c/llvm/include/llvm/Demangle/MicrosoftDemangle.h" , 59, __extension__ __PRETTY_FUNCTION__)); | |||
60 | ||||
61 | uint8_t *P = Head->Buf + Head->Used; | |||
62 | ||||
63 | Head->Used += Size; | |||
64 | if (Head->Used <= Head->Capacity) | |||
65 | return reinterpret_cast<char *>(P); | |||
66 | ||||
67 | addNode(std::max(AllocUnit, Size)); | |||
68 | Head->Used = Size; | |||
69 | return reinterpret_cast<char *>(Head->Buf); | |||
70 | } | |||
71 | ||||
72 | template <typename T, typename... Args> T *allocArray(size_t Count) { | |||
73 | size_t Size = Count * sizeof(T); | |||
74 | assert(Head && Head->Buf)(static_cast <bool> (Head && Head->Buf) ? void (0) : __assert_fail ("Head && Head->Buf", "/build/llvm-toolchain-snapshot-13~++20210726100616+dead50d4427c/llvm/include/llvm/Demangle/MicrosoftDemangle.h" , 74, __extension__ __PRETTY_FUNCTION__)); | |||
75 | ||||
76 | size_t P = (size_t)Head->Buf + Head->Used; | |||
77 | uintptr_t AlignedP = | |||
78 | (((size_t)P + alignof(T) - 1) & ~(size_t)(alignof(T) - 1)); | |||
79 | uint8_t *PP = (uint8_t *)AlignedP; | |||
80 | size_t Adjustment = AlignedP - P; | |||
81 | ||||
82 | Head->Used += Size + Adjustment; | |||
83 | if (Head->Used <= Head->Capacity) | |||
84 | return new (PP) T[Count](); | |||
85 | ||||
86 | addNode(std::max(AllocUnit, Size)); | |||
87 | Head->Used = Size; | |||
88 | return new (Head->Buf) T[Count](); | |||
| ||||
89 | } | |||
90 | ||||
91 | template <typename T, typename... Args> T *alloc(Args &&... ConstructorArgs) { | |||
92 | constexpr size_t Size = sizeof(T); | |||
93 | assert(Head && Head->Buf)(static_cast <bool> (Head && Head->Buf) ? void (0) : __assert_fail ("Head && Head->Buf", "/build/llvm-toolchain-snapshot-13~++20210726100616+dead50d4427c/llvm/include/llvm/Demangle/MicrosoftDemangle.h" , 93, __extension__ __PRETTY_FUNCTION__)); | |||
94 | ||||
95 | size_t P = (size_t)Head->Buf + Head->Used; | |||
96 | uintptr_t AlignedP = | |||
97 | (((size_t)P + alignof(T) - 1) & ~(size_t)(alignof(T) - 1)); | |||
98 | uint8_t *PP = (uint8_t *)AlignedP; | |||
99 | size_t Adjustment = AlignedP - P; | |||
100 | ||||
101 | Head->Used += Size + Adjustment; | |||
102 | if (Head->Used <= Head->Capacity) | |||
103 | return new (PP) T(std::forward<Args>(ConstructorArgs)...); | |||
104 | ||||
105 | static_assert(Size < AllocUnit, ""); | |||
106 | addNode(AllocUnit); | |||
107 | Head->Used = Size; | |||
108 | return new (Head->Buf) T(std::forward<Args>(ConstructorArgs)...); | |||
109 | } | |||
110 | ||||
111 | private: | |||
112 | AllocatorNode *Head = nullptr; | |||
113 | }; | |||
114 | ||||
115 | struct BackrefContext { | |||
116 | static constexpr size_t Max = 10; | |||
117 | ||||
118 | TypeNode *FunctionParams[Max]; | |||
119 | size_t FunctionParamCount = 0; | |||
120 | ||||
121 | // The first 10 BackReferences in a mangled name can be back-referenced by | |||
122 | // special name @[0-9]. This is a storage for the first 10 BackReferences. | |||
123 | NamedIdentifierNode *Names[Max]; | |||
124 | size_t NamesCount = 0; | |||
125 | }; | |||
126 | ||||
127 | enum class QualifierMangleMode { Drop, Mangle, Result }; | |||
128 | ||||
129 | enum NameBackrefBehavior : uint8_t { | |||
130 | NBB_None = 0, // don't save any names as backrefs. | |||
131 | NBB_Template = 1 << 0, // save template instanations. | |||
132 | NBB_Simple = 1 << 1, // save simple names. | |||
133 | }; | |||
134 | ||||
135 | enum class FunctionIdentifierCodeGroup { Basic, Under, DoubleUnder }; | |||
136 | ||||
137 | // Demangler class takes the main role in demangling symbols. | |||
138 | // It has a set of functions to parse mangled symbols into Type instances. | |||
139 | // It also has a set of functions to convert Type instances to strings. | |||
140 | class Demangler { | |||
141 | public: | |||
142 | Demangler() = default; | |||
143 | virtual ~Demangler() = default; | |||
144 | ||||
145 | // You are supposed to call parse() first and then check if error is true. If | |||
146 | // it is false, call output() to write the formatted name to the given stream. | |||
147 | SymbolNode *parse(StringView &MangledName); | |||
148 | ||||
149 | TagTypeNode *parseTagUniqueName(StringView &MangledName); | |||
150 | ||||
151 | // True if an error occurred. | |||
152 | bool Error = false; | |||
153 | ||||
154 | void dumpBackReferences(); | |||
155 | ||||
156 | private: | |||
157 | SymbolNode *demangleEncodedSymbol(StringView &MangledName, | |||
158 | QualifiedNameNode *QN); | |||
159 | SymbolNode *demangleDeclarator(StringView &MangledName); | |||
160 | SymbolNode *demangleMD5Name(StringView &MangledName); | |||
161 | SymbolNode *demangleTypeinfoName(StringView &MangledName); | |||
162 | ||||
163 | VariableSymbolNode *demangleVariableEncoding(StringView &MangledName, | |||
164 | StorageClass SC); | |||
165 | FunctionSymbolNode *demangleFunctionEncoding(StringView &MangledName); | |||
166 | ||||
167 | Qualifiers demanglePointerExtQualifiers(StringView &MangledName); | |||
168 | ||||
169 | // Parser functions. This is a recursive-descent parser. | |||
170 | TypeNode *demangleType(StringView &MangledName, QualifierMangleMode QMM); | |||
171 | PrimitiveTypeNode *demanglePrimitiveType(StringView &MangledName); | |||
172 | CustomTypeNode *demangleCustomType(StringView &MangledName); | |||
173 | TagTypeNode *demangleClassType(StringView &MangledName); | |||
174 | PointerTypeNode *demanglePointerType(StringView &MangledName); | |||
175 | PointerTypeNode *demangleMemberPointerType(StringView &MangledName); | |||
176 | FunctionSignatureNode *demangleFunctionType(StringView &MangledName, | |||
177 | bool HasThisQuals); | |||
178 | ||||
179 | ArrayTypeNode *demangleArrayType(StringView &MangledName); | |||
180 | ||||
181 | NodeArrayNode *demangleFunctionParameterList(StringView &MangledName, | |||
182 | bool &IsVariadic); | |||
183 | NodeArrayNode *demangleTemplateParameterList(StringView &MangledName); | |||
184 | ||||
185 | std::pair<uint64_t, bool> demangleNumber(StringView &MangledName); | |||
186 | uint64_t demangleUnsigned(StringView &MangledName); | |||
187 | int64_t demangleSigned(StringView &MangledName); | |||
188 | ||||
189 | void memorizeString(StringView s); | |||
190 | void memorizeIdentifier(IdentifierNode *Identifier); | |||
191 | ||||
192 | /// Allocate a copy of \p Borrowed into memory that we own. | |||
193 | StringView copyString(StringView Borrowed); | |||
194 | ||||
195 | QualifiedNameNode *demangleFullyQualifiedTypeName(StringView &MangledName); | |||
196 | QualifiedNameNode *demangleFullyQualifiedSymbolName(StringView &MangledName); | |||
197 | ||||
198 | IdentifierNode *demangleUnqualifiedTypeName(StringView &MangledName, | |||
199 | bool Memorize); | |||
200 | IdentifierNode *demangleUnqualifiedSymbolName(StringView &MangledName, | |||
201 | NameBackrefBehavior NBB); | |||
202 | ||||
203 | QualifiedNameNode *demangleNameScopeChain(StringView &MangledName, | |||
204 | IdentifierNode *UnqualifiedName); | |||
205 | IdentifierNode *demangleNameScopePiece(StringView &MangledName); | |||
206 | ||||
207 | NamedIdentifierNode *demangleBackRefName(StringView &MangledName); | |||
208 | IdentifierNode *demangleTemplateInstantiationName(StringView &MangledName, | |||
209 | NameBackrefBehavior NBB); | |||
210 | IntrinsicFunctionKind | |||
211 | translateIntrinsicFunctionCode(char CH, FunctionIdentifierCodeGroup Group); | |||
212 | IdentifierNode *demangleFunctionIdentifierCode(StringView &MangledName); | |||
213 | IdentifierNode * | |||
214 | demangleFunctionIdentifierCode(StringView &MangledName, | |||
215 | FunctionIdentifierCodeGroup Group); | |||
216 | StructorIdentifierNode *demangleStructorIdentifier(StringView &MangledName, | |||
217 | bool IsDestructor); | |||
218 | ConversionOperatorIdentifierNode * | |||
219 | demangleConversionOperatorIdentifier(StringView &MangledName); | |||
220 | LiteralOperatorIdentifierNode * | |||
221 | demangleLiteralOperatorIdentifier(StringView &MangledName); | |||
222 | ||||
223 | SymbolNode *demangleSpecialIntrinsic(StringView &MangledName); | |||
224 | SpecialTableSymbolNode * | |||
225 | demangleSpecialTableSymbolNode(StringView &MangledName, | |||
226 | SpecialIntrinsicKind SIK); | |||
227 | LocalStaticGuardVariableNode * | |||
228 | demangleLocalStaticGuard(StringView &MangledName, bool IsThread); | |||
229 | VariableSymbolNode *demangleUntypedVariable(ArenaAllocator &Arena, | |||
230 | StringView &MangledName, | |||
231 | StringView VariableName); | |||
232 | VariableSymbolNode * | |||
233 | demangleRttiBaseClassDescriptorNode(ArenaAllocator &Arena, | |||
234 | StringView &MangledName); | |||
235 | FunctionSymbolNode *demangleInitFiniStub(StringView &MangledName, | |||
236 | bool IsDestructor); | |||
237 | ||||
238 | NamedIdentifierNode *demangleSimpleName(StringView &MangledName, | |||
239 | bool Memorize); | |||
240 | NamedIdentifierNode *demangleAnonymousNamespaceName(StringView &MangledName); | |||
241 | NamedIdentifierNode *demangleLocallyScopedNamePiece(StringView &MangledName); | |||
242 | EncodedStringLiteralNode *demangleStringLiteral(StringView &MangledName); | |||
243 | FunctionSymbolNode *demangleVcallThunkNode(StringView &MangledName); | |||
244 | ||||
245 | StringView demangleSimpleString(StringView &MangledName, bool Memorize); | |||
246 | ||||
247 | FuncClass demangleFunctionClass(StringView &MangledName); | |||
248 | CallingConv demangleCallingConvention(StringView &MangledName); | |||
249 | StorageClass demangleVariableStorageClass(StringView &MangledName); | |||
250 | bool demangleThrowSpecification(StringView &MangledName); | |||
251 | wchar_t demangleWcharLiteral(StringView &MangledName); | |||
252 | uint8_t demangleCharLiteral(StringView &MangledName); | |||
253 | ||||
254 | std::pair<Qualifiers, bool> demangleQualifiers(StringView &MangledName); | |||
255 | ||||
256 | // Memory allocator. | |||
257 | ArenaAllocator Arena; | |||
258 | ||||
259 | // A single type uses one global back-ref table for all function params. | |||
260 | // This means back-refs can even go "into" other types. Examples: | |||
261 | // | |||
262 | // // Second int* is a back-ref to first. | |||
263 | // void foo(int *, int*); | |||
264 | // | |||
265 | // // Second int* is not a back-ref to first (first is not a function param). | |||
266 | // int* foo(int*); | |||
267 | // | |||
268 | // // Second int* is a back-ref to first (ALL function types share the same | |||
269 | // // back-ref map. | |||
270 | // using F = void(*)(int*); | |||
271 | // F G(int *); | |||
272 | BackrefContext Backrefs; | |||
273 | }; | |||
274 | ||||
275 | } // namespace ms_demangle | |||
276 | } // namespace llvm | |||
277 | ||||
278 | #endif // LLVM_DEMANGLE_MICROSOFTDEMANGLE_H |