xref: /aosp_15_r20/external/libcxxabi/src/cxa_demangle.cpp (revision c05d8e5dc3e10f6ce4317e8bc22cc4a25f55fa94)
1*c05d8e5dSAndroid Build Coastguard Worker //===-------------------------- cxa_demangle.cpp --------------------------===//
2*c05d8e5dSAndroid Build Coastguard Worker //
3*c05d8e5dSAndroid Build Coastguard Worker //                     The LLVM Compiler Infrastructure
4*c05d8e5dSAndroid Build Coastguard Worker //
5*c05d8e5dSAndroid Build Coastguard Worker // This file is dual licensed under the MIT and the University of Illinois Open
6*c05d8e5dSAndroid Build Coastguard Worker // Source Licenses. See LICENSE.TXT for details.
7*c05d8e5dSAndroid Build Coastguard Worker //
8*c05d8e5dSAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
9*c05d8e5dSAndroid Build Coastguard Worker 
10*c05d8e5dSAndroid Build Coastguard Worker // FIXME: (possibly) incomplete list of features that clang mangles that this
11*c05d8e5dSAndroid Build Coastguard Worker // file does not yet support:
12*c05d8e5dSAndroid Build Coastguard Worker //   - C++ modules TS
13*c05d8e5dSAndroid Build Coastguard Worker 
14*c05d8e5dSAndroid Build Coastguard Worker #define _LIBCPP_NO_EXCEPTIONS
15*c05d8e5dSAndroid Build Coastguard Worker 
16*c05d8e5dSAndroid Build Coastguard Worker #include "__cxxabi_config.h"
17*c05d8e5dSAndroid Build Coastguard Worker 
18*c05d8e5dSAndroid Build Coastguard Worker #include "demangle/ItaniumDemangle.h"
19*c05d8e5dSAndroid Build Coastguard Worker 
20*c05d8e5dSAndroid Build Coastguard Worker #include <cassert>
21*c05d8e5dSAndroid Build Coastguard Worker #include <cctype>
22*c05d8e5dSAndroid Build Coastguard Worker #include <cstdio>
23*c05d8e5dSAndroid Build Coastguard Worker #include <cstdlib>
24*c05d8e5dSAndroid Build Coastguard Worker #include <cstring>
25*c05d8e5dSAndroid Build Coastguard Worker #include <functional>
26*c05d8e5dSAndroid Build Coastguard Worker #include <numeric>
27*c05d8e5dSAndroid Build Coastguard Worker #include <utility>
28*c05d8e5dSAndroid Build Coastguard Worker #include <vector>
29*c05d8e5dSAndroid Build Coastguard Worker 
30*c05d8e5dSAndroid Build Coastguard Worker using namespace itanium_demangle;
31*c05d8e5dSAndroid Build Coastguard Worker 
32*c05d8e5dSAndroid Build Coastguard Worker constexpr const char *itanium_demangle::FloatData<float>::spec;
33*c05d8e5dSAndroid Build Coastguard Worker constexpr const char *itanium_demangle::FloatData<double>::spec;
34*c05d8e5dSAndroid Build Coastguard Worker constexpr const char *itanium_demangle::FloatData<long double>::spec;
35*c05d8e5dSAndroid Build Coastguard Worker 
36*c05d8e5dSAndroid Build Coastguard Worker // <discriminator> := _ <non-negative number>      # when number < 10
37*c05d8e5dSAndroid Build Coastguard Worker //                 := __ <non-negative number> _   # when number >= 10
38*c05d8e5dSAndroid Build Coastguard Worker //  extension      := decimal-digit+               # at the end of string
parse_discriminator(const char * first,const char * last)39*c05d8e5dSAndroid Build Coastguard Worker const char *itanium_demangle::parse_discriminator(const char *first,
40*c05d8e5dSAndroid Build Coastguard Worker                                                   const char *last) {
41*c05d8e5dSAndroid Build Coastguard Worker   // parse but ignore discriminator
42*c05d8e5dSAndroid Build Coastguard Worker   if (first != last) {
43*c05d8e5dSAndroid Build Coastguard Worker     if (*first == '_') {
44*c05d8e5dSAndroid Build Coastguard Worker       const char *t1 = first + 1;
45*c05d8e5dSAndroid Build Coastguard Worker       if (t1 != last) {
46*c05d8e5dSAndroid Build Coastguard Worker         if (std::isdigit(*t1))
47*c05d8e5dSAndroid Build Coastguard Worker           first = t1 + 1;
48*c05d8e5dSAndroid Build Coastguard Worker         else if (*t1 == '_') {
49*c05d8e5dSAndroid Build Coastguard Worker           for (++t1; t1 != last && std::isdigit(*t1); ++t1)
50*c05d8e5dSAndroid Build Coastguard Worker             ;
51*c05d8e5dSAndroid Build Coastguard Worker           if (t1 != last && *t1 == '_')
52*c05d8e5dSAndroid Build Coastguard Worker             first = t1 + 1;
53*c05d8e5dSAndroid Build Coastguard Worker         }
54*c05d8e5dSAndroid Build Coastguard Worker       }
55*c05d8e5dSAndroid Build Coastguard Worker     } else if (std::isdigit(*first)) {
56*c05d8e5dSAndroid Build Coastguard Worker       const char *t1 = first + 1;
57*c05d8e5dSAndroid Build Coastguard Worker       for (; t1 != last && std::isdigit(*t1); ++t1)
58*c05d8e5dSAndroid Build Coastguard Worker         ;
59*c05d8e5dSAndroid Build Coastguard Worker       if (t1 == last)
60*c05d8e5dSAndroid Build Coastguard Worker         first = last;
61*c05d8e5dSAndroid Build Coastguard Worker     }
62*c05d8e5dSAndroid Build Coastguard Worker   }
63*c05d8e5dSAndroid Build Coastguard Worker   return first;
64*c05d8e5dSAndroid Build Coastguard Worker }
65*c05d8e5dSAndroid Build Coastguard Worker 
66*c05d8e5dSAndroid Build Coastguard Worker #ifndef NDEBUG
67*c05d8e5dSAndroid Build Coastguard Worker namespace {
68*c05d8e5dSAndroid Build Coastguard Worker struct DumpVisitor {
69*c05d8e5dSAndroid Build Coastguard Worker   unsigned Depth = 0;
70*c05d8e5dSAndroid Build Coastguard Worker   bool PendingNewline = false;
71*c05d8e5dSAndroid Build Coastguard Worker 
wantsNewline__anon29fe2f4c0111::DumpVisitor72*c05d8e5dSAndroid Build Coastguard Worker   template<typename NodeT> static constexpr bool wantsNewline(const NodeT *) {
73*c05d8e5dSAndroid Build Coastguard Worker     return true;
74*c05d8e5dSAndroid Build Coastguard Worker   }
wantsNewline__anon29fe2f4c0111::DumpVisitor75*c05d8e5dSAndroid Build Coastguard Worker   static bool wantsNewline(NodeArray A) { return !A.empty(); }
wantsNewline__anon29fe2f4c0111::DumpVisitor76*c05d8e5dSAndroid Build Coastguard Worker   static constexpr bool wantsNewline(...) { return false; }
77*c05d8e5dSAndroid Build Coastguard Worker 
anyWantNewline__anon29fe2f4c0111::DumpVisitor78*c05d8e5dSAndroid Build Coastguard Worker   template<typename ...Ts> static bool anyWantNewline(Ts ...Vs) {
79*c05d8e5dSAndroid Build Coastguard Worker     for (bool B : {wantsNewline(Vs)...})
80*c05d8e5dSAndroid Build Coastguard Worker       if (B)
81*c05d8e5dSAndroid Build Coastguard Worker         return true;
82*c05d8e5dSAndroid Build Coastguard Worker     return false;
83*c05d8e5dSAndroid Build Coastguard Worker   }
84*c05d8e5dSAndroid Build Coastguard Worker 
printStr__anon29fe2f4c0111::DumpVisitor85*c05d8e5dSAndroid Build Coastguard Worker   void printStr(const char *S) { fprintf(stderr, "%s", S); }
print__anon29fe2f4c0111::DumpVisitor86*c05d8e5dSAndroid Build Coastguard Worker   void print(StringView SV) {
87*c05d8e5dSAndroid Build Coastguard Worker     fprintf(stderr, "\"%.*s\"", (int)SV.size(), SV.begin());
88*c05d8e5dSAndroid Build Coastguard Worker   }
print__anon29fe2f4c0111::DumpVisitor89*c05d8e5dSAndroid Build Coastguard Worker   void print(const Node *N) {
90*c05d8e5dSAndroid Build Coastguard Worker     if (N)
91*c05d8e5dSAndroid Build Coastguard Worker       N->visit(std::ref(*this));
92*c05d8e5dSAndroid Build Coastguard Worker     else
93*c05d8e5dSAndroid Build Coastguard Worker       printStr("<null>");
94*c05d8e5dSAndroid Build Coastguard Worker   }
print__anon29fe2f4c0111::DumpVisitor95*c05d8e5dSAndroid Build Coastguard Worker   void print(NodeOrString NS) {
96*c05d8e5dSAndroid Build Coastguard Worker     if (NS.isNode())
97*c05d8e5dSAndroid Build Coastguard Worker       print(NS.asNode());
98*c05d8e5dSAndroid Build Coastguard Worker     else if (NS.isString())
99*c05d8e5dSAndroid Build Coastguard Worker       print(NS.asString());
100*c05d8e5dSAndroid Build Coastguard Worker     else
101*c05d8e5dSAndroid Build Coastguard Worker       printStr("NodeOrString()");
102*c05d8e5dSAndroid Build Coastguard Worker   }
print__anon29fe2f4c0111::DumpVisitor103*c05d8e5dSAndroid Build Coastguard Worker   void print(NodeArray A) {
104*c05d8e5dSAndroid Build Coastguard Worker     ++Depth;
105*c05d8e5dSAndroid Build Coastguard Worker     printStr("{");
106*c05d8e5dSAndroid Build Coastguard Worker     bool First = true;
107*c05d8e5dSAndroid Build Coastguard Worker     for (const Node *N : A) {
108*c05d8e5dSAndroid Build Coastguard Worker       if (First)
109*c05d8e5dSAndroid Build Coastguard Worker         print(N);
110*c05d8e5dSAndroid Build Coastguard Worker       else
111*c05d8e5dSAndroid Build Coastguard Worker         printWithComma(N);
112*c05d8e5dSAndroid Build Coastguard Worker       First = false;
113*c05d8e5dSAndroid Build Coastguard Worker     }
114*c05d8e5dSAndroid Build Coastguard Worker     printStr("}");
115*c05d8e5dSAndroid Build Coastguard Worker     --Depth;
116*c05d8e5dSAndroid Build Coastguard Worker   }
117*c05d8e5dSAndroid Build Coastguard Worker 
118*c05d8e5dSAndroid Build Coastguard Worker   // Overload used when T is exactly 'bool', not merely convertible to 'bool'.
print__anon29fe2f4c0111::DumpVisitor119*c05d8e5dSAndroid Build Coastguard Worker   void print(bool B) { printStr(B ? "true" : "false"); }
120*c05d8e5dSAndroid Build Coastguard Worker 
121*c05d8e5dSAndroid Build Coastguard Worker   template <class T>
print__anon29fe2f4c0111::DumpVisitor122*c05d8e5dSAndroid Build Coastguard Worker   typename std::enable_if<std::is_unsigned<T>::value>::type print(T N) {
123*c05d8e5dSAndroid Build Coastguard Worker     fprintf(stderr, "%llu", (unsigned long long)N);
124*c05d8e5dSAndroid Build Coastguard Worker   }
125*c05d8e5dSAndroid Build Coastguard Worker 
126*c05d8e5dSAndroid Build Coastguard Worker   template <class T>
print__anon29fe2f4c0111::DumpVisitor127*c05d8e5dSAndroid Build Coastguard Worker   typename std::enable_if<std::is_signed<T>::value>::type print(T N) {
128*c05d8e5dSAndroid Build Coastguard Worker     fprintf(stderr, "%lld", (long long)N);
129*c05d8e5dSAndroid Build Coastguard Worker   }
130*c05d8e5dSAndroid Build Coastguard Worker 
print__anon29fe2f4c0111::DumpVisitor131*c05d8e5dSAndroid Build Coastguard Worker   void print(ReferenceKind RK) {
132*c05d8e5dSAndroid Build Coastguard Worker     switch (RK) {
133*c05d8e5dSAndroid Build Coastguard Worker     case ReferenceKind::LValue:
134*c05d8e5dSAndroid Build Coastguard Worker       return printStr("ReferenceKind::LValue");
135*c05d8e5dSAndroid Build Coastguard Worker     case ReferenceKind::RValue:
136*c05d8e5dSAndroid Build Coastguard Worker       return printStr("ReferenceKind::RValue");
137*c05d8e5dSAndroid Build Coastguard Worker     }
138*c05d8e5dSAndroid Build Coastguard Worker   }
print__anon29fe2f4c0111::DumpVisitor139*c05d8e5dSAndroid Build Coastguard Worker   void print(FunctionRefQual RQ) {
140*c05d8e5dSAndroid Build Coastguard Worker     switch (RQ) {
141*c05d8e5dSAndroid Build Coastguard Worker     case FunctionRefQual::FrefQualNone:
142*c05d8e5dSAndroid Build Coastguard Worker       return printStr("FunctionRefQual::FrefQualNone");
143*c05d8e5dSAndroid Build Coastguard Worker     case FunctionRefQual::FrefQualLValue:
144*c05d8e5dSAndroid Build Coastguard Worker       return printStr("FunctionRefQual::FrefQualLValue");
145*c05d8e5dSAndroid Build Coastguard Worker     case FunctionRefQual::FrefQualRValue:
146*c05d8e5dSAndroid Build Coastguard Worker       return printStr("FunctionRefQual::FrefQualRValue");
147*c05d8e5dSAndroid Build Coastguard Worker     }
148*c05d8e5dSAndroid Build Coastguard Worker   }
print__anon29fe2f4c0111::DumpVisitor149*c05d8e5dSAndroid Build Coastguard Worker   void print(Qualifiers Qs) {
150*c05d8e5dSAndroid Build Coastguard Worker     if (!Qs) return printStr("QualNone");
151*c05d8e5dSAndroid Build Coastguard Worker     struct QualName { Qualifiers Q; const char *Name; } Names[] = {
152*c05d8e5dSAndroid Build Coastguard Worker       {QualConst, "QualConst"},
153*c05d8e5dSAndroid Build Coastguard Worker       {QualVolatile, "QualVolatile"},
154*c05d8e5dSAndroid Build Coastguard Worker       {QualRestrict, "QualRestrict"},
155*c05d8e5dSAndroid Build Coastguard Worker     };
156*c05d8e5dSAndroid Build Coastguard Worker     for (QualName Name : Names) {
157*c05d8e5dSAndroid Build Coastguard Worker       if (Qs & Name.Q) {
158*c05d8e5dSAndroid Build Coastguard Worker         printStr(Name.Name);
159*c05d8e5dSAndroid Build Coastguard Worker         Qs = Qualifiers(Qs & ~Name.Q);
160*c05d8e5dSAndroid Build Coastguard Worker         if (Qs) printStr(" | ");
161*c05d8e5dSAndroid Build Coastguard Worker       }
162*c05d8e5dSAndroid Build Coastguard Worker     }
163*c05d8e5dSAndroid Build Coastguard Worker   }
print__anon29fe2f4c0111::DumpVisitor164*c05d8e5dSAndroid Build Coastguard Worker   void print(SpecialSubKind SSK) {
165*c05d8e5dSAndroid Build Coastguard Worker     switch (SSK) {
166*c05d8e5dSAndroid Build Coastguard Worker     case SpecialSubKind::allocator:
167*c05d8e5dSAndroid Build Coastguard Worker       return printStr("SpecialSubKind::allocator");
168*c05d8e5dSAndroid Build Coastguard Worker     case SpecialSubKind::basic_string:
169*c05d8e5dSAndroid Build Coastguard Worker       return printStr("SpecialSubKind::basic_string");
170*c05d8e5dSAndroid Build Coastguard Worker     case SpecialSubKind::string:
171*c05d8e5dSAndroid Build Coastguard Worker       return printStr("SpecialSubKind::string");
172*c05d8e5dSAndroid Build Coastguard Worker     case SpecialSubKind::istream:
173*c05d8e5dSAndroid Build Coastguard Worker       return printStr("SpecialSubKind::istream");
174*c05d8e5dSAndroid Build Coastguard Worker     case SpecialSubKind::ostream:
175*c05d8e5dSAndroid Build Coastguard Worker       return printStr("SpecialSubKind::ostream");
176*c05d8e5dSAndroid Build Coastguard Worker     case SpecialSubKind::iostream:
177*c05d8e5dSAndroid Build Coastguard Worker       return printStr("SpecialSubKind::iostream");
178*c05d8e5dSAndroid Build Coastguard Worker     }
179*c05d8e5dSAndroid Build Coastguard Worker   }
180*c05d8e5dSAndroid Build Coastguard Worker 
newLine__anon29fe2f4c0111::DumpVisitor181*c05d8e5dSAndroid Build Coastguard Worker   void newLine() {
182*c05d8e5dSAndroid Build Coastguard Worker     printStr("\n");
183*c05d8e5dSAndroid Build Coastguard Worker     for (unsigned I = 0; I != Depth; ++I)
184*c05d8e5dSAndroid Build Coastguard Worker       printStr(" ");
185*c05d8e5dSAndroid Build Coastguard Worker     PendingNewline = false;
186*c05d8e5dSAndroid Build Coastguard Worker   }
187*c05d8e5dSAndroid Build Coastguard Worker 
printWithPendingNewline__anon29fe2f4c0111::DumpVisitor188*c05d8e5dSAndroid Build Coastguard Worker   template<typename T> void printWithPendingNewline(T V) {
189*c05d8e5dSAndroid Build Coastguard Worker     print(V);
190*c05d8e5dSAndroid Build Coastguard Worker     if (wantsNewline(V))
191*c05d8e5dSAndroid Build Coastguard Worker       PendingNewline = true;
192*c05d8e5dSAndroid Build Coastguard Worker   }
193*c05d8e5dSAndroid Build Coastguard Worker 
printWithComma__anon29fe2f4c0111::DumpVisitor194*c05d8e5dSAndroid Build Coastguard Worker   template<typename T> void printWithComma(T V) {
195*c05d8e5dSAndroid Build Coastguard Worker     if (PendingNewline || wantsNewline(V)) {
196*c05d8e5dSAndroid Build Coastguard Worker       printStr(",");
197*c05d8e5dSAndroid Build Coastguard Worker       newLine();
198*c05d8e5dSAndroid Build Coastguard Worker     } else {
199*c05d8e5dSAndroid Build Coastguard Worker       printStr(", ");
200*c05d8e5dSAndroid Build Coastguard Worker     }
201*c05d8e5dSAndroid Build Coastguard Worker 
202*c05d8e5dSAndroid Build Coastguard Worker     printWithPendingNewline(V);
203*c05d8e5dSAndroid Build Coastguard Worker   }
204*c05d8e5dSAndroid Build Coastguard Worker 
205*c05d8e5dSAndroid Build Coastguard Worker   struct CtorArgPrinter {
206*c05d8e5dSAndroid Build Coastguard Worker     DumpVisitor &Visitor;
207*c05d8e5dSAndroid Build Coastguard Worker 
operator ()__anon29fe2f4c0111::DumpVisitor::CtorArgPrinter208*c05d8e5dSAndroid Build Coastguard Worker     template<typename T, typename ...Rest> void operator()(T V, Rest ...Vs) {
209*c05d8e5dSAndroid Build Coastguard Worker       if (Visitor.anyWantNewline(V, Vs...))
210*c05d8e5dSAndroid Build Coastguard Worker         Visitor.newLine();
211*c05d8e5dSAndroid Build Coastguard Worker       Visitor.printWithPendingNewline(V);
212*c05d8e5dSAndroid Build Coastguard Worker       int PrintInOrder[] = { (Visitor.printWithComma(Vs), 0)..., 0 };
213*c05d8e5dSAndroid Build Coastguard Worker       (void)PrintInOrder;
214*c05d8e5dSAndroid Build Coastguard Worker     }
215*c05d8e5dSAndroid Build Coastguard Worker   };
216*c05d8e5dSAndroid Build Coastguard Worker 
operator ()__anon29fe2f4c0111::DumpVisitor217*c05d8e5dSAndroid Build Coastguard Worker   template<typename NodeT> void operator()(const NodeT *Node) {
218*c05d8e5dSAndroid Build Coastguard Worker     Depth += 2;
219*c05d8e5dSAndroid Build Coastguard Worker     fprintf(stderr, "%s(", itanium_demangle::NodeKind<NodeT>::name());
220*c05d8e5dSAndroid Build Coastguard Worker     Node->match(CtorArgPrinter{*this});
221*c05d8e5dSAndroid Build Coastguard Worker     fprintf(stderr, ")");
222*c05d8e5dSAndroid Build Coastguard Worker     Depth -= 2;
223*c05d8e5dSAndroid Build Coastguard Worker   }
224*c05d8e5dSAndroid Build Coastguard Worker 
operator ()__anon29fe2f4c0111::DumpVisitor225*c05d8e5dSAndroid Build Coastguard Worker   void operator()(const ForwardTemplateReference *Node) {
226*c05d8e5dSAndroid Build Coastguard Worker     Depth += 2;
227*c05d8e5dSAndroid Build Coastguard Worker     fprintf(stderr, "ForwardTemplateReference(");
228*c05d8e5dSAndroid Build Coastguard Worker     if (Node->Ref && !Node->Printing) {
229*c05d8e5dSAndroid Build Coastguard Worker       Node->Printing = true;
230*c05d8e5dSAndroid Build Coastguard Worker       CtorArgPrinter{*this}(Node->Ref);
231*c05d8e5dSAndroid Build Coastguard Worker       Node->Printing = false;
232*c05d8e5dSAndroid Build Coastguard Worker     } else {
233*c05d8e5dSAndroid Build Coastguard Worker       CtorArgPrinter{*this}(Node->Index);
234*c05d8e5dSAndroid Build Coastguard Worker     }
235*c05d8e5dSAndroid Build Coastguard Worker     fprintf(stderr, ")");
236*c05d8e5dSAndroid Build Coastguard Worker     Depth -= 2;
237*c05d8e5dSAndroid Build Coastguard Worker   }
238*c05d8e5dSAndroid Build Coastguard Worker };
239*c05d8e5dSAndroid Build Coastguard Worker }
240*c05d8e5dSAndroid Build Coastguard Worker 
dump() const241*c05d8e5dSAndroid Build Coastguard Worker void itanium_demangle::Node::dump() const {
242*c05d8e5dSAndroid Build Coastguard Worker   DumpVisitor V;
243*c05d8e5dSAndroid Build Coastguard Worker   visit(std::ref(V));
244*c05d8e5dSAndroid Build Coastguard Worker   V.newLine();
245*c05d8e5dSAndroid Build Coastguard Worker }
246*c05d8e5dSAndroid Build Coastguard Worker #endif
247*c05d8e5dSAndroid Build Coastguard Worker 
248*c05d8e5dSAndroid Build Coastguard Worker namespace {
249*c05d8e5dSAndroid Build Coastguard Worker class BumpPointerAllocator {
250*c05d8e5dSAndroid Build Coastguard Worker   struct BlockMeta {
251*c05d8e5dSAndroid Build Coastguard Worker     BlockMeta* Next;
252*c05d8e5dSAndroid Build Coastguard Worker     size_t Current;
253*c05d8e5dSAndroid Build Coastguard Worker   };
254*c05d8e5dSAndroid Build Coastguard Worker 
255*c05d8e5dSAndroid Build Coastguard Worker   static constexpr size_t AllocSize = 4096;
256*c05d8e5dSAndroid Build Coastguard Worker   static constexpr size_t UsableAllocSize = AllocSize - sizeof(BlockMeta);
257*c05d8e5dSAndroid Build Coastguard Worker 
258*c05d8e5dSAndroid Build Coastguard Worker   alignas(long double) char InitialBuffer[AllocSize];
259*c05d8e5dSAndroid Build Coastguard Worker   BlockMeta* BlockList = nullptr;
260*c05d8e5dSAndroid Build Coastguard Worker 
grow()261*c05d8e5dSAndroid Build Coastguard Worker   void grow() {
262*c05d8e5dSAndroid Build Coastguard Worker     char* NewMeta = static_cast<char *>(std::malloc(AllocSize));
263*c05d8e5dSAndroid Build Coastguard Worker     if (NewMeta == nullptr)
264*c05d8e5dSAndroid Build Coastguard Worker       std::terminate();
265*c05d8e5dSAndroid Build Coastguard Worker     BlockList = new (NewMeta) BlockMeta{BlockList, 0};
266*c05d8e5dSAndroid Build Coastguard Worker   }
267*c05d8e5dSAndroid Build Coastguard Worker 
allocateMassive(size_t NBytes)268*c05d8e5dSAndroid Build Coastguard Worker   void* allocateMassive(size_t NBytes) {
269*c05d8e5dSAndroid Build Coastguard Worker     NBytes += sizeof(BlockMeta);
270*c05d8e5dSAndroid Build Coastguard Worker     BlockMeta* NewMeta = reinterpret_cast<BlockMeta*>(std::malloc(NBytes));
271*c05d8e5dSAndroid Build Coastguard Worker     if (NewMeta == nullptr)
272*c05d8e5dSAndroid Build Coastguard Worker       std::terminate();
273*c05d8e5dSAndroid Build Coastguard Worker     BlockList->Next = new (NewMeta) BlockMeta{BlockList->Next, 0};
274*c05d8e5dSAndroid Build Coastguard Worker     return static_cast<void*>(NewMeta + 1);
275*c05d8e5dSAndroid Build Coastguard Worker   }
276*c05d8e5dSAndroid Build Coastguard Worker 
277*c05d8e5dSAndroid Build Coastguard Worker public:
BumpPointerAllocator()278*c05d8e5dSAndroid Build Coastguard Worker   BumpPointerAllocator()
279*c05d8e5dSAndroid Build Coastguard Worker       : BlockList(new (InitialBuffer) BlockMeta{nullptr, 0}) {}
280*c05d8e5dSAndroid Build Coastguard Worker 
allocate(size_t N)281*c05d8e5dSAndroid Build Coastguard Worker   void* allocate(size_t N) {
282*c05d8e5dSAndroid Build Coastguard Worker     N = (N + 15u) & ~15u;
283*c05d8e5dSAndroid Build Coastguard Worker     if (N + BlockList->Current >= UsableAllocSize) {
284*c05d8e5dSAndroid Build Coastguard Worker       if (N > UsableAllocSize)
285*c05d8e5dSAndroid Build Coastguard Worker         return allocateMassive(N);
286*c05d8e5dSAndroid Build Coastguard Worker       grow();
287*c05d8e5dSAndroid Build Coastguard Worker     }
288*c05d8e5dSAndroid Build Coastguard Worker     BlockList->Current += N;
289*c05d8e5dSAndroid Build Coastguard Worker     return static_cast<void*>(reinterpret_cast<char*>(BlockList + 1) +
290*c05d8e5dSAndroid Build Coastguard Worker                               BlockList->Current - N);
291*c05d8e5dSAndroid Build Coastguard Worker   }
292*c05d8e5dSAndroid Build Coastguard Worker 
reset()293*c05d8e5dSAndroid Build Coastguard Worker   void reset() {
294*c05d8e5dSAndroid Build Coastguard Worker     while (BlockList) {
295*c05d8e5dSAndroid Build Coastguard Worker       BlockMeta* Tmp = BlockList;
296*c05d8e5dSAndroid Build Coastguard Worker       BlockList = BlockList->Next;
297*c05d8e5dSAndroid Build Coastguard Worker       if (reinterpret_cast<char*>(Tmp) != InitialBuffer)
298*c05d8e5dSAndroid Build Coastguard Worker         std::free(Tmp);
299*c05d8e5dSAndroid Build Coastguard Worker     }
300*c05d8e5dSAndroid Build Coastguard Worker     BlockList = new (InitialBuffer) BlockMeta{nullptr, 0};
301*c05d8e5dSAndroid Build Coastguard Worker   }
302*c05d8e5dSAndroid Build Coastguard Worker 
~BumpPointerAllocator()303*c05d8e5dSAndroid Build Coastguard Worker   ~BumpPointerAllocator() { reset(); }
304*c05d8e5dSAndroid Build Coastguard Worker };
305*c05d8e5dSAndroid Build Coastguard Worker 
306*c05d8e5dSAndroid Build Coastguard Worker class DefaultAllocator {
307*c05d8e5dSAndroid Build Coastguard Worker   BumpPointerAllocator Alloc;
308*c05d8e5dSAndroid Build Coastguard Worker 
309*c05d8e5dSAndroid Build Coastguard Worker public:
reset()310*c05d8e5dSAndroid Build Coastguard Worker   void reset() { Alloc.reset(); }
311*c05d8e5dSAndroid Build Coastguard Worker 
makeNode(Args &&...args)312*c05d8e5dSAndroid Build Coastguard Worker   template<typename T, typename ...Args> T *makeNode(Args &&...args) {
313*c05d8e5dSAndroid Build Coastguard Worker     return new (Alloc.allocate(sizeof(T)))
314*c05d8e5dSAndroid Build Coastguard Worker         T(std::forward<Args>(args)...);
315*c05d8e5dSAndroid Build Coastguard Worker   }
316*c05d8e5dSAndroid Build Coastguard Worker 
allocateNodeArray(size_t sz)317*c05d8e5dSAndroid Build Coastguard Worker   void *allocateNodeArray(size_t sz) {
318*c05d8e5dSAndroid Build Coastguard Worker     return Alloc.allocate(sizeof(Node *) * sz);
319*c05d8e5dSAndroid Build Coastguard Worker   }
320*c05d8e5dSAndroid Build Coastguard Worker };
321*c05d8e5dSAndroid Build Coastguard Worker }  // unnamed namespace
322*c05d8e5dSAndroid Build Coastguard Worker 
323*c05d8e5dSAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
324*c05d8e5dSAndroid Build Coastguard Worker // Code beyond this point should not be synchronized with LLVM.
325*c05d8e5dSAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
326*c05d8e5dSAndroid Build Coastguard Worker 
327*c05d8e5dSAndroid Build Coastguard Worker using Demangler = itanium_demangle::ManglingParser<DefaultAllocator>;
328*c05d8e5dSAndroid Build Coastguard Worker 
329*c05d8e5dSAndroid Build Coastguard Worker namespace {
330*c05d8e5dSAndroid Build Coastguard Worker enum : int {
331*c05d8e5dSAndroid Build Coastguard Worker   demangle_invalid_args = -3,
332*c05d8e5dSAndroid Build Coastguard Worker   demangle_invalid_mangled_name = -2,
333*c05d8e5dSAndroid Build Coastguard Worker   demangle_memory_alloc_failure = -1,
334*c05d8e5dSAndroid Build Coastguard Worker   demangle_success = 0,
335*c05d8e5dSAndroid Build Coastguard Worker };
336*c05d8e5dSAndroid Build Coastguard Worker }
337*c05d8e5dSAndroid Build Coastguard Worker 
338*c05d8e5dSAndroid Build Coastguard Worker namespace __cxxabiv1 {
339*c05d8e5dSAndroid Build Coastguard Worker extern "C" _LIBCXXABI_FUNC_VIS char *
__cxa_demangle(const char * MangledName,char * Buf,size_t * N,int * Status)340*c05d8e5dSAndroid Build Coastguard Worker __cxa_demangle(const char *MangledName, char *Buf, size_t *N, int *Status) {
341*c05d8e5dSAndroid Build Coastguard Worker   if (MangledName == nullptr || (Buf != nullptr && N == nullptr)) {
342*c05d8e5dSAndroid Build Coastguard Worker     if (Status)
343*c05d8e5dSAndroid Build Coastguard Worker       *Status = demangle_invalid_args;
344*c05d8e5dSAndroid Build Coastguard Worker     return nullptr;
345*c05d8e5dSAndroid Build Coastguard Worker   }
346*c05d8e5dSAndroid Build Coastguard Worker 
347*c05d8e5dSAndroid Build Coastguard Worker   int InternalStatus = demangle_success;
348*c05d8e5dSAndroid Build Coastguard Worker   Demangler Parser(MangledName, MangledName + std::strlen(MangledName));
349*c05d8e5dSAndroid Build Coastguard Worker   OutputStream S;
350*c05d8e5dSAndroid Build Coastguard Worker 
351*c05d8e5dSAndroid Build Coastguard Worker   Node *AST = Parser.parse();
352*c05d8e5dSAndroid Build Coastguard Worker 
353*c05d8e5dSAndroid Build Coastguard Worker   if (AST == nullptr)
354*c05d8e5dSAndroid Build Coastguard Worker     InternalStatus = demangle_invalid_mangled_name;
355*c05d8e5dSAndroid Build Coastguard Worker   else if (!initializeOutputStream(Buf, N, S, 1024))
356*c05d8e5dSAndroid Build Coastguard Worker     InternalStatus = demangle_memory_alloc_failure;
357*c05d8e5dSAndroid Build Coastguard Worker   else {
358*c05d8e5dSAndroid Build Coastguard Worker     assert(Parser.ForwardTemplateRefs.empty());
359*c05d8e5dSAndroid Build Coastguard Worker     AST->print(S);
360*c05d8e5dSAndroid Build Coastguard Worker     S += '\0';
361*c05d8e5dSAndroid Build Coastguard Worker     if (N != nullptr)
362*c05d8e5dSAndroid Build Coastguard Worker       *N = S.getCurrentPosition();
363*c05d8e5dSAndroid Build Coastguard Worker     Buf = S.getBuffer();
364*c05d8e5dSAndroid Build Coastguard Worker   }
365*c05d8e5dSAndroid Build Coastguard Worker 
366*c05d8e5dSAndroid Build Coastguard Worker   if (Status)
367*c05d8e5dSAndroid Build Coastguard Worker     *Status = InternalStatus;
368*c05d8e5dSAndroid Build Coastguard Worker   return InternalStatus == demangle_success ? Buf : nullptr;
369*c05d8e5dSAndroid Build Coastguard Worker }
370*c05d8e5dSAndroid Build Coastguard Worker }  // __cxxabiv1
371