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