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