10b57cec5SDimitry Andric //===------------------------- ItaniumDemangle.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 // FIXME: (possibly) incomplete list of features that clang mangles that this
100b57cec5SDimitry Andric // file does not yet support:
110b57cec5SDimitry Andric //   - C++ modules TS
120b57cec5SDimitry Andric 
130b57cec5SDimitry Andric #include "llvm/Demangle/Demangle.h"
140b57cec5SDimitry Andric #include "llvm/Demangle/ItaniumDemangle.h"
150b57cec5SDimitry Andric 
160b57cec5SDimitry Andric #include <cassert>
170b57cec5SDimitry Andric #include <cctype>
180b57cec5SDimitry Andric #include <cstdio>
190b57cec5SDimitry Andric #include <cstdlib>
200b57cec5SDimitry Andric #include <cstring>
2106c3fb27SDimitry Andric #include <exception>
220b57cec5SDimitry Andric #include <functional>
230b57cec5SDimitry Andric #include <utility>
240b57cec5SDimitry Andric 
250b57cec5SDimitry Andric using namespace llvm;
260b57cec5SDimitry Andric using namespace llvm::itanium_demangle;
270b57cec5SDimitry Andric 
280b57cec5SDimitry Andric constexpr const char *itanium_demangle::FloatData<float>::spec;
290b57cec5SDimitry Andric constexpr const char *itanium_demangle::FloatData<double>::spec;
300b57cec5SDimitry Andric constexpr const char *itanium_demangle::FloatData<long double>::spec;
310b57cec5SDimitry Andric 
320b57cec5SDimitry Andric // <discriminator> := _ <non-negative number>      # when number < 10
330b57cec5SDimitry Andric //                 := __ <non-negative number> _   # when number >= 10
340b57cec5SDimitry Andric //  extension      := decimal-digit+               # at the end of string
parse_discriminator(const char * first,const char * last)350b57cec5SDimitry Andric const char *itanium_demangle::parse_discriminator(const char *first,
360b57cec5SDimitry Andric                                                   const char *last) {
370b57cec5SDimitry Andric   // parse but ignore discriminator
380b57cec5SDimitry Andric   if (first != last) {
390b57cec5SDimitry Andric     if (*first == '_') {
400b57cec5SDimitry Andric       const char *t1 = first + 1;
410b57cec5SDimitry Andric       if (t1 != last) {
420b57cec5SDimitry Andric         if (std::isdigit(*t1))
430b57cec5SDimitry Andric           first = t1 + 1;
440b57cec5SDimitry Andric         else if (*t1 == '_') {
450b57cec5SDimitry Andric           for (++t1; t1 != last && std::isdigit(*t1); ++t1)
460b57cec5SDimitry Andric             ;
470b57cec5SDimitry Andric           if (t1 != last && *t1 == '_')
480b57cec5SDimitry Andric             first = t1 + 1;
490b57cec5SDimitry Andric         }
500b57cec5SDimitry Andric       }
510b57cec5SDimitry Andric     } else if (std::isdigit(*first)) {
520b57cec5SDimitry Andric       const char *t1 = first + 1;
530b57cec5SDimitry Andric       for (; t1 != last && std::isdigit(*t1); ++t1)
540b57cec5SDimitry Andric         ;
550b57cec5SDimitry Andric       if (t1 == last)
560b57cec5SDimitry Andric         first = last;
570b57cec5SDimitry Andric     }
580b57cec5SDimitry Andric   }
590b57cec5SDimitry Andric   return first;
600b57cec5SDimitry Andric }
610b57cec5SDimitry Andric 
620b57cec5SDimitry Andric #ifndef NDEBUG
630b57cec5SDimitry Andric namespace {
640b57cec5SDimitry Andric struct DumpVisitor {
650b57cec5SDimitry Andric   unsigned Depth = 0;
660b57cec5SDimitry Andric   bool PendingNewline = false;
670b57cec5SDimitry Andric 
wantsNewline__anon39624eb80111::DumpVisitor680b57cec5SDimitry Andric   template<typename NodeT> static constexpr bool wantsNewline(const NodeT *) {
690b57cec5SDimitry Andric     return true;
700b57cec5SDimitry Andric   }
wantsNewline__anon39624eb80111::DumpVisitor710b57cec5SDimitry Andric   static bool wantsNewline(NodeArray A) { return !A.empty(); }
wantsNewline__anon39624eb80111::DumpVisitor720b57cec5SDimitry Andric   static constexpr bool wantsNewline(...) { return false; }
730b57cec5SDimitry Andric 
anyWantNewline__anon39624eb80111::DumpVisitor740b57cec5SDimitry Andric   template<typename ...Ts> static bool anyWantNewline(Ts ...Vs) {
750b57cec5SDimitry Andric     for (bool B : {wantsNewline(Vs)...})
760b57cec5SDimitry Andric       if (B)
770b57cec5SDimitry Andric         return true;
780b57cec5SDimitry Andric     return false;
790b57cec5SDimitry Andric   }
800b57cec5SDimitry Andric 
printStr__anon39624eb80111::DumpVisitor810b57cec5SDimitry Andric   void printStr(const char *S) { fprintf(stderr, "%s", S); }
print__anon39624eb80111::DumpVisitor8206c3fb27SDimitry Andric   void print(std::string_view SV) {
8306c3fb27SDimitry Andric     fprintf(stderr, "\"%.*s\"", (int)SV.size(), SV.data());
840b57cec5SDimitry Andric   }
print__anon39624eb80111::DumpVisitor850b57cec5SDimitry Andric   void print(const Node *N) {
860b57cec5SDimitry Andric     if (N)
870b57cec5SDimitry Andric       N->visit(std::ref(*this));
880b57cec5SDimitry Andric     else
890b57cec5SDimitry Andric       printStr("<null>");
900b57cec5SDimitry Andric   }
print__anon39624eb80111::DumpVisitor910b57cec5SDimitry Andric   void print(NodeArray A) {
920b57cec5SDimitry Andric     ++Depth;
930b57cec5SDimitry Andric     printStr("{");
940b57cec5SDimitry Andric     bool First = true;
950b57cec5SDimitry Andric     for (const Node *N : A) {
960b57cec5SDimitry Andric       if (First)
970b57cec5SDimitry Andric         print(N);
980b57cec5SDimitry Andric       else
990b57cec5SDimitry Andric         printWithComma(N);
1000b57cec5SDimitry Andric       First = false;
1010b57cec5SDimitry Andric     }
1020b57cec5SDimitry Andric     printStr("}");
1030b57cec5SDimitry Andric     --Depth;
1040b57cec5SDimitry Andric   }
1050b57cec5SDimitry Andric 
1060b57cec5SDimitry Andric   // Overload used when T is exactly 'bool', not merely convertible to 'bool'.
print__anon39624eb80111::DumpVisitor1070b57cec5SDimitry Andric   void print(bool B) { printStr(B ? "true" : "false"); }
1080b57cec5SDimitry Andric 
print__anon39624eb80111::DumpVisitor1095ffd83dbSDimitry Andric   template <class T> std::enable_if_t<std::is_unsigned<T>::value> print(T N) {
1100b57cec5SDimitry Andric     fprintf(stderr, "%llu", (unsigned long long)N);
1110b57cec5SDimitry Andric   }
1120b57cec5SDimitry Andric 
print__anon39624eb80111::DumpVisitor1135ffd83dbSDimitry Andric   template <class T> std::enable_if_t<std::is_signed<T>::value> print(T N) {
1140b57cec5SDimitry Andric     fprintf(stderr, "%lld", (long long)N);
1150b57cec5SDimitry Andric   }
1160b57cec5SDimitry Andric 
print__anon39624eb80111::DumpVisitor1170b57cec5SDimitry Andric   void print(ReferenceKind RK) {
1180b57cec5SDimitry Andric     switch (RK) {
1190b57cec5SDimitry Andric     case ReferenceKind::LValue:
1200b57cec5SDimitry Andric       return printStr("ReferenceKind::LValue");
1210b57cec5SDimitry Andric     case ReferenceKind::RValue:
1220b57cec5SDimitry Andric       return printStr("ReferenceKind::RValue");
1230b57cec5SDimitry Andric     }
1240b57cec5SDimitry Andric   }
print__anon39624eb80111::DumpVisitor1250b57cec5SDimitry Andric   void print(FunctionRefQual RQ) {
1260b57cec5SDimitry Andric     switch (RQ) {
1270b57cec5SDimitry Andric     case FunctionRefQual::FrefQualNone:
1280b57cec5SDimitry Andric       return printStr("FunctionRefQual::FrefQualNone");
1290b57cec5SDimitry Andric     case FunctionRefQual::FrefQualLValue:
1300b57cec5SDimitry Andric       return printStr("FunctionRefQual::FrefQualLValue");
1310b57cec5SDimitry Andric     case FunctionRefQual::FrefQualRValue:
1320b57cec5SDimitry Andric       return printStr("FunctionRefQual::FrefQualRValue");
1330b57cec5SDimitry Andric     }
1340b57cec5SDimitry Andric   }
print__anon39624eb80111::DumpVisitor1350b57cec5SDimitry Andric   void print(Qualifiers Qs) {
1360b57cec5SDimitry Andric     if (!Qs) return printStr("QualNone");
1370b57cec5SDimitry Andric     struct QualName { Qualifiers Q; const char *Name; } Names[] = {
1380b57cec5SDimitry Andric       {QualConst, "QualConst"},
1390b57cec5SDimitry Andric       {QualVolatile, "QualVolatile"},
1400b57cec5SDimitry Andric       {QualRestrict, "QualRestrict"},
1410b57cec5SDimitry Andric     };
1420b57cec5SDimitry Andric     for (QualName Name : Names) {
1430b57cec5SDimitry Andric       if (Qs & Name.Q) {
1440b57cec5SDimitry Andric         printStr(Name.Name);
1450b57cec5SDimitry Andric         Qs = Qualifiers(Qs & ~Name.Q);
1460b57cec5SDimitry Andric         if (Qs) printStr(" | ");
1470b57cec5SDimitry Andric       }
1480b57cec5SDimitry Andric     }
1490b57cec5SDimitry Andric   }
print__anon39624eb80111::DumpVisitor1500b57cec5SDimitry Andric   void print(SpecialSubKind SSK) {
1510b57cec5SDimitry Andric     switch (SSK) {
1520b57cec5SDimitry Andric     case SpecialSubKind::allocator:
1530b57cec5SDimitry Andric       return printStr("SpecialSubKind::allocator");
1540b57cec5SDimitry Andric     case SpecialSubKind::basic_string:
1550b57cec5SDimitry Andric       return printStr("SpecialSubKind::basic_string");
1560b57cec5SDimitry Andric     case SpecialSubKind::string:
1570b57cec5SDimitry Andric       return printStr("SpecialSubKind::string");
1580b57cec5SDimitry Andric     case SpecialSubKind::istream:
1590b57cec5SDimitry Andric       return printStr("SpecialSubKind::istream");
1600b57cec5SDimitry Andric     case SpecialSubKind::ostream:
1610b57cec5SDimitry Andric       return printStr("SpecialSubKind::ostream");
1620b57cec5SDimitry Andric     case SpecialSubKind::iostream:
1630b57cec5SDimitry Andric       return printStr("SpecialSubKind::iostream");
1640b57cec5SDimitry Andric     }
1650b57cec5SDimitry Andric   }
print__anon39624eb80111::DumpVisitor1668bcb0991SDimitry Andric   void print(TemplateParamKind TPK) {
1678bcb0991SDimitry Andric     switch (TPK) {
1688bcb0991SDimitry Andric     case TemplateParamKind::Type:
1698bcb0991SDimitry Andric       return printStr("TemplateParamKind::Type");
1708bcb0991SDimitry Andric     case TemplateParamKind::NonType:
1718bcb0991SDimitry Andric       return printStr("TemplateParamKind::NonType");
1728bcb0991SDimitry Andric     case TemplateParamKind::Template:
1738bcb0991SDimitry Andric       return printStr("TemplateParamKind::Template");
1748bcb0991SDimitry Andric     }
1758bcb0991SDimitry Andric   }
print__anon39624eb80111::DumpVisitor17681ad6265SDimitry Andric   void print(Node::Prec P) {
17781ad6265SDimitry Andric     switch (P) {
17881ad6265SDimitry Andric     case Node::Prec::Primary:
17981ad6265SDimitry Andric       return printStr("Node::Prec::Primary");
18081ad6265SDimitry Andric     case Node::Prec::Postfix:
18181ad6265SDimitry Andric       return printStr("Node::Prec::Postfix");
18281ad6265SDimitry Andric     case Node::Prec::Unary:
18381ad6265SDimitry Andric       return printStr("Node::Prec::Unary");
18481ad6265SDimitry Andric     case Node::Prec::Cast:
18581ad6265SDimitry Andric       return printStr("Node::Prec::Cast");
18681ad6265SDimitry Andric     case Node::Prec::PtrMem:
18781ad6265SDimitry Andric       return printStr("Node::Prec::PtrMem");
18881ad6265SDimitry Andric     case Node::Prec::Multiplicative:
18981ad6265SDimitry Andric       return printStr("Node::Prec::Multiplicative");
19081ad6265SDimitry Andric     case Node::Prec::Additive:
19181ad6265SDimitry Andric       return printStr("Node::Prec::Additive");
19281ad6265SDimitry Andric     case Node::Prec::Shift:
19381ad6265SDimitry Andric       return printStr("Node::Prec::Shift");
19481ad6265SDimitry Andric     case Node::Prec::Spaceship:
19581ad6265SDimitry Andric       return printStr("Node::Prec::Spaceship");
19681ad6265SDimitry Andric     case Node::Prec::Relational:
19781ad6265SDimitry Andric       return printStr("Node::Prec::Relational");
19881ad6265SDimitry Andric     case Node::Prec::Equality:
19981ad6265SDimitry Andric       return printStr("Node::Prec::Equality");
20081ad6265SDimitry Andric     case Node::Prec::And:
20181ad6265SDimitry Andric       return printStr("Node::Prec::And");
20281ad6265SDimitry Andric     case Node::Prec::Xor:
20381ad6265SDimitry Andric       return printStr("Node::Prec::Xor");
20481ad6265SDimitry Andric     case Node::Prec::Ior:
20581ad6265SDimitry Andric       return printStr("Node::Prec::Ior");
20681ad6265SDimitry Andric     case Node::Prec::AndIf:
20781ad6265SDimitry Andric       return printStr("Node::Prec::AndIf");
20881ad6265SDimitry Andric     case Node::Prec::OrIf:
20981ad6265SDimitry Andric       return printStr("Node::Prec::OrIf");
21081ad6265SDimitry Andric     case Node::Prec::Conditional:
21181ad6265SDimitry Andric       return printStr("Node::Prec::Conditional");
21281ad6265SDimitry Andric     case Node::Prec::Assign:
21381ad6265SDimitry Andric       return printStr("Node::Prec::Assign");
21481ad6265SDimitry Andric     case Node::Prec::Comma:
21581ad6265SDimitry Andric       return printStr("Node::Prec::Comma");
21681ad6265SDimitry Andric     case Node::Prec::Default:
21781ad6265SDimitry Andric       return printStr("Node::Prec::Default");
21881ad6265SDimitry Andric     }
21981ad6265SDimitry Andric   }
2200b57cec5SDimitry Andric 
newLine__anon39624eb80111::DumpVisitor2210b57cec5SDimitry Andric   void newLine() {
2220b57cec5SDimitry Andric     printStr("\n");
2230b57cec5SDimitry Andric     for (unsigned I = 0; I != Depth; ++I)
2240b57cec5SDimitry Andric       printStr(" ");
2250b57cec5SDimitry Andric     PendingNewline = false;
2260b57cec5SDimitry Andric   }
2270b57cec5SDimitry Andric 
printWithPendingNewline__anon39624eb80111::DumpVisitor2280b57cec5SDimitry Andric   template<typename T> void printWithPendingNewline(T V) {
2290b57cec5SDimitry Andric     print(V);
2300b57cec5SDimitry Andric     if (wantsNewline(V))
2310b57cec5SDimitry Andric       PendingNewline = true;
2320b57cec5SDimitry Andric   }
2330b57cec5SDimitry Andric 
printWithComma__anon39624eb80111::DumpVisitor2340b57cec5SDimitry Andric   template<typename T> void printWithComma(T V) {
2350b57cec5SDimitry Andric     if (PendingNewline || wantsNewline(V)) {
2360b57cec5SDimitry Andric       printStr(",");
2370b57cec5SDimitry Andric       newLine();
2380b57cec5SDimitry Andric     } else {
2390b57cec5SDimitry Andric       printStr(", ");
2400b57cec5SDimitry Andric     }
2410b57cec5SDimitry Andric 
2420b57cec5SDimitry Andric     printWithPendingNewline(V);
2430b57cec5SDimitry Andric   }
2440b57cec5SDimitry Andric 
2450b57cec5SDimitry Andric   struct CtorArgPrinter {
2460b57cec5SDimitry Andric     DumpVisitor &Visitor;
2470b57cec5SDimitry Andric 
operator ()__anon39624eb80111::DumpVisitor::CtorArgPrinter2480b57cec5SDimitry Andric     template<typename T, typename ...Rest> void operator()(T V, Rest ...Vs) {
2490b57cec5SDimitry Andric       if (Visitor.anyWantNewline(V, Vs...))
2500b57cec5SDimitry Andric         Visitor.newLine();
2510b57cec5SDimitry Andric       Visitor.printWithPendingNewline(V);
2520b57cec5SDimitry Andric       int PrintInOrder[] = { (Visitor.printWithComma(Vs), 0)..., 0 };
2530b57cec5SDimitry Andric       (void)PrintInOrder;
2540b57cec5SDimitry Andric     }
2550b57cec5SDimitry Andric   };
2560b57cec5SDimitry Andric 
operator ()__anon39624eb80111::DumpVisitor2570b57cec5SDimitry Andric   template<typename NodeT> void operator()(const NodeT *Node) {
2580b57cec5SDimitry Andric     Depth += 2;
2590b57cec5SDimitry Andric     fprintf(stderr, "%s(", itanium_demangle::NodeKind<NodeT>::name());
2600b57cec5SDimitry Andric     Node->match(CtorArgPrinter{*this});
2610b57cec5SDimitry Andric     fprintf(stderr, ")");
2620b57cec5SDimitry Andric     Depth -= 2;
2630b57cec5SDimitry Andric   }
2640b57cec5SDimitry Andric 
operator ()__anon39624eb80111::DumpVisitor2650b57cec5SDimitry Andric   void operator()(const ForwardTemplateReference *Node) {
2660b57cec5SDimitry Andric     Depth += 2;
2670b57cec5SDimitry Andric     fprintf(stderr, "ForwardTemplateReference(");
2680b57cec5SDimitry Andric     if (Node->Ref && !Node->Printing) {
2690b57cec5SDimitry Andric       Node->Printing = true;
2700b57cec5SDimitry Andric       CtorArgPrinter{*this}(Node->Ref);
2710b57cec5SDimitry Andric       Node->Printing = false;
2720b57cec5SDimitry Andric     } else {
2730b57cec5SDimitry Andric       CtorArgPrinter{*this}(Node->Index);
2740b57cec5SDimitry Andric     }
2750b57cec5SDimitry Andric     fprintf(stderr, ")");
2760b57cec5SDimitry Andric     Depth -= 2;
2770b57cec5SDimitry Andric   }
2780b57cec5SDimitry Andric };
2790b57cec5SDimitry Andric }
2800b57cec5SDimitry Andric 
dump() const2810b57cec5SDimitry Andric void itanium_demangle::Node::dump() const {
2820b57cec5SDimitry Andric   DumpVisitor V;
2830b57cec5SDimitry Andric   visit(std::ref(V));
2840b57cec5SDimitry Andric   V.newLine();
2850b57cec5SDimitry Andric }
2860b57cec5SDimitry Andric #endif
2870b57cec5SDimitry Andric 
2880b57cec5SDimitry Andric namespace {
2890b57cec5SDimitry Andric class BumpPointerAllocator {
2900b57cec5SDimitry Andric   struct BlockMeta {
2910b57cec5SDimitry Andric     BlockMeta* Next;
2920b57cec5SDimitry Andric     size_t Current;
2930b57cec5SDimitry Andric   };
2940b57cec5SDimitry Andric 
2950b57cec5SDimitry Andric   static constexpr size_t AllocSize = 4096;
2960b57cec5SDimitry Andric   static constexpr size_t UsableAllocSize = AllocSize - sizeof(BlockMeta);
2970b57cec5SDimitry Andric 
2980b57cec5SDimitry Andric   alignas(long double) char InitialBuffer[AllocSize];
2990b57cec5SDimitry Andric   BlockMeta* BlockList = nullptr;
3000b57cec5SDimitry Andric 
grow()3010b57cec5SDimitry Andric   void grow() {
3020b57cec5SDimitry Andric     char* NewMeta = static_cast<char *>(std::malloc(AllocSize));
3030b57cec5SDimitry Andric     if (NewMeta == nullptr)
3040b57cec5SDimitry Andric       std::terminate();
3050b57cec5SDimitry Andric     BlockList = new (NewMeta) BlockMeta{BlockList, 0};
3060b57cec5SDimitry Andric   }
3070b57cec5SDimitry Andric 
allocateMassive(size_t NBytes)3080b57cec5SDimitry Andric   void* allocateMassive(size_t NBytes) {
3090b57cec5SDimitry Andric     NBytes += sizeof(BlockMeta);
3100b57cec5SDimitry Andric     BlockMeta* NewMeta = reinterpret_cast<BlockMeta*>(std::malloc(NBytes));
3110b57cec5SDimitry Andric     if (NewMeta == nullptr)
3120b57cec5SDimitry Andric       std::terminate();
3130b57cec5SDimitry Andric     BlockList->Next = new (NewMeta) BlockMeta{BlockList->Next, 0};
3140b57cec5SDimitry Andric     return static_cast<void*>(NewMeta + 1);
3150b57cec5SDimitry Andric   }
3160b57cec5SDimitry Andric 
3170b57cec5SDimitry Andric public:
BumpPointerAllocator()3180b57cec5SDimitry Andric   BumpPointerAllocator()
3190b57cec5SDimitry Andric       : BlockList(new (InitialBuffer) BlockMeta{nullptr, 0}) {}
3200b57cec5SDimitry Andric 
allocate(size_t N)3210b57cec5SDimitry Andric   void* allocate(size_t N) {
3220b57cec5SDimitry Andric     N = (N + 15u) & ~15u;
3230b57cec5SDimitry Andric     if (N + BlockList->Current >= UsableAllocSize) {
3240b57cec5SDimitry Andric       if (N > UsableAllocSize)
3250b57cec5SDimitry Andric         return allocateMassive(N);
3260b57cec5SDimitry Andric       grow();
3270b57cec5SDimitry Andric     }
3280b57cec5SDimitry Andric     BlockList->Current += N;
3290b57cec5SDimitry Andric     return static_cast<void*>(reinterpret_cast<char*>(BlockList + 1) +
3300b57cec5SDimitry Andric                               BlockList->Current - N);
3310b57cec5SDimitry Andric   }
3320b57cec5SDimitry Andric 
reset()3330b57cec5SDimitry Andric   void reset() {
3340b57cec5SDimitry Andric     while (BlockList) {
3350b57cec5SDimitry Andric       BlockMeta* Tmp = BlockList;
3360b57cec5SDimitry Andric       BlockList = BlockList->Next;
3370b57cec5SDimitry Andric       if (reinterpret_cast<char*>(Tmp) != InitialBuffer)
3380b57cec5SDimitry Andric         std::free(Tmp);
3390b57cec5SDimitry Andric     }
3400b57cec5SDimitry Andric     BlockList = new (InitialBuffer) BlockMeta{nullptr, 0};
3410b57cec5SDimitry Andric   }
3420b57cec5SDimitry Andric 
~BumpPointerAllocator()3430b57cec5SDimitry Andric   ~BumpPointerAllocator() { reset(); }
3440b57cec5SDimitry Andric };
3450b57cec5SDimitry Andric 
3460b57cec5SDimitry Andric class DefaultAllocator {
3470b57cec5SDimitry Andric   BumpPointerAllocator Alloc;
3480b57cec5SDimitry Andric 
3490b57cec5SDimitry Andric public:
reset()3500b57cec5SDimitry Andric   void reset() { Alloc.reset(); }
3510b57cec5SDimitry Andric 
3520b57cec5SDimitry Andric   template<typename T, typename ...Args> T *makeNode(Args &&...args) {
3530b57cec5SDimitry Andric     return new (Alloc.allocate(sizeof(T)))
3540b57cec5SDimitry Andric         T(std::forward<Args>(args)...);
3550b57cec5SDimitry Andric   }
3560b57cec5SDimitry Andric 
allocateNodeArray(size_t sz)3570b57cec5SDimitry Andric   void *allocateNodeArray(size_t sz) {
3580b57cec5SDimitry Andric     return Alloc.allocate(sizeof(Node *) * sz);
3590b57cec5SDimitry Andric   }
3600b57cec5SDimitry Andric };
3610b57cec5SDimitry Andric }  // unnamed namespace
3620b57cec5SDimitry Andric 
3630b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
3640b57cec5SDimitry Andric // Code beyond this point should not be synchronized with libc++abi.
3650b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
3660b57cec5SDimitry Andric 
3670b57cec5SDimitry Andric using Demangler = itanium_demangle::ManglingParser<DefaultAllocator>;
3680b57cec5SDimitry Andric 
itaniumDemangle(std::string_view MangledName,bool ParseParams)3691db9f3b2SDimitry Andric char *llvm::itaniumDemangle(std::string_view MangledName, bool ParseParams) {
37006c3fb27SDimitry Andric   if (MangledName.empty())
3710b57cec5SDimitry Andric     return nullptr;
3720b57cec5SDimitry Andric 
37306c3fb27SDimitry Andric   Demangler Parser(MangledName.data(),
37406c3fb27SDimitry Andric                    MangledName.data() + MangledName.length());
3751db9f3b2SDimitry Andric   Node *AST = Parser.parse(ParseParams);
37606c3fb27SDimitry Andric   if (!AST)
37706c3fb27SDimitry Andric     return nullptr;
3780b57cec5SDimitry Andric 
37906c3fb27SDimitry Andric   OutputBuffer OB;
3800b57cec5SDimitry Andric   assert(Parser.ForwardTemplateRefs.empty());
381349cc55cSDimitry Andric   AST->print(OB);
382349cc55cSDimitry Andric   OB += '\0';
38306c3fb27SDimitry Andric   return OB.getBuffer();
3840b57cec5SDimitry Andric }
3850b57cec5SDimitry Andric 
ItaniumPartialDemangler()3860b57cec5SDimitry Andric ItaniumPartialDemangler::ItaniumPartialDemangler()
3870b57cec5SDimitry Andric     : RootNode(nullptr), Context(new Demangler{nullptr, nullptr}) {}
3880b57cec5SDimitry Andric 
~ItaniumPartialDemangler()3890b57cec5SDimitry Andric ItaniumPartialDemangler::~ItaniumPartialDemangler() {
3900b57cec5SDimitry Andric   delete static_cast<Demangler *>(Context);
3910b57cec5SDimitry Andric }
3920b57cec5SDimitry Andric 
ItaniumPartialDemangler(ItaniumPartialDemangler && Other)3930b57cec5SDimitry Andric ItaniumPartialDemangler::ItaniumPartialDemangler(
3940b57cec5SDimitry Andric     ItaniumPartialDemangler &&Other)
3950b57cec5SDimitry Andric     : RootNode(Other.RootNode), Context(Other.Context) {
3960b57cec5SDimitry Andric   Other.Context = Other.RootNode = nullptr;
3970b57cec5SDimitry Andric }
3980b57cec5SDimitry Andric 
3990b57cec5SDimitry Andric ItaniumPartialDemangler &ItaniumPartialDemangler::
operator =(ItaniumPartialDemangler && Other)4000b57cec5SDimitry Andric operator=(ItaniumPartialDemangler &&Other) {
4010b57cec5SDimitry Andric   std::swap(RootNode, Other.RootNode);
4020b57cec5SDimitry Andric   std::swap(Context, Other.Context);
4030b57cec5SDimitry Andric   return *this;
4040b57cec5SDimitry Andric }
4050b57cec5SDimitry Andric 
4060b57cec5SDimitry Andric // Demangle MangledName into an AST, storing it into this->RootNode.
partialDemangle(const char * MangledName)4070b57cec5SDimitry Andric bool ItaniumPartialDemangler::partialDemangle(const char *MangledName) {
4080b57cec5SDimitry Andric   Demangler *Parser = static_cast<Demangler *>(Context);
4090b57cec5SDimitry Andric   size_t Len = std::strlen(MangledName);
4100b57cec5SDimitry Andric   Parser->reset(MangledName, MangledName + Len);
4110b57cec5SDimitry Andric   RootNode = Parser->parse();
4120b57cec5SDimitry Andric   return RootNode == nullptr;
4130b57cec5SDimitry Andric }
4140b57cec5SDimitry Andric 
printNode(const Node * RootNode,char * Buf,size_t * N)4150b57cec5SDimitry Andric static char *printNode(const Node *RootNode, char *Buf, size_t *N) {
416bdd1243dSDimitry Andric   OutputBuffer OB(Buf, N);
417349cc55cSDimitry Andric   RootNode->print(OB);
418349cc55cSDimitry Andric   OB += '\0';
4190b57cec5SDimitry Andric   if (N != nullptr)
420349cc55cSDimitry Andric     *N = OB.getCurrentPosition();
421349cc55cSDimitry Andric   return OB.getBuffer();
4220b57cec5SDimitry Andric }
4230b57cec5SDimitry Andric 
getFunctionBaseName(char * Buf,size_t * N) const4240b57cec5SDimitry Andric char *ItaniumPartialDemangler::getFunctionBaseName(char *Buf, size_t *N) const {
4250b57cec5SDimitry Andric   if (!isFunction())
4260b57cec5SDimitry Andric     return nullptr;
4270b57cec5SDimitry Andric 
4280b57cec5SDimitry Andric   const Node *Name = static_cast<const FunctionEncoding *>(RootNode)->getName();
4290b57cec5SDimitry Andric 
4300b57cec5SDimitry Andric   while (true) {
4310b57cec5SDimitry Andric     switch (Name->getKind()) {
4320b57cec5SDimitry Andric     case Node::KAbiTagAttr:
4330b57cec5SDimitry Andric       Name = static_cast<const AbiTagAttr *>(Name)->Base;
4340b57cec5SDimitry Andric       continue;
43581ad6265SDimitry Andric     case Node::KModuleEntity:
43681ad6265SDimitry Andric       Name = static_cast<const ModuleEntity *>(Name)->Name;
4370b57cec5SDimitry Andric       continue;
4380b57cec5SDimitry Andric     case Node::KNestedName:
4390b57cec5SDimitry Andric       Name = static_cast<const NestedName *>(Name)->Name;
4400b57cec5SDimitry Andric       continue;
4410b57cec5SDimitry Andric     case Node::KLocalName:
4420b57cec5SDimitry Andric       Name = static_cast<const LocalName *>(Name)->Entity;
4430b57cec5SDimitry Andric       continue;
4440b57cec5SDimitry Andric     case Node::KNameWithTemplateArgs:
4450b57cec5SDimitry Andric       Name = static_cast<const NameWithTemplateArgs *>(Name)->Name;
4460b57cec5SDimitry Andric       continue;
4470b57cec5SDimitry Andric     default:
4480b57cec5SDimitry Andric       return printNode(Name, Buf, N);
4490b57cec5SDimitry Andric     }
4500b57cec5SDimitry Andric   }
4510b57cec5SDimitry Andric }
4520b57cec5SDimitry Andric 
getFunctionDeclContextName(char * Buf,size_t * N) const4530b57cec5SDimitry Andric char *ItaniumPartialDemangler::getFunctionDeclContextName(char *Buf,
4540b57cec5SDimitry Andric                                                           size_t *N) const {
4550b57cec5SDimitry Andric   if (!isFunction())
4560b57cec5SDimitry Andric     return nullptr;
4570b57cec5SDimitry Andric   const Node *Name = static_cast<const FunctionEncoding *>(RootNode)->getName();
4580b57cec5SDimitry Andric 
459bdd1243dSDimitry Andric   OutputBuffer OB(Buf, N);
4600b57cec5SDimitry Andric 
4610b57cec5SDimitry Andric  KeepGoingLocalFunction:
4620b57cec5SDimitry Andric   while (true) {
4630b57cec5SDimitry Andric     if (Name->getKind() == Node::KAbiTagAttr) {
4640b57cec5SDimitry Andric       Name = static_cast<const AbiTagAttr *>(Name)->Base;
4650b57cec5SDimitry Andric       continue;
4660b57cec5SDimitry Andric     }
4670b57cec5SDimitry Andric     if (Name->getKind() == Node::KNameWithTemplateArgs) {
4680b57cec5SDimitry Andric       Name = static_cast<const NameWithTemplateArgs *>(Name)->Name;
4690b57cec5SDimitry Andric       continue;
4700b57cec5SDimitry Andric     }
4710b57cec5SDimitry Andric     break;
4720b57cec5SDimitry Andric   }
4730b57cec5SDimitry Andric 
47481ad6265SDimitry Andric   if (Name->getKind() == Node::KModuleEntity)
47581ad6265SDimitry Andric     Name = static_cast<const ModuleEntity *>(Name)->Name;
47681ad6265SDimitry Andric 
4770b57cec5SDimitry Andric   switch (Name->getKind()) {
4780b57cec5SDimitry Andric   case Node::KNestedName:
479349cc55cSDimitry Andric     static_cast<const NestedName *>(Name)->Qual->print(OB);
4800b57cec5SDimitry Andric     break;
4810b57cec5SDimitry Andric   case Node::KLocalName: {
4820b57cec5SDimitry Andric     auto *LN = static_cast<const LocalName *>(Name);
483349cc55cSDimitry Andric     LN->Encoding->print(OB);
484349cc55cSDimitry Andric     OB += "::";
4850b57cec5SDimitry Andric     Name = LN->Entity;
4860b57cec5SDimitry Andric     goto KeepGoingLocalFunction;
4870b57cec5SDimitry Andric   }
4880b57cec5SDimitry Andric   default:
4890b57cec5SDimitry Andric     break;
4900b57cec5SDimitry Andric   }
491349cc55cSDimitry Andric   OB += '\0';
4920b57cec5SDimitry Andric   if (N != nullptr)
493349cc55cSDimitry Andric     *N = OB.getCurrentPosition();
494349cc55cSDimitry Andric   return OB.getBuffer();
4950b57cec5SDimitry Andric }
4960b57cec5SDimitry Andric 
getFunctionName(char * Buf,size_t * N) const4970b57cec5SDimitry Andric char *ItaniumPartialDemangler::getFunctionName(char *Buf, size_t *N) const {
4980b57cec5SDimitry Andric   if (!isFunction())
4990b57cec5SDimitry Andric     return nullptr;
5000b57cec5SDimitry Andric   auto *Name = static_cast<FunctionEncoding *>(RootNode)->getName();
5010b57cec5SDimitry Andric   return printNode(Name, Buf, N);
5020b57cec5SDimitry Andric }
5030b57cec5SDimitry Andric 
getFunctionParameters(char * Buf,size_t * N) const5040b57cec5SDimitry Andric char *ItaniumPartialDemangler::getFunctionParameters(char *Buf,
5050b57cec5SDimitry Andric                                                      size_t *N) const {
5060b57cec5SDimitry Andric   if (!isFunction())
5070b57cec5SDimitry Andric     return nullptr;
5080b57cec5SDimitry Andric   NodeArray Params = static_cast<FunctionEncoding *>(RootNode)->getParams();
5090b57cec5SDimitry Andric 
510bdd1243dSDimitry Andric   OutputBuffer OB(Buf, N);
5110b57cec5SDimitry Andric 
512349cc55cSDimitry Andric   OB += '(';
513349cc55cSDimitry Andric   Params.printWithComma(OB);
514349cc55cSDimitry Andric   OB += ')';
515349cc55cSDimitry Andric   OB += '\0';
5160b57cec5SDimitry Andric   if (N != nullptr)
517349cc55cSDimitry Andric     *N = OB.getCurrentPosition();
518349cc55cSDimitry Andric   return OB.getBuffer();
5190b57cec5SDimitry Andric }
5200b57cec5SDimitry Andric 
getFunctionReturnType(char * Buf,size_t * N) const5210b57cec5SDimitry Andric char *ItaniumPartialDemangler::getFunctionReturnType(
5220b57cec5SDimitry Andric     char *Buf, size_t *N) const {
5230b57cec5SDimitry Andric   if (!isFunction())
5240b57cec5SDimitry Andric     return nullptr;
5250b57cec5SDimitry Andric 
526bdd1243dSDimitry Andric   OutputBuffer OB(Buf, N);
5270b57cec5SDimitry Andric 
5280b57cec5SDimitry Andric   if (const Node *Ret =
5290b57cec5SDimitry Andric           static_cast<const FunctionEncoding *>(RootNode)->getReturnType())
530349cc55cSDimitry Andric     Ret->print(OB);
5310b57cec5SDimitry Andric 
532349cc55cSDimitry Andric   OB += '\0';
5330b57cec5SDimitry Andric   if (N != nullptr)
534349cc55cSDimitry Andric     *N = OB.getCurrentPosition();
535349cc55cSDimitry Andric   return OB.getBuffer();
5360b57cec5SDimitry Andric }
5370b57cec5SDimitry Andric 
finishDemangle(char * Buf,size_t * N) const5380b57cec5SDimitry Andric char *ItaniumPartialDemangler::finishDemangle(char *Buf, size_t *N) const {
5390b57cec5SDimitry Andric   assert(RootNode != nullptr && "must call partialDemangle()");
5400b57cec5SDimitry Andric   return printNode(static_cast<Node *>(RootNode), Buf, N);
5410b57cec5SDimitry Andric }
5420b57cec5SDimitry Andric 
hasFunctionQualifiers() const5430b57cec5SDimitry Andric bool ItaniumPartialDemangler::hasFunctionQualifiers() const {
5440b57cec5SDimitry Andric   assert(RootNode != nullptr && "must call partialDemangle()");
5450b57cec5SDimitry Andric   if (!isFunction())
5460b57cec5SDimitry Andric     return false;
5470b57cec5SDimitry Andric   auto *E = static_cast<const FunctionEncoding *>(RootNode);
5480b57cec5SDimitry Andric   return E->getCVQuals() != QualNone || E->getRefQual() != FrefQualNone;
5490b57cec5SDimitry Andric }
5500b57cec5SDimitry Andric 
isCtorOrDtor() const5510b57cec5SDimitry Andric bool ItaniumPartialDemangler::isCtorOrDtor() const {
5520b57cec5SDimitry Andric   const Node *N = static_cast<const Node *>(RootNode);
5530b57cec5SDimitry Andric   while (N) {
5540b57cec5SDimitry Andric     switch (N->getKind()) {
5550b57cec5SDimitry Andric     default:
5560b57cec5SDimitry Andric       return false;
5570b57cec5SDimitry Andric     case Node::KCtorDtorName:
5580b57cec5SDimitry Andric       return true;
5590b57cec5SDimitry Andric 
5600b57cec5SDimitry Andric     case Node::KAbiTagAttr:
5610b57cec5SDimitry Andric       N = static_cast<const AbiTagAttr *>(N)->Base;
5620b57cec5SDimitry Andric       break;
5630b57cec5SDimitry Andric     case Node::KFunctionEncoding:
5640b57cec5SDimitry Andric       N = static_cast<const FunctionEncoding *>(N)->getName();
5650b57cec5SDimitry Andric       break;
5660b57cec5SDimitry Andric     case Node::KLocalName:
5670b57cec5SDimitry Andric       N = static_cast<const LocalName *>(N)->Entity;
5680b57cec5SDimitry Andric       break;
5690b57cec5SDimitry Andric     case Node::KNameWithTemplateArgs:
5700b57cec5SDimitry Andric       N = static_cast<const NameWithTemplateArgs *>(N)->Name;
5710b57cec5SDimitry Andric       break;
5720b57cec5SDimitry Andric     case Node::KNestedName:
5730b57cec5SDimitry Andric       N = static_cast<const NestedName *>(N)->Name;
5740b57cec5SDimitry Andric       break;
57581ad6265SDimitry Andric     case Node::KModuleEntity:
57681ad6265SDimitry Andric       N = static_cast<const ModuleEntity *>(N)->Name;
5770b57cec5SDimitry Andric       break;
5780b57cec5SDimitry Andric     }
5790b57cec5SDimitry Andric   }
5800b57cec5SDimitry Andric   return false;
5810b57cec5SDimitry Andric }
5820b57cec5SDimitry Andric 
isFunction() const5830b57cec5SDimitry Andric bool ItaniumPartialDemangler::isFunction() const {
5840b57cec5SDimitry Andric   assert(RootNode != nullptr && "must call partialDemangle()");
5850b57cec5SDimitry Andric   return static_cast<const Node *>(RootNode)->getKind() ==
5860b57cec5SDimitry Andric          Node::KFunctionEncoding;
5870b57cec5SDimitry Andric }
5880b57cec5SDimitry Andric 
isSpecialName() const5890b57cec5SDimitry Andric bool ItaniumPartialDemangler::isSpecialName() const {
5900b57cec5SDimitry Andric   assert(RootNode != nullptr && "must call partialDemangle()");
5910b57cec5SDimitry Andric   auto K = static_cast<const Node *>(RootNode)->getKind();
5920b57cec5SDimitry Andric   return K == Node::KSpecialName || K == Node::KCtorVtableSpecialName;
5930b57cec5SDimitry Andric }
5940b57cec5SDimitry Andric 
isData() const5950b57cec5SDimitry Andric bool ItaniumPartialDemangler::isData() const {
5960b57cec5SDimitry Andric   return !isFunction() && !isSpecialName();
5970b57cec5SDimitry Andric }
598