xref: /freebsd-src/contrib/llvm-project/llvm/lib/Demangle/MicrosoftDemangle.cpp (revision 415efcecd8b80f68e76376ef2b854cb6f5c84b5a)
10b57cec5SDimitry Andric //===- MicrosoftDemangle.cpp ----------------------------------------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // This file defines a demangler for MSVC-style mangled symbols.
100b57cec5SDimitry Andric //
110b57cec5SDimitry Andric // This file has no dependencies on the rest of LLVM so that it can be
120b57cec5SDimitry Andric // easily reused in other programs such as libcxxabi.
130b57cec5SDimitry Andric //
140b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
150b57cec5SDimitry Andric 
160b57cec5SDimitry Andric #include "llvm/Demangle/MicrosoftDemangle.h"
170b57cec5SDimitry Andric 
1806c3fb27SDimitry Andric #include "llvm/Demangle/Demangle.h"
190b57cec5SDimitry Andric #include "llvm/Demangle/DemangleConfig.h"
2006c3fb27SDimitry Andric #include "llvm/Demangle/MicrosoftDemangleNodes.h"
2106c3fb27SDimitry Andric #include "llvm/Demangle/StringViewExtras.h"
220b57cec5SDimitry Andric #include "llvm/Demangle/Utility.h"
230b57cec5SDimitry Andric 
240b57cec5SDimitry Andric #include <array>
250b57cec5SDimitry Andric #include <cctype>
260b57cec5SDimitry Andric #include <cstdio>
27*415efcecSDimitry Andric #include <optional>
2806c3fb27SDimitry Andric #include <string_view>
290b57cec5SDimitry Andric #include <tuple>
300b57cec5SDimitry Andric 
310b57cec5SDimitry Andric using namespace llvm;
320b57cec5SDimitry Andric using namespace ms_demangle;
330b57cec5SDimitry Andric 
3406c3fb27SDimitry Andric static bool startsWithDigit(std::string_view S) {
350b57cec5SDimitry Andric   return !S.empty() && std::isdigit(S.front());
360b57cec5SDimitry Andric }
370b57cec5SDimitry Andric 
380b57cec5SDimitry Andric struct NodeList {
390b57cec5SDimitry Andric   Node *N = nullptr;
400b57cec5SDimitry Andric   NodeList *Next = nullptr;
410b57cec5SDimitry Andric };
420b57cec5SDimitry Andric 
4306c3fb27SDimitry Andric static bool consumeFront(std::string_view &S, char C) {
4406c3fb27SDimitry Andric   if (!llvm::itanium_demangle::starts_with(S, C))
4506c3fb27SDimitry Andric     return false;
4606c3fb27SDimitry Andric   S.remove_prefix(1);
4706c3fb27SDimitry Andric   return true;
4806c3fb27SDimitry Andric }
4906c3fb27SDimitry Andric 
5006c3fb27SDimitry Andric static bool consumeFront(std::string_view &S, std::string_view C) {
5106c3fb27SDimitry Andric   if (!llvm::itanium_demangle::starts_with(S, C))
5206c3fb27SDimitry Andric     return false;
5306c3fb27SDimitry Andric   S.remove_prefix(C.size());
5406c3fb27SDimitry Andric   return true;
5506c3fb27SDimitry Andric }
5606c3fb27SDimitry Andric 
570fca6ea1SDimitry Andric static bool consumeFront(std::string_view &S, std::string_view PrefixA,
580fca6ea1SDimitry Andric                          std::string_view PrefixB, bool A) {
590fca6ea1SDimitry Andric   const std::string_view &Prefix = A ? PrefixA : PrefixB;
600fca6ea1SDimitry Andric   return consumeFront(S, Prefix);
610fca6ea1SDimitry Andric }
620fca6ea1SDimitry Andric 
630fca6ea1SDimitry Andric static bool startsWith(std::string_view S, std::string_view PrefixA,
640fca6ea1SDimitry Andric                        std::string_view PrefixB, bool A) {
650fca6ea1SDimitry Andric   const std::string_view &Prefix = A ? PrefixA : PrefixB;
660fca6ea1SDimitry Andric   return llvm::itanium_demangle::starts_with(S, Prefix);
670fca6ea1SDimitry Andric }
680fca6ea1SDimitry Andric 
6906c3fb27SDimitry Andric static bool isMemberPointer(std::string_view MangledName, bool &Error) {
700b57cec5SDimitry Andric   Error = false;
7106c3fb27SDimitry Andric   const char F = MangledName.front();
7206c3fb27SDimitry Andric   MangledName.remove_prefix(1);
7306c3fb27SDimitry Andric   switch (F) {
740b57cec5SDimitry Andric   case '$':
750b57cec5SDimitry Andric     // This is probably an rvalue reference (e.g. $$Q), and you cannot have an
760b57cec5SDimitry Andric     // rvalue reference to a member.
770b57cec5SDimitry Andric     return false;
780b57cec5SDimitry Andric   case 'A':
790b57cec5SDimitry Andric     // 'A' indicates a reference, and you cannot have a reference to a member
800b57cec5SDimitry Andric     // function or member.
810b57cec5SDimitry Andric     return false;
820b57cec5SDimitry Andric   case 'P':
830b57cec5SDimitry Andric   case 'Q':
840b57cec5SDimitry Andric   case 'R':
850b57cec5SDimitry Andric   case 'S':
860b57cec5SDimitry Andric     // These 4 values indicate some kind of pointer, but we still don't know
870b57cec5SDimitry Andric     // what.
880b57cec5SDimitry Andric     break;
890b57cec5SDimitry Andric   default:
900b57cec5SDimitry Andric     // isMemberPointer() is called only if isPointerType() returns true,
910b57cec5SDimitry Andric     // and it rejects other prefixes.
920b57cec5SDimitry Andric     DEMANGLE_UNREACHABLE;
930b57cec5SDimitry Andric   }
940b57cec5SDimitry Andric 
950b57cec5SDimitry Andric   // If it starts with a number, then 6 indicates a non-member function
960b57cec5SDimitry Andric   // pointer, and 8 indicates a member function pointer.
970b57cec5SDimitry Andric   if (startsWithDigit(MangledName)) {
980b57cec5SDimitry Andric     if (MangledName[0] != '6' && MangledName[0] != '8') {
990b57cec5SDimitry Andric       Error = true;
1000b57cec5SDimitry Andric       return false;
1010b57cec5SDimitry Andric     }
1020b57cec5SDimitry Andric     return (MangledName[0] == '8');
1030b57cec5SDimitry Andric   }
1040b57cec5SDimitry Andric 
1050b57cec5SDimitry Andric   // Remove ext qualifiers since those can appear on either type and are
1060b57cec5SDimitry Andric   // therefore not indicative.
10706c3fb27SDimitry Andric   consumeFront(MangledName, 'E'); // 64-bit
10806c3fb27SDimitry Andric   consumeFront(MangledName, 'I'); // restrict
10906c3fb27SDimitry Andric   consumeFront(MangledName, 'F'); // unaligned
1100b57cec5SDimitry Andric 
1110b57cec5SDimitry Andric   if (MangledName.empty()) {
1120b57cec5SDimitry Andric     Error = true;
1130b57cec5SDimitry Andric     return false;
1140b57cec5SDimitry Andric   }
1150b57cec5SDimitry Andric 
1160b57cec5SDimitry Andric   // The next value should be either ABCD (non-member) or QRST (member).
1170b57cec5SDimitry Andric   switch (MangledName.front()) {
1180b57cec5SDimitry Andric   case 'A':
1190b57cec5SDimitry Andric   case 'B':
1200b57cec5SDimitry Andric   case 'C':
1210b57cec5SDimitry Andric   case 'D':
1220b57cec5SDimitry Andric     return false;
1230b57cec5SDimitry Andric   case 'Q':
1240b57cec5SDimitry Andric   case 'R':
1250b57cec5SDimitry Andric   case 'S':
1260b57cec5SDimitry Andric   case 'T':
1270b57cec5SDimitry Andric     return true;
1280b57cec5SDimitry Andric   default:
1290b57cec5SDimitry Andric     Error = true;
1300b57cec5SDimitry Andric     return false;
1310b57cec5SDimitry Andric   }
1320b57cec5SDimitry Andric }
1330b57cec5SDimitry Andric 
1340b57cec5SDimitry Andric static SpecialIntrinsicKind
13506c3fb27SDimitry Andric consumeSpecialIntrinsicKind(std::string_view &MangledName) {
13606c3fb27SDimitry Andric   if (consumeFront(MangledName, "?_7"))
1370b57cec5SDimitry Andric     return SpecialIntrinsicKind::Vftable;
13806c3fb27SDimitry Andric   if (consumeFront(MangledName, "?_8"))
1390b57cec5SDimitry Andric     return SpecialIntrinsicKind::Vbtable;
14006c3fb27SDimitry Andric   if (consumeFront(MangledName, "?_9"))
1410b57cec5SDimitry Andric     return SpecialIntrinsicKind::VcallThunk;
14206c3fb27SDimitry Andric   if (consumeFront(MangledName, "?_A"))
1430b57cec5SDimitry Andric     return SpecialIntrinsicKind::Typeof;
14406c3fb27SDimitry Andric   if (consumeFront(MangledName, "?_B"))
1450b57cec5SDimitry Andric     return SpecialIntrinsicKind::LocalStaticGuard;
14606c3fb27SDimitry Andric   if (consumeFront(MangledName, "?_C"))
1470b57cec5SDimitry Andric     return SpecialIntrinsicKind::StringLiteralSymbol;
14806c3fb27SDimitry Andric   if (consumeFront(MangledName, "?_P"))
1490b57cec5SDimitry Andric     return SpecialIntrinsicKind::UdtReturning;
15006c3fb27SDimitry Andric   if (consumeFront(MangledName, "?_R0"))
1510b57cec5SDimitry Andric     return SpecialIntrinsicKind::RttiTypeDescriptor;
15206c3fb27SDimitry Andric   if (consumeFront(MangledName, "?_R1"))
1530b57cec5SDimitry Andric     return SpecialIntrinsicKind::RttiBaseClassDescriptor;
15406c3fb27SDimitry Andric   if (consumeFront(MangledName, "?_R2"))
1550b57cec5SDimitry Andric     return SpecialIntrinsicKind::RttiBaseClassArray;
15606c3fb27SDimitry Andric   if (consumeFront(MangledName, "?_R3"))
1570b57cec5SDimitry Andric     return SpecialIntrinsicKind::RttiClassHierarchyDescriptor;
15806c3fb27SDimitry Andric   if (consumeFront(MangledName, "?_R4"))
1590b57cec5SDimitry Andric     return SpecialIntrinsicKind::RttiCompleteObjLocator;
16006c3fb27SDimitry Andric   if (consumeFront(MangledName, "?_S"))
1610b57cec5SDimitry Andric     return SpecialIntrinsicKind::LocalVftable;
16206c3fb27SDimitry Andric   if (consumeFront(MangledName, "?__E"))
1630b57cec5SDimitry Andric     return SpecialIntrinsicKind::DynamicInitializer;
16406c3fb27SDimitry Andric   if (consumeFront(MangledName, "?__F"))
1650b57cec5SDimitry Andric     return SpecialIntrinsicKind::DynamicAtexitDestructor;
16606c3fb27SDimitry Andric   if (consumeFront(MangledName, "?__J"))
1670b57cec5SDimitry Andric     return SpecialIntrinsicKind::LocalStaticThreadGuard;
1680b57cec5SDimitry Andric   return SpecialIntrinsicKind::None;
1690b57cec5SDimitry Andric }
1700b57cec5SDimitry Andric 
17106c3fb27SDimitry Andric static bool startsWithLocalScopePattern(std::string_view S) {
17206c3fb27SDimitry Andric   if (!consumeFront(S, '?'))
1730b57cec5SDimitry Andric     return false;
1740b57cec5SDimitry Andric 
1750b57cec5SDimitry Andric   size_t End = S.find('?');
17606c3fb27SDimitry Andric   if (End == std::string_view::npos)
1770b57cec5SDimitry Andric     return false;
17806c3fb27SDimitry Andric   std::string_view Candidate = S.substr(0, End);
1790b57cec5SDimitry Andric   if (Candidate.empty())
1800b57cec5SDimitry Andric     return false;
1810b57cec5SDimitry Andric 
1820b57cec5SDimitry Andric   // \?[0-9]\?
1830b57cec5SDimitry Andric   // ?@? is the discriminator 0.
1840b57cec5SDimitry Andric   if (Candidate.size() == 1)
1850b57cec5SDimitry Andric     return Candidate[0] == '@' || (Candidate[0] >= '0' && Candidate[0] <= '9');
1860b57cec5SDimitry Andric 
1870b57cec5SDimitry Andric   // If it's not 0-9, then it's an encoded number terminated with an @
1880b57cec5SDimitry Andric   if (Candidate.back() != '@')
1890b57cec5SDimitry Andric     return false;
19006c3fb27SDimitry Andric   Candidate.remove_suffix(1);
1910b57cec5SDimitry Andric 
1920b57cec5SDimitry Andric   // An encoded number starts with B-P and all subsequent digits are in A-P.
1930b57cec5SDimitry Andric   // Note that the reason the first digit cannot be A is two fold.  First, it
1940b57cec5SDimitry Andric   // would create an ambiguity with ?A which delimits the beginning of an
1950b57cec5SDimitry Andric   // anonymous namespace.  Second, A represents 0, and you don't start a multi
1960b57cec5SDimitry Andric   // digit number with a leading 0.  Presumably the anonymous namespace
1970b57cec5SDimitry Andric   // ambiguity is also why single digit encoded numbers use 0-9 rather than A-J.
1980b57cec5SDimitry Andric   if (Candidate[0] < 'B' || Candidate[0] > 'P')
1990b57cec5SDimitry Andric     return false;
20006c3fb27SDimitry Andric   Candidate.remove_prefix(1);
2010b57cec5SDimitry Andric   while (!Candidate.empty()) {
2020b57cec5SDimitry Andric     if (Candidate[0] < 'A' || Candidate[0] > 'P')
2030b57cec5SDimitry Andric       return false;
20406c3fb27SDimitry Andric     Candidate.remove_prefix(1);
2050b57cec5SDimitry Andric   }
2060b57cec5SDimitry Andric 
2070b57cec5SDimitry Andric   return true;
2080b57cec5SDimitry Andric }
2090b57cec5SDimitry Andric 
21006c3fb27SDimitry Andric static bool isTagType(std::string_view S) {
2110b57cec5SDimitry Andric   switch (S.front()) {
2120b57cec5SDimitry Andric   case 'T': // union
2130b57cec5SDimitry Andric   case 'U': // struct
2140b57cec5SDimitry Andric   case 'V': // class
2150b57cec5SDimitry Andric   case 'W': // enum
2160b57cec5SDimitry Andric     return true;
2170b57cec5SDimitry Andric   }
2180b57cec5SDimitry Andric   return false;
2190b57cec5SDimitry Andric }
2200b57cec5SDimitry Andric 
22106c3fb27SDimitry Andric static bool isCustomType(std::string_view S) { return S[0] == '?'; }
2220b57cec5SDimitry Andric 
22306c3fb27SDimitry Andric static bool isPointerType(std::string_view S) {
22406c3fb27SDimitry Andric   if (llvm::itanium_demangle::starts_with(S, "$$Q")) // foo &&
2250b57cec5SDimitry Andric     return true;
2260b57cec5SDimitry Andric 
2270b57cec5SDimitry Andric   switch (S.front()) {
2280b57cec5SDimitry Andric   case 'A': // foo &
2290b57cec5SDimitry Andric   case 'P': // foo *
2300b57cec5SDimitry Andric   case 'Q': // foo *const
2310b57cec5SDimitry Andric   case 'R': // foo *volatile
2320b57cec5SDimitry Andric   case 'S': // foo *const volatile
2330b57cec5SDimitry Andric     return true;
2340b57cec5SDimitry Andric   }
2350b57cec5SDimitry Andric   return false;
2360b57cec5SDimitry Andric }
2370b57cec5SDimitry Andric 
23806c3fb27SDimitry Andric static bool isArrayType(std::string_view S) { return S[0] == 'Y'; }
2390b57cec5SDimitry Andric 
24006c3fb27SDimitry Andric static bool isFunctionType(std::string_view S) {
24106c3fb27SDimitry Andric   return llvm::itanium_demangle::starts_with(S, "$$A8@@") ||
24206c3fb27SDimitry Andric          llvm::itanium_demangle::starts_with(S, "$$A6");
2430b57cec5SDimitry Andric }
2440b57cec5SDimitry Andric 
2450b57cec5SDimitry Andric static FunctionRefQualifier
24606c3fb27SDimitry Andric demangleFunctionRefQualifier(std::string_view &MangledName) {
24706c3fb27SDimitry Andric   if (consumeFront(MangledName, 'G'))
2480b57cec5SDimitry Andric     return FunctionRefQualifier::Reference;
24906c3fb27SDimitry Andric   else if (consumeFront(MangledName, 'H'))
2500b57cec5SDimitry Andric     return FunctionRefQualifier::RValueReference;
2510b57cec5SDimitry Andric   return FunctionRefQualifier::None;
2520b57cec5SDimitry Andric }
2530b57cec5SDimitry Andric 
2540b57cec5SDimitry Andric static std::pair<Qualifiers, PointerAffinity>
25506c3fb27SDimitry Andric demanglePointerCVQualifiers(std::string_view &MangledName) {
25606c3fb27SDimitry Andric   if (consumeFront(MangledName, "$$Q"))
2570b57cec5SDimitry Andric     return std::make_pair(Q_None, PointerAffinity::RValueReference);
2580b57cec5SDimitry Andric 
25906c3fb27SDimitry Andric   const char F = MangledName.front();
26006c3fb27SDimitry Andric   MangledName.remove_prefix(1);
26106c3fb27SDimitry Andric   switch (F) {
2620b57cec5SDimitry Andric   case 'A':
2630b57cec5SDimitry Andric     return std::make_pair(Q_None, PointerAffinity::Reference);
2640b57cec5SDimitry Andric   case 'P':
2650b57cec5SDimitry Andric     return std::make_pair(Q_None, PointerAffinity::Pointer);
2660b57cec5SDimitry Andric   case 'Q':
2670b57cec5SDimitry Andric     return std::make_pair(Q_Const, PointerAffinity::Pointer);
2680b57cec5SDimitry Andric   case 'R':
2690b57cec5SDimitry Andric     return std::make_pair(Q_Volatile, PointerAffinity::Pointer);
2700b57cec5SDimitry Andric   case 'S':
2710b57cec5SDimitry Andric     return std::make_pair(Qualifiers(Q_Const | Q_Volatile),
2720b57cec5SDimitry Andric                           PointerAffinity::Pointer);
2730b57cec5SDimitry Andric   }
2740b57cec5SDimitry Andric   // This function is only called if isPointerType() returns true,
2750b57cec5SDimitry Andric   // and it only returns true for the six cases listed above.
2760b57cec5SDimitry Andric   DEMANGLE_UNREACHABLE;
2770b57cec5SDimitry Andric }
2780b57cec5SDimitry Andric 
27906c3fb27SDimitry Andric std::string_view Demangler::copyString(std::string_view Borrowed) {
28081ad6265SDimitry Andric   char *Stable = Arena.allocUnalignedBuffer(Borrowed.size());
281bdd1243dSDimitry Andric   // This is not a micro-optimization, it avoids UB, should Borrowed be an null
282bdd1243dSDimitry Andric   // buffer.
283bdd1243dSDimitry Andric   if (Borrowed.size())
28406c3fb27SDimitry Andric     std::memcpy(Stable, Borrowed.data(), Borrowed.size());
2850b57cec5SDimitry Andric 
2860b57cec5SDimitry Andric   return {Stable, Borrowed.size()};
2870b57cec5SDimitry Andric }
2880b57cec5SDimitry Andric 
2890b57cec5SDimitry Andric SpecialTableSymbolNode *
29006c3fb27SDimitry Andric Demangler::demangleSpecialTableSymbolNode(std::string_view &MangledName,
2910b57cec5SDimitry Andric                                           SpecialIntrinsicKind K) {
2920b57cec5SDimitry Andric   NamedIdentifierNode *NI = Arena.alloc<NamedIdentifierNode>();
2930b57cec5SDimitry Andric   switch (K) {
2940b57cec5SDimitry Andric   case SpecialIntrinsicKind::Vftable:
2950b57cec5SDimitry Andric     NI->Name = "`vftable'";
2960b57cec5SDimitry Andric     break;
2970b57cec5SDimitry Andric   case SpecialIntrinsicKind::Vbtable:
2980b57cec5SDimitry Andric     NI->Name = "`vbtable'";
2990b57cec5SDimitry Andric     break;
3000b57cec5SDimitry Andric   case SpecialIntrinsicKind::LocalVftable:
3010b57cec5SDimitry Andric     NI->Name = "`local vftable'";
3020b57cec5SDimitry Andric     break;
3030b57cec5SDimitry Andric   case SpecialIntrinsicKind::RttiCompleteObjLocator:
3040b57cec5SDimitry Andric     NI->Name = "`RTTI Complete Object Locator'";
3050b57cec5SDimitry Andric     break;
3060b57cec5SDimitry Andric   default:
3070b57cec5SDimitry Andric     DEMANGLE_UNREACHABLE;
3080b57cec5SDimitry Andric   }
3090b57cec5SDimitry Andric   QualifiedNameNode *QN = demangleNameScopeChain(MangledName, NI);
3100b57cec5SDimitry Andric   SpecialTableSymbolNode *STSN = Arena.alloc<SpecialTableSymbolNode>();
3110b57cec5SDimitry Andric   STSN->Name = QN;
3120b57cec5SDimitry Andric   bool IsMember = false;
3130b57cec5SDimitry Andric   if (MangledName.empty()) {
3140b57cec5SDimitry Andric     Error = true;
3150b57cec5SDimitry Andric     return nullptr;
3160b57cec5SDimitry Andric   }
31706c3fb27SDimitry Andric   char Front = MangledName.front();
31806c3fb27SDimitry Andric   MangledName.remove_prefix(1);
3190b57cec5SDimitry Andric   if (Front != '6' && Front != '7') {
3200b57cec5SDimitry Andric     Error = true;
3210b57cec5SDimitry Andric     return nullptr;
3220b57cec5SDimitry Andric   }
3230b57cec5SDimitry Andric 
3240b57cec5SDimitry Andric   std::tie(STSN->Quals, IsMember) = demangleQualifiers(MangledName);
32506c3fb27SDimitry Andric   if (!consumeFront(MangledName, '@'))
3260b57cec5SDimitry Andric     STSN->TargetName = demangleFullyQualifiedTypeName(MangledName);
3270b57cec5SDimitry Andric   return STSN;
3280b57cec5SDimitry Andric }
3290b57cec5SDimitry Andric 
3300b57cec5SDimitry Andric LocalStaticGuardVariableNode *
33106c3fb27SDimitry Andric Demangler::demangleLocalStaticGuard(std::string_view &MangledName,
33206c3fb27SDimitry Andric                                     bool IsThread) {
3330b57cec5SDimitry Andric   LocalStaticGuardIdentifierNode *LSGI =
3340b57cec5SDimitry Andric       Arena.alloc<LocalStaticGuardIdentifierNode>();
3350b57cec5SDimitry Andric   LSGI->IsThread = IsThread;
3360b57cec5SDimitry Andric   QualifiedNameNode *QN = demangleNameScopeChain(MangledName, LSGI);
3370b57cec5SDimitry Andric   LocalStaticGuardVariableNode *LSGVN =
3380b57cec5SDimitry Andric       Arena.alloc<LocalStaticGuardVariableNode>();
3390b57cec5SDimitry Andric   LSGVN->Name = QN;
3400b57cec5SDimitry Andric 
34106c3fb27SDimitry Andric   if (consumeFront(MangledName, "4IA"))
3420b57cec5SDimitry Andric     LSGVN->IsVisible = false;
34306c3fb27SDimitry Andric   else if (consumeFront(MangledName, "5"))
3440b57cec5SDimitry Andric     LSGVN->IsVisible = true;
3450b57cec5SDimitry Andric   else {
3460b57cec5SDimitry Andric     Error = true;
3470b57cec5SDimitry Andric     return nullptr;
3480b57cec5SDimitry Andric   }
3490b57cec5SDimitry Andric 
3500b57cec5SDimitry Andric   if (!MangledName.empty())
3510b57cec5SDimitry Andric     LSGI->ScopeIndex = demangleUnsigned(MangledName);
3520b57cec5SDimitry Andric   return LSGVN;
3530b57cec5SDimitry Andric }
3540b57cec5SDimitry Andric 
3550b57cec5SDimitry Andric static NamedIdentifierNode *synthesizeNamedIdentifier(ArenaAllocator &Arena,
35606c3fb27SDimitry Andric                                                       std::string_view Name) {
3570b57cec5SDimitry Andric   NamedIdentifierNode *Id = Arena.alloc<NamedIdentifierNode>();
3580b57cec5SDimitry Andric   Id->Name = Name;
3590b57cec5SDimitry Andric   return Id;
3600b57cec5SDimitry Andric }
3610b57cec5SDimitry Andric 
3620b57cec5SDimitry Andric static QualifiedNameNode *synthesizeQualifiedName(ArenaAllocator &Arena,
3630b57cec5SDimitry Andric                                                   IdentifierNode *Identifier) {
3640b57cec5SDimitry Andric   QualifiedNameNode *QN = Arena.alloc<QualifiedNameNode>();
3650b57cec5SDimitry Andric   QN->Components = Arena.alloc<NodeArrayNode>();
3660b57cec5SDimitry Andric   QN->Components->Count = 1;
3670b57cec5SDimitry Andric   QN->Components->Nodes = Arena.allocArray<Node *>(1);
3680b57cec5SDimitry Andric   QN->Components->Nodes[0] = Identifier;
3690b57cec5SDimitry Andric   return QN;
3700b57cec5SDimitry Andric }
3710b57cec5SDimitry Andric 
3720b57cec5SDimitry Andric static QualifiedNameNode *synthesizeQualifiedName(ArenaAllocator &Arena,
37306c3fb27SDimitry Andric                                                   std::string_view Name) {
3740b57cec5SDimitry Andric   NamedIdentifierNode *Id = synthesizeNamedIdentifier(Arena, Name);
3750b57cec5SDimitry Andric   return synthesizeQualifiedName(Arena, Id);
3760b57cec5SDimitry Andric }
3770b57cec5SDimitry Andric 
3780b57cec5SDimitry Andric static VariableSymbolNode *synthesizeVariable(ArenaAllocator &Arena,
3790b57cec5SDimitry Andric                                               TypeNode *Type,
38006c3fb27SDimitry Andric                                               std::string_view VariableName) {
3810b57cec5SDimitry Andric   VariableSymbolNode *VSN = Arena.alloc<VariableSymbolNode>();
3820b57cec5SDimitry Andric   VSN->Type = Type;
3830b57cec5SDimitry Andric   VSN->Name = synthesizeQualifiedName(Arena, VariableName);
3840b57cec5SDimitry Andric   return VSN;
3850b57cec5SDimitry Andric }
3860b57cec5SDimitry Andric 
38706c3fb27SDimitry Andric VariableSymbolNode *
38806c3fb27SDimitry Andric Demangler::demangleUntypedVariable(ArenaAllocator &Arena,
38906c3fb27SDimitry Andric                                    std::string_view &MangledName,
39006c3fb27SDimitry Andric                                    std::string_view VariableName) {
3910b57cec5SDimitry Andric   NamedIdentifierNode *NI = synthesizeNamedIdentifier(Arena, VariableName);
3920b57cec5SDimitry Andric   QualifiedNameNode *QN = demangleNameScopeChain(MangledName, NI);
3930b57cec5SDimitry Andric   VariableSymbolNode *VSN = Arena.alloc<VariableSymbolNode>();
3940b57cec5SDimitry Andric   VSN->Name = QN;
39506c3fb27SDimitry Andric   if (consumeFront(MangledName, "8"))
3960b57cec5SDimitry Andric     return VSN;
3970b57cec5SDimitry Andric 
3980b57cec5SDimitry Andric   Error = true;
3990b57cec5SDimitry Andric   return nullptr;
4000b57cec5SDimitry Andric }
4010b57cec5SDimitry Andric 
4020b57cec5SDimitry Andric VariableSymbolNode *
4030b57cec5SDimitry Andric Demangler::demangleRttiBaseClassDescriptorNode(ArenaAllocator &Arena,
40406c3fb27SDimitry Andric                                                std::string_view &MangledName) {
4050b57cec5SDimitry Andric   RttiBaseClassDescriptorNode *RBCDN =
4060b57cec5SDimitry Andric       Arena.alloc<RttiBaseClassDescriptorNode>();
4070b57cec5SDimitry Andric   RBCDN->NVOffset = demangleUnsigned(MangledName);
4080b57cec5SDimitry Andric   RBCDN->VBPtrOffset = demangleSigned(MangledName);
4090b57cec5SDimitry Andric   RBCDN->VBTableOffset = demangleUnsigned(MangledName);
4100b57cec5SDimitry Andric   RBCDN->Flags = demangleUnsigned(MangledName);
4110b57cec5SDimitry Andric   if (Error)
4120b57cec5SDimitry Andric     return nullptr;
4130b57cec5SDimitry Andric 
4140b57cec5SDimitry Andric   VariableSymbolNode *VSN = Arena.alloc<VariableSymbolNode>();
4150b57cec5SDimitry Andric   VSN->Name = demangleNameScopeChain(MangledName, RBCDN);
41606c3fb27SDimitry Andric   consumeFront(MangledName, '8');
4170b57cec5SDimitry Andric   return VSN;
4180b57cec5SDimitry Andric }
4190b57cec5SDimitry Andric 
42006c3fb27SDimitry Andric FunctionSymbolNode *
42106c3fb27SDimitry Andric Demangler::demangleInitFiniStub(std::string_view &MangledName,
4220b57cec5SDimitry Andric                                 bool IsDestructor) {
4230b57cec5SDimitry Andric   DynamicStructorIdentifierNode *DSIN =
4240b57cec5SDimitry Andric       Arena.alloc<DynamicStructorIdentifierNode>();
4250b57cec5SDimitry Andric   DSIN->IsDestructor = IsDestructor;
4260b57cec5SDimitry Andric 
4270b57cec5SDimitry Andric   bool IsKnownStaticDataMember = false;
42806c3fb27SDimitry Andric   if (consumeFront(MangledName, '?'))
4290b57cec5SDimitry Andric     IsKnownStaticDataMember = true;
4300b57cec5SDimitry Andric 
4310b57cec5SDimitry Andric   SymbolNode *Symbol = demangleDeclarator(MangledName);
4320b57cec5SDimitry Andric   if (Error)
4330b57cec5SDimitry Andric     return nullptr;
4340b57cec5SDimitry Andric 
4350b57cec5SDimitry Andric   FunctionSymbolNode *FSN = nullptr;
4360b57cec5SDimitry Andric 
4370b57cec5SDimitry Andric   if (Symbol->kind() == NodeKind::VariableSymbol) {
4380b57cec5SDimitry Andric     DSIN->Variable = static_cast<VariableSymbolNode *>(Symbol);
4390b57cec5SDimitry Andric 
4400b57cec5SDimitry Andric     // Older versions of clang mangled this type of symbol incorrectly.  They
4410b57cec5SDimitry Andric     // would omit the leading ? and they would only emit a single @ at the end.
4420b57cec5SDimitry Andric     // The correct mangling is a leading ? and 2 trailing @ signs.  Handle
4430b57cec5SDimitry Andric     // both cases.
4440b57cec5SDimitry Andric     int AtCount = IsKnownStaticDataMember ? 2 : 1;
4450b57cec5SDimitry Andric     for (int I = 0; I < AtCount; ++I) {
44606c3fb27SDimitry Andric       if (consumeFront(MangledName, '@'))
4470b57cec5SDimitry Andric         continue;
4480b57cec5SDimitry Andric       Error = true;
4490b57cec5SDimitry Andric       return nullptr;
4500b57cec5SDimitry Andric     }
4510b57cec5SDimitry Andric 
4520b57cec5SDimitry Andric     FSN = demangleFunctionEncoding(MangledName);
4530b57cec5SDimitry Andric     if (FSN)
4540b57cec5SDimitry Andric       FSN->Name = synthesizeQualifiedName(Arena, DSIN);
4550b57cec5SDimitry Andric   } else {
4560b57cec5SDimitry Andric     if (IsKnownStaticDataMember) {
4570b57cec5SDimitry Andric       // This was supposed to be a static data member, but we got a function.
4580b57cec5SDimitry Andric       Error = true;
4590b57cec5SDimitry Andric       return nullptr;
4600b57cec5SDimitry Andric     }
4610b57cec5SDimitry Andric 
4620b57cec5SDimitry Andric     FSN = static_cast<FunctionSymbolNode *>(Symbol);
4630b57cec5SDimitry Andric     DSIN->Name = Symbol->Name;
4640b57cec5SDimitry Andric     FSN->Name = synthesizeQualifiedName(Arena, DSIN);
4650b57cec5SDimitry Andric   }
4660b57cec5SDimitry Andric 
4670b57cec5SDimitry Andric   return FSN;
4680b57cec5SDimitry Andric }
4690b57cec5SDimitry Andric 
47006c3fb27SDimitry Andric SymbolNode *Demangler::demangleSpecialIntrinsic(std::string_view &MangledName) {
4710b57cec5SDimitry Andric   SpecialIntrinsicKind SIK = consumeSpecialIntrinsicKind(MangledName);
4720b57cec5SDimitry Andric 
4730b57cec5SDimitry Andric   switch (SIK) {
4740b57cec5SDimitry Andric   case SpecialIntrinsicKind::None:
4750b57cec5SDimitry Andric     return nullptr;
4760b57cec5SDimitry Andric   case SpecialIntrinsicKind::StringLiteralSymbol:
4770b57cec5SDimitry Andric     return demangleStringLiteral(MangledName);
4780b57cec5SDimitry Andric   case SpecialIntrinsicKind::Vftable:
4790b57cec5SDimitry Andric   case SpecialIntrinsicKind::Vbtable:
4800b57cec5SDimitry Andric   case SpecialIntrinsicKind::LocalVftable:
4810b57cec5SDimitry Andric   case SpecialIntrinsicKind::RttiCompleteObjLocator:
4820b57cec5SDimitry Andric     return demangleSpecialTableSymbolNode(MangledName, SIK);
4830b57cec5SDimitry Andric   case SpecialIntrinsicKind::VcallThunk:
4840b57cec5SDimitry Andric     return demangleVcallThunkNode(MangledName);
4850b57cec5SDimitry Andric   case SpecialIntrinsicKind::LocalStaticGuard:
4860b57cec5SDimitry Andric     return demangleLocalStaticGuard(MangledName, /*IsThread=*/false);
4870b57cec5SDimitry Andric   case SpecialIntrinsicKind::LocalStaticThreadGuard:
4880b57cec5SDimitry Andric     return demangleLocalStaticGuard(MangledName, /*IsThread=*/true);
4890b57cec5SDimitry Andric   case SpecialIntrinsicKind::RttiTypeDescriptor: {
4900b57cec5SDimitry Andric     TypeNode *T = demangleType(MangledName, QualifierMangleMode::Result);
4910b57cec5SDimitry Andric     if (Error)
4920b57cec5SDimitry Andric       break;
49306c3fb27SDimitry Andric     if (!consumeFront(MangledName, "@8"))
4940b57cec5SDimitry Andric       break;
4950b57cec5SDimitry Andric     if (!MangledName.empty())
4960b57cec5SDimitry Andric       break;
4970b57cec5SDimitry Andric     return synthesizeVariable(Arena, T, "`RTTI Type Descriptor'");
4980b57cec5SDimitry Andric   }
4990b57cec5SDimitry Andric   case SpecialIntrinsicKind::RttiBaseClassArray:
5000b57cec5SDimitry Andric     return demangleUntypedVariable(Arena, MangledName,
5010b57cec5SDimitry Andric                                    "`RTTI Base Class Array'");
5020b57cec5SDimitry Andric   case SpecialIntrinsicKind::RttiClassHierarchyDescriptor:
5030b57cec5SDimitry Andric     return demangleUntypedVariable(Arena, MangledName,
5040b57cec5SDimitry Andric                                    "`RTTI Class Hierarchy Descriptor'");
5050b57cec5SDimitry Andric   case SpecialIntrinsicKind::RttiBaseClassDescriptor:
5060b57cec5SDimitry Andric     return demangleRttiBaseClassDescriptorNode(Arena, MangledName);
5070b57cec5SDimitry Andric   case SpecialIntrinsicKind::DynamicInitializer:
5080b57cec5SDimitry Andric     return demangleInitFiniStub(MangledName, /*IsDestructor=*/false);
5090b57cec5SDimitry Andric   case SpecialIntrinsicKind::DynamicAtexitDestructor:
5100b57cec5SDimitry Andric     return demangleInitFiniStub(MangledName, /*IsDestructor=*/true);
5110b57cec5SDimitry Andric   case SpecialIntrinsicKind::Typeof:
5120b57cec5SDimitry Andric   case SpecialIntrinsicKind::UdtReturning:
5130b57cec5SDimitry Andric     // It's unclear which tools produces these manglings, so demangling
5140b57cec5SDimitry Andric     // support is not (yet?) implemented.
5150b57cec5SDimitry Andric     break;
5160b57cec5SDimitry Andric   case SpecialIntrinsicKind::Unknown:
5170b57cec5SDimitry Andric     DEMANGLE_UNREACHABLE; // Never returned by consumeSpecialIntrinsicKind.
5180b57cec5SDimitry Andric   }
5190b57cec5SDimitry Andric   Error = true;
5200b57cec5SDimitry Andric   return nullptr;
5210b57cec5SDimitry Andric }
5220b57cec5SDimitry Andric 
5230b57cec5SDimitry Andric IdentifierNode *
52406c3fb27SDimitry Andric Demangler::demangleFunctionIdentifierCode(std::string_view &MangledName) {
52506c3fb27SDimitry Andric   assert(llvm::itanium_demangle::starts_with(MangledName, '?'));
52606c3fb27SDimitry Andric   MangledName.remove_prefix(1);
5270b57cec5SDimitry Andric   if (MangledName.empty()) {
5280b57cec5SDimitry Andric     Error = true;
5290b57cec5SDimitry Andric     return nullptr;
5300b57cec5SDimitry Andric   }
5310b57cec5SDimitry Andric 
53206c3fb27SDimitry Andric   if (consumeFront(MangledName, "__"))
5330b57cec5SDimitry Andric     return demangleFunctionIdentifierCode(
5340b57cec5SDimitry Andric         MangledName, FunctionIdentifierCodeGroup::DoubleUnder);
53506c3fb27SDimitry Andric   if (consumeFront(MangledName, "_"))
5360b57cec5SDimitry Andric     return demangleFunctionIdentifierCode(MangledName,
5370b57cec5SDimitry Andric                                           FunctionIdentifierCodeGroup::Under);
5380b57cec5SDimitry Andric   return demangleFunctionIdentifierCode(MangledName,
5390b57cec5SDimitry Andric                                         FunctionIdentifierCodeGroup::Basic);
5400b57cec5SDimitry Andric }
5410b57cec5SDimitry Andric 
5420b57cec5SDimitry Andric StructorIdentifierNode *
54306c3fb27SDimitry Andric Demangler::demangleStructorIdentifier(std::string_view &MangledName,
5440b57cec5SDimitry Andric                                       bool IsDestructor) {
5450b57cec5SDimitry Andric   StructorIdentifierNode *N = Arena.alloc<StructorIdentifierNode>();
5460b57cec5SDimitry Andric   N->IsDestructor = IsDestructor;
5470b57cec5SDimitry Andric   return N;
5480b57cec5SDimitry Andric }
5490b57cec5SDimitry Andric 
5500b57cec5SDimitry Andric ConversionOperatorIdentifierNode *
55106c3fb27SDimitry Andric Demangler::demangleConversionOperatorIdentifier(std::string_view &MangledName) {
5520b57cec5SDimitry Andric   ConversionOperatorIdentifierNode *N =
5530b57cec5SDimitry Andric       Arena.alloc<ConversionOperatorIdentifierNode>();
5540b57cec5SDimitry Andric   return N;
5550b57cec5SDimitry Andric }
5560b57cec5SDimitry Andric 
5570b57cec5SDimitry Andric LiteralOperatorIdentifierNode *
55806c3fb27SDimitry Andric Demangler::demangleLiteralOperatorIdentifier(std::string_view &MangledName) {
5590b57cec5SDimitry Andric   LiteralOperatorIdentifierNode *N =
5600b57cec5SDimitry Andric       Arena.alloc<LiteralOperatorIdentifierNode>();
5610b57cec5SDimitry Andric   N->Name = demangleSimpleString(MangledName, /*Memorize=*/false);
5620b57cec5SDimitry Andric   return N;
5630b57cec5SDimitry Andric }
5640b57cec5SDimitry Andric 
5650b57cec5SDimitry Andric IntrinsicFunctionKind
5660b57cec5SDimitry Andric Demangler::translateIntrinsicFunctionCode(char CH,
5670b57cec5SDimitry Andric                                           FunctionIdentifierCodeGroup Group) {
5680b57cec5SDimitry Andric   using IFK = IntrinsicFunctionKind;
5690b57cec5SDimitry Andric   if (!(CH >= '0' && CH <= '9') && !(CH >= 'A' && CH <= 'Z')) {
5700b57cec5SDimitry Andric     Error = true;
5710b57cec5SDimitry Andric     return IFK::None;
5720b57cec5SDimitry Andric   }
5730b57cec5SDimitry Andric 
5740b57cec5SDimitry Andric   // Not all ? identifiers are intrinsics *functions*.  This function only maps
5750b57cec5SDimitry Andric   // operator codes for the special functions, all others are handled elsewhere,
5760b57cec5SDimitry Andric   // hence the IFK::None entries in the table.
5770b57cec5SDimitry Andric   static IFK Basic[36] = {
5780b57cec5SDimitry Andric       IFK::None,             // ?0 # Foo::Foo()
5790b57cec5SDimitry Andric       IFK::None,             // ?1 # Foo::~Foo()
5800b57cec5SDimitry Andric       IFK::New,              // ?2 # operator new
5810b57cec5SDimitry Andric       IFK::Delete,           // ?3 # operator delete
5820b57cec5SDimitry Andric       IFK::Assign,           // ?4 # operator=
5830b57cec5SDimitry Andric       IFK::RightShift,       // ?5 # operator>>
5840b57cec5SDimitry Andric       IFK::LeftShift,        // ?6 # operator<<
5850b57cec5SDimitry Andric       IFK::LogicalNot,       // ?7 # operator!
5860b57cec5SDimitry Andric       IFK::Equals,           // ?8 # operator==
5870b57cec5SDimitry Andric       IFK::NotEquals,        // ?9 # operator!=
5880b57cec5SDimitry Andric       IFK::ArraySubscript,   // ?A # operator[]
5890b57cec5SDimitry Andric       IFK::None,             // ?B # Foo::operator <type>()
5900b57cec5SDimitry Andric       IFK::Pointer,          // ?C # operator->
5910b57cec5SDimitry Andric       IFK::Dereference,      // ?D # operator*
5920b57cec5SDimitry Andric       IFK::Increment,        // ?E # operator++
5930b57cec5SDimitry Andric       IFK::Decrement,        // ?F # operator--
5940b57cec5SDimitry Andric       IFK::Minus,            // ?G # operator-
5950b57cec5SDimitry Andric       IFK::Plus,             // ?H # operator+
5960b57cec5SDimitry Andric       IFK::BitwiseAnd,       // ?I # operator&
5970b57cec5SDimitry Andric       IFK::MemberPointer,    // ?J # operator->*
5980b57cec5SDimitry Andric       IFK::Divide,           // ?K # operator/
5990b57cec5SDimitry Andric       IFK::Modulus,          // ?L # operator%
6000b57cec5SDimitry Andric       IFK::LessThan,         // ?M operator<
6010b57cec5SDimitry Andric       IFK::LessThanEqual,    // ?N operator<=
6020b57cec5SDimitry Andric       IFK::GreaterThan,      // ?O operator>
6030b57cec5SDimitry Andric       IFK::GreaterThanEqual, // ?P operator>=
6040b57cec5SDimitry Andric       IFK::Comma,            // ?Q operator,
6050b57cec5SDimitry Andric       IFK::Parens,           // ?R operator()
6060b57cec5SDimitry Andric       IFK::BitwiseNot,       // ?S operator~
6070b57cec5SDimitry Andric       IFK::BitwiseXor,       // ?T operator^
6080b57cec5SDimitry Andric       IFK::BitwiseOr,        // ?U operator|
6090b57cec5SDimitry Andric       IFK::LogicalAnd,       // ?V operator&&
6100b57cec5SDimitry Andric       IFK::LogicalOr,        // ?W operator||
6110b57cec5SDimitry Andric       IFK::TimesEqual,       // ?X operator*=
6120b57cec5SDimitry Andric       IFK::PlusEqual,        // ?Y operator+=
6130b57cec5SDimitry Andric       IFK::MinusEqual,       // ?Z operator-=
6140b57cec5SDimitry Andric   };
6150b57cec5SDimitry Andric   static IFK Under[36] = {
6160b57cec5SDimitry Andric       IFK::DivEqual,           // ?_0 operator/=
6170b57cec5SDimitry Andric       IFK::ModEqual,           // ?_1 operator%=
6180b57cec5SDimitry Andric       IFK::RshEqual,           // ?_2 operator>>=
6190b57cec5SDimitry Andric       IFK::LshEqual,           // ?_3 operator<<=
6200b57cec5SDimitry Andric       IFK::BitwiseAndEqual,    // ?_4 operator&=
6210b57cec5SDimitry Andric       IFK::BitwiseOrEqual,     // ?_5 operator|=
6220b57cec5SDimitry Andric       IFK::BitwiseXorEqual,    // ?_6 operator^=
6230b57cec5SDimitry Andric       IFK::None,               // ?_7 # vftable
6240b57cec5SDimitry Andric       IFK::None,               // ?_8 # vbtable
6250b57cec5SDimitry Andric       IFK::None,               // ?_9 # vcall
6260b57cec5SDimitry Andric       IFK::None,               // ?_A # typeof
6270b57cec5SDimitry Andric       IFK::None,               // ?_B # local static guard
6280b57cec5SDimitry Andric       IFK::None,               // ?_C # string literal
6290b57cec5SDimitry Andric       IFK::VbaseDtor,          // ?_D # vbase destructor
6300b57cec5SDimitry Andric       IFK::VecDelDtor,         // ?_E # vector deleting destructor
6310b57cec5SDimitry Andric       IFK::DefaultCtorClosure, // ?_F # default constructor closure
6320b57cec5SDimitry Andric       IFK::ScalarDelDtor,      // ?_G # scalar deleting destructor
6330b57cec5SDimitry Andric       IFK::VecCtorIter,        // ?_H # vector constructor iterator
6340b57cec5SDimitry Andric       IFK::VecDtorIter,        // ?_I # vector destructor iterator
6350b57cec5SDimitry Andric       IFK::VecVbaseCtorIter,   // ?_J # vector vbase constructor iterator
6360b57cec5SDimitry Andric       IFK::VdispMap,           // ?_K # virtual displacement map
6370b57cec5SDimitry Andric       IFK::EHVecCtorIter,      // ?_L # eh vector constructor iterator
6380b57cec5SDimitry Andric       IFK::EHVecDtorIter,      // ?_M # eh vector destructor iterator
6390b57cec5SDimitry Andric       IFK::EHVecVbaseCtorIter, // ?_N # eh vector vbase constructor iterator
6400b57cec5SDimitry Andric       IFK::CopyCtorClosure,    // ?_O # copy constructor closure
6410b57cec5SDimitry Andric       IFK::None,               // ?_P<name> # udt returning <name>
6420b57cec5SDimitry Andric       IFK::None,               // ?_Q # <unknown>
6430b57cec5SDimitry Andric       IFK::None,               // ?_R0 - ?_R4 # RTTI Codes
6440b57cec5SDimitry Andric       IFK::None,               // ?_S # local vftable
6450b57cec5SDimitry Andric       IFK::LocalVftableCtorClosure, // ?_T # local vftable constructor closure
6460b57cec5SDimitry Andric       IFK::ArrayNew,                // ?_U operator new[]
6470b57cec5SDimitry Andric       IFK::ArrayDelete,             // ?_V operator delete[]
6480b57cec5SDimitry Andric       IFK::None,                    // ?_W <unused>
6490b57cec5SDimitry Andric       IFK::None,                    // ?_X <unused>
6500b57cec5SDimitry Andric       IFK::None,                    // ?_Y <unused>
6510b57cec5SDimitry Andric       IFK::None,                    // ?_Z <unused>
6520b57cec5SDimitry Andric   };
6530b57cec5SDimitry Andric   static IFK DoubleUnder[36] = {
6540b57cec5SDimitry Andric       IFK::None,                       // ?__0 <unused>
6550b57cec5SDimitry Andric       IFK::None,                       // ?__1 <unused>
6560b57cec5SDimitry Andric       IFK::None,                       // ?__2 <unused>
6570b57cec5SDimitry Andric       IFK::None,                       // ?__3 <unused>
6580b57cec5SDimitry Andric       IFK::None,                       // ?__4 <unused>
6590b57cec5SDimitry Andric       IFK::None,                       // ?__5 <unused>
6600b57cec5SDimitry Andric       IFK::None,                       // ?__6 <unused>
6610b57cec5SDimitry Andric       IFK::None,                       // ?__7 <unused>
6620b57cec5SDimitry Andric       IFK::None,                       // ?__8 <unused>
6630b57cec5SDimitry Andric       IFK::None,                       // ?__9 <unused>
6640b57cec5SDimitry Andric       IFK::ManVectorCtorIter,          // ?__A managed vector ctor iterator
6650b57cec5SDimitry Andric       IFK::ManVectorDtorIter,          // ?__B managed vector dtor iterator
6660b57cec5SDimitry Andric       IFK::EHVectorCopyCtorIter,       // ?__C EH vector copy ctor iterator
6670b57cec5SDimitry Andric       IFK::EHVectorVbaseCopyCtorIter,  // ?__D EH vector vbase copy ctor iter
6680b57cec5SDimitry Andric       IFK::None,                       // ?__E dynamic initializer for `T'
6690b57cec5SDimitry Andric       IFK::None,                       // ?__F dynamic atexit destructor for `T'
6700b57cec5SDimitry Andric       IFK::VectorCopyCtorIter,         // ?__G vector copy constructor iter
6710b57cec5SDimitry Andric       IFK::VectorVbaseCopyCtorIter,    // ?__H vector vbase copy ctor iter
6720b57cec5SDimitry Andric       IFK::ManVectorVbaseCopyCtorIter, // ?__I managed vector vbase copy ctor
6730b57cec5SDimitry Andric                                        // iter
6740b57cec5SDimitry Andric       IFK::None,                       // ?__J local static thread guard
6750b57cec5SDimitry Andric       IFK::None,                       // ?__K operator ""_name
6760b57cec5SDimitry Andric       IFK::CoAwait,                    // ?__L operator co_await
6770b57cec5SDimitry Andric       IFK::Spaceship,                  // ?__M operator<=>
6780b57cec5SDimitry Andric       IFK::None,                       // ?__N <unused>
6790b57cec5SDimitry Andric       IFK::None,                       // ?__O <unused>
6800b57cec5SDimitry Andric       IFK::None,                       // ?__P <unused>
6810b57cec5SDimitry Andric       IFK::None,                       // ?__Q <unused>
6820b57cec5SDimitry Andric       IFK::None,                       // ?__R <unused>
6830b57cec5SDimitry Andric       IFK::None,                       // ?__S <unused>
6840b57cec5SDimitry Andric       IFK::None,                       // ?__T <unused>
6850b57cec5SDimitry Andric       IFK::None,                       // ?__U <unused>
6860b57cec5SDimitry Andric       IFK::None,                       // ?__V <unused>
6870b57cec5SDimitry Andric       IFK::None,                       // ?__W <unused>
6880b57cec5SDimitry Andric       IFK::None,                       // ?__X <unused>
6890b57cec5SDimitry Andric       IFK::None,                       // ?__Y <unused>
6900b57cec5SDimitry Andric       IFK::None,                       // ?__Z <unused>
6910b57cec5SDimitry Andric   };
6920b57cec5SDimitry Andric 
6930b57cec5SDimitry Andric   int Index = (CH >= '0' && CH <= '9') ? (CH - '0') : (CH - 'A' + 10);
6940b57cec5SDimitry Andric   switch (Group) {
6950b57cec5SDimitry Andric   case FunctionIdentifierCodeGroup::Basic:
6960b57cec5SDimitry Andric     return Basic[Index];
6970b57cec5SDimitry Andric   case FunctionIdentifierCodeGroup::Under:
6980b57cec5SDimitry Andric     return Under[Index];
6990b57cec5SDimitry Andric   case FunctionIdentifierCodeGroup::DoubleUnder:
7000b57cec5SDimitry Andric     return DoubleUnder[Index];
7010b57cec5SDimitry Andric   }
7020b57cec5SDimitry Andric   DEMANGLE_UNREACHABLE;
7030b57cec5SDimitry Andric }
7040b57cec5SDimitry Andric 
7050b57cec5SDimitry Andric IdentifierNode *
70606c3fb27SDimitry Andric Demangler::demangleFunctionIdentifierCode(std::string_view &MangledName,
7070b57cec5SDimitry Andric                                           FunctionIdentifierCodeGroup Group) {
7080b57cec5SDimitry Andric   if (MangledName.empty()) {
7090b57cec5SDimitry Andric     Error = true;
7100b57cec5SDimitry Andric     return nullptr;
7110b57cec5SDimitry Andric   }
71206c3fb27SDimitry Andric   const char CH = MangledName.front();
7130b57cec5SDimitry Andric   switch (Group) {
7140b57cec5SDimitry Andric   case FunctionIdentifierCodeGroup::Basic:
71506c3fb27SDimitry Andric     MangledName.remove_prefix(1);
71606c3fb27SDimitry Andric     switch (CH) {
7170b57cec5SDimitry Andric     case '0':
7180b57cec5SDimitry Andric     case '1':
7190b57cec5SDimitry Andric       return demangleStructorIdentifier(MangledName, CH == '1');
7200b57cec5SDimitry Andric     case 'B':
7210b57cec5SDimitry Andric       return demangleConversionOperatorIdentifier(MangledName);
7220b57cec5SDimitry Andric     default:
7230b57cec5SDimitry Andric       return Arena.alloc<IntrinsicFunctionIdentifierNode>(
7240b57cec5SDimitry Andric           translateIntrinsicFunctionCode(CH, Group));
7250b57cec5SDimitry Andric     }
7260b57cec5SDimitry Andric   case FunctionIdentifierCodeGroup::Under:
72706c3fb27SDimitry Andric     MangledName.remove_prefix(1);
7280b57cec5SDimitry Andric     return Arena.alloc<IntrinsicFunctionIdentifierNode>(
72906c3fb27SDimitry Andric         translateIntrinsicFunctionCode(CH, Group));
7300b57cec5SDimitry Andric   case FunctionIdentifierCodeGroup::DoubleUnder:
73106c3fb27SDimitry Andric     MangledName.remove_prefix(1);
73206c3fb27SDimitry Andric     switch (CH) {
7330b57cec5SDimitry Andric     case 'K':
7340b57cec5SDimitry Andric       return demangleLiteralOperatorIdentifier(MangledName);
7350b57cec5SDimitry Andric     default:
7360b57cec5SDimitry Andric       return Arena.alloc<IntrinsicFunctionIdentifierNode>(
7370b57cec5SDimitry Andric           translateIntrinsicFunctionCode(CH, Group));
7380b57cec5SDimitry Andric     }
7390b57cec5SDimitry Andric   }
7400b57cec5SDimitry Andric 
7410b57cec5SDimitry Andric   DEMANGLE_UNREACHABLE;
7420b57cec5SDimitry Andric }
7430b57cec5SDimitry Andric 
74406c3fb27SDimitry Andric SymbolNode *Demangler::demangleEncodedSymbol(std::string_view &MangledName,
7450b57cec5SDimitry Andric                                              QualifiedNameNode *Name) {
7460b57cec5SDimitry Andric   if (MangledName.empty()) {
7470b57cec5SDimitry Andric     Error = true;
7480b57cec5SDimitry Andric     return nullptr;
7490b57cec5SDimitry Andric   }
7500b57cec5SDimitry Andric 
7510b57cec5SDimitry Andric   // Read a variable.
7520b57cec5SDimitry Andric   switch (MangledName.front()) {
7530b57cec5SDimitry Andric   case '0':
7540b57cec5SDimitry Andric   case '1':
7550b57cec5SDimitry Andric   case '2':
7560b57cec5SDimitry Andric   case '3':
7570b57cec5SDimitry Andric   case '4': {
7580b57cec5SDimitry Andric     StorageClass SC = demangleVariableStorageClass(MangledName);
7590b57cec5SDimitry Andric     return demangleVariableEncoding(MangledName, SC);
7600b57cec5SDimitry Andric   }
7610b57cec5SDimitry Andric   }
7620b57cec5SDimitry Andric   FunctionSymbolNode *FSN = demangleFunctionEncoding(MangledName);
7630b57cec5SDimitry Andric 
7640b57cec5SDimitry Andric   IdentifierNode *UQN = Name->getUnqualifiedIdentifier();
7650b57cec5SDimitry Andric   if (UQN->kind() == NodeKind::ConversionOperatorIdentifier) {
7660b57cec5SDimitry Andric     ConversionOperatorIdentifierNode *COIN =
7670b57cec5SDimitry Andric         static_cast<ConversionOperatorIdentifierNode *>(UQN);
7680b57cec5SDimitry Andric     if (FSN)
7690b57cec5SDimitry Andric       COIN->TargetType = FSN->Signature->ReturnType;
7700b57cec5SDimitry Andric   }
7710b57cec5SDimitry Andric   return FSN;
7720b57cec5SDimitry Andric }
7730b57cec5SDimitry Andric 
77406c3fb27SDimitry Andric SymbolNode *Demangler::demangleDeclarator(std::string_view &MangledName) {
7750b57cec5SDimitry Andric   // What follows is a main symbol name. This may include namespaces or class
7760b57cec5SDimitry Andric   // back references.
7770b57cec5SDimitry Andric   QualifiedNameNode *QN = demangleFullyQualifiedSymbolName(MangledName);
7780b57cec5SDimitry Andric   if (Error)
7790b57cec5SDimitry Andric     return nullptr;
7800b57cec5SDimitry Andric 
7810b57cec5SDimitry Andric   SymbolNode *Symbol = demangleEncodedSymbol(MangledName, QN);
7820b57cec5SDimitry Andric   if (Error)
7830b57cec5SDimitry Andric     return nullptr;
7840b57cec5SDimitry Andric   Symbol->Name = QN;
7850b57cec5SDimitry Andric 
7860b57cec5SDimitry Andric   IdentifierNode *UQN = QN->getUnqualifiedIdentifier();
7870b57cec5SDimitry Andric   if (UQN->kind() == NodeKind::ConversionOperatorIdentifier) {
7880b57cec5SDimitry Andric     ConversionOperatorIdentifierNode *COIN =
7890b57cec5SDimitry Andric         static_cast<ConversionOperatorIdentifierNode *>(UQN);
7900b57cec5SDimitry Andric     if (!COIN->TargetType) {
7910b57cec5SDimitry Andric       Error = true;
7920b57cec5SDimitry Andric       return nullptr;
7930b57cec5SDimitry Andric     }
7940b57cec5SDimitry Andric   }
7950b57cec5SDimitry Andric   return Symbol;
7960b57cec5SDimitry Andric }
7970b57cec5SDimitry Andric 
79806c3fb27SDimitry Andric SymbolNode *Demangler::demangleMD5Name(std::string_view &MangledName) {
79906c3fb27SDimitry Andric   assert(llvm::itanium_demangle::starts_with(MangledName, "??@"));
8000b57cec5SDimitry Andric   // This is an MD5 mangled name.  We can't demangle it, just return the
8010b57cec5SDimitry Andric   // mangled name.
8020b57cec5SDimitry Andric   // An MD5 mangled name is ??@ followed by 32 characters and a terminating @.
8030b57cec5SDimitry Andric   size_t MD5Last = MangledName.find('@', strlen("??@"));
80406c3fb27SDimitry Andric   if (MD5Last == std::string_view::npos) {
8050b57cec5SDimitry Andric     Error = true;
8060b57cec5SDimitry Andric     return nullptr;
8070b57cec5SDimitry Andric   }
80806c3fb27SDimitry Andric   const char *Start = MangledName.data();
80906c3fb27SDimitry Andric   const size_t StartSize = MangledName.size();
81006c3fb27SDimitry Andric   MangledName.remove_prefix(MD5Last + 1);
8110b57cec5SDimitry Andric 
8120b57cec5SDimitry Andric   // There are two additional special cases for MD5 names:
8130b57cec5SDimitry Andric   // 1. For complete object locators where the object name is long enough
8140b57cec5SDimitry Andric   //    for the object to have an MD5 name, the complete object locator is
8150b57cec5SDimitry Andric   //    called ??@...@??_R4@ (with a trailing "??_R4@" instead of the usual
8160b57cec5SDimitry Andric   //    leading "??_R4". This is handled here.
8170b57cec5SDimitry Andric   // 2. For catchable types, in versions of MSVC before 2015 (<1900) or after
8180b57cec5SDimitry Andric   //    2017.2 (>= 1914), the catchable type mangling is _CT??@...@??@...@8
8190b57cec5SDimitry Andric   //    instead of_CT??@...@8 with just one MD5 name. Since we don't yet
8200b57cec5SDimitry Andric   //    demangle catchable types anywhere, this isn't handled for MD5 names
8210b57cec5SDimitry Andric   //    either.
82206c3fb27SDimitry Andric   consumeFront(MangledName, "??_R4@");
8230b57cec5SDimitry Andric 
82406c3fb27SDimitry Andric   assert(MangledName.size() < StartSize);
82506c3fb27SDimitry Andric   const size_t Count = StartSize - MangledName.size();
82606c3fb27SDimitry Andric   std::string_view MD5(Start, Count);
8270b57cec5SDimitry Andric   SymbolNode *S = Arena.alloc<SymbolNode>(NodeKind::Md5Symbol);
8280b57cec5SDimitry Andric   S->Name = synthesizeQualifiedName(Arena, MD5);
8290b57cec5SDimitry Andric 
8300b57cec5SDimitry Andric   return S;
8310b57cec5SDimitry Andric }
8320b57cec5SDimitry Andric 
83306c3fb27SDimitry Andric SymbolNode *Demangler::demangleTypeinfoName(std::string_view &MangledName) {
83406c3fb27SDimitry Andric   assert(llvm::itanium_demangle::starts_with(MangledName, '.'));
83506c3fb27SDimitry Andric   consumeFront(MangledName, '.');
8368bcb0991SDimitry Andric 
8378bcb0991SDimitry Andric   TypeNode *T = demangleType(MangledName, QualifierMangleMode::Result);
8388bcb0991SDimitry Andric   if (Error || !MangledName.empty()) {
8398bcb0991SDimitry Andric     Error = true;
8408bcb0991SDimitry Andric     return nullptr;
8418bcb0991SDimitry Andric   }
8428bcb0991SDimitry Andric   return synthesizeVariable(Arena, T, "`RTTI Type Descriptor Name'");
8438bcb0991SDimitry Andric }
8448bcb0991SDimitry Andric 
8450b57cec5SDimitry Andric // Parser entry point.
84606c3fb27SDimitry Andric SymbolNode *Demangler::parse(std::string_view &MangledName) {
8478bcb0991SDimitry Andric   // Typeinfo names are strings stored in RTTI data. They're not symbol names.
8488bcb0991SDimitry Andric   // It's still useful to demangle them. They're the only demangled entity
8498bcb0991SDimitry Andric   // that doesn't start with a "?" but a ".".
85006c3fb27SDimitry Andric   if (llvm::itanium_demangle::starts_with(MangledName, '.'))
8518bcb0991SDimitry Andric     return demangleTypeinfoName(MangledName);
8528bcb0991SDimitry Andric 
85306c3fb27SDimitry Andric   if (llvm::itanium_demangle::starts_with(MangledName, "??@"))
8540b57cec5SDimitry Andric     return demangleMD5Name(MangledName);
8550b57cec5SDimitry Andric 
8560b57cec5SDimitry Andric   // MSVC-style mangled symbols must start with '?'.
85706c3fb27SDimitry Andric   if (!llvm::itanium_demangle::starts_with(MangledName, '?')) {
8580b57cec5SDimitry Andric     Error = true;
8590b57cec5SDimitry Andric     return nullptr;
8600b57cec5SDimitry Andric   }
8610b57cec5SDimitry Andric 
86206c3fb27SDimitry Andric   consumeFront(MangledName, '?');
8630b57cec5SDimitry Andric 
8640b57cec5SDimitry Andric   // ?$ is a template instantiation, but all other names that start with ? are
8650b57cec5SDimitry Andric   // operators / special names.
8660b57cec5SDimitry Andric   if (SymbolNode *SI = demangleSpecialIntrinsic(MangledName))
8670b57cec5SDimitry Andric     return SI;
8680b57cec5SDimitry Andric 
8690b57cec5SDimitry Andric   return demangleDeclarator(MangledName);
8700b57cec5SDimitry Andric }
8710b57cec5SDimitry Andric 
87206c3fb27SDimitry Andric TagTypeNode *Demangler::parseTagUniqueName(std::string_view &MangledName) {
87306c3fb27SDimitry Andric   if (!consumeFront(MangledName, ".?A")) {
87481ad6265SDimitry Andric     Error = true;
8750b57cec5SDimitry Andric     return nullptr;
87681ad6265SDimitry Andric   }
87706c3fb27SDimitry Andric   consumeFront(MangledName, ".?A");
87881ad6265SDimitry Andric   if (MangledName.empty()) {
87981ad6265SDimitry Andric     Error = true;
8800b57cec5SDimitry Andric     return nullptr;
88181ad6265SDimitry Andric   }
8820b57cec5SDimitry Andric 
8830b57cec5SDimitry Andric   return demangleClassType(MangledName);
8840b57cec5SDimitry Andric }
8850b57cec5SDimitry Andric 
8860b57cec5SDimitry Andric // <type-encoding> ::= <storage-class> <variable-type>
8870b57cec5SDimitry Andric // <storage-class> ::= 0  # private static member
8880b57cec5SDimitry Andric //                 ::= 1  # protected static member
8890b57cec5SDimitry Andric //                 ::= 2  # public static member
8900b57cec5SDimitry Andric //                 ::= 3  # global
8910b57cec5SDimitry Andric //                 ::= 4  # static local
8920b57cec5SDimitry Andric 
89306c3fb27SDimitry Andric VariableSymbolNode *
89406c3fb27SDimitry Andric Demangler::demangleVariableEncoding(std::string_view &MangledName,
8950b57cec5SDimitry Andric                                     StorageClass SC) {
8960b57cec5SDimitry Andric   VariableSymbolNode *VSN = Arena.alloc<VariableSymbolNode>();
8970b57cec5SDimitry Andric 
8980b57cec5SDimitry Andric   VSN->Type = demangleType(MangledName, QualifierMangleMode::Drop);
8990b57cec5SDimitry Andric   VSN->SC = SC;
9000b57cec5SDimitry Andric 
9010b57cec5SDimitry Andric   if (Error)
9020b57cec5SDimitry Andric     return nullptr;
9030b57cec5SDimitry Andric 
9040b57cec5SDimitry Andric   // <variable-type> ::= <type> <cvr-qualifiers>
9050b57cec5SDimitry Andric   //                 ::= <type> <pointee-cvr-qualifiers> # pointers, references
9060b57cec5SDimitry Andric   switch (VSN->Type->kind()) {
9070b57cec5SDimitry Andric   case NodeKind::PointerType: {
9080b57cec5SDimitry Andric     PointerTypeNode *PTN = static_cast<PointerTypeNode *>(VSN->Type);
9090b57cec5SDimitry Andric 
9100b57cec5SDimitry Andric     Qualifiers ExtraChildQuals = Q_None;
9110b57cec5SDimitry Andric     PTN->Quals = Qualifiers(VSN->Type->Quals |
9120b57cec5SDimitry Andric                             demanglePointerExtQualifiers(MangledName));
9130b57cec5SDimitry Andric 
9140b57cec5SDimitry Andric     bool IsMember = false;
9150b57cec5SDimitry Andric     std::tie(ExtraChildQuals, IsMember) = demangleQualifiers(MangledName);
9160b57cec5SDimitry Andric 
9170b57cec5SDimitry Andric     if (PTN->ClassParent) {
9180b57cec5SDimitry Andric       QualifiedNameNode *BackRefName =
9190b57cec5SDimitry Andric           demangleFullyQualifiedTypeName(MangledName);
9200b57cec5SDimitry Andric       (void)BackRefName;
9210b57cec5SDimitry Andric     }
9220b57cec5SDimitry Andric     PTN->Pointee->Quals = Qualifiers(PTN->Pointee->Quals | ExtraChildQuals);
9230b57cec5SDimitry Andric 
9240b57cec5SDimitry Andric     break;
9250b57cec5SDimitry Andric   }
9260b57cec5SDimitry Andric   default:
9270b57cec5SDimitry Andric     VSN->Type->Quals = demangleQualifiers(MangledName).first;
9280b57cec5SDimitry Andric     break;
9290b57cec5SDimitry Andric   }
9300b57cec5SDimitry Andric 
9310b57cec5SDimitry Andric   return VSN;
9320b57cec5SDimitry Andric }
9330b57cec5SDimitry Andric 
9340b57cec5SDimitry Andric // Sometimes numbers are encoded in mangled symbols. For example,
9350b57cec5SDimitry Andric // "int (*x)[20]" is a valid C type (x is a pointer to an array of
9360b57cec5SDimitry Andric // length 20), so we need some way to embed numbers as part of symbols.
9370b57cec5SDimitry Andric // This function parses it.
9380b57cec5SDimitry Andric //
9390b57cec5SDimitry Andric // <number>               ::= [?] <non-negative integer>
9400b57cec5SDimitry Andric //
9410b57cec5SDimitry Andric // <non-negative integer> ::= <decimal digit> # when 1 <= Number <= 10
9420b57cec5SDimitry Andric //                        ::= <hex digit>+ @  # when Number == 0 or >= 10
9430b57cec5SDimitry Andric //
9440b57cec5SDimitry Andric // <hex-digit>            ::= [A-P]           # A = 0, B = 1, ...
94506c3fb27SDimitry Andric std::pair<uint64_t, bool>
94606c3fb27SDimitry Andric Demangler::demangleNumber(std::string_view &MangledName) {
94706c3fb27SDimitry Andric   bool IsNegative = consumeFront(MangledName, '?');
9480b57cec5SDimitry Andric 
9490b57cec5SDimitry Andric   if (startsWithDigit(MangledName)) {
9500b57cec5SDimitry Andric     uint64_t Ret = MangledName[0] - '0' + 1;
95106c3fb27SDimitry Andric     MangledName.remove_prefix(1);
9520b57cec5SDimitry Andric     return {Ret, IsNegative};
9530b57cec5SDimitry Andric   }
9540b57cec5SDimitry Andric 
9550b57cec5SDimitry Andric   uint64_t Ret = 0;
9560b57cec5SDimitry Andric   for (size_t i = 0; i < MangledName.size(); ++i) {
9570b57cec5SDimitry Andric     char C = MangledName[i];
9580b57cec5SDimitry Andric     if (C == '@') {
95906c3fb27SDimitry Andric       MangledName.remove_prefix(i + 1);
9600b57cec5SDimitry Andric       return {Ret, IsNegative};
9610b57cec5SDimitry Andric     }
9620b57cec5SDimitry Andric     if ('A' <= C && C <= 'P') {
9630b57cec5SDimitry Andric       Ret = (Ret << 4) + (C - 'A');
9640b57cec5SDimitry Andric       continue;
9650b57cec5SDimitry Andric     }
9660b57cec5SDimitry Andric     break;
9670b57cec5SDimitry Andric   }
9680b57cec5SDimitry Andric 
9690b57cec5SDimitry Andric   Error = true;
9700b57cec5SDimitry Andric   return {0ULL, false};
9710b57cec5SDimitry Andric }
9720b57cec5SDimitry Andric 
97306c3fb27SDimitry Andric uint64_t Demangler::demangleUnsigned(std::string_view &MangledName) {
9740b57cec5SDimitry Andric   bool IsNegative = false;
9750b57cec5SDimitry Andric   uint64_t Number = 0;
9760b57cec5SDimitry Andric   std::tie(Number, IsNegative) = demangleNumber(MangledName);
9770b57cec5SDimitry Andric   if (IsNegative)
9780b57cec5SDimitry Andric     Error = true;
9790b57cec5SDimitry Andric   return Number;
9800b57cec5SDimitry Andric }
9810b57cec5SDimitry Andric 
98206c3fb27SDimitry Andric int64_t Demangler::demangleSigned(std::string_view &MangledName) {
9830b57cec5SDimitry Andric   bool IsNegative = false;
9840b57cec5SDimitry Andric   uint64_t Number = 0;
9850b57cec5SDimitry Andric   std::tie(Number, IsNegative) = demangleNumber(MangledName);
9860b57cec5SDimitry Andric   if (Number > INT64_MAX)
9870b57cec5SDimitry Andric     Error = true;
9880b57cec5SDimitry Andric   int64_t I = static_cast<int64_t>(Number);
9890b57cec5SDimitry Andric   return IsNegative ? -I : I;
9900b57cec5SDimitry Andric }
9910b57cec5SDimitry Andric 
9920b57cec5SDimitry Andric // First 10 strings can be referenced by special BackReferences ?0, ?1, ..., ?9.
9930b57cec5SDimitry Andric // Memorize it.
99406c3fb27SDimitry Andric void Demangler::memorizeString(std::string_view S) {
9950b57cec5SDimitry Andric   if (Backrefs.NamesCount >= BackrefContext::Max)
9960b57cec5SDimitry Andric     return;
9970b57cec5SDimitry Andric   for (size_t i = 0; i < Backrefs.NamesCount; ++i)
9980b57cec5SDimitry Andric     if (S == Backrefs.Names[i]->Name)
9990b57cec5SDimitry Andric       return;
10000b57cec5SDimitry Andric   NamedIdentifierNode *N = Arena.alloc<NamedIdentifierNode>();
10010b57cec5SDimitry Andric   N->Name = S;
10020b57cec5SDimitry Andric   Backrefs.Names[Backrefs.NamesCount++] = N;
10030b57cec5SDimitry Andric }
10040b57cec5SDimitry Andric 
100506c3fb27SDimitry Andric NamedIdentifierNode *
100606c3fb27SDimitry Andric Demangler::demangleBackRefName(std::string_view &MangledName) {
10070b57cec5SDimitry Andric   assert(startsWithDigit(MangledName));
10080b57cec5SDimitry Andric 
10090b57cec5SDimitry Andric   size_t I = MangledName[0] - '0';
10100b57cec5SDimitry Andric   if (I >= Backrefs.NamesCount) {
10110b57cec5SDimitry Andric     Error = true;
10120b57cec5SDimitry Andric     return nullptr;
10130b57cec5SDimitry Andric   }
10140b57cec5SDimitry Andric 
101506c3fb27SDimitry Andric   MangledName.remove_prefix(1);
10160b57cec5SDimitry Andric   return Backrefs.Names[I];
10170b57cec5SDimitry Andric }
10180b57cec5SDimitry Andric 
10190b57cec5SDimitry Andric void Demangler::memorizeIdentifier(IdentifierNode *Identifier) {
10200b57cec5SDimitry Andric   // Render this class template name into a string buffer so that we can
10210b57cec5SDimitry Andric   // memorize it for the purpose of back-referencing.
1022349cc55cSDimitry Andric   OutputBuffer OB;
1023349cc55cSDimitry Andric   Identifier->output(OB, OF_Default);
102406c3fb27SDimitry Andric   std::string_view Owned = copyString(OB);
10250b57cec5SDimitry Andric   memorizeString(Owned);
102681ad6265SDimitry Andric   std::free(OB.getBuffer());
10270b57cec5SDimitry Andric }
10280b57cec5SDimitry Andric 
10290b57cec5SDimitry Andric IdentifierNode *
103006c3fb27SDimitry Andric Demangler::demangleTemplateInstantiationName(std::string_view &MangledName,
10310b57cec5SDimitry Andric                                              NameBackrefBehavior NBB) {
103206c3fb27SDimitry Andric   assert(llvm::itanium_demangle::starts_with(MangledName, "?$"));
103306c3fb27SDimitry Andric   consumeFront(MangledName, "?$");
10340b57cec5SDimitry Andric 
10350b57cec5SDimitry Andric   BackrefContext OuterContext;
10360b57cec5SDimitry Andric   std::swap(OuterContext, Backrefs);
10370b57cec5SDimitry Andric 
10380b57cec5SDimitry Andric   IdentifierNode *Identifier =
10390b57cec5SDimitry Andric       demangleUnqualifiedSymbolName(MangledName, NBB_Simple);
10400b57cec5SDimitry Andric   if (!Error)
10410b57cec5SDimitry Andric     Identifier->TemplateParams = demangleTemplateParameterList(MangledName);
10420b57cec5SDimitry Andric 
10430b57cec5SDimitry Andric   std::swap(OuterContext, Backrefs);
10440b57cec5SDimitry Andric   if (Error)
10450b57cec5SDimitry Andric     return nullptr;
10460b57cec5SDimitry Andric 
10470b57cec5SDimitry Andric   if (NBB & NBB_Template) {
10480b57cec5SDimitry Andric     // NBB_Template is only set for types and non-leaf names ("a::" in "a::b").
10490b57cec5SDimitry Andric     // Structors and conversion operators only makes sense in a leaf name, so
10500b57cec5SDimitry Andric     // reject them in NBB_Template contexts.
10510b57cec5SDimitry Andric     if (Identifier->kind() == NodeKind::ConversionOperatorIdentifier ||
10520b57cec5SDimitry Andric         Identifier->kind() == NodeKind::StructorIdentifier) {
10530b57cec5SDimitry Andric       Error = true;
10540b57cec5SDimitry Andric       return nullptr;
10550b57cec5SDimitry Andric     }
10560b57cec5SDimitry Andric 
10570b57cec5SDimitry Andric     memorizeIdentifier(Identifier);
10580b57cec5SDimitry Andric   }
10590b57cec5SDimitry Andric 
10600b57cec5SDimitry Andric   return Identifier;
10610b57cec5SDimitry Andric }
10620b57cec5SDimitry Andric 
106306c3fb27SDimitry Andric NamedIdentifierNode *
106406c3fb27SDimitry Andric Demangler::demangleSimpleName(std::string_view &MangledName, bool Memorize) {
106506c3fb27SDimitry Andric   std::string_view S = demangleSimpleString(MangledName, Memorize);
10660b57cec5SDimitry Andric   if (Error)
10670b57cec5SDimitry Andric     return nullptr;
10680b57cec5SDimitry Andric 
10690b57cec5SDimitry Andric   NamedIdentifierNode *Name = Arena.alloc<NamedIdentifierNode>();
10700b57cec5SDimitry Andric   Name->Name = S;
10710b57cec5SDimitry Andric   return Name;
10720b57cec5SDimitry Andric }
10730b57cec5SDimitry Andric 
10740b57cec5SDimitry Andric static bool isRebasedHexDigit(char C) { return (C >= 'A' && C <= 'P'); }
10750b57cec5SDimitry Andric 
10760b57cec5SDimitry Andric static uint8_t rebasedHexDigitToNumber(char C) {
10770b57cec5SDimitry Andric   assert(isRebasedHexDigit(C));
10780b57cec5SDimitry Andric   return (C <= 'J') ? (C - 'A') : (10 + C - 'K');
10790b57cec5SDimitry Andric }
10800b57cec5SDimitry Andric 
108106c3fb27SDimitry Andric uint8_t Demangler::demangleCharLiteral(std::string_view &MangledName) {
10820b57cec5SDimitry Andric   assert(!MangledName.empty());
108306c3fb27SDimitry Andric   if (!llvm::itanium_demangle::starts_with(MangledName, '?')) {
108406c3fb27SDimitry Andric     const uint8_t F = MangledName.front();
108506c3fb27SDimitry Andric     MangledName.remove_prefix(1);
108606c3fb27SDimitry Andric     return F;
108706c3fb27SDimitry Andric   }
10880b57cec5SDimitry Andric 
108906c3fb27SDimitry Andric   MangledName.remove_prefix(1);
10900b57cec5SDimitry Andric   if (MangledName.empty())
10910b57cec5SDimitry Andric     goto CharLiteralError;
10920b57cec5SDimitry Andric 
109306c3fb27SDimitry Andric   if (consumeFront(MangledName, '$')) {
10940b57cec5SDimitry Andric     // Two hex digits
10950b57cec5SDimitry Andric     if (MangledName.size() < 2)
10960b57cec5SDimitry Andric       goto CharLiteralError;
109706c3fb27SDimitry Andric     std::string_view Nibbles = MangledName.substr(0, 2);
10980b57cec5SDimitry Andric     if (!isRebasedHexDigit(Nibbles[0]) || !isRebasedHexDigit(Nibbles[1]))
10990b57cec5SDimitry Andric       goto CharLiteralError;
11000b57cec5SDimitry Andric     // Don't append the null terminator.
11010b57cec5SDimitry Andric     uint8_t C1 = rebasedHexDigitToNumber(Nibbles[0]);
11020b57cec5SDimitry Andric     uint8_t C2 = rebasedHexDigitToNumber(Nibbles[1]);
110306c3fb27SDimitry Andric     MangledName.remove_prefix(2);
11040b57cec5SDimitry Andric     return (C1 << 4) | C2;
11050b57cec5SDimitry Andric   }
11060b57cec5SDimitry Andric 
11070b57cec5SDimitry Andric   if (startsWithDigit(MangledName)) {
11080b57cec5SDimitry Andric     const char *Lookup = ",/\\:. \n\t'-";
11090b57cec5SDimitry Andric     char C = Lookup[MangledName[0] - '0'];
111006c3fb27SDimitry Andric     MangledName.remove_prefix(1);
11110b57cec5SDimitry Andric     return C;
11120b57cec5SDimitry Andric   }
11130b57cec5SDimitry Andric 
11140b57cec5SDimitry Andric   if (MangledName[0] >= 'a' && MangledName[0] <= 'z') {
11150b57cec5SDimitry Andric     char Lookup[26] = {'\xE1', '\xE2', '\xE3', '\xE4', '\xE5', '\xE6', '\xE7',
11160b57cec5SDimitry Andric                        '\xE8', '\xE9', '\xEA', '\xEB', '\xEC', '\xED', '\xEE',
11170b57cec5SDimitry Andric                        '\xEF', '\xF0', '\xF1', '\xF2', '\xF3', '\xF4', '\xF5',
11180b57cec5SDimitry Andric                        '\xF6', '\xF7', '\xF8', '\xF9', '\xFA'};
11190b57cec5SDimitry Andric     char C = Lookup[MangledName[0] - 'a'];
112006c3fb27SDimitry Andric     MangledName.remove_prefix(1);
11210b57cec5SDimitry Andric     return C;
11220b57cec5SDimitry Andric   }
11230b57cec5SDimitry Andric 
11240b57cec5SDimitry Andric   if (MangledName[0] >= 'A' && MangledName[0] <= 'Z') {
11250b57cec5SDimitry Andric     char Lookup[26] = {'\xC1', '\xC2', '\xC3', '\xC4', '\xC5', '\xC6', '\xC7',
11260b57cec5SDimitry Andric                        '\xC8', '\xC9', '\xCA', '\xCB', '\xCC', '\xCD', '\xCE',
11270b57cec5SDimitry Andric                        '\xCF', '\xD0', '\xD1', '\xD2', '\xD3', '\xD4', '\xD5',
11280b57cec5SDimitry Andric                        '\xD6', '\xD7', '\xD8', '\xD9', '\xDA'};
11290b57cec5SDimitry Andric     char C = Lookup[MangledName[0] - 'A'];
113006c3fb27SDimitry Andric     MangledName.remove_prefix(1);
11310b57cec5SDimitry Andric     return C;
11320b57cec5SDimitry Andric   }
11330b57cec5SDimitry Andric 
11340b57cec5SDimitry Andric CharLiteralError:
11350b57cec5SDimitry Andric   Error = true;
11360b57cec5SDimitry Andric   return '\0';
11370b57cec5SDimitry Andric }
11380b57cec5SDimitry Andric 
113906c3fb27SDimitry Andric wchar_t Demangler::demangleWcharLiteral(std::string_view &MangledName) {
11400b57cec5SDimitry Andric   uint8_t C1, C2;
11410b57cec5SDimitry Andric 
11420b57cec5SDimitry Andric   C1 = demangleCharLiteral(MangledName);
11430b57cec5SDimitry Andric   if (Error || MangledName.empty())
11440b57cec5SDimitry Andric     goto WCharLiteralError;
11450b57cec5SDimitry Andric   C2 = demangleCharLiteral(MangledName);
11460b57cec5SDimitry Andric   if (Error)
11470b57cec5SDimitry Andric     goto WCharLiteralError;
11480b57cec5SDimitry Andric 
11490b57cec5SDimitry Andric   return ((wchar_t)C1 << 8) | (wchar_t)C2;
11500b57cec5SDimitry Andric 
11510b57cec5SDimitry Andric WCharLiteralError:
11520b57cec5SDimitry Andric   Error = true;
11530b57cec5SDimitry Andric   return L'\0';
11540b57cec5SDimitry Andric }
11550b57cec5SDimitry Andric 
11560b57cec5SDimitry Andric static void writeHexDigit(char *Buffer, uint8_t Digit) {
11570b57cec5SDimitry Andric   assert(Digit <= 15);
11580b57cec5SDimitry Andric   *Buffer = (Digit < 10) ? ('0' + Digit) : ('A' + Digit - 10);
11590b57cec5SDimitry Andric }
11600b57cec5SDimitry Andric 
1161349cc55cSDimitry Andric static void outputHex(OutputBuffer &OB, unsigned C) {
11620b57cec5SDimitry Andric   assert (C != 0);
11630b57cec5SDimitry Andric 
11640b57cec5SDimitry Andric   // It's easier to do the math if we can work from right to left, but we need
11650b57cec5SDimitry Andric   // to print the numbers from left to right.  So render this into a temporary
11660b57cec5SDimitry Andric   // buffer first, then output the temporary buffer.  Each byte is of the form
11670b57cec5SDimitry Andric   // \xAB, which means that each byte needs 4 characters.  Since there are at
11680b57cec5SDimitry Andric   // most 4 bytes, we need a 4*4+1 = 17 character temporary buffer.
11690b57cec5SDimitry Andric   char TempBuffer[17];
11700b57cec5SDimitry Andric 
11710b57cec5SDimitry Andric   ::memset(TempBuffer, 0, sizeof(TempBuffer));
11720b57cec5SDimitry Andric   constexpr int MaxPos = sizeof(TempBuffer) - 1;
11730b57cec5SDimitry Andric 
11740b57cec5SDimitry Andric   int Pos = MaxPos - 1; // TempBuffer[MaxPos] is the terminating \0.
11750b57cec5SDimitry Andric   while (C != 0) {
11760b57cec5SDimitry Andric     for (int I = 0; I < 2; ++I) {
11770b57cec5SDimitry Andric       writeHexDigit(&TempBuffer[Pos--], C % 16);
11780b57cec5SDimitry Andric       C /= 16;
11790b57cec5SDimitry Andric     }
11800b57cec5SDimitry Andric   }
11810b57cec5SDimitry Andric   TempBuffer[Pos--] = 'x';
11820b57cec5SDimitry Andric   assert(Pos >= 0);
11830b57cec5SDimitry Andric   TempBuffer[Pos--] = '\\';
118406c3fb27SDimitry Andric   OB << std::string_view(&TempBuffer[Pos + 1]);
11850b57cec5SDimitry Andric }
11860b57cec5SDimitry Andric 
1187349cc55cSDimitry Andric static void outputEscapedChar(OutputBuffer &OB, unsigned C) {
11880b57cec5SDimitry Andric   switch (C) {
11890b57cec5SDimitry Andric   case '\0': // nul
1190349cc55cSDimitry Andric     OB << "\\0";
11910b57cec5SDimitry Andric     return;
11920b57cec5SDimitry Andric   case '\'': // single quote
1193349cc55cSDimitry Andric     OB << "\\\'";
11940b57cec5SDimitry Andric     return;
11950b57cec5SDimitry Andric   case '\"': // double quote
1196349cc55cSDimitry Andric     OB << "\\\"";
11970b57cec5SDimitry Andric     return;
11980b57cec5SDimitry Andric   case '\\': // backslash
1199349cc55cSDimitry Andric     OB << "\\\\";
12000b57cec5SDimitry Andric     return;
12010b57cec5SDimitry Andric   case '\a': // bell
1202349cc55cSDimitry Andric     OB << "\\a";
12030b57cec5SDimitry Andric     return;
12040b57cec5SDimitry Andric   case '\b': // backspace
1205349cc55cSDimitry Andric     OB << "\\b";
12060b57cec5SDimitry Andric     return;
12070b57cec5SDimitry Andric   case '\f': // form feed
1208349cc55cSDimitry Andric     OB << "\\f";
12090b57cec5SDimitry Andric     return;
12100b57cec5SDimitry Andric   case '\n': // new line
1211349cc55cSDimitry Andric     OB << "\\n";
12120b57cec5SDimitry Andric     return;
12130b57cec5SDimitry Andric   case '\r': // carriage return
1214349cc55cSDimitry Andric     OB << "\\r";
12150b57cec5SDimitry Andric     return;
12160b57cec5SDimitry Andric   case '\t': // tab
1217349cc55cSDimitry Andric     OB << "\\t";
12180b57cec5SDimitry Andric     return;
12190b57cec5SDimitry Andric   case '\v': // vertical tab
1220349cc55cSDimitry Andric     OB << "\\v";
12210b57cec5SDimitry Andric     return;
12220b57cec5SDimitry Andric   default:
12230b57cec5SDimitry Andric     break;
12240b57cec5SDimitry Andric   }
12250b57cec5SDimitry Andric 
12260b57cec5SDimitry Andric   if (C > 0x1F && C < 0x7F) {
12270b57cec5SDimitry Andric     // Standard ascii char.
1228349cc55cSDimitry Andric     OB << (char)C;
12290b57cec5SDimitry Andric     return;
12300b57cec5SDimitry Andric   }
12310b57cec5SDimitry Andric 
1232349cc55cSDimitry Andric   outputHex(OB, C);
12330b57cec5SDimitry Andric }
12340b57cec5SDimitry Andric 
12350b57cec5SDimitry Andric static unsigned countTrailingNullBytes(const uint8_t *StringBytes, int Length) {
12360b57cec5SDimitry Andric   const uint8_t *End = StringBytes + Length - 1;
12370b57cec5SDimitry Andric   unsigned Count = 0;
12380b57cec5SDimitry Andric   while (Length > 0 && *End == 0) {
12390b57cec5SDimitry Andric     --Length;
12400b57cec5SDimitry Andric     --End;
12410b57cec5SDimitry Andric     ++Count;
12420b57cec5SDimitry Andric   }
12430b57cec5SDimitry Andric   return Count;
12440b57cec5SDimitry Andric }
12450b57cec5SDimitry Andric 
12460b57cec5SDimitry Andric static unsigned countEmbeddedNulls(const uint8_t *StringBytes,
12470b57cec5SDimitry Andric                                    unsigned Length) {
12480b57cec5SDimitry Andric   unsigned Result = 0;
12490b57cec5SDimitry Andric   for (unsigned I = 0; I < Length; ++I) {
12500b57cec5SDimitry Andric     if (*StringBytes++ == 0)
12510b57cec5SDimitry Andric       ++Result;
12520b57cec5SDimitry Andric   }
12530b57cec5SDimitry Andric   return Result;
12540b57cec5SDimitry Andric }
12550b57cec5SDimitry Andric 
12560b57cec5SDimitry Andric // A mangled (non-wide) string literal stores the total length of the string it
12570b57cec5SDimitry Andric // refers to (passed in NumBytes), and it contains up to 32 bytes of actual text
12580b57cec5SDimitry Andric // (passed in StringBytes, NumChars).
12590b57cec5SDimitry Andric static unsigned guessCharByteSize(const uint8_t *StringBytes, unsigned NumChars,
12600b57cec5SDimitry Andric                                   uint64_t NumBytes) {
12610b57cec5SDimitry Andric   assert(NumBytes > 0);
12620b57cec5SDimitry Andric 
12630b57cec5SDimitry Andric   // If the number of bytes is odd, this is guaranteed to be a char string.
12640b57cec5SDimitry Andric   if (NumBytes % 2 == 1)
12650b57cec5SDimitry Andric     return 1;
12660b57cec5SDimitry Andric 
12670b57cec5SDimitry Andric   // All strings can encode at most 32 bytes of data.  If it's less than that,
12680b57cec5SDimitry Andric   // then we encoded the entire string.  In this case we check for a 1-byte,
12690b57cec5SDimitry Andric   // 2-byte, or 4-byte null terminator.
12700b57cec5SDimitry Andric   if (NumBytes < 32) {
12710b57cec5SDimitry Andric     unsigned TrailingNulls = countTrailingNullBytes(StringBytes, NumChars);
12720b57cec5SDimitry Andric     if (TrailingNulls >= 4 && NumBytes % 4 == 0)
12730b57cec5SDimitry Andric       return 4;
12740b57cec5SDimitry Andric     if (TrailingNulls >= 2)
12750b57cec5SDimitry Andric       return 2;
12760b57cec5SDimitry Andric     return 1;
12770b57cec5SDimitry Andric   }
12780b57cec5SDimitry Andric 
12790b57cec5SDimitry Andric   // The whole string was not able to be encoded.  Try to look at embedded null
12800b57cec5SDimitry Andric   // terminators to guess.  The heuristic is that we count all embedded null
12810b57cec5SDimitry Andric   // terminators.  If more than 2/3 are null, it's a char32.  If more than 1/3
12820b57cec5SDimitry Andric   // are null, it's a char16.  Otherwise it's a char8.  This obviously isn't
12830b57cec5SDimitry Andric   // perfect and is biased towards languages that have ascii alphabets, but this
12840b57cec5SDimitry Andric   // was always going to be best effort since the encoding is lossy.
12850b57cec5SDimitry Andric   unsigned Nulls = countEmbeddedNulls(StringBytes, NumChars);
12860b57cec5SDimitry Andric   if (Nulls >= 2 * NumChars / 3 && NumBytes % 4 == 0)
12870b57cec5SDimitry Andric     return 4;
12880b57cec5SDimitry Andric   if (Nulls >= NumChars / 3)
12890b57cec5SDimitry Andric     return 2;
12900b57cec5SDimitry Andric   return 1;
12910b57cec5SDimitry Andric }
12920b57cec5SDimitry Andric 
12930b57cec5SDimitry Andric static unsigned decodeMultiByteChar(const uint8_t *StringBytes,
12940b57cec5SDimitry Andric                                     unsigned CharIndex, unsigned CharBytes) {
12950b57cec5SDimitry Andric   assert(CharBytes == 1 || CharBytes == 2 || CharBytes == 4);
12960b57cec5SDimitry Andric   unsigned Offset = CharIndex * CharBytes;
12970b57cec5SDimitry Andric   unsigned Result = 0;
12980b57cec5SDimitry Andric   StringBytes = StringBytes + Offset;
12990b57cec5SDimitry Andric   for (unsigned I = 0; I < CharBytes; ++I) {
13000b57cec5SDimitry Andric     unsigned C = static_cast<unsigned>(StringBytes[I]);
13010b57cec5SDimitry Andric     Result |= C << (8 * I);
13020b57cec5SDimitry Andric   }
13030b57cec5SDimitry Andric   return Result;
13040b57cec5SDimitry Andric }
13050b57cec5SDimitry Andric 
130606c3fb27SDimitry Andric FunctionSymbolNode *
130706c3fb27SDimitry Andric Demangler::demangleVcallThunkNode(std::string_view &MangledName) {
13080b57cec5SDimitry Andric   FunctionSymbolNode *FSN = Arena.alloc<FunctionSymbolNode>();
13090b57cec5SDimitry Andric   VcallThunkIdentifierNode *VTIN = Arena.alloc<VcallThunkIdentifierNode>();
13100b57cec5SDimitry Andric   FSN->Signature = Arena.alloc<ThunkSignatureNode>();
13110b57cec5SDimitry Andric   FSN->Signature->FunctionClass = FC_NoParameterList;
13120b57cec5SDimitry Andric 
13130b57cec5SDimitry Andric   FSN->Name = demangleNameScopeChain(MangledName, VTIN);
13140b57cec5SDimitry Andric   if (!Error)
131506c3fb27SDimitry Andric     Error = !consumeFront(MangledName, "$B");
13160b57cec5SDimitry Andric   if (!Error)
13170b57cec5SDimitry Andric     VTIN->OffsetInVTable = demangleUnsigned(MangledName);
13180b57cec5SDimitry Andric   if (!Error)
131906c3fb27SDimitry Andric     Error = !consumeFront(MangledName, 'A');
13200b57cec5SDimitry Andric   if (!Error)
13210b57cec5SDimitry Andric     FSN->Signature->CallConvention = demangleCallingConvention(MangledName);
13220b57cec5SDimitry Andric   return (Error) ? nullptr : FSN;
13230b57cec5SDimitry Andric }
13240b57cec5SDimitry Andric 
13250b57cec5SDimitry Andric EncodedStringLiteralNode *
132606c3fb27SDimitry Andric Demangler::demangleStringLiteral(std::string_view &MangledName) {
13270b57cec5SDimitry Andric   // This function uses goto, so declare all variables up front.
1328349cc55cSDimitry Andric   OutputBuffer OB;
132906c3fb27SDimitry Andric   std::string_view CRC;
13300b57cec5SDimitry Andric   uint64_t StringByteSize;
13310b57cec5SDimitry Andric   bool IsWcharT = false;
13320b57cec5SDimitry Andric   bool IsNegative = false;
13330b57cec5SDimitry Andric   size_t CrcEndPos = 0;
133406c3fb27SDimitry Andric   char F;
13350b57cec5SDimitry Andric 
13360b57cec5SDimitry Andric   EncodedStringLiteralNode *Result = Arena.alloc<EncodedStringLiteralNode>();
13370b57cec5SDimitry Andric 
13380b57cec5SDimitry Andric   // Prefix indicating the beginning of a string literal
133906c3fb27SDimitry Andric   if (!consumeFront(MangledName, "@_"))
13400b57cec5SDimitry Andric     goto StringLiteralError;
13410b57cec5SDimitry Andric   if (MangledName.empty())
13420b57cec5SDimitry Andric     goto StringLiteralError;
13430b57cec5SDimitry Andric 
13440b57cec5SDimitry Andric   // Char Type (regular or wchar_t)
134506c3fb27SDimitry Andric   F = MangledName.front();
134606c3fb27SDimitry Andric   MangledName.remove_prefix(1);
134706c3fb27SDimitry Andric   switch (F) {
13480b57cec5SDimitry Andric   case '1':
13490b57cec5SDimitry Andric     IsWcharT = true;
13500b57cec5SDimitry Andric     DEMANGLE_FALLTHROUGH;
13510b57cec5SDimitry Andric   case '0':
13520b57cec5SDimitry Andric     break;
13530b57cec5SDimitry Andric   default:
13540b57cec5SDimitry Andric     goto StringLiteralError;
13550b57cec5SDimitry Andric   }
13560b57cec5SDimitry Andric 
13570b57cec5SDimitry Andric   // Encoded Length
13580b57cec5SDimitry Andric   std::tie(StringByteSize, IsNegative) = demangleNumber(MangledName);
13590b57cec5SDimitry Andric   if (Error || IsNegative || StringByteSize < (IsWcharT ? 2 : 1))
13600b57cec5SDimitry Andric     goto StringLiteralError;
13610b57cec5SDimitry Andric 
13620b57cec5SDimitry Andric   // CRC 32 (always 8 characters plus a terminator)
13630b57cec5SDimitry Andric   CrcEndPos = MangledName.find('@');
136406c3fb27SDimitry Andric   if (CrcEndPos == std::string_view::npos)
13650b57cec5SDimitry Andric     goto StringLiteralError;
13660b57cec5SDimitry Andric   CRC = MangledName.substr(0, CrcEndPos);
136706c3fb27SDimitry Andric   MangledName.remove_prefix(CrcEndPos + 1);
13680b57cec5SDimitry Andric   if (MangledName.empty())
13690b57cec5SDimitry Andric     goto StringLiteralError;
13700b57cec5SDimitry Andric 
13710b57cec5SDimitry Andric   if (IsWcharT) {
13720b57cec5SDimitry Andric     Result->Char = CharKind::Wchar;
13730b57cec5SDimitry Andric     if (StringByteSize > 64)
13740b57cec5SDimitry Andric       Result->IsTruncated = true;
13750b57cec5SDimitry Andric 
137606c3fb27SDimitry Andric     while (!consumeFront(MangledName, '@')) {
13770b57cec5SDimitry Andric       if (MangledName.size() < 2)
13780b57cec5SDimitry Andric         goto StringLiteralError;
13790b57cec5SDimitry Andric       wchar_t W = demangleWcharLiteral(MangledName);
13800b57cec5SDimitry Andric       if (StringByteSize != 2 || Result->IsTruncated)
1381349cc55cSDimitry Andric         outputEscapedChar(OB, W);
13820b57cec5SDimitry Andric       StringByteSize -= 2;
13830b57cec5SDimitry Andric       if (Error)
13840b57cec5SDimitry Andric         goto StringLiteralError;
13850b57cec5SDimitry Andric     }
13860b57cec5SDimitry Andric   } else {
13870b57cec5SDimitry Andric     // The max byte length is actually 32, but some compilers mangled strings
13880b57cec5SDimitry Andric     // incorrectly, so we have to assume it can go higher.
13890b57cec5SDimitry Andric     constexpr unsigned MaxStringByteLength = 32 * 4;
13900b57cec5SDimitry Andric     uint8_t StringBytes[MaxStringByteLength];
13910b57cec5SDimitry Andric 
13920b57cec5SDimitry Andric     unsigned BytesDecoded = 0;
139306c3fb27SDimitry Andric     while (!consumeFront(MangledName, '@')) {
13940b57cec5SDimitry Andric       if (MangledName.size() < 1 || BytesDecoded >= MaxStringByteLength)
13950b57cec5SDimitry Andric         goto StringLiteralError;
13960b57cec5SDimitry Andric       StringBytes[BytesDecoded++] = demangleCharLiteral(MangledName);
13970b57cec5SDimitry Andric     }
13980b57cec5SDimitry Andric 
13990b57cec5SDimitry Andric     if (StringByteSize > BytesDecoded)
14000b57cec5SDimitry Andric       Result->IsTruncated = true;
14010b57cec5SDimitry Andric 
14020b57cec5SDimitry Andric     unsigned CharBytes =
14030b57cec5SDimitry Andric         guessCharByteSize(StringBytes, BytesDecoded, StringByteSize);
14040b57cec5SDimitry Andric     assert(StringByteSize % CharBytes == 0);
14050b57cec5SDimitry Andric     switch (CharBytes) {
14060b57cec5SDimitry Andric     case 1:
14070b57cec5SDimitry Andric       Result->Char = CharKind::Char;
14080b57cec5SDimitry Andric       break;
14090b57cec5SDimitry Andric     case 2:
14100b57cec5SDimitry Andric       Result->Char = CharKind::Char16;
14110b57cec5SDimitry Andric       break;
14120b57cec5SDimitry Andric     case 4:
14130b57cec5SDimitry Andric       Result->Char = CharKind::Char32;
14140b57cec5SDimitry Andric       break;
14150b57cec5SDimitry Andric     default:
14160b57cec5SDimitry Andric       DEMANGLE_UNREACHABLE;
14170b57cec5SDimitry Andric     }
14180b57cec5SDimitry Andric     const unsigned NumChars = BytesDecoded / CharBytes;
14190b57cec5SDimitry Andric     for (unsigned CharIndex = 0; CharIndex < NumChars; ++CharIndex) {
14200b57cec5SDimitry Andric       unsigned NextChar =
14210b57cec5SDimitry Andric           decodeMultiByteChar(StringBytes, CharIndex, CharBytes);
14220b57cec5SDimitry Andric       if (CharIndex + 1 < NumChars || Result->IsTruncated)
1423349cc55cSDimitry Andric         outputEscapedChar(OB, NextChar);
14240b57cec5SDimitry Andric     }
14250b57cec5SDimitry Andric   }
14260b57cec5SDimitry Andric 
142781ad6265SDimitry Andric   Result->DecodedString = copyString(OB);
142881ad6265SDimitry Andric   std::free(OB.getBuffer());
14290b57cec5SDimitry Andric   return Result;
14300b57cec5SDimitry Andric 
14310b57cec5SDimitry Andric StringLiteralError:
14320b57cec5SDimitry Andric   Error = true;
1433349cc55cSDimitry Andric   std::free(OB.getBuffer());
14340b57cec5SDimitry Andric   return nullptr;
14350b57cec5SDimitry Andric }
14360b57cec5SDimitry Andric 
14370b57cec5SDimitry Andric // Returns MangledName's prefix before the first '@', or an error if
14380b57cec5SDimitry Andric // MangledName contains no '@' or the prefix has length 0.
143906c3fb27SDimitry Andric std::string_view Demangler::demangleSimpleString(std::string_view &MangledName,
14400b57cec5SDimitry Andric                                                  bool Memorize) {
144106c3fb27SDimitry Andric   std::string_view S;
14420b57cec5SDimitry Andric   for (size_t i = 0; i < MangledName.size(); ++i) {
14430b57cec5SDimitry Andric     if (MangledName[i] != '@')
14440b57cec5SDimitry Andric       continue;
14450b57cec5SDimitry Andric     if (i == 0)
14460b57cec5SDimitry Andric       break;
14470b57cec5SDimitry Andric     S = MangledName.substr(0, i);
144806c3fb27SDimitry Andric     MangledName.remove_prefix(i + 1);
14490b57cec5SDimitry Andric 
14500b57cec5SDimitry Andric     if (Memorize)
14510b57cec5SDimitry Andric       memorizeString(S);
14520b57cec5SDimitry Andric     return S;
14530b57cec5SDimitry Andric   }
14540b57cec5SDimitry Andric 
14550b57cec5SDimitry Andric   Error = true;
14560b57cec5SDimitry Andric   return {};
14570b57cec5SDimitry Andric }
14580b57cec5SDimitry Andric 
14590b57cec5SDimitry Andric NamedIdentifierNode *
146006c3fb27SDimitry Andric Demangler::demangleAnonymousNamespaceName(std::string_view &MangledName) {
146106c3fb27SDimitry Andric   assert(llvm::itanium_demangle::starts_with(MangledName, "?A"));
146206c3fb27SDimitry Andric   consumeFront(MangledName, "?A");
14630b57cec5SDimitry Andric 
14640b57cec5SDimitry Andric   NamedIdentifierNode *Node = Arena.alloc<NamedIdentifierNode>();
14650b57cec5SDimitry Andric   Node->Name = "`anonymous namespace'";
14660b57cec5SDimitry Andric   size_t EndPos = MangledName.find('@');
146706c3fb27SDimitry Andric   if (EndPos == std::string_view::npos) {
14680b57cec5SDimitry Andric     Error = true;
14690b57cec5SDimitry Andric     return nullptr;
14700b57cec5SDimitry Andric   }
147106c3fb27SDimitry Andric   std::string_view NamespaceKey = MangledName.substr(0, EndPos);
14720b57cec5SDimitry Andric   memorizeString(NamespaceKey);
14730b57cec5SDimitry Andric   MangledName = MangledName.substr(EndPos + 1);
14740b57cec5SDimitry Andric   return Node;
14750b57cec5SDimitry Andric }
14760b57cec5SDimitry Andric 
14770b57cec5SDimitry Andric NamedIdentifierNode *
147806c3fb27SDimitry Andric Demangler::demangleLocallyScopedNamePiece(std::string_view &MangledName) {
14790b57cec5SDimitry Andric   assert(startsWithLocalScopePattern(MangledName));
14800b57cec5SDimitry Andric 
14810b57cec5SDimitry Andric   NamedIdentifierNode *Identifier = Arena.alloc<NamedIdentifierNode>();
148206c3fb27SDimitry Andric   consumeFront(MangledName, '?');
14830b57cec5SDimitry Andric   uint64_t Number = 0;
14840b57cec5SDimitry Andric   bool IsNegative = false;
14850b57cec5SDimitry Andric   std::tie(Number, IsNegative) = demangleNumber(MangledName);
14860b57cec5SDimitry Andric   assert(!IsNegative);
14870b57cec5SDimitry Andric 
14880b57cec5SDimitry Andric   // One ? to terminate the number
148906c3fb27SDimitry Andric   consumeFront(MangledName, '?');
14900b57cec5SDimitry Andric 
14910b57cec5SDimitry Andric   assert(!Error);
14920b57cec5SDimitry Andric   Node *Scope = parse(MangledName);
14930b57cec5SDimitry Andric   if (Error)
14940b57cec5SDimitry Andric     return nullptr;
14950b57cec5SDimitry Andric 
14960b57cec5SDimitry Andric   // Render the parent symbol's name into a buffer.
1497349cc55cSDimitry Andric   OutputBuffer OB;
1498349cc55cSDimitry Andric   OB << '`';
1499349cc55cSDimitry Andric   Scope->output(OB, OF_Default);
1500349cc55cSDimitry Andric   OB << '\'';
1501349cc55cSDimitry Andric   OB << "::`" << Number << "'";
150281ad6265SDimitry Andric 
150381ad6265SDimitry Andric   Identifier->Name = copyString(OB);
150481ad6265SDimitry Andric   std::free(OB.getBuffer());
15050b57cec5SDimitry Andric   return Identifier;
15060b57cec5SDimitry Andric }
15070b57cec5SDimitry Andric 
15080b57cec5SDimitry Andric // Parses a type name in the form of A@B@C@@ which represents C::B::A.
15090b57cec5SDimitry Andric QualifiedNameNode *
151006c3fb27SDimitry Andric Demangler::demangleFullyQualifiedTypeName(std::string_view &MangledName) {
15110b57cec5SDimitry Andric   IdentifierNode *Identifier =
15120b57cec5SDimitry Andric       demangleUnqualifiedTypeName(MangledName, /*Memorize=*/true);
15130b57cec5SDimitry Andric   if (Error)
15140b57cec5SDimitry Andric     return nullptr;
15150b57cec5SDimitry Andric   assert(Identifier);
15160b57cec5SDimitry Andric 
15170b57cec5SDimitry Andric   QualifiedNameNode *QN = demangleNameScopeChain(MangledName, Identifier);
15180b57cec5SDimitry Andric   if (Error)
15190b57cec5SDimitry Andric     return nullptr;
15200b57cec5SDimitry Andric   assert(QN);
15210b57cec5SDimitry Andric   return QN;
15220b57cec5SDimitry Andric }
15230b57cec5SDimitry Andric 
15240b57cec5SDimitry Andric // Parses a symbol name in the form of A@B@C@@ which represents C::B::A.
15250b57cec5SDimitry Andric // Symbol names have slightly different rules regarding what can appear
15260b57cec5SDimitry Andric // so we separate out the implementations for flexibility.
15270b57cec5SDimitry Andric QualifiedNameNode *
152806c3fb27SDimitry Andric Demangler::demangleFullyQualifiedSymbolName(std::string_view &MangledName) {
15290b57cec5SDimitry Andric   // This is the final component of a symbol name (i.e. the leftmost component
15300b57cec5SDimitry Andric   // of a mangled name.  Since the only possible template instantiation that
15310b57cec5SDimitry Andric   // can appear in this context is a function template, and since those are
15320b57cec5SDimitry Andric   // not saved for the purposes of name backreferences, only backref simple
15330b57cec5SDimitry Andric   // names.
15340b57cec5SDimitry Andric   IdentifierNode *Identifier =
15350b57cec5SDimitry Andric       demangleUnqualifiedSymbolName(MangledName, NBB_Simple);
15360b57cec5SDimitry Andric   if (Error)
15370b57cec5SDimitry Andric     return nullptr;
15380b57cec5SDimitry Andric 
15390b57cec5SDimitry Andric   QualifiedNameNode *QN = demangleNameScopeChain(MangledName, Identifier);
15400b57cec5SDimitry Andric   if (Error)
15410b57cec5SDimitry Andric     return nullptr;
15420b57cec5SDimitry Andric 
15430b57cec5SDimitry Andric   if (Identifier->kind() == NodeKind::StructorIdentifier) {
15440b57cec5SDimitry Andric     if (QN->Components->Count < 2) {
15450b57cec5SDimitry Andric       Error = true;
15460b57cec5SDimitry Andric       return nullptr;
15470b57cec5SDimitry Andric     }
15480b57cec5SDimitry Andric     StructorIdentifierNode *SIN =
15490b57cec5SDimitry Andric         static_cast<StructorIdentifierNode *>(Identifier);
15500b57cec5SDimitry Andric     Node *ClassNode = QN->Components->Nodes[QN->Components->Count - 2];
15510b57cec5SDimitry Andric     SIN->Class = static_cast<IdentifierNode *>(ClassNode);
15520b57cec5SDimitry Andric   }
15530b57cec5SDimitry Andric   assert(QN);
15540b57cec5SDimitry Andric   return QN;
15550b57cec5SDimitry Andric }
15560b57cec5SDimitry Andric 
155706c3fb27SDimitry Andric IdentifierNode *
155806c3fb27SDimitry Andric Demangler::demangleUnqualifiedTypeName(std::string_view &MangledName,
15590b57cec5SDimitry Andric                                        bool Memorize) {
15600b57cec5SDimitry Andric   // An inner-most name can be a back-reference, because a fully-qualified name
15610b57cec5SDimitry Andric   // (e.g. Scope + Inner) can contain other fully qualified names inside of
15620b57cec5SDimitry Andric   // them (for example template parameters), and these nested parameters can
15630b57cec5SDimitry Andric   // refer to previously mangled types.
15640b57cec5SDimitry Andric   if (startsWithDigit(MangledName))
15650b57cec5SDimitry Andric     return demangleBackRefName(MangledName);
15660b57cec5SDimitry Andric 
156706c3fb27SDimitry Andric   if (llvm::itanium_demangle::starts_with(MangledName, "?$"))
15680b57cec5SDimitry Andric     return demangleTemplateInstantiationName(MangledName, NBB_Template);
15690b57cec5SDimitry Andric 
15700b57cec5SDimitry Andric   return demangleSimpleName(MangledName, Memorize);
15710b57cec5SDimitry Andric }
15720b57cec5SDimitry Andric 
15730b57cec5SDimitry Andric IdentifierNode *
157406c3fb27SDimitry Andric Demangler::demangleUnqualifiedSymbolName(std::string_view &MangledName,
15750b57cec5SDimitry Andric                                          NameBackrefBehavior NBB) {
15760b57cec5SDimitry Andric   if (startsWithDigit(MangledName))
15770b57cec5SDimitry Andric     return demangleBackRefName(MangledName);
157806c3fb27SDimitry Andric   if (llvm::itanium_demangle::starts_with(MangledName, "?$"))
15790b57cec5SDimitry Andric     return demangleTemplateInstantiationName(MangledName, NBB);
158006c3fb27SDimitry Andric   if (llvm::itanium_demangle::starts_with(MangledName, '?'))
15810b57cec5SDimitry Andric     return demangleFunctionIdentifierCode(MangledName);
15820b57cec5SDimitry Andric   return demangleSimpleName(MangledName, /*Memorize=*/(NBB & NBB_Simple) != 0);
15830b57cec5SDimitry Andric }
15840b57cec5SDimitry Andric 
158506c3fb27SDimitry Andric IdentifierNode *
158606c3fb27SDimitry Andric Demangler::demangleNameScopePiece(std::string_view &MangledName) {
15870b57cec5SDimitry Andric   if (startsWithDigit(MangledName))
15880b57cec5SDimitry Andric     return demangleBackRefName(MangledName);
15890b57cec5SDimitry Andric 
159006c3fb27SDimitry Andric   if (llvm::itanium_demangle::starts_with(MangledName, "?$"))
15910b57cec5SDimitry Andric     return demangleTemplateInstantiationName(MangledName, NBB_Template);
15920b57cec5SDimitry Andric 
159306c3fb27SDimitry Andric   if (llvm::itanium_demangle::starts_with(MangledName, "?A"))
15940b57cec5SDimitry Andric     return demangleAnonymousNamespaceName(MangledName);
15950b57cec5SDimitry Andric 
15960b57cec5SDimitry Andric   if (startsWithLocalScopePattern(MangledName))
15970b57cec5SDimitry Andric     return demangleLocallyScopedNamePiece(MangledName);
15980b57cec5SDimitry Andric 
15990b57cec5SDimitry Andric   return demangleSimpleName(MangledName, /*Memorize=*/true);
16000b57cec5SDimitry Andric }
16010b57cec5SDimitry Andric 
16020b57cec5SDimitry Andric static NodeArrayNode *nodeListToNodeArray(ArenaAllocator &Arena, NodeList *Head,
16030b57cec5SDimitry Andric                                           size_t Count) {
16040b57cec5SDimitry Andric   NodeArrayNode *N = Arena.alloc<NodeArrayNode>();
16050b57cec5SDimitry Andric   N->Count = Count;
16060b57cec5SDimitry Andric   N->Nodes = Arena.allocArray<Node *>(Count);
16070b57cec5SDimitry Andric   for (size_t I = 0; I < Count; ++I) {
16080b57cec5SDimitry Andric     N->Nodes[I] = Head->N;
16090b57cec5SDimitry Andric     Head = Head->Next;
16100b57cec5SDimitry Andric   }
16110b57cec5SDimitry Andric   return N;
16120b57cec5SDimitry Andric }
16130b57cec5SDimitry Andric 
16140b57cec5SDimitry Andric QualifiedNameNode *
161506c3fb27SDimitry Andric Demangler::demangleNameScopeChain(std::string_view &MangledName,
16160b57cec5SDimitry Andric                                   IdentifierNode *UnqualifiedName) {
16170b57cec5SDimitry Andric   NodeList *Head = Arena.alloc<NodeList>();
16180b57cec5SDimitry Andric 
16190b57cec5SDimitry Andric   Head->N = UnqualifiedName;
16200b57cec5SDimitry Andric 
16210b57cec5SDimitry Andric   size_t Count = 1;
162206c3fb27SDimitry Andric   while (!consumeFront(MangledName, "@")) {
16230b57cec5SDimitry Andric     ++Count;
16240b57cec5SDimitry Andric     NodeList *NewHead = Arena.alloc<NodeList>();
16250b57cec5SDimitry Andric     NewHead->Next = Head;
16260b57cec5SDimitry Andric     Head = NewHead;
16270b57cec5SDimitry Andric 
16280b57cec5SDimitry Andric     if (MangledName.empty()) {
16290b57cec5SDimitry Andric       Error = true;
16300b57cec5SDimitry Andric       return nullptr;
16310b57cec5SDimitry Andric     }
16320b57cec5SDimitry Andric 
16330b57cec5SDimitry Andric     assert(!Error);
16340b57cec5SDimitry Andric     IdentifierNode *Elem = demangleNameScopePiece(MangledName);
16350b57cec5SDimitry Andric     if (Error)
16360b57cec5SDimitry Andric       return nullptr;
16370b57cec5SDimitry Andric 
16380b57cec5SDimitry Andric     Head->N = Elem;
16390b57cec5SDimitry Andric   }
16400b57cec5SDimitry Andric 
16410b57cec5SDimitry Andric   QualifiedNameNode *QN = Arena.alloc<QualifiedNameNode>();
16420b57cec5SDimitry Andric   QN->Components = nodeListToNodeArray(Arena, Head, Count);
16430b57cec5SDimitry Andric   return QN;
16440b57cec5SDimitry Andric }
16450b57cec5SDimitry Andric 
164606c3fb27SDimitry Andric FuncClass Demangler::demangleFunctionClass(std::string_view &MangledName) {
164706c3fb27SDimitry Andric   const char F = MangledName.front();
164806c3fb27SDimitry Andric   MangledName.remove_prefix(1);
164906c3fb27SDimitry Andric   switch (F) {
16500b57cec5SDimitry Andric   case '9':
16510b57cec5SDimitry Andric     return FuncClass(FC_ExternC | FC_NoParameterList);
16520b57cec5SDimitry Andric   case 'A':
16530b57cec5SDimitry Andric     return FC_Private;
16540b57cec5SDimitry Andric   case 'B':
16550b57cec5SDimitry Andric     return FuncClass(FC_Private | FC_Far);
16560b57cec5SDimitry Andric   case 'C':
16570b57cec5SDimitry Andric     return FuncClass(FC_Private | FC_Static);
16580b57cec5SDimitry Andric   case 'D':
16590b57cec5SDimitry Andric     return FuncClass(FC_Private | FC_Static | FC_Far);
16600b57cec5SDimitry Andric   case 'E':
16610b57cec5SDimitry Andric     return FuncClass(FC_Private | FC_Virtual);
16620b57cec5SDimitry Andric   case 'F':
16630b57cec5SDimitry Andric     return FuncClass(FC_Private | FC_Virtual | FC_Far);
16640b57cec5SDimitry Andric   case 'G':
16650b57cec5SDimitry Andric     return FuncClass(FC_Private | FC_StaticThisAdjust);
16660b57cec5SDimitry Andric   case 'H':
16670b57cec5SDimitry Andric     return FuncClass(FC_Private | FC_StaticThisAdjust | FC_Far);
16680b57cec5SDimitry Andric   case 'I':
16690b57cec5SDimitry Andric     return FuncClass(FC_Protected);
16700b57cec5SDimitry Andric   case 'J':
16710b57cec5SDimitry Andric     return FuncClass(FC_Protected | FC_Far);
16720b57cec5SDimitry Andric   case 'K':
16730b57cec5SDimitry Andric     return FuncClass(FC_Protected | FC_Static);
16740b57cec5SDimitry Andric   case 'L':
16750b57cec5SDimitry Andric     return FuncClass(FC_Protected | FC_Static | FC_Far);
16760b57cec5SDimitry Andric   case 'M':
16770b57cec5SDimitry Andric     return FuncClass(FC_Protected | FC_Virtual);
16780b57cec5SDimitry Andric   case 'N':
16790b57cec5SDimitry Andric     return FuncClass(FC_Protected | FC_Virtual | FC_Far);
16800b57cec5SDimitry Andric   case 'O':
16810b57cec5SDimitry Andric     return FuncClass(FC_Protected | FC_Virtual | FC_StaticThisAdjust);
16820b57cec5SDimitry Andric   case 'P':
16830b57cec5SDimitry Andric     return FuncClass(FC_Protected | FC_Virtual | FC_StaticThisAdjust | FC_Far);
16840b57cec5SDimitry Andric   case 'Q':
16850b57cec5SDimitry Andric     return FuncClass(FC_Public);
16860b57cec5SDimitry Andric   case 'R':
16870b57cec5SDimitry Andric     return FuncClass(FC_Public | FC_Far);
16880b57cec5SDimitry Andric   case 'S':
16890b57cec5SDimitry Andric     return FuncClass(FC_Public | FC_Static);
16900b57cec5SDimitry Andric   case 'T':
16910b57cec5SDimitry Andric     return FuncClass(FC_Public | FC_Static | FC_Far);
16920b57cec5SDimitry Andric   case 'U':
16930b57cec5SDimitry Andric     return FuncClass(FC_Public | FC_Virtual);
16940b57cec5SDimitry Andric   case 'V':
16950b57cec5SDimitry Andric     return FuncClass(FC_Public | FC_Virtual | FC_Far);
16960b57cec5SDimitry Andric   case 'W':
16970b57cec5SDimitry Andric     return FuncClass(FC_Public | FC_Virtual | FC_StaticThisAdjust);
16980b57cec5SDimitry Andric   case 'X':
16990b57cec5SDimitry Andric     return FuncClass(FC_Public | FC_Virtual | FC_StaticThisAdjust | FC_Far);
17000b57cec5SDimitry Andric   case 'Y':
17010b57cec5SDimitry Andric     return FuncClass(FC_Global);
17020b57cec5SDimitry Andric   case 'Z':
17030b57cec5SDimitry Andric     return FuncClass(FC_Global | FC_Far);
17040b57cec5SDimitry Andric   case '$': {
17050b57cec5SDimitry Andric     FuncClass VFlag = FC_VirtualThisAdjust;
170606c3fb27SDimitry Andric     if (consumeFront(MangledName, 'R'))
17070b57cec5SDimitry Andric       VFlag = FuncClass(VFlag | FC_VirtualThisAdjustEx);
17080b57cec5SDimitry Andric     if (MangledName.empty())
17090b57cec5SDimitry Andric       break;
171006c3fb27SDimitry Andric     const char F = MangledName.front();
171106c3fb27SDimitry Andric     MangledName.remove_prefix(1);
171206c3fb27SDimitry Andric     switch (F) {
17130b57cec5SDimitry Andric     case '0':
17140b57cec5SDimitry Andric       return FuncClass(FC_Private | FC_Virtual | VFlag);
17150b57cec5SDimitry Andric     case '1':
17160b57cec5SDimitry Andric       return FuncClass(FC_Private | FC_Virtual | VFlag | FC_Far);
17170b57cec5SDimitry Andric     case '2':
17180b57cec5SDimitry Andric       return FuncClass(FC_Protected | FC_Virtual | VFlag);
17190b57cec5SDimitry Andric     case '3':
17200b57cec5SDimitry Andric       return FuncClass(FC_Protected | FC_Virtual | VFlag | FC_Far);
17210b57cec5SDimitry Andric     case '4':
17220b57cec5SDimitry Andric       return FuncClass(FC_Public | FC_Virtual | VFlag);
17230b57cec5SDimitry Andric     case '5':
17240b57cec5SDimitry Andric       return FuncClass(FC_Public | FC_Virtual | VFlag | FC_Far);
17250b57cec5SDimitry Andric     }
17260b57cec5SDimitry Andric   }
17270b57cec5SDimitry Andric   }
17280b57cec5SDimitry Andric 
17290b57cec5SDimitry Andric   Error = true;
17300b57cec5SDimitry Andric   return FC_Public;
17310b57cec5SDimitry Andric }
17320b57cec5SDimitry Andric 
173306c3fb27SDimitry Andric CallingConv
173406c3fb27SDimitry Andric Demangler::demangleCallingConvention(std::string_view &MangledName) {
17350b57cec5SDimitry Andric   if (MangledName.empty()) {
17360b57cec5SDimitry Andric     Error = true;
17370b57cec5SDimitry Andric     return CallingConv::None;
17380b57cec5SDimitry Andric   }
17390b57cec5SDimitry Andric 
174006c3fb27SDimitry Andric   const char F = MangledName.front();
174106c3fb27SDimitry Andric   MangledName.remove_prefix(1);
174206c3fb27SDimitry Andric   switch (F) {
17430b57cec5SDimitry Andric   case 'A':
17440b57cec5SDimitry Andric   case 'B':
17450b57cec5SDimitry Andric     return CallingConv::Cdecl;
17460b57cec5SDimitry Andric   case 'C':
17470b57cec5SDimitry Andric   case 'D':
17480b57cec5SDimitry Andric     return CallingConv::Pascal;
17490b57cec5SDimitry Andric   case 'E':
17500b57cec5SDimitry Andric   case 'F':
17510b57cec5SDimitry Andric     return CallingConv::Thiscall;
17520b57cec5SDimitry Andric   case 'G':
17530b57cec5SDimitry Andric   case 'H':
17540b57cec5SDimitry Andric     return CallingConv::Stdcall;
17550b57cec5SDimitry Andric   case 'I':
17560b57cec5SDimitry Andric   case 'J':
17570b57cec5SDimitry Andric     return CallingConv::Fastcall;
17580b57cec5SDimitry Andric   case 'M':
17590b57cec5SDimitry Andric   case 'N':
17600b57cec5SDimitry Andric     return CallingConv::Clrcall;
17610b57cec5SDimitry Andric   case 'O':
17620b57cec5SDimitry Andric   case 'P':
17630b57cec5SDimitry Andric     return CallingConv::Eabi;
17640b57cec5SDimitry Andric   case 'Q':
17650b57cec5SDimitry Andric     return CallingConv::Vectorcall;
1766fe6060f1SDimitry Andric   case 'S':
1767fe6060f1SDimitry Andric     return CallingConv::Swift;
1768fe6060f1SDimitry Andric   case 'W':
1769fe6060f1SDimitry Andric     return CallingConv::SwiftAsync;
17700b57cec5SDimitry Andric   }
17710b57cec5SDimitry Andric 
17720b57cec5SDimitry Andric   return CallingConv::None;
17730b57cec5SDimitry Andric }
17740b57cec5SDimitry Andric 
177506c3fb27SDimitry Andric StorageClass
177606c3fb27SDimitry Andric Demangler::demangleVariableStorageClass(std::string_view &MangledName) {
17770b57cec5SDimitry Andric   assert(MangledName.front() >= '0' && MangledName.front() <= '4');
17780b57cec5SDimitry Andric 
177906c3fb27SDimitry Andric   const char F = MangledName.front();
178006c3fb27SDimitry Andric   MangledName.remove_prefix(1);
178106c3fb27SDimitry Andric   switch (F) {
17820b57cec5SDimitry Andric   case '0':
17830b57cec5SDimitry Andric     return StorageClass::PrivateStatic;
17840b57cec5SDimitry Andric   case '1':
17850b57cec5SDimitry Andric     return StorageClass::ProtectedStatic;
17860b57cec5SDimitry Andric   case '2':
17870b57cec5SDimitry Andric     return StorageClass::PublicStatic;
17880b57cec5SDimitry Andric   case '3':
17890b57cec5SDimitry Andric     return StorageClass::Global;
17900b57cec5SDimitry Andric   case '4':
17910b57cec5SDimitry Andric     return StorageClass::FunctionLocalStatic;
17920b57cec5SDimitry Andric   }
17930b57cec5SDimitry Andric   DEMANGLE_UNREACHABLE;
17940b57cec5SDimitry Andric }
17950b57cec5SDimitry Andric 
17960b57cec5SDimitry Andric std::pair<Qualifiers, bool>
179706c3fb27SDimitry Andric Demangler::demangleQualifiers(std::string_view &MangledName) {
17980b57cec5SDimitry Andric   if (MangledName.empty()) {
17990b57cec5SDimitry Andric     Error = true;
18000b57cec5SDimitry Andric     return std::make_pair(Q_None, false);
18010b57cec5SDimitry Andric   }
18020b57cec5SDimitry Andric 
180306c3fb27SDimitry Andric   const char F = MangledName.front();
180406c3fb27SDimitry Andric   MangledName.remove_prefix(1);
180506c3fb27SDimitry Andric   switch (F) {
18060b57cec5SDimitry Andric   // Member qualifiers
18070b57cec5SDimitry Andric   case 'Q':
18080b57cec5SDimitry Andric     return std::make_pair(Q_None, true);
18090b57cec5SDimitry Andric   case 'R':
18100b57cec5SDimitry Andric     return std::make_pair(Q_Const, true);
18110b57cec5SDimitry Andric   case 'S':
18120b57cec5SDimitry Andric     return std::make_pair(Q_Volatile, true);
18130b57cec5SDimitry Andric   case 'T':
18140b57cec5SDimitry Andric     return std::make_pair(Qualifiers(Q_Const | Q_Volatile), true);
18150b57cec5SDimitry Andric   // Non-Member qualifiers
18160b57cec5SDimitry Andric   case 'A':
18170b57cec5SDimitry Andric     return std::make_pair(Q_None, false);
18180b57cec5SDimitry Andric   case 'B':
18190b57cec5SDimitry Andric     return std::make_pair(Q_Const, false);
18200b57cec5SDimitry Andric   case 'C':
18210b57cec5SDimitry Andric     return std::make_pair(Q_Volatile, false);
18220b57cec5SDimitry Andric   case 'D':
18230b57cec5SDimitry Andric     return std::make_pair(Qualifiers(Q_Const | Q_Volatile), false);
18240b57cec5SDimitry Andric   }
18250b57cec5SDimitry Andric   Error = true;
18260b57cec5SDimitry Andric   return std::make_pair(Q_None, false);
18270b57cec5SDimitry Andric }
18280b57cec5SDimitry Andric 
18290b57cec5SDimitry Andric // <variable-type> ::= <type> <cvr-qualifiers>
18300b57cec5SDimitry Andric //                 ::= <type> <pointee-cvr-qualifiers> # pointers, references
183106c3fb27SDimitry Andric TypeNode *Demangler::demangleType(std::string_view &MangledName,
18320b57cec5SDimitry Andric                                   QualifierMangleMode QMM) {
18330b57cec5SDimitry Andric   Qualifiers Quals = Q_None;
18340b57cec5SDimitry Andric   bool IsMember = false;
18350b57cec5SDimitry Andric   if (QMM == QualifierMangleMode::Mangle) {
18360b57cec5SDimitry Andric     std::tie(Quals, IsMember) = demangleQualifiers(MangledName);
18370b57cec5SDimitry Andric   } else if (QMM == QualifierMangleMode::Result) {
183806c3fb27SDimitry Andric     if (consumeFront(MangledName, '?'))
18390b57cec5SDimitry Andric       std::tie(Quals, IsMember) = demangleQualifiers(MangledName);
18400b57cec5SDimitry Andric   }
18410b57cec5SDimitry Andric 
18420b57cec5SDimitry Andric   if (MangledName.empty()) {
18430b57cec5SDimitry Andric     Error = true;
18440b57cec5SDimitry Andric     return nullptr;
18450b57cec5SDimitry Andric   }
18460b57cec5SDimitry Andric 
18470b57cec5SDimitry Andric   TypeNode *Ty = nullptr;
18480b57cec5SDimitry Andric   if (isTagType(MangledName))
18490b57cec5SDimitry Andric     Ty = demangleClassType(MangledName);
18500b57cec5SDimitry Andric   else if (isPointerType(MangledName)) {
18510b57cec5SDimitry Andric     if (isMemberPointer(MangledName, Error))
18520b57cec5SDimitry Andric       Ty = demangleMemberPointerType(MangledName);
18530b57cec5SDimitry Andric     else if (!Error)
18540b57cec5SDimitry Andric       Ty = demanglePointerType(MangledName);
18550b57cec5SDimitry Andric     else
18560b57cec5SDimitry Andric       return nullptr;
18570b57cec5SDimitry Andric   } else if (isArrayType(MangledName))
18580b57cec5SDimitry Andric     Ty = demangleArrayType(MangledName);
18590b57cec5SDimitry Andric   else if (isFunctionType(MangledName)) {
186006c3fb27SDimitry Andric     if (consumeFront(MangledName, "$$A8@@"))
18610b57cec5SDimitry Andric       Ty = demangleFunctionType(MangledName, true);
18620b57cec5SDimitry Andric     else {
186306c3fb27SDimitry Andric       assert(llvm::itanium_demangle::starts_with(MangledName, "$$A6"));
186406c3fb27SDimitry Andric       consumeFront(MangledName, "$$A6");
18650b57cec5SDimitry Andric       Ty = demangleFunctionType(MangledName, false);
18660b57cec5SDimitry Andric     }
18670b57cec5SDimitry Andric   } else if (isCustomType(MangledName)) {
18680b57cec5SDimitry Andric     Ty = demangleCustomType(MangledName);
18690b57cec5SDimitry Andric   } else {
18700b57cec5SDimitry Andric     Ty = demanglePrimitiveType(MangledName);
18710b57cec5SDimitry Andric   }
18720b57cec5SDimitry Andric 
18730b57cec5SDimitry Andric   if (!Ty || Error)
18740b57cec5SDimitry Andric     return Ty;
18750b57cec5SDimitry Andric   Ty->Quals = Qualifiers(Ty->Quals | Quals);
18760b57cec5SDimitry Andric   return Ty;
18770b57cec5SDimitry Andric }
18780b57cec5SDimitry Andric 
187906c3fb27SDimitry Andric bool Demangler::demangleThrowSpecification(std::string_view &MangledName) {
188006c3fb27SDimitry Andric   if (consumeFront(MangledName, "_E"))
18810b57cec5SDimitry Andric     return true;
188206c3fb27SDimitry Andric   if (consumeFront(MangledName, 'Z'))
18830b57cec5SDimitry Andric     return false;
18840b57cec5SDimitry Andric 
18850b57cec5SDimitry Andric   Error = true;
18860b57cec5SDimitry Andric   return false;
18870b57cec5SDimitry Andric }
18880b57cec5SDimitry Andric 
188906c3fb27SDimitry Andric FunctionSignatureNode *
189006c3fb27SDimitry Andric Demangler::demangleFunctionType(std::string_view &MangledName,
18910b57cec5SDimitry Andric                                 bool HasThisQuals) {
18920b57cec5SDimitry Andric   FunctionSignatureNode *FTy = Arena.alloc<FunctionSignatureNode>();
18930b57cec5SDimitry Andric 
18940b57cec5SDimitry Andric   if (HasThisQuals) {
18950b57cec5SDimitry Andric     FTy->Quals = demanglePointerExtQualifiers(MangledName);
18960b57cec5SDimitry Andric     FTy->RefQualifier = demangleFunctionRefQualifier(MangledName);
18970b57cec5SDimitry Andric     FTy->Quals = Qualifiers(FTy->Quals | demangleQualifiers(MangledName).first);
18980b57cec5SDimitry Andric   }
18990b57cec5SDimitry Andric 
19000b57cec5SDimitry Andric   // Fields that appear on both member and non-member functions.
19010b57cec5SDimitry Andric   FTy->CallConvention = demangleCallingConvention(MangledName);
19020b57cec5SDimitry Andric 
19030b57cec5SDimitry Andric   // <return-type> ::= <type>
19040b57cec5SDimitry Andric   //               ::= @ # structors (they have no declared return type)
190506c3fb27SDimitry Andric   bool IsStructor = consumeFront(MangledName, '@');
19060b57cec5SDimitry Andric   if (!IsStructor)
19070b57cec5SDimitry Andric     FTy->ReturnType = demangleType(MangledName, QualifierMangleMode::Result);
19080b57cec5SDimitry Andric 
19090b57cec5SDimitry Andric   FTy->Params = demangleFunctionParameterList(MangledName, FTy->IsVariadic);
19100b57cec5SDimitry Andric 
19110b57cec5SDimitry Andric   FTy->IsNoexcept = demangleThrowSpecification(MangledName);
19120b57cec5SDimitry Andric 
19130b57cec5SDimitry Andric   return FTy;
19140b57cec5SDimitry Andric }
19150b57cec5SDimitry Andric 
19160b57cec5SDimitry Andric FunctionSymbolNode *
191706c3fb27SDimitry Andric Demangler::demangleFunctionEncoding(std::string_view &MangledName) {
19180b57cec5SDimitry Andric   FuncClass ExtraFlags = FC_None;
191906c3fb27SDimitry Andric   if (consumeFront(MangledName, "$$J0"))
19200b57cec5SDimitry Andric     ExtraFlags = FC_ExternC;
19210b57cec5SDimitry Andric 
19220b57cec5SDimitry Andric   if (MangledName.empty()) {
19230b57cec5SDimitry Andric     Error = true;
19240b57cec5SDimitry Andric     return nullptr;
19250b57cec5SDimitry Andric   }
19260b57cec5SDimitry Andric 
19270b57cec5SDimitry Andric   FuncClass FC = demangleFunctionClass(MangledName);
19280b57cec5SDimitry Andric   FC = FuncClass(ExtraFlags | FC);
19290b57cec5SDimitry Andric 
19300b57cec5SDimitry Andric   FunctionSignatureNode *FSN = nullptr;
19310b57cec5SDimitry Andric   ThunkSignatureNode *TTN = nullptr;
19320b57cec5SDimitry Andric   if (FC & FC_StaticThisAdjust) {
19330b57cec5SDimitry Andric     TTN = Arena.alloc<ThunkSignatureNode>();
19340b57cec5SDimitry Andric     TTN->ThisAdjust.StaticOffset = demangleSigned(MangledName);
19350b57cec5SDimitry Andric   } else if (FC & FC_VirtualThisAdjust) {
19360b57cec5SDimitry Andric     TTN = Arena.alloc<ThunkSignatureNode>();
19370b57cec5SDimitry Andric     if (FC & FC_VirtualThisAdjustEx) {
19380b57cec5SDimitry Andric       TTN->ThisAdjust.VBPtrOffset = demangleSigned(MangledName);
19390b57cec5SDimitry Andric       TTN->ThisAdjust.VBOffsetOffset = demangleSigned(MangledName);
19400b57cec5SDimitry Andric     }
19410b57cec5SDimitry Andric     TTN->ThisAdjust.VtordispOffset = demangleSigned(MangledName);
19420b57cec5SDimitry Andric     TTN->ThisAdjust.StaticOffset = demangleSigned(MangledName);
19430b57cec5SDimitry Andric   }
19440b57cec5SDimitry Andric 
19450b57cec5SDimitry Andric   if (FC & FC_NoParameterList) {
19460b57cec5SDimitry Andric     // This is an extern "C" function whose full signature hasn't been mangled.
19470b57cec5SDimitry Andric     // This happens when we need to mangle a local symbol inside of an extern
19480b57cec5SDimitry Andric     // "C" function.
19490b57cec5SDimitry Andric     FSN = Arena.alloc<FunctionSignatureNode>();
19500b57cec5SDimitry Andric   } else {
19510b57cec5SDimitry Andric     bool HasThisQuals = !(FC & (FC_Global | FC_Static));
19520b57cec5SDimitry Andric     FSN = demangleFunctionType(MangledName, HasThisQuals);
19530b57cec5SDimitry Andric   }
19540b57cec5SDimitry Andric 
19550b57cec5SDimitry Andric   if (Error)
19560b57cec5SDimitry Andric     return nullptr;
19570b57cec5SDimitry Andric 
19580b57cec5SDimitry Andric   if (TTN) {
19590b57cec5SDimitry Andric     *static_cast<FunctionSignatureNode *>(TTN) = *FSN;
19600b57cec5SDimitry Andric     FSN = TTN;
19610b57cec5SDimitry Andric   }
19620b57cec5SDimitry Andric   FSN->FunctionClass = FC;
19630b57cec5SDimitry Andric 
19640b57cec5SDimitry Andric   FunctionSymbolNode *Symbol = Arena.alloc<FunctionSymbolNode>();
19650b57cec5SDimitry Andric   Symbol->Signature = FSN;
19660b57cec5SDimitry Andric   return Symbol;
19670b57cec5SDimitry Andric }
19680b57cec5SDimitry Andric 
196906c3fb27SDimitry Andric CustomTypeNode *Demangler::demangleCustomType(std::string_view &MangledName) {
197006c3fb27SDimitry Andric   assert(llvm::itanium_demangle::starts_with(MangledName, '?'));
197106c3fb27SDimitry Andric   MangledName.remove_prefix(1);
19720b57cec5SDimitry Andric 
19730b57cec5SDimitry Andric   CustomTypeNode *CTN = Arena.alloc<CustomTypeNode>();
19740b57cec5SDimitry Andric   CTN->Identifier = demangleUnqualifiedTypeName(MangledName, /*Memorize=*/true);
197506c3fb27SDimitry Andric   if (!consumeFront(MangledName, '@'))
19760b57cec5SDimitry Andric     Error = true;
19770b57cec5SDimitry Andric   if (Error)
19780b57cec5SDimitry Andric     return nullptr;
19790b57cec5SDimitry Andric   return CTN;
19800b57cec5SDimitry Andric }
19810b57cec5SDimitry Andric 
19820b57cec5SDimitry Andric // Reads a primitive type.
198306c3fb27SDimitry Andric PrimitiveTypeNode *
198406c3fb27SDimitry Andric Demangler::demanglePrimitiveType(std::string_view &MangledName) {
198506c3fb27SDimitry Andric   if (consumeFront(MangledName, "$$T"))
19860b57cec5SDimitry Andric     return Arena.alloc<PrimitiveTypeNode>(PrimitiveKind::Nullptr);
19870b57cec5SDimitry Andric 
198806c3fb27SDimitry Andric   const char F = MangledName.front();
198906c3fb27SDimitry Andric   MangledName.remove_prefix(1);
199006c3fb27SDimitry Andric   switch (F) {
19910b57cec5SDimitry Andric   case 'X':
19920b57cec5SDimitry Andric     return Arena.alloc<PrimitiveTypeNode>(PrimitiveKind::Void);
19930b57cec5SDimitry Andric   case 'D':
19940b57cec5SDimitry Andric     return Arena.alloc<PrimitiveTypeNode>(PrimitiveKind::Char);
19950b57cec5SDimitry Andric   case 'C':
19960b57cec5SDimitry Andric     return Arena.alloc<PrimitiveTypeNode>(PrimitiveKind::Schar);
19970b57cec5SDimitry Andric   case 'E':
19980b57cec5SDimitry Andric     return Arena.alloc<PrimitiveTypeNode>(PrimitiveKind::Uchar);
19990b57cec5SDimitry Andric   case 'F':
20000b57cec5SDimitry Andric     return Arena.alloc<PrimitiveTypeNode>(PrimitiveKind::Short);
20010b57cec5SDimitry Andric   case 'G':
20020b57cec5SDimitry Andric     return Arena.alloc<PrimitiveTypeNode>(PrimitiveKind::Ushort);
20030b57cec5SDimitry Andric   case 'H':
20040b57cec5SDimitry Andric     return Arena.alloc<PrimitiveTypeNode>(PrimitiveKind::Int);
20050b57cec5SDimitry Andric   case 'I':
20060b57cec5SDimitry Andric     return Arena.alloc<PrimitiveTypeNode>(PrimitiveKind::Uint);
20070b57cec5SDimitry Andric   case 'J':
20080b57cec5SDimitry Andric     return Arena.alloc<PrimitiveTypeNode>(PrimitiveKind::Long);
20090b57cec5SDimitry Andric   case 'K':
20100b57cec5SDimitry Andric     return Arena.alloc<PrimitiveTypeNode>(PrimitiveKind::Ulong);
20110b57cec5SDimitry Andric   case 'M':
20120b57cec5SDimitry Andric     return Arena.alloc<PrimitiveTypeNode>(PrimitiveKind::Float);
20130b57cec5SDimitry Andric   case 'N':
20140b57cec5SDimitry Andric     return Arena.alloc<PrimitiveTypeNode>(PrimitiveKind::Double);
20150b57cec5SDimitry Andric   case 'O':
20160b57cec5SDimitry Andric     return Arena.alloc<PrimitiveTypeNode>(PrimitiveKind::Ldouble);
20170b57cec5SDimitry Andric   case '_': {
20180b57cec5SDimitry Andric     if (MangledName.empty()) {
20190b57cec5SDimitry Andric       Error = true;
20200b57cec5SDimitry Andric       return nullptr;
20210b57cec5SDimitry Andric     }
202206c3fb27SDimitry Andric     const char F = MangledName.front();
202306c3fb27SDimitry Andric     MangledName.remove_prefix(1);
202406c3fb27SDimitry Andric     switch (F) {
20250b57cec5SDimitry Andric     case 'N':
20260b57cec5SDimitry Andric       return Arena.alloc<PrimitiveTypeNode>(PrimitiveKind::Bool);
20270b57cec5SDimitry Andric     case 'J':
20280b57cec5SDimitry Andric       return Arena.alloc<PrimitiveTypeNode>(PrimitiveKind::Int64);
20290b57cec5SDimitry Andric     case 'K':
20300b57cec5SDimitry Andric       return Arena.alloc<PrimitiveTypeNode>(PrimitiveKind::Uint64);
20310b57cec5SDimitry Andric     case 'W':
20320b57cec5SDimitry Andric       return Arena.alloc<PrimitiveTypeNode>(PrimitiveKind::Wchar);
20330b57cec5SDimitry Andric     case 'Q':
20340b57cec5SDimitry Andric       return Arena.alloc<PrimitiveTypeNode>(PrimitiveKind::Char8);
20350b57cec5SDimitry Andric     case 'S':
20360b57cec5SDimitry Andric       return Arena.alloc<PrimitiveTypeNode>(PrimitiveKind::Char16);
20370b57cec5SDimitry Andric     case 'U':
20380b57cec5SDimitry Andric       return Arena.alloc<PrimitiveTypeNode>(PrimitiveKind::Char32);
20390b57cec5SDimitry Andric     }
20400b57cec5SDimitry Andric     break;
20410b57cec5SDimitry Andric   }
20420b57cec5SDimitry Andric   }
20430b57cec5SDimitry Andric   Error = true;
20440b57cec5SDimitry Andric   return nullptr;
20450b57cec5SDimitry Andric }
20460b57cec5SDimitry Andric 
204706c3fb27SDimitry Andric TagTypeNode *Demangler::demangleClassType(std::string_view &MangledName) {
20480b57cec5SDimitry Andric   TagTypeNode *TT = nullptr;
20490b57cec5SDimitry Andric 
205006c3fb27SDimitry Andric   const char F = MangledName.front();
205106c3fb27SDimitry Andric   MangledName.remove_prefix(1);
205206c3fb27SDimitry Andric   switch (F) {
20530b57cec5SDimitry Andric   case 'T':
20540b57cec5SDimitry Andric     TT = Arena.alloc<TagTypeNode>(TagKind::Union);
20550b57cec5SDimitry Andric     break;
20560b57cec5SDimitry Andric   case 'U':
20570b57cec5SDimitry Andric     TT = Arena.alloc<TagTypeNode>(TagKind::Struct);
20580b57cec5SDimitry Andric     break;
20590b57cec5SDimitry Andric   case 'V':
20600b57cec5SDimitry Andric     TT = Arena.alloc<TagTypeNode>(TagKind::Class);
20610b57cec5SDimitry Andric     break;
20620b57cec5SDimitry Andric   case 'W':
206306c3fb27SDimitry Andric     if (!consumeFront(MangledName, '4')) {
20640b57cec5SDimitry Andric       Error = true;
20650b57cec5SDimitry Andric       return nullptr;
20660b57cec5SDimitry Andric     }
20670b57cec5SDimitry Andric     TT = Arena.alloc<TagTypeNode>(TagKind::Enum);
20680b57cec5SDimitry Andric     break;
20690b57cec5SDimitry Andric   default:
20700b57cec5SDimitry Andric     assert(false);
20710b57cec5SDimitry Andric   }
20720b57cec5SDimitry Andric 
20730b57cec5SDimitry Andric   TT->QualifiedName = demangleFullyQualifiedTypeName(MangledName);
20740b57cec5SDimitry Andric   return TT;
20750b57cec5SDimitry Andric }
20760b57cec5SDimitry Andric 
20770b57cec5SDimitry Andric // <pointer-type> ::= E? <pointer-cvr-qualifiers> <ext-qualifiers> <type>
20780b57cec5SDimitry Andric //                       # the E is required for 64-bit non-static pointers
207906c3fb27SDimitry Andric PointerTypeNode *Demangler::demanglePointerType(std::string_view &MangledName) {
20800b57cec5SDimitry Andric   PointerTypeNode *Pointer = Arena.alloc<PointerTypeNode>();
20810b57cec5SDimitry Andric 
20820b57cec5SDimitry Andric   std::tie(Pointer->Quals, Pointer->Affinity) =
20830b57cec5SDimitry Andric       demanglePointerCVQualifiers(MangledName);
20840b57cec5SDimitry Andric 
208506c3fb27SDimitry Andric   if (consumeFront(MangledName, "6")) {
20860b57cec5SDimitry Andric     Pointer->Pointee = demangleFunctionType(MangledName, false);
20870b57cec5SDimitry Andric     return Pointer;
20880b57cec5SDimitry Andric   }
20890b57cec5SDimitry Andric 
20900b57cec5SDimitry Andric   Qualifiers ExtQuals = demanglePointerExtQualifiers(MangledName);
20910b57cec5SDimitry Andric   Pointer->Quals = Qualifiers(Pointer->Quals | ExtQuals);
20920b57cec5SDimitry Andric 
20930b57cec5SDimitry Andric   Pointer->Pointee = demangleType(MangledName, QualifierMangleMode::Mangle);
20940b57cec5SDimitry Andric   return Pointer;
20950b57cec5SDimitry Andric }
20960b57cec5SDimitry Andric 
209706c3fb27SDimitry Andric PointerTypeNode *
209806c3fb27SDimitry Andric Demangler::demangleMemberPointerType(std::string_view &MangledName) {
20990b57cec5SDimitry Andric   PointerTypeNode *Pointer = Arena.alloc<PointerTypeNode>();
21000b57cec5SDimitry Andric 
21010b57cec5SDimitry Andric   std::tie(Pointer->Quals, Pointer->Affinity) =
21020b57cec5SDimitry Andric       demanglePointerCVQualifiers(MangledName);
21030b57cec5SDimitry Andric   assert(Pointer->Affinity == PointerAffinity::Pointer);
21040b57cec5SDimitry Andric 
21050b57cec5SDimitry Andric   Qualifiers ExtQuals = demanglePointerExtQualifiers(MangledName);
21060b57cec5SDimitry Andric   Pointer->Quals = Qualifiers(Pointer->Quals | ExtQuals);
21070b57cec5SDimitry Andric 
21080b57cec5SDimitry Andric   // isMemberPointer() only returns true if there is at least one character
21090b57cec5SDimitry Andric   // after the qualifiers.
211006c3fb27SDimitry Andric   if (consumeFront(MangledName, "8")) {
21110b57cec5SDimitry Andric     Pointer->ClassParent = demangleFullyQualifiedTypeName(MangledName);
21120b57cec5SDimitry Andric     Pointer->Pointee = demangleFunctionType(MangledName, true);
21130b57cec5SDimitry Andric   } else {
21140b57cec5SDimitry Andric     Qualifiers PointeeQuals = Q_None;
21150b57cec5SDimitry Andric     bool IsMember = false;
21160b57cec5SDimitry Andric     std::tie(PointeeQuals, IsMember) = demangleQualifiers(MangledName);
21170b57cec5SDimitry Andric     assert(IsMember || Error);
21180b57cec5SDimitry Andric     Pointer->ClassParent = demangleFullyQualifiedTypeName(MangledName);
21190b57cec5SDimitry Andric 
21200b57cec5SDimitry Andric     Pointer->Pointee = demangleType(MangledName, QualifierMangleMode::Drop);
21210b57cec5SDimitry Andric     if (Pointer->Pointee)
21220b57cec5SDimitry Andric       Pointer->Pointee->Quals = PointeeQuals;
21230b57cec5SDimitry Andric   }
21240b57cec5SDimitry Andric 
21250b57cec5SDimitry Andric   return Pointer;
21260b57cec5SDimitry Andric }
21270b57cec5SDimitry Andric 
212806c3fb27SDimitry Andric Qualifiers
212906c3fb27SDimitry Andric Demangler::demanglePointerExtQualifiers(std::string_view &MangledName) {
21300b57cec5SDimitry Andric   Qualifiers Quals = Q_None;
213106c3fb27SDimitry Andric   if (consumeFront(MangledName, 'E'))
21320b57cec5SDimitry Andric     Quals = Qualifiers(Quals | Q_Pointer64);
213306c3fb27SDimitry Andric   if (consumeFront(MangledName, 'I'))
21340b57cec5SDimitry Andric     Quals = Qualifiers(Quals | Q_Restrict);
213506c3fb27SDimitry Andric   if (consumeFront(MangledName, 'F'))
21360b57cec5SDimitry Andric     Quals = Qualifiers(Quals | Q_Unaligned);
21370b57cec5SDimitry Andric 
21380b57cec5SDimitry Andric   return Quals;
21390b57cec5SDimitry Andric }
21400b57cec5SDimitry Andric 
214106c3fb27SDimitry Andric ArrayTypeNode *Demangler::demangleArrayType(std::string_view &MangledName) {
21420b57cec5SDimitry Andric   assert(MangledName.front() == 'Y');
214306c3fb27SDimitry Andric   MangledName.remove_prefix(1);
21440b57cec5SDimitry Andric 
21450b57cec5SDimitry Andric   uint64_t Rank = 0;
21460b57cec5SDimitry Andric   bool IsNegative = false;
21470b57cec5SDimitry Andric   std::tie(Rank, IsNegative) = demangleNumber(MangledName);
21480b57cec5SDimitry Andric   if (IsNegative || Rank == 0) {
21490b57cec5SDimitry Andric     Error = true;
21500b57cec5SDimitry Andric     return nullptr;
21510b57cec5SDimitry Andric   }
21520b57cec5SDimitry Andric 
21530b57cec5SDimitry Andric   ArrayTypeNode *ATy = Arena.alloc<ArrayTypeNode>();
21540b57cec5SDimitry Andric   NodeList *Head = Arena.alloc<NodeList>();
21550b57cec5SDimitry Andric   NodeList *Tail = Head;
21560b57cec5SDimitry Andric 
21570b57cec5SDimitry Andric   for (uint64_t I = 0; I < Rank; ++I) {
21580b57cec5SDimitry Andric     uint64_t D = 0;
21590b57cec5SDimitry Andric     std::tie(D, IsNegative) = demangleNumber(MangledName);
21600b57cec5SDimitry Andric     if (Error || IsNegative) {
21610b57cec5SDimitry Andric       Error = true;
21620b57cec5SDimitry Andric       return nullptr;
21630b57cec5SDimitry Andric     }
21640b57cec5SDimitry Andric     Tail->N = Arena.alloc<IntegerLiteralNode>(D, IsNegative);
21650b57cec5SDimitry Andric     if (I + 1 < Rank) {
21660b57cec5SDimitry Andric       Tail->Next = Arena.alloc<NodeList>();
21670b57cec5SDimitry Andric       Tail = Tail->Next;
21680b57cec5SDimitry Andric     }
21690b57cec5SDimitry Andric   }
21700b57cec5SDimitry Andric   ATy->Dimensions = nodeListToNodeArray(Arena, Head, Rank);
21710b57cec5SDimitry Andric 
217206c3fb27SDimitry Andric   if (consumeFront(MangledName, "$$C")) {
21730b57cec5SDimitry Andric     bool IsMember = false;
21740b57cec5SDimitry Andric     std::tie(ATy->Quals, IsMember) = demangleQualifiers(MangledName);
21750b57cec5SDimitry Andric     if (IsMember) {
21760b57cec5SDimitry Andric       Error = true;
21770b57cec5SDimitry Andric       return nullptr;
21780b57cec5SDimitry Andric     }
21790b57cec5SDimitry Andric   }
21800b57cec5SDimitry Andric 
21810b57cec5SDimitry Andric   ATy->ElementType = demangleType(MangledName, QualifierMangleMode::Drop);
21820b57cec5SDimitry Andric   return ATy;
21830b57cec5SDimitry Andric }
21840b57cec5SDimitry Andric 
21850b57cec5SDimitry Andric // Reads a function's parameters.
218606c3fb27SDimitry Andric NodeArrayNode *
218706c3fb27SDimitry Andric Demangler::demangleFunctionParameterList(std::string_view &MangledName,
21880b57cec5SDimitry Andric                                          bool &IsVariadic) {
21890b57cec5SDimitry Andric   // Empty parameter list.
219006c3fb27SDimitry Andric   if (consumeFront(MangledName, 'X'))
21910b57cec5SDimitry Andric     return nullptr;
21920b57cec5SDimitry Andric 
21930b57cec5SDimitry Andric   NodeList *Head = Arena.alloc<NodeList>();
21940b57cec5SDimitry Andric   NodeList **Current = &Head;
21950b57cec5SDimitry Andric   size_t Count = 0;
219606c3fb27SDimitry Andric   while (!Error && !llvm::itanium_demangle::starts_with(MangledName, '@') &&
219706c3fb27SDimitry Andric          !llvm::itanium_demangle::starts_with(MangledName, 'Z')) {
21980b57cec5SDimitry Andric     ++Count;
21990b57cec5SDimitry Andric 
22000b57cec5SDimitry Andric     if (startsWithDigit(MangledName)) {
22010b57cec5SDimitry Andric       size_t N = MangledName[0] - '0';
22020b57cec5SDimitry Andric       if (N >= Backrefs.FunctionParamCount) {
22030b57cec5SDimitry Andric         Error = true;
22040b57cec5SDimitry Andric         return nullptr;
22050b57cec5SDimitry Andric       }
220606c3fb27SDimitry Andric       MangledName.remove_prefix(1);
22070b57cec5SDimitry Andric 
22080b57cec5SDimitry Andric       *Current = Arena.alloc<NodeList>();
22090b57cec5SDimitry Andric       (*Current)->N = Backrefs.FunctionParams[N];
22100b57cec5SDimitry Andric       Current = &(*Current)->Next;
22110b57cec5SDimitry Andric       continue;
22120b57cec5SDimitry Andric     }
22130b57cec5SDimitry Andric 
22140b57cec5SDimitry Andric     size_t OldSize = MangledName.size();
22150b57cec5SDimitry Andric 
22160b57cec5SDimitry Andric     *Current = Arena.alloc<NodeList>();
22170b57cec5SDimitry Andric     TypeNode *TN = demangleType(MangledName, QualifierMangleMode::Drop);
22180b57cec5SDimitry Andric     if (!TN || Error)
22190b57cec5SDimitry Andric       return nullptr;
22200b57cec5SDimitry Andric 
22210b57cec5SDimitry Andric     (*Current)->N = TN;
22220b57cec5SDimitry Andric 
22230b57cec5SDimitry Andric     size_t CharsConsumed = OldSize - MangledName.size();
22240b57cec5SDimitry Andric     assert(CharsConsumed != 0);
22250b57cec5SDimitry Andric 
22260b57cec5SDimitry Andric     // Single-letter types are ignored for backreferences because memorizing
22270b57cec5SDimitry Andric     // them doesn't save anything.
22280b57cec5SDimitry Andric     if (Backrefs.FunctionParamCount <= 9 && CharsConsumed > 1)
22290b57cec5SDimitry Andric       Backrefs.FunctionParams[Backrefs.FunctionParamCount++] = TN;
22300b57cec5SDimitry Andric 
22310b57cec5SDimitry Andric     Current = &(*Current)->Next;
22320b57cec5SDimitry Andric   }
22330b57cec5SDimitry Andric 
22340b57cec5SDimitry Andric   if (Error)
22350b57cec5SDimitry Andric     return nullptr;
22360b57cec5SDimitry Andric 
22370b57cec5SDimitry Andric   NodeArrayNode *NA = nodeListToNodeArray(Arena, Head, Count);
22380b57cec5SDimitry Andric   // A non-empty parameter list is terminated by either 'Z' (variadic) parameter
22390b57cec5SDimitry Andric   // list or '@' (non variadic).  Careful not to consume "@Z", as in that case
22400b57cec5SDimitry Andric   // the following Z could be a throw specifier.
224106c3fb27SDimitry Andric   if (consumeFront(MangledName, '@'))
22420b57cec5SDimitry Andric     return NA;
22430b57cec5SDimitry Andric 
224406c3fb27SDimitry Andric   if (consumeFront(MangledName, 'Z')) {
22450b57cec5SDimitry Andric     IsVariadic = true;
22460b57cec5SDimitry Andric     return NA;
22470b57cec5SDimitry Andric   }
22480b57cec5SDimitry Andric 
22490b57cec5SDimitry Andric   DEMANGLE_UNREACHABLE;
22500b57cec5SDimitry Andric }
22510b57cec5SDimitry Andric 
22520b57cec5SDimitry Andric NodeArrayNode *
225306c3fb27SDimitry Andric Demangler::demangleTemplateParameterList(std::string_view &MangledName) {
22548bcb0991SDimitry Andric   NodeList *Head = nullptr;
22550b57cec5SDimitry Andric   NodeList **Current = &Head;
22560b57cec5SDimitry Andric   size_t Count = 0;
22570b57cec5SDimitry Andric 
225806c3fb27SDimitry Andric   while (!llvm::itanium_demangle::starts_with(MangledName, '@')) {
225906c3fb27SDimitry Andric     if (consumeFront(MangledName, "$S") || consumeFront(MangledName, "$$V") ||
226006c3fb27SDimitry Andric         consumeFront(MangledName, "$$$V") || consumeFront(MangledName, "$$Z")) {
22610b57cec5SDimitry Andric       // parameter pack separator
22620b57cec5SDimitry Andric       continue;
22630b57cec5SDimitry Andric     }
22640b57cec5SDimitry Andric 
22650b57cec5SDimitry Andric     ++Count;
22660b57cec5SDimitry Andric 
22670b57cec5SDimitry Andric     // Template parameter lists don't participate in back-referencing.
22680b57cec5SDimitry Andric     *Current = Arena.alloc<NodeList>();
22690b57cec5SDimitry Andric 
22700b57cec5SDimitry Andric     NodeList &TP = **Current;
22710b57cec5SDimitry Andric 
22720fca6ea1SDimitry Andric     // <auto-nttp> ::= $ M <type> <nttp>
22730fca6ea1SDimitry Andric     const bool IsAutoNTTP = consumeFront(MangledName, "$M");
22740fca6ea1SDimitry Andric     if (IsAutoNTTP) {
22750fca6ea1SDimitry Andric       // The deduced type of the auto NTTP parameter isn't printed so
22760fca6ea1SDimitry Andric       // we want to ignore the AST created from demangling the type.
22770fca6ea1SDimitry Andric       //
22780fca6ea1SDimitry Andric       // TODO: Avoid the extra allocations to the bump allocator in this case.
22790fca6ea1SDimitry Andric       (void)demangleType(MangledName, QualifierMangleMode::Drop);
22800fca6ea1SDimitry Andric       if (Error)
22810fca6ea1SDimitry Andric         return nullptr;
22820fca6ea1SDimitry Andric     }
22830fca6ea1SDimitry Andric 
22840b57cec5SDimitry Andric     TemplateParameterReferenceNode *TPRN = nullptr;
228506c3fb27SDimitry Andric     if (consumeFront(MangledName, "$$Y")) {
22860b57cec5SDimitry Andric       // Template alias
22870b57cec5SDimitry Andric       TP.N = demangleFullyQualifiedTypeName(MangledName);
228806c3fb27SDimitry Andric     } else if (consumeFront(MangledName, "$$B")) {
22890b57cec5SDimitry Andric       // Array
22900b57cec5SDimitry Andric       TP.N = demangleType(MangledName, QualifierMangleMode::Drop);
229106c3fb27SDimitry Andric     } else if (consumeFront(MangledName, "$$C")) {
22920b57cec5SDimitry Andric       // Type has qualifiers.
22930b57cec5SDimitry Andric       TP.N = demangleType(MangledName, QualifierMangleMode::Mangle);
22940fca6ea1SDimitry Andric     } else if (startsWith(MangledName, "$1", "1", !IsAutoNTTP) ||
22950fca6ea1SDimitry Andric                startsWith(MangledName, "$H", "H", !IsAutoNTTP) ||
22960fca6ea1SDimitry Andric                startsWith(MangledName, "$I", "I", !IsAutoNTTP) ||
22970fca6ea1SDimitry Andric                startsWith(MangledName, "$J", "J", !IsAutoNTTP)) {
22980b57cec5SDimitry Andric       // Pointer to member
22990b57cec5SDimitry Andric       TP.N = TPRN = Arena.alloc<TemplateParameterReferenceNode>();
23000b57cec5SDimitry Andric       TPRN->IsMemberPointer = true;
23010b57cec5SDimitry Andric 
23020fca6ea1SDimitry Andric       if (!IsAutoNTTP)
23030fca6ea1SDimitry Andric         MangledName.remove_prefix(1); // Remove leading '$'
23040fca6ea1SDimitry Andric 
23050b57cec5SDimitry Andric       // 1 - single inheritance       <name>
23060b57cec5SDimitry Andric       // H - multiple inheritance     <name> <number>
23070b57cec5SDimitry Andric       // I - virtual inheritance      <name> <number> <number>
23080b57cec5SDimitry Andric       // J - unspecified inheritance  <name> <number> <number> <number>
230906c3fb27SDimitry Andric       char InheritanceSpecifier = MangledName.front();
231006c3fb27SDimitry Andric       MangledName.remove_prefix(1);
23110b57cec5SDimitry Andric       SymbolNode *S = nullptr;
231206c3fb27SDimitry Andric       if (llvm::itanium_demangle::starts_with(MangledName, '?')) {
23130b57cec5SDimitry Andric         S = parse(MangledName);
23140b57cec5SDimitry Andric         if (Error || !S->Name) {
23150b57cec5SDimitry Andric           Error = true;
23160b57cec5SDimitry Andric           return nullptr;
23170b57cec5SDimitry Andric         }
23180b57cec5SDimitry Andric         memorizeIdentifier(S->Name->getUnqualifiedIdentifier());
23190b57cec5SDimitry Andric       }
23200b57cec5SDimitry Andric 
23210b57cec5SDimitry Andric       switch (InheritanceSpecifier) {
23220b57cec5SDimitry Andric       case 'J':
23230b57cec5SDimitry Andric         TPRN->ThunkOffsets[TPRN->ThunkOffsetCount++] =
23240b57cec5SDimitry Andric             demangleSigned(MangledName);
23250b57cec5SDimitry Andric         DEMANGLE_FALLTHROUGH;
23260b57cec5SDimitry Andric       case 'I':
23270b57cec5SDimitry Andric         TPRN->ThunkOffsets[TPRN->ThunkOffsetCount++] =
23280b57cec5SDimitry Andric             demangleSigned(MangledName);
23290b57cec5SDimitry Andric         DEMANGLE_FALLTHROUGH;
23300b57cec5SDimitry Andric       case 'H':
23310b57cec5SDimitry Andric         TPRN->ThunkOffsets[TPRN->ThunkOffsetCount++] =
23320b57cec5SDimitry Andric             demangleSigned(MangledName);
23330b57cec5SDimitry Andric         DEMANGLE_FALLTHROUGH;
23340b57cec5SDimitry Andric       case '1':
23350b57cec5SDimitry Andric         break;
23360b57cec5SDimitry Andric       default:
23370b57cec5SDimitry Andric         DEMANGLE_UNREACHABLE;
23380b57cec5SDimitry Andric       }
23390b57cec5SDimitry Andric       TPRN->Affinity = PointerAffinity::Pointer;
23400b57cec5SDimitry Andric       TPRN->Symbol = S;
234106c3fb27SDimitry Andric     } else if (llvm::itanium_demangle::starts_with(MangledName, "$E?")) {
234206c3fb27SDimitry Andric       consumeFront(MangledName, "$E");
23430b57cec5SDimitry Andric       // Reference to symbol
23440b57cec5SDimitry Andric       TP.N = TPRN = Arena.alloc<TemplateParameterReferenceNode>();
23450b57cec5SDimitry Andric       TPRN->Symbol = parse(MangledName);
23460b57cec5SDimitry Andric       TPRN->Affinity = PointerAffinity::Reference;
23470fca6ea1SDimitry Andric     } else if (startsWith(MangledName, "$F", "F", !IsAutoNTTP) ||
23480fca6ea1SDimitry Andric                startsWith(MangledName, "$G", "G", !IsAutoNTTP)) {
23490b57cec5SDimitry Andric       TP.N = TPRN = Arena.alloc<TemplateParameterReferenceNode>();
23500b57cec5SDimitry Andric 
23510b57cec5SDimitry Andric       // Data member pointer.
23520fca6ea1SDimitry Andric       if (!IsAutoNTTP)
23530fca6ea1SDimitry Andric         MangledName.remove_prefix(1); // Remove leading '$'
235406c3fb27SDimitry Andric       char InheritanceSpecifier = MangledName.front();
235506c3fb27SDimitry Andric       MangledName.remove_prefix(1);
23560b57cec5SDimitry Andric 
23570b57cec5SDimitry Andric       switch (InheritanceSpecifier) {
23580b57cec5SDimitry Andric       case 'G':
23590b57cec5SDimitry Andric         TPRN->ThunkOffsets[TPRN->ThunkOffsetCount++] =
23600b57cec5SDimitry Andric             demangleSigned(MangledName);
23610b57cec5SDimitry Andric         DEMANGLE_FALLTHROUGH;
23620b57cec5SDimitry Andric       case 'F':
23630b57cec5SDimitry Andric         TPRN->ThunkOffsets[TPRN->ThunkOffsetCount++] =
23640b57cec5SDimitry Andric             demangleSigned(MangledName);
23650b57cec5SDimitry Andric         TPRN->ThunkOffsets[TPRN->ThunkOffsetCount++] =
23660b57cec5SDimitry Andric             demangleSigned(MangledName);
23670b57cec5SDimitry Andric         break;
23680b57cec5SDimitry Andric       default:
23690b57cec5SDimitry Andric         DEMANGLE_UNREACHABLE;
23700b57cec5SDimitry Andric       }
23710b57cec5SDimitry Andric       TPRN->IsMemberPointer = true;
23720b57cec5SDimitry Andric 
23730fca6ea1SDimitry Andric     } else if (consumeFront(MangledName, "$0", "0", !IsAutoNTTP)) {
23740b57cec5SDimitry Andric       // Integral non-type template parameter
23750b57cec5SDimitry Andric       bool IsNegative = false;
23760b57cec5SDimitry Andric       uint64_t Value = 0;
23770b57cec5SDimitry Andric       std::tie(Value, IsNegative) = demangleNumber(MangledName);
23780b57cec5SDimitry Andric 
23790b57cec5SDimitry Andric       TP.N = Arena.alloc<IntegerLiteralNode>(Value, IsNegative);
23800b57cec5SDimitry Andric     } else {
23810b57cec5SDimitry Andric       TP.N = demangleType(MangledName, QualifierMangleMode::Drop);
23820b57cec5SDimitry Andric     }
23830b57cec5SDimitry Andric     if (Error)
23840b57cec5SDimitry Andric       return nullptr;
23850b57cec5SDimitry Andric 
23860b57cec5SDimitry Andric     Current = &TP.Next;
23870b57cec5SDimitry Andric   }
23880b57cec5SDimitry Andric 
23890b57cec5SDimitry Andric   // The loop above returns nullptr on Error.
23900b57cec5SDimitry Andric   assert(!Error);
23910b57cec5SDimitry Andric 
23920b57cec5SDimitry Andric   // Template parameter lists cannot be variadic, so it can only be terminated
23930b57cec5SDimitry Andric   // by @ (as opposed to 'Z' in the function parameter case).
239406c3fb27SDimitry Andric   assert(llvm::itanium_demangle::starts_with(
239506c3fb27SDimitry Andric       MangledName, '@')); // The above loop exits only on '@'.
239606c3fb27SDimitry Andric   consumeFront(MangledName, '@');
23970b57cec5SDimitry Andric   return nodeListToNodeArray(Arena, Head, Count);
23980b57cec5SDimitry Andric }
23990b57cec5SDimitry Andric 
24000b57cec5SDimitry Andric void Demangler::dumpBackReferences() {
24010b57cec5SDimitry Andric   std::printf("%d function parameter backreferences\n",
24020b57cec5SDimitry Andric               (int)Backrefs.FunctionParamCount);
24030b57cec5SDimitry Andric 
24040b57cec5SDimitry Andric   // Create an output stream so we can render each type.
2405349cc55cSDimitry Andric   OutputBuffer OB;
24060b57cec5SDimitry Andric   for (size_t I = 0; I < Backrefs.FunctionParamCount; ++I) {
2407349cc55cSDimitry Andric     OB.setCurrentPosition(0);
24080b57cec5SDimitry Andric 
24090b57cec5SDimitry Andric     TypeNode *T = Backrefs.FunctionParams[I];
2410349cc55cSDimitry Andric     T->output(OB, OF_Default);
24110b57cec5SDimitry Andric 
241206c3fb27SDimitry Andric     std::string_view B = OB;
241306c3fb27SDimitry Andric     std::printf("  [%d] - %.*s\n", (int)I, (int)B.size(), B.data());
24140b57cec5SDimitry Andric   }
2415349cc55cSDimitry Andric   std::free(OB.getBuffer());
24160b57cec5SDimitry Andric 
24170b57cec5SDimitry Andric   if (Backrefs.FunctionParamCount > 0)
24180b57cec5SDimitry Andric     std::printf("\n");
24190b57cec5SDimitry Andric   std::printf("%d name backreferences\n", (int)Backrefs.NamesCount);
24200b57cec5SDimitry Andric   for (size_t I = 0; I < Backrefs.NamesCount; ++I) {
24210b57cec5SDimitry Andric     std::printf("  [%d] - %.*s\n", (int)I, (int)Backrefs.Names[I]->Name.size(),
242206c3fb27SDimitry Andric                 Backrefs.Names[I]->Name.data());
24230b57cec5SDimitry Andric   }
24240b57cec5SDimitry Andric   if (Backrefs.NamesCount > 0)
24250b57cec5SDimitry Andric     std::printf("\n");
24260b57cec5SDimitry Andric }
24270b57cec5SDimitry Andric 
2428*415efcecSDimitry Andric std::optional<size_t>
2429*415efcecSDimitry Andric llvm::getArm64ECInsertionPointInMangledName(std::string_view MangledName) {
2430*415efcecSDimitry Andric   std::string_view ProcessedName{MangledName};
2431*415efcecSDimitry Andric 
2432*415efcecSDimitry Andric   // We only support this for MSVC-style C++ symbols.
2433*415efcecSDimitry Andric   if (!consumeFront(ProcessedName, '?'))
2434*415efcecSDimitry Andric     return std::nullopt;
2435*415efcecSDimitry Andric 
2436*415efcecSDimitry Andric   // The insertion point is just after the name of the symbol, so parse that to
2437*415efcecSDimitry Andric   // remove it from the processed name.
2438*415efcecSDimitry Andric   Demangler D;
2439*415efcecSDimitry Andric   D.demangleFullyQualifiedSymbolName(ProcessedName);
2440*415efcecSDimitry Andric   if (D.Error)
2441*415efcecSDimitry Andric     return std::nullopt;
2442*415efcecSDimitry Andric 
2443*415efcecSDimitry Andric   return MangledName.length() - ProcessedName.length();
2444*415efcecSDimitry Andric }
2445*415efcecSDimitry Andric 
244606c3fb27SDimitry Andric char *llvm::microsoftDemangle(std::string_view MangledName, size_t *NMangled,
24470b57cec5SDimitry Andric                               int *Status, MSDemangleFlags Flags) {
24480b57cec5SDimitry Andric   Demangler D;
24490b57cec5SDimitry Andric 
245006c3fb27SDimitry Andric   std::string_view Name{MangledName};
24510b57cec5SDimitry Andric   SymbolNode *AST = D.parse(Name);
24525ffd83dbSDimitry Andric   if (!D.Error && NMangled)
245306c3fb27SDimitry Andric     *NMangled = MangledName.size() - Name.size();
24540b57cec5SDimitry Andric 
24550b57cec5SDimitry Andric   if (Flags & MSDF_DumpBackrefs)
24560b57cec5SDimitry Andric     D.dumpBackReferences();
24570b57cec5SDimitry Andric 
24588bcb0991SDimitry Andric   OutputFlags OF = OF_Default;
24598bcb0991SDimitry Andric   if (Flags & MSDF_NoCallingConvention)
24608bcb0991SDimitry Andric     OF = OutputFlags(OF | OF_NoCallingConvention);
24618bcb0991SDimitry Andric   if (Flags & MSDF_NoAccessSpecifier)
24628bcb0991SDimitry Andric     OF = OutputFlags(OF | OF_NoAccessSpecifier);
24638bcb0991SDimitry Andric   if (Flags & MSDF_NoReturnType)
24648bcb0991SDimitry Andric     OF = OutputFlags(OF | OF_NoReturnType);
24658bcb0991SDimitry Andric   if (Flags & MSDF_NoMemberType)
24668bcb0991SDimitry Andric     OF = OutputFlags(OF | OF_NoMemberType);
2467349cc55cSDimitry Andric   if (Flags & MSDF_NoVariableType)
2468349cc55cSDimitry Andric     OF = OutputFlags(OF | OF_NoVariableType);
24698bcb0991SDimitry Andric 
24705ffd83dbSDimitry Andric   int InternalStatus = demangle_success;
247106c3fb27SDimitry Andric   char *Buf;
24720b57cec5SDimitry Andric   if (D.Error)
24730b57cec5SDimitry Andric     InternalStatus = demangle_invalid_mangled_name;
24740b57cec5SDimitry Andric   else {
247506c3fb27SDimitry Andric     OutputBuffer OB;
2476349cc55cSDimitry Andric     AST->output(OB, OF);
2477349cc55cSDimitry Andric     OB += '\0';
2478349cc55cSDimitry Andric     Buf = OB.getBuffer();
24790b57cec5SDimitry Andric   }
24800b57cec5SDimitry Andric 
24810b57cec5SDimitry Andric   if (Status)
24820b57cec5SDimitry Andric     *Status = InternalStatus;
24830b57cec5SDimitry Andric   return InternalStatus == demangle_success ? Buf : nullptr;
24840b57cec5SDimitry Andric }
2485