1*5f7ddb14SDimitry Andric //===--- RustDemangle.cpp ---------------------------------------*- C++ -*-===//
2*5f7ddb14SDimitry Andric //
3*5f7ddb14SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*5f7ddb14SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5*5f7ddb14SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*5f7ddb14SDimitry Andric //
7*5f7ddb14SDimitry Andric //===----------------------------------------------------------------------===//
8*5f7ddb14SDimitry Andric //
9*5f7ddb14SDimitry Andric // This file defines a demangler for Rust v0 mangled symbols as specified in
10*5f7ddb14SDimitry Andric // https://rust-lang.github.io/rfcs/2603-rust-symbol-name-mangling-v0.html
11*5f7ddb14SDimitry Andric //
12*5f7ddb14SDimitry Andric //===----------------------------------------------------------------------===//
13*5f7ddb14SDimitry Andric
14*5f7ddb14SDimitry Andric #include "llvm/Demangle/Demangle.h"
15*5f7ddb14SDimitry Andric #include "llvm/Demangle/StringView.h"
16*5f7ddb14SDimitry Andric #include "llvm/Demangle/Utility.h"
17*5f7ddb14SDimitry Andric
18*5f7ddb14SDimitry Andric #include <algorithm>
19*5f7ddb14SDimitry Andric #include <cassert>
20*5f7ddb14SDimitry Andric #include <cstdint>
21*5f7ddb14SDimitry Andric #include <cstring>
22*5f7ddb14SDimitry Andric #include <limits>
23*5f7ddb14SDimitry Andric
24*5f7ddb14SDimitry Andric using namespace llvm;
25*5f7ddb14SDimitry Andric
26*5f7ddb14SDimitry Andric using llvm::itanium_demangle::OutputStream;
27*5f7ddb14SDimitry Andric using llvm::itanium_demangle::StringView;
28*5f7ddb14SDimitry Andric using llvm::itanium_demangle::SwapAndRestore;
29*5f7ddb14SDimitry Andric
30*5f7ddb14SDimitry Andric namespace {
31*5f7ddb14SDimitry Andric
32*5f7ddb14SDimitry Andric struct Identifier {
33*5f7ddb14SDimitry Andric StringView Name;
34*5f7ddb14SDimitry Andric bool Punycode;
35*5f7ddb14SDimitry Andric
empty__anonecbbd5db0111::Identifier36*5f7ddb14SDimitry Andric bool empty() const { return Name.empty(); }
37*5f7ddb14SDimitry Andric };
38*5f7ddb14SDimitry Andric
39*5f7ddb14SDimitry Andric enum class BasicType {
40*5f7ddb14SDimitry Andric Bool,
41*5f7ddb14SDimitry Andric Char,
42*5f7ddb14SDimitry Andric I8,
43*5f7ddb14SDimitry Andric I16,
44*5f7ddb14SDimitry Andric I32,
45*5f7ddb14SDimitry Andric I64,
46*5f7ddb14SDimitry Andric I128,
47*5f7ddb14SDimitry Andric ISize,
48*5f7ddb14SDimitry Andric U8,
49*5f7ddb14SDimitry Andric U16,
50*5f7ddb14SDimitry Andric U32,
51*5f7ddb14SDimitry Andric U64,
52*5f7ddb14SDimitry Andric U128,
53*5f7ddb14SDimitry Andric USize,
54*5f7ddb14SDimitry Andric F32,
55*5f7ddb14SDimitry Andric F64,
56*5f7ddb14SDimitry Andric Str,
57*5f7ddb14SDimitry Andric Placeholder,
58*5f7ddb14SDimitry Andric Unit,
59*5f7ddb14SDimitry Andric Variadic,
60*5f7ddb14SDimitry Andric Never,
61*5f7ddb14SDimitry Andric };
62*5f7ddb14SDimitry Andric
63*5f7ddb14SDimitry Andric enum class IsInType {
64*5f7ddb14SDimitry Andric No,
65*5f7ddb14SDimitry Andric Yes,
66*5f7ddb14SDimitry Andric };
67*5f7ddb14SDimitry Andric
68*5f7ddb14SDimitry Andric enum class LeaveGenericsOpen {
69*5f7ddb14SDimitry Andric No,
70*5f7ddb14SDimitry Andric Yes,
71*5f7ddb14SDimitry Andric };
72*5f7ddb14SDimitry Andric
73*5f7ddb14SDimitry Andric class Demangler {
74*5f7ddb14SDimitry Andric // Maximum recursion level. Used to avoid stack overflow.
75*5f7ddb14SDimitry Andric size_t MaxRecursionLevel;
76*5f7ddb14SDimitry Andric // Current recursion level.
77*5f7ddb14SDimitry Andric size_t RecursionLevel;
78*5f7ddb14SDimitry Andric size_t BoundLifetimes;
79*5f7ddb14SDimitry Andric // Input string that is being demangled with "_R" prefix removed.
80*5f7ddb14SDimitry Andric StringView Input;
81*5f7ddb14SDimitry Andric // Position in the input string.
82*5f7ddb14SDimitry Andric size_t Position;
83*5f7ddb14SDimitry Andric // When true, print methods append the output to the stream.
84*5f7ddb14SDimitry Andric // When false, the output is suppressed.
85*5f7ddb14SDimitry Andric bool Print;
86*5f7ddb14SDimitry Andric // True if an error occurred.
87*5f7ddb14SDimitry Andric bool Error;
88*5f7ddb14SDimitry Andric
89*5f7ddb14SDimitry Andric public:
90*5f7ddb14SDimitry Andric // Demangled output.
91*5f7ddb14SDimitry Andric OutputStream Output;
92*5f7ddb14SDimitry Andric
93*5f7ddb14SDimitry Andric Demangler(size_t MaxRecursionLevel = 500);
94*5f7ddb14SDimitry Andric
95*5f7ddb14SDimitry Andric bool demangle(StringView MangledName);
96*5f7ddb14SDimitry Andric
97*5f7ddb14SDimitry Andric private:
98*5f7ddb14SDimitry Andric bool demanglePath(IsInType Type,
99*5f7ddb14SDimitry Andric LeaveGenericsOpen LeaveOpen = LeaveGenericsOpen::No);
100*5f7ddb14SDimitry Andric void demangleImplPath(IsInType InType);
101*5f7ddb14SDimitry Andric void demangleGenericArg();
102*5f7ddb14SDimitry Andric void demangleType();
103*5f7ddb14SDimitry Andric void demangleFnSig();
104*5f7ddb14SDimitry Andric void demangleDynBounds();
105*5f7ddb14SDimitry Andric void demangleDynTrait();
106*5f7ddb14SDimitry Andric void demangleOptionalBinder();
107*5f7ddb14SDimitry Andric void demangleConst();
108*5f7ddb14SDimitry Andric void demangleConstInt();
109*5f7ddb14SDimitry Andric void demangleConstBool();
110*5f7ddb14SDimitry Andric void demangleConstChar();
111*5f7ddb14SDimitry Andric
demangleBackref(Callable Demangler)112*5f7ddb14SDimitry Andric template <typename Callable> void demangleBackref(Callable Demangler) {
113*5f7ddb14SDimitry Andric uint64_t Backref = parseBase62Number();
114*5f7ddb14SDimitry Andric if (Error || Backref >= Position) {
115*5f7ddb14SDimitry Andric Error = true;
116*5f7ddb14SDimitry Andric return;
117*5f7ddb14SDimitry Andric }
118*5f7ddb14SDimitry Andric
119*5f7ddb14SDimitry Andric if (!Print)
120*5f7ddb14SDimitry Andric return;
121*5f7ddb14SDimitry Andric
122*5f7ddb14SDimitry Andric SwapAndRestore<size_t> SavePosition(Position, Position);
123*5f7ddb14SDimitry Andric Position = Backref;
124*5f7ddb14SDimitry Andric Demangler();
125*5f7ddb14SDimitry Andric }
126*5f7ddb14SDimitry Andric
127*5f7ddb14SDimitry Andric Identifier parseIdentifier();
128*5f7ddb14SDimitry Andric uint64_t parseOptionalBase62Number(char Tag);
129*5f7ddb14SDimitry Andric uint64_t parseBase62Number();
130*5f7ddb14SDimitry Andric uint64_t parseDecimalNumber();
131*5f7ddb14SDimitry Andric uint64_t parseHexNumber(StringView &HexDigits);
132*5f7ddb14SDimitry Andric
133*5f7ddb14SDimitry Andric void print(char C);
134*5f7ddb14SDimitry Andric void print(StringView S);
135*5f7ddb14SDimitry Andric void printDecimalNumber(uint64_t N);
136*5f7ddb14SDimitry Andric void printBasicType(BasicType);
137*5f7ddb14SDimitry Andric void printLifetime(uint64_t Index);
138*5f7ddb14SDimitry Andric
139*5f7ddb14SDimitry Andric char look() const;
140*5f7ddb14SDimitry Andric char consume();
141*5f7ddb14SDimitry Andric bool consumeIf(char Prefix);
142*5f7ddb14SDimitry Andric
143*5f7ddb14SDimitry Andric bool addAssign(uint64_t &A, uint64_t B);
144*5f7ddb14SDimitry Andric bool mulAssign(uint64_t &A, uint64_t B);
145*5f7ddb14SDimitry Andric };
146*5f7ddb14SDimitry Andric
147*5f7ddb14SDimitry Andric } // namespace
148*5f7ddb14SDimitry Andric
rustDemangle(const char * MangledName,char * Buf,size_t * N,int * Status)149*5f7ddb14SDimitry Andric char *llvm::rustDemangle(const char *MangledName, char *Buf, size_t *N,
150*5f7ddb14SDimitry Andric int *Status) {
151*5f7ddb14SDimitry Andric if (MangledName == nullptr || (Buf != nullptr && N == nullptr)) {
152*5f7ddb14SDimitry Andric if (Status != nullptr)
153*5f7ddb14SDimitry Andric *Status = demangle_invalid_args;
154*5f7ddb14SDimitry Andric return nullptr;
155*5f7ddb14SDimitry Andric }
156*5f7ddb14SDimitry Andric
157*5f7ddb14SDimitry Andric // Return early if mangled name doesn't look like a Rust symbol.
158*5f7ddb14SDimitry Andric StringView Mangled(MangledName);
159*5f7ddb14SDimitry Andric if (!Mangled.startsWith("_R")) {
160*5f7ddb14SDimitry Andric if (Status != nullptr)
161*5f7ddb14SDimitry Andric *Status = demangle_invalid_mangled_name;
162*5f7ddb14SDimitry Andric return nullptr;
163*5f7ddb14SDimitry Andric }
164*5f7ddb14SDimitry Andric
165*5f7ddb14SDimitry Andric Demangler D;
166*5f7ddb14SDimitry Andric if (!initializeOutputStream(nullptr, nullptr, D.Output, 1024)) {
167*5f7ddb14SDimitry Andric if (Status != nullptr)
168*5f7ddb14SDimitry Andric *Status = demangle_memory_alloc_failure;
169*5f7ddb14SDimitry Andric return nullptr;
170*5f7ddb14SDimitry Andric }
171*5f7ddb14SDimitry Andric
172*5f7ddb14SDimitry Andric if (!D.demangle(Mangled)) {
173*5f7ddb14SDimitry Andric if (Status != nullptr)
174*5f7ddb14SDimitry Andric *Status = demangle_invalid_mangled_name;
175*5f7ddb14SDimitry Andric std::free(D.Output.getBuffer());
176*5f7ddb14SDimitry Andric return nullptr;
177*5f7ddb14SDimitry Andric }
178*5f7ddb14SDimitry Andric
179*5f7ddb14SDimitry Andric D.Output += '\0';
180*5f7ddb14SDimitry Andric char *Demangled = D.Output.getBuffer();
181*5f7ddb14SDimitry Andric size_t DemangledLen = D.Output.getCurrentPosition();
182*5f7ddb14SDimitry Andric
183*5f7ddb14SDimitry Andric if (Buf != nullptr) {
184*5f7ddb14SDimitry Andric if (DemangledLen <= *N) {
185*5f7ddb14SDimitry Andric std::memcpy(Buf, Demangled, DemangledLen);
186*5f7ddb14SDimitry Andric std::free(Demangled);
187*5f7ddb14SDimitry Andric Demangled = Buf;
188*5f7ddb14SDimitry Andric } else {
189*5f7ddb14SDimitry Andric std::free(Buf);
190*5f7ddb14SDimitry Andric }
191*5f7ddb14SDimitry Andric }
192*5f7ddb14SDimitry Andric
193*5f7ddb14SDimitry Andric if (N != nullptr)
194*5f7ddb14SDimitry Andric *N = DemangledLen;
195*5f7ddb14SDimitry Andric
196*5f7ddb14SDimitry Andric if (Status != nullptr)
197*5f7ddb14SDimitry Andric *Status = demangle_success;
198*5f7ddb14SDimitry Andric
199*5f7ddb14SDimitry Andric return Demangled;
200*5f7ddb14SDimitry Andric }
201*5f7ddb14SDimitry Andric
Demangler(size_t MaxRecursionLevel)202*5f7ddb14SDimitry Andric Demangler::Demangler(size_t MaxRecursionLevel)
203*5f7ddb14SDimitry Andric : MaxRecursionLevel(MaxRecursionLevel) {}
204*5f7ddb14SDimitry Andric
isDigit(const char C)205*5f7ddb14SDimitry Andric static inline bool isDigit(const char C) { return '0' <= C && C <= '9'; }
206*5f7ddb14SDimitry Andric
isHexDigit(const char C)207*5f7ddb14SDimitry Andric static inline bool isHexDigit(const char C) {
208*5f7ddb14SDimitry Andric return ('0' <= C && C <= '9') || ('a' <= C && C <= 'f');
209*5f7ddb14SDimitry Andric }
210*5f7ddb14SDimitry Andric
isLower(const char C)211*5f7ddb14SDimitry Andric static inline bool isLower(const char C) { return 'a' <= C && C <= 'z'; }
212*5f7ddb14SDimitry Andric
isUpper(const char C)213*5f7ddb14SDimitry Andric static inline bool isUpper(const char C) { return 'A' <= C && C <= 'Z'; }
214*5f7ddb14SDimitry Andric
215*5f7ddb14SDimitry Andric /// Returns true if C is a valid mangled character: <0-9a-zA-Z_>.
isValid(const char C)216*5f7ddb14SDimitry Andric static inline bool isValid(const char C) {
217*5f7ddb14SDimitry Andric return isDigit(C) || isLower(C) || isUpper(C) || C == '_';
218*5f7ddb14SDimitry Andric }
219*5f7ddb14SDimitry Andric
220*5f7ddb14SDimitry Andric // Demangles Rust v0 mangled symbol. Returns true when successful, and false
221*5f7ddb14SDimitry Andric // otherwise. The demangled symbol is stored in Output field. It is
222*5f7ddb14SDimitry Andric // responsibility of the caller to free the memory behind the output stream.
223*5f7ddb14SDimitry Andric //
224*5f7ddb14SDimitry Andric // <symbol-name> = "_R" <path> [<instantiating-crate>]
demangle(StringView Mangled)225*5f7ddb14SDimitry Andric bool Demangler::demangle(StringView Mangled) {
226*5f7ddb14SDimitry Andric Position = 0;
227*5f7ddb14SDimitry Andric Error = false;
228*5f7ddb14SDimitry Andric Print = true;
229*5f7ddb14SDimitry Andric RecursionLevel = 0;
230*5f7ddb14SDimitry Andric BoundLifetimes = 0;
231*5f7ddb14SDimitry Andric
232*5f7ddb14SDimitry Andric if (!Mangled.consumeFront("_R")) {
233*5f7ddb14SDimitry Andric Error = true;
234*5f7ddb14SDimitry Andric return false;
235*5f7ddb14SDimitry Andric }
236*5f7ddb14SDimitry Andric size_t Dot = Mangled.find('.');
237*5f7ddb14SDimitry Andric Input = Mangled.substr(0, Dot);
238*5f7ddb14SDimitry Andric StringView Suffix = Mangled.dropFront(Dot);
239*5f7ddb14SDimitry Andric
240*5f7ddb14SDimitry Andric demanglePath(IsInType::No);
241*5f7ddb14SDimitry Andric
242*5f7ddb14SDimitry Andric if (Position != Input.size()) {
243*5f7ddb14SDimitry Andric SwapAndRestore<bool> SavePrint(Print, false);
244*5f7ddb14SDimitry Andric demanglePath(IsInType::No);
245*5f7ddb14SDimitry Andric }
246*5f7ddb14SDimitry Andric
247*5f7ddb14SDimitry Andric if (Position != Input.size())
248*5f7ddb14SDimitry Andric Error = true;
249*5f7ddb14SDimitry Andric
250*5f7ddb14SDimitry Andric if (!Suffix.empty()) {
251*5f7ddb14SDimitry Andric print(" (");
252*5f7ddb14SDimitry Andric print(Suffix);
253*5f7ddb14SDimitry Andric print(")");
254*5f7ddb14SDimitry Andric }
255*5f7ddb14SDimitry Andric
256*5f7ddb14SDimitry Andric return !Error;
257*5f7ddb14SDimitry Andric }
258*5f7ddb14SDimitry Andric
259*5f7ddb14SDimitry Andric // Demangles a path. InType indicates whether a path is inside a type. When
260*5f7ddb14SDimitry Andric // LeaveOpen is true, a closing `>` after generic arguments is omitted from the
261*5f7ddb14SDimitry Andric // output. Return value indicates whether generics arguments have been left
262*5f7ddb14SDimitry Andric // open.
263*5f7ddb14SDimitry Andric //
264*5f7ddb14SDimitry Andric // <path> = "C" <identifier> // crate root
265*5f7ddb14SDimitry Andric // | "M" <impl-path> <type> // <T> (inherent impl)
266*5f7ddb14SDimitry Andric // | "X" <impl-path> <type> <path> // <T as Trait> (trait impl)
267*5f7ddb14SDimitry Andric // | "Y" <type> <path> // <T as Trait> (trait definition)
268*5f7ddb14SDimitry Andric // | "N" <ns> <path> <identifier> // ...::ident (nested path)
269*5f7ddb14SDimitry Andric // | "I" <path> {<generic-arg>} "E" // ...<T, U> (generic args)
270*5f7ddb14SDimitry Andric // | <backref>
271*5f7ddb14SDimitry Andric // <identifier> = [<disambiguator>] <undisambiguated-identifier>
272*5f7ddb14SDimitry Andric // <ns> = "C" // closure
273*5f7ddb14SDimitry Andric // | "S" // shim
274*5f7ddb14SDimitry Andric // | <A-Z> // other special namespaces
275*5f7ddb14SDimitry Andric // | <a-z> // internal namespaces
demanglePath(IsInType InType,LeaveGenericsOpen LeaveOpen)276*5f7ddb14SDimitry Andric bool Demangler::demanglePath(IsInType InType, LeaveGenericsOpen LeaveOpen) {
277*5f7ddb14SDimitry Andric if (Error || RecursionLevel >= MaxRecursionLevel) {
278*5f7ddb14SDimitry Andric Error = true;
279*5f7ddb14SDimitry Andric return false;
280*5f7ddb14SDimitry Andric }
281*5f7ddb14SDimitry Andric SwapAndRestore<size_t> SaveRecursionLevel(RecursionLevel, RecursionLevel + 1);
282*5f7ddb14SDimitry Andric
283*5f7ddb14SDimitry Andric switch (consume()) {
284*5f7ddb14SDimitry Andric case 'C': {
285*5f7ddb14SDimitry Andric parseOptionalBase62Number('s');
286*5f7ddb14SDimitry Andric Identifier Ident = parseIdentifier();
287*5f7ddb14SDimitry Andric print(Ident.Name);
288*5f7ddb14SDimitry Andric break;
289*5f7ddb14SDimitry Andric }
290*5f7ddb14SDimitry Andric case 'M': {
291*5f7ddb14SDimitry Andric demangleImplPath(InType);
292*5f7ddb14SDimitry Andric print("<");
293*5f7ddb14SDimitry Andric demangleType();
294*5f7ddb14SDimitry Andric print(">");
295*5f7ddb14SDimitry Andric break;
296*5f7ddb14SDimitry Andric }
297*5f7ddb14SDimitry Andric case 'X': {
298*5f7ddb14SDimitry Andric demangleImplPath(InType);
299*5f7ddb14SDimitry Andric print("<");
300*5f7ddb14SDimitry Andric demangleType();
301*5f7ddb14SDimitry Andric print(" as ");
302*5f7ddb14SDimitry Andric demanglePath(IsInType::Yes);
303*5f7ddb14SDimitry Andric print(">");
304*5f7ddb14SDimitry Andric break;
305*5f7ddb14SDimitry Andric }
306*5f7ddb14SDimitry Andric case 'Y': {
307*5f7ddb14SDimitry Andric print("<");
308*5f7ddb14SDimitry Andric demangleType();
309*5f7ddb14SDimitry Andric print(" as ");
310*5f7ddb14SDimitry Andric demanglePath(IsInType::Yes);
311*5f7ddb14SDimitry Andric print(">");
312*5f7ddb14SDimitry Andric break;
313*5f7ddb14SDimitry Andric }
314*5f7ddb14SDimitry Andric case 'N': {
315*5f7ddb14SDimitry Andric char NS = consume();
316*5f7ddb14SDimitry Andric if (!isLower(NS) && !isUpper(NS)) {
317*5f7ddb14SDimitry Andric Error = true;
318*5f7ddb14SDimitry Andric break;
319*5f7ddb14SDimitry Andric }
320*5f7ddb14SDimitry Andric demanglePath(InType);
321*5f7ddb14SDimitry Andric
322*5f7ddb14SDimitry Andric uint64_t Disambiguator = parseOptionalBase62Number('s');
323*5f7ddb14SDimitry Andric Identifier Ident = parseIdentifier();
324*5f7ddb14SDimitry Andric
325*5f7ddb14SDimitry Andric if (isUpper(NS)) {
326*5f7ddb14SDimitry Andric // Special namespaces
327*5f7ddb14SDimitry Andric print("::{");
328*5f7ddb14SDimitry Andric if (NS == 'C')
329*5f7ddb14SDimitry Andric print("closure");
330*5f7ddb14SDimitry Andric else if (NS == 'S')
331*5f7ddb14SDimitry Andric print("shim");
332*5f7ddb14SDimitry Andric else
333*5f7ddb14SDimitry Andric print(NS);
334*5f7ddb14SDimitry Andric if (!Ident.empty()) {
335*5f7ddb14SDimitry Andric print(":");
336*5f7ddb14SDimitry Andric print(Ident.Name);
337*5f7ddb14SDimitry Andric }
338*5f7ddb14SDimitry Andric print('#');
339*5f7ddb14SDimitry Andric printDecimalNumber(Disambiguator);
340*5f7ddb14SDimitry Andric print('}');
341*5f7ddb14SDimitry Andric } else {
342*5f7ddb14SDimitry Andric // Implementation internal namespaces.
343*5f7ddb14SDimitry Andric if (!Ident.empty()) {
344*5f7ddb14SDimitry Andric print("::");
345*5f7ddb14SDimitry Andric print(Ident.Name);
346*5f7ddb14SDimitry Andric }
347*5f7ddb14SDimitry Andric }
348*5f7ddb14SDimitry Andric break;
349*5f7ddb14SDimitry Andric }
350*5f7ddb14SDimitry Andric case 'I': {
351*5f7ddb14SDimitry Andric demanglePath(InType);
352*5f7ddb14SDimitry Andric // Omit "::" when in a type, where it is optional.
353*5f7ddb14SDimitry Andric if (InType == IsInType::No)
354*5f7ddb14SDimitry Andric print("::");
355*5f7ddb14SDimitry Andric print("<");
356*5f7ddb14SDimitry Andric for (size_t I = 0; !Error && !consumeIf('E'); ++I) {
357*5f7ddb14SDimitry Andric if (I > 0)
358*5f7ddb14SDimitry Andric print(", ");
359*5f7ddb14SDimitry Andric demangleGenericArg();
360*5f7ddb14SDimitry Andric }
361*5f7ddb14SDimitry Andric if (LeaveOpen == LeaveGenericsOpen::Yes)
362*5f7ddb14SDimitry Andric return true;
363*5f7ddb14SDimitry Andric else
364*5f7ddb14SDimitry Andric print(">");
365*5f7ddb14SDimitry Andric break;
366*5f7ddb14SDimitry Andric }
367*5f7ddb14SDimitry Andric case 'B': {
368*5f7ddb14SDimitry Andric bool IsOpen = false;
369*5f7ddb14SDimitry Andric demangleBackref([&] { IsOpen = demanglePath(InType, LeaveOpen); });
370*5f7ddb14SDimitry Andric return IsOpen;
371*5f7ddb14SDimitry Andric }
372*5f7ddb14SDimitry Andric default:
373*5f7ddb14SDimitry Andric Error = true;
374*5f7ddb14SDimitry Andric break;
375*5f7ddb14SDimitry Andric }
376*5f7ddb14SDimitry Andric
377*5f7ddb14SDimitry Andric return false;
378*5f7ddb14SDimitry Andric }
379*5f7ddb14SDimitry Andric
380*5f7ddb14SDimitry Andric // <impl-path> = [<disambiguator>] <path>
381*5f7ddb14SDimitry Andric // <disambiguator> = "s" <base-62-number>
demangleImplPath(IsInType InType)382*5f7ddb14SDimitry Andric void Demangler::demangleImplPath(IsInType InType) {
383*5f7ddb14SDimitry Andric SwapAndRestore<bool> SavePrint(Print, false);
384*5f7ddb14SDimitry Andric parseOptionalBase62Number('s');
385*5f7ddb14SDimitry Andric demanglePath(InType);
386*5f7ddb14SDimitry Andric }
387*5f7ddb14SDimitry Andric
388*5f7ddb14SDimitry Andric // <generic-arg> = <lifetime>
389*5f7ddb14SDimitry Andric // | <type>
390*5f7ddb14SDimitry Andric // | "K" <const>
391*5f7ddb14SDimitry Andric // <lifetime> = "L" <base-62-number>
demangleGenericArg()392*5f7ddb14SDimitry Andric void Demangler::demangleGenericArg() {
393*5f7ddb14SDimitry Andric if (consumeIf('L'))
394*5f7ddb14SDimitry Andric printLifetime(parseBase62Number());
395*5f7ddb14SDimitry Andric else if (consumeIf('K'))
396*5f7ddb14SDimitry Andric demangleConst();
397*5f7ddb14SDimitry Andric else
398*5f7ddb14SDimitry Andric demangleType();
399*5f7ddb14SDimitry Andric }
400*5f7ddb14SDimitry Andric
401*5f7ddb14SDimitry Andric // <basic-type> = "a" // i8
402*5f7ddb14SDimitry Andric // | "b" // bool
403*5f7ddb14SDimitry Andric // | "c" // char
404*5f7ddb14SDimitry Andric // | "d" // f64
405*5f7ddb14SDimitry Andric // | "e" // str
406*5f7ddb14SDimitry Andric // | "f" // f32
407*5f7ddb14SDimitry Andric // | "h" // u8
408*5f7ddb14SDimitry Andric // | "i" // isize
409*5f7ddb14SDimitry Andric // | "j" // usize
410*5f7ddb14SDimitry Andric // | "l" // i32
411*5f7ddb14SDimitry Andric // | "m" // u32
412*5f7ddb14SDimitry Andric // | "n" // i128
413*5f7ddb14SDimitry Andric // | "o" // u128
414*5f7ddb14SDimitry Andric // | "s" // i16
415*5f7ddb14SDimitry Andric // | "t" // u16
416*5f7ddb14SDimitry Andric // | "u" // ()
417*5f7ddb14SDimitry Andric // | "v" // ...
418*5f7ddb14SDimitry Andric // | "x" // i64
419*5f7ddb14SDimitry Andric // | "y" // u64
420*5f7ddb14SDimitry Andric // | "z" // !
421*5f7ddb14SDimitry Andric // | "p" // placeholder (e.g. for generic params), shown as _
parseBasicType(char C,BasicType & Type)422*5f7ddb14SDimitry Andric static bool parseBasicType(char C, BasicType &Type) {
423*5f7ddb14SDimitry Andric switch (C) {
424*5f7ddb14SDimitry Andric case 'a':
425*5f7ddb14SDimitry Andric Type = BasicType::I8;
426*5f7ddb14SDimitry Andric return true;
427*5f7ddb14SDimitry Andric case 'b':
428*5f7ddb14SDimitry Andric Type = BasicType::Bool;
429*5f7ddb14SDimitry Andric return true;
430*5f7ddb14SDimitry Andric case 'c':
431*5f7ddb14SDimitry Andric Type = BasicType::Char;
432*5f7ddb14SDimitry Andric return true;
433*5f7ddb14SDimitry Andric case 'd':
434*5f7ddb14SDimitry Andric Type = BasicType::F64;
435*5f7ddb14SDimitry Andric return true;
436*5f7ddb14SDimitry Andric case 'e':
437*5f7ddb14SDimitry Andric Type = BasicType::Str;
438*5f7ddb14SDimitry Andric return true;
439*5f7ddb14SDimitry Andric case 'f':
440*5f7ddb14SDimitry Andric Type = BasicType::F32;
441*5f7ddb14SDimitry Andric return true;
442*5f7ddb14SDimitry Andric case 'h':
443*5f7ddb14SDimitry Andric Type = BasicType::U8;
444*5f7ddb14SDimitry Andric return true;
445*5f7ddb14SDimitry Andric case 'i':
446*5f7ddb14SDimitry Andric Type = BasicType::ISize;
447*5f7ddb14SDimitry Andric return true;
448*5f7ddb14SDimitry Andric case 'j':
449*5f7ddb14SDimitry Andric Type = BasicType::USize;
450*5f7ddb14SDimitry Andric return true;
451*5f7ddb14SDimitry Andric case 'l':
452*5f7ddb14SDimitry Andric Type = BasicType::I32;
453*5f7ddb14SDimitry Andric return true;
454*5f7ddb14SDimitry Andric case 'm':
455*5f7ddb14SDimitry Andric Type = BasicType::U32;
456*5f7ddb14SDimitry Andric return true;
457*5f7ddb14SDimitry Andric case 'n':
458*5f7ddb14SDimitry Andric Type = BasicType::I128;
459*5f7ddb14SDimitry Andric return true;
460*5f7ddb14SDimitry Andric case 'o':
461*5f7ddb14SDimitry Andric Type = BasicType::U128;
462*5f7ddb14SDimitry Andric return true;
463*5f7ddb14SDimitry Andric case 'p':
464*5f7ddb14SDimitry Andric Type = BasicType::Placeholder;
465*5f7ddb14SDimitry Andric return true;
466*5f7ddb14SDimitry Andric case 's':
467*5f7ddb14SDimitry Andric Type = BasicType::I16;
468*5f7ddb14SDimitry Andric return true;
469*5f7ddb14SDimitry Andric case 't':
470*5f7ddb14SDimitry Andric Type = BasicType::U16;
471*5f7ddb14SDimitry Andric return true;
472*5f7ddb14SDimitry Andric case 'u':
473*5f7ddb14SDimitry Andric Type = BasicType::Unit;
474*5f7ddb14SDimitry Andric return true;
475*5f7ddb14SDimitry Andric case 'v':
476*5f7ddb14SDimitry Andric Type = BasicType::Variadic;
477*5f7ddb14SDimitry Andric return true;
478*5f7ddb14SDimitry Andric case 'x':
479*5f7ddb14SDimitry Andric Type = BasicType::I64;
480*5f7ddb14SDimitry Andric return true;
481*5f7ddb14SDimitry Andric case 'y':
482*5f7ddb14SDimitry Andric Type = BasicType::U64;
483*5f7ddb14SDimitry Andric return true;
484*5f7ddb14SDimitry Andric case 'z':
485*5f7ddb14SDimitry Andric Type = BasicType::Never;
486*5f7ddb14SDimitry Andric return true;
487*5f7ddb14SDimitry Andric default:
488*5f7ddb14SDimitry Andric return false;
489*5f7ddb14SDimitry Andric }
490*5f7ddb14SDimitry Andric }
491*5f7ddb14SDimitry Andric
printBasicType(BasicType Type)492*5f7ddb14SDimitry Andric void Demangler::printBasicType(BasicType Type) {
493*5f7ddb14SDimitry Andric switch (Type) {
494*5f7ddb14SDimitry Andric case BasicType::Bool:
495*5f7ddb14SDimitry Andric print("bool");
496*5f7ddb14SDimitry Andric break;
497*5f7ddb14SDimitry Andric case BasicType::Char:
498*5f7ddb14SDimitry Andric print("char");
499*5f7ddb14SDimitry Andric break;
500*5f7ddb14SDimitry Andric case BasicType::I8:
501*5f7ddb14SDimitry Andric print("i8");
502*5f7ddb14SDimitry Andric break;
503*5f7ddb14SDimitry Andric case BasicType::I16:
504*5f7ddb14SDimitry Andric print("i16");
505*5f7ddb14SDimitry Andric break;
506*5f7ddb14SDimitry Andric case BasicType::I32:
507*5f7ddb14SDimitry Andric print("i32");
508*5f7ddb14SDimitry Andric break;
509*5f7ddb14SDimitry Andric case BasicType::I64:
510*5f7ddb14SDimitry Andric print("i64");
511*5f7ddb14SDimitry Andric break;
512*5f7ddb14SDimitry Andric case BasicType::I128:
513*5f7ddb14SDimitry Andric print("i128");
514*5f7ddb14SDimitry Andric break;
515*5f7ddb14SDimitry Andric case BasicType::ISize:
516*5f7ddb14SDimitry Andric print("isize");
517*5f7ddb14SDimitry Andric break;
518*5f7ddb14SDimitry Andric case BasicType::U8:
519*5f7ddb14SDimitry Andric print("u8");
520*5f7ddb14SDimitry Andric break;
521*5f7ddb14SDimitry Andric case BasicType::U16:
522*5f7ddb14SDimitry Andric print("u16");
523*5f7ddb14SDimitry Andric break;
524*5f7ddb14SDimitry Andric case BasicType::U32:
525*5f7ddb14SDimitry Andric print("u32");
526*5f7ddb14SDimitry Andric break;
527*5f7ddb14SDimitry Andric case BasicType::U64:
528*5f7ddb14SDimitry Andric print("u64");
529*5f7ddb14SDimitry Andric break;
530*5f7ddb14SDimitry Andric case BasicType::U128:
531*5f7ddb14SDimitry Andric print("u128");
532*5f7ddb14SDimitry Andric break;
533*5f7ddb14SDimitry Andric case BasicType::USize:
534*5f7ddb14SDimitry Andric print("usize");
535*5f7ddb14SDimitry Andric break;
536*5f7ddb14SDimitry Andric case BasicType::F32:
537*5f7ddb14SDimitry Andric print("f32");
538*5f7ddb14SDimitry Andric break;
539*5f7ddb14SDimitry Andric case BasicType::F64:
540*5f7ddb14SDimitry Andric print("f64");
541*5f7ddb14SDimitry Andric break;
542*5f7ddb14SDimitry Andric case BasicType::Str:
543*5f7ddb14SDimitry Andric print("str");
544*5f7ddb14SDimitry Andric break;
545*5f7ddb14SDimitry Andric case BasicType::Placeholder:
546*5f7ddb14SDimitry Andric print("_");
547*5f7ddb14SDimitry Andric break;
548*5f7ddb14SDimitry Andric case BasicType::Unit:
549*5f7ddb14SDimitry Andric print("()");
550*5f7ddb14SDimitry Andric break;
551*5f7ddb14SDimitry Andric case BasicType::Variadic:
552*5f7ddb14SDimitry Andric print("...");
553*5f7ddb14SDimitry Andric break;
554*5f7ddb14SDimitry Andric case BasicType::Never:
555*5f7ddb14SDimitry Andric print("!");
556*5f7ddb14SDimitry Andric break;
557*5f7ddb14SDimitry Andric }
558*5f7ddb14SDimitry Andric }
559*5f7ddb14SDimitry Andric
560*5f7ddb14SDimitry Andric // <type> = | <basic-type>
561*5f7ddb14SDimitry Andric // | <path> // named type
562*5f7ddb14SDimitry Andric // | "A" <type> <const> // [T; N]
563*5f7ddb14SDimitry Andric // | "S" <type> // [T]
564*5f7ddb14SDimitry Andric // | "T" {<type>} "E" // (T1, T2, T3, ...)
565*5f7ddb14SDimitry Andric // | "R" [<lifetime>] <type> // &T
566*5f7ddb14SDimitry Andric // | "Q" [<lifetime>] <type> // &mut T
567*5f7ddb14SDimitry Andric // | "P" <type> // *const T
568*5f7ddb14SDimitry Andric // | "O" <type> // *mut T
569*5f7ddb14SDimitry Andric // | "F" <fn-sig> // fn(...) -> ...
570*5f7ddb14SDimitry Andric // | "D" <dyn-bounds> <lifetime> // dyn Trait<Assoc = X> + Send + 'a
571*5f7ddb14SDimitry Andric // | <backref> // backref
demangleType()572*5f7ddb14SDimitry Andric void Demangler::demangleType() {
573*5f7ddb14SDimitry Andric if (Error || RecursionLevel >= MaxRecursionLevel) {
574*5f7ddb14SDimitry Andric Error = true;
575*5f7ddb14SDimitry Andric return;
576*5f7ddb14SDimitry Andric }
577*5f7ddb14SDimitry Andric SwapAndRestore<size_t> SaveRecursionLevel(RecursionLevel, RecursionLevel + 1);
578*5f7ddb14SDimitry Andric
579*5f7ddb14SDimitry Andric size_t Start = Position;
580*5f7ddb14SDimitry Andric char C = consume();
581*5f7ddb14SDimitry Andric BasicType Type;
582*5f7ddb14SDimitry Andric if (parseBasicType(C, Type))
583*5f7ddb14SDimitry Andric return printBasicType(Type);
584*5f7ddb14SDimitry Andric
585*5f7ddb14SDimitry Andric switch (C) {
586*5f7ddb14SDimitry Andric case 'A':
587*5f7ddb14SDimitry Andric print("[");
588*5f7ddb14SDimitry Andric demangleType();
589*5f7ddb14SDimitry Andric print("; ");
590*5f7ddb14SDimitry Andric demangleConst();
591*5f7ddb14SDimitry Andric print("]");
592*5f7ddb14SDimitry Andric break;
593*5f7ddb14SDimitry Andric case 'S':
594*5f7ddb14SDimitry Andric print("[");
595*5f7ddb14SDimitry Andric demangleType();
596*5f7ddb14SDimitry Andric print("]");
597*5f7ddb14SDimitry Andric break;
598*5f7ddb14SDimitry Andric case 'T': {
599*5f7ddb14SDimitry Andric print("(");
600*5f7ddb14SDimitry Andric size_t I = 0;
601*5f7ddb14SDimitry Andric for (; !Error && !consumeIf('E'); ++I) {
602*5f7ddb14SDimitry Andric if (I > 0)
603*5f7ddb14SDimitry Andric print(", ");
604*5f7ddb14SDimitry Andric demangleType();
605*5f7ddb14SDimitry Andric }
606*5f7ddb14SDimitry Andric if (I == 1)
607*5f7ddb14SDimitry Andric print(",");
608*5f7ddb14SDimitry Andric print(")");
609*5f7ddb14SDimitry Andric break;
610*5f7ddb14SDimitry Andric }
611*5f7ddb14SDimitry Andric case 'R':
612*5f7ddb14SDimitry Andric case 'Q':
613*5f7ddb14SDimitry Andric print('&');
614*5f7ddb14SDimitry Andric if (consumeIf('L')) {
615*5f7ddb14SDimitry Andric if (auto Lifetime = parseBase62Number()) {
616*5f7ddb14SDimitry Andric printLifetime(Lifetime);
617*5f7ddb14SDimitry Andric print(' ');
618*5f7ddb14SDimitry Andric }
619*5f7ddb14SDimitry Andric }
620*5f7ddb14SDimitry Andric if (C == 'Q')
621*5f7ddb14SDimitry Andric print("mut ");
622*5f7ddb14SDimitry Andric demangleType();
623*5f7ddb14SDimitry Andric break;
624*5f7ddb14SDimitry Andric case 'P':
625*5f7ddb14SDimitry Andric print("*const ");
626*5f7ddb14SDimitry Andric demangleType();
627*5f7ddb14SDimitry Andric break;
628*5f7ddb14SDimitry Andric case 'O':
629*5f7ddb14SDimitry Andric print("*mut ");
630*5f7ddb14SDimitry Andric demangleType();
631*5f7ddb14SDimitry Andric break;
632*5f7ddb14SDimitry Andric case 'F':
633*5f7ddb14SDimitry Andric demangleFnSig();
634*5f7ddb14SDimitry Andric break;
635*5f7ddb14SDimitry Andric case 'D':
636*5f7ddb14SDimitry Andric demangleDynBounds();
637*5f7ddb14SDimitry Andric if (consumeIf('L')) {
638*5f7ddb14SDimitry Andric if (auto Lifetime = parseBase62Number()) {
639*5f7ddb14SDimitry Andric print(" + ");
640*5f7ddb14SDimitry Andric printLifetime(Lifetime);
641*5f7ddb14SDimitry Andric }
642*5f7ddb14SDimitry Andric } else {
643*5f7ddb14SDimitry Andric Error = true;
644*5f7ddb14SDimitry Andric }
645*5f7ddb14SDimitry Andric break;
646*5f7ddb14SDimitry Andric case 'B':
647*5f7ddb14SDimitry Andric demangleBackref([&] { demangleType(); });
648*5f7ddb14SDimitry Andric break;
649*5f7ddb14SDimitry Andric default:
650*5f7ddb14SDimitry Andric Position = Start;
651*5f7ddb14SDimitry Andric demanglePath(IsInType::Yes);
652*5f7ddb14SDimitry Andric break;
653*5f7ddb14SDimitry Andric }
654*5f7ddb14SDimitry Andric }
655*5f7ddb14SDimitry Andric
656*5f7ddb14SDimitry Andric // <fn-sig> := [<binder>] ["U"] ["K" <abi>] {<type>} "E" <type>
657*5f7ddb14SDimitry Andric // <abi> = "C"
658*5f7ddb14SDimitry Andric // | <undisambiguated-identifier>
demangleFnSig()659*5f7ddb14SDimitry Andric void Demangler::demangleFnSig() {
660*5f7ddb14SDimitry Andric SwapAndRestore<size_t> SaveBoundLifetimes(BoundLifetimes, BoundLifetimes);
661*5f7ddb14SDimitry Andric demangleOptionalBinder();
662*5f7ddb14SDimitry Andric
663*5f7ddb14SDimitry Andric if (consumeIf('U'))
664*5f7ddb14SDimitry Andric print("unsafe ");
665*5f7ddb14SDimitry Andric
666*5f7ddb14SDimitry Andric if (consumeIf('K')) {
667*5f7ddb14SDimitry Andric print("extern \"");
668*5f7ddb14SDimitry Andric if (consumeIf('C')) {
669*5f7ddb14SDimitry Andric print("C");
670*5f7ddb14SDimitry Andric } else {
671*5f7ddb14SDimitry Andric Identifier Ident = parseIdentifier();
672*5f7ddb14SDimitry Andric for (char C : Ident.Name) {
673*5f7ddb14SDimitry Andric // When mangling ABI string, the "-" is replaced with "_".
674*5f7ddb14SDimitry Andric if (C == '_')
675*5f7ddb14SDimitry Andric C = '-';
676*5f7ddb14SDimitry Andric print(C);
677*5f7ddb14SDimitry Andric }
678*5f7ddb14SDimitry Andric }
679*5f7ddb14SDimitry Andric print("\" ");
680*5f7ddb14SDimitry Andric }
681*5f7ddb14SDimitry Andric
682*5f7ddb14SDimitry Andric print("fn(");
683*5f7ddb14SDimitry Andric for (size_t I = 0; !Error && !consumeIf('E'); ++I) {
684*5f7ddb14SDimitry Andric if (I > 0)
685*5f7ddb14SDimitry Andric print(", ");
686*5f7ddb14SDimitry Andric demangleType();
687*5f7ddb14SDimitry Andric }
688*5f7ddb14SDimitry Andric print(")");
689*5f7ddb14SDimitry Andric
690*5f7ddb14SDimitry Andric if (consumeIf('u')) {
691*5f7ddb14SDimitry Andric // Skip the unit type from the output.
692*5f7ddb14SDimitry Andric } else {
693*5f7ddb14SDimitry Andric print(" -> ");
694*5f7ddb14SDimitry Andric demangleType();
695*5f7ddb14SDimitry Andric }
696*5f7ddb14SDimitry Andric }
697*5f7ddb14SDimitry Andric
698*5f7ddb14SDimitry Andric // <dyn-bounds> = [<binder>] {<dyn-trait>} "E"
demangleDynBounds()699*5f7ddb14SDimitry Andric void Demangler::demangleDynBounds() {
700*5f7ddb14SDimitry Andric SwapAndRestore<size_t> SaveBoundLifetimes(BoundLifetimes, BoundLifetimes);
701*5f7ddb14SDimitry Andric print("dyn ");
702*5f7ddb14SDimitry Andric demangleOptionalBinder();
703*5f7ddb14SDimitry Andric for (size_t I = 0; !Error && !consumeIf('E'); ++I) {
704*5f7ddb14SDimitry Andric if (I > 0)
705*5f7ddb14SDimitry Andric print(" + ");
706*5f7ddb14SDimitry Andric demangleDynTrait();
707*5f7ddb14SDimitry Andric }
708*5f7ddb14SDimitry Andric }
709*5f7ddb14SDimitry Andric
710*5f7ddb14SDimitry Andric // <dyn-trait> = <path> {<dyn-trait-assoc-binding>}
711*5f7ddb14SDimitry Andric // <dyn-trait-assoc-binding> = "p" <undisambiguated-identifier> <type>
demangleDynTrait()712*5f7ddb14SDimitry Andric void Demangler::demangleDynTrait() {
713*5f7ddb14SDimitry Andric bool IsOpen = demanglePath(IsInType::Yes, LeaveGenericsOpen::Yes);
714*5f7ddb14SDimitry Andric while (!Error && consumeIf('p')) {
715*5f7ddb14SDimitry Andric if (!IsOpen) {
716*5f7ddb14SDimitry Andric IsOpen = true;
717*5f7ddb14SDimitry Andric print('<');
718*5f7ddb14SDimitry Andric } else {
719*5f7ddb14SDimitry Andric print(", ");
720*5f7ddb14SDimitry Andric }
721*5f7ddb14SDimitry Andric print(parseIdentifier().Name);
722*5f7ddb14SDimitry Andric print(" = ");
723*5f7ddb14SDimitry Andric demangleType();
724*5f7ddb14SDimitry Andric }
725*5f7ddb14SDimitry Andric if (IsOpen)
726*5f7ddb14SDimitry Andric print(">");
727*5f7ddb14SDimitry Andric }
728*5f7ddb14SDimitry Andric
729*5f7ddb14SDimitry Andric // Demangles optional binder and updates the number of bound lifetimes.
730*5f7ddb14SDimitry Andric //
731*5f7ddb14SDimitry Andric // <binder> = "G" <base-62-number>
demangleOptionalBinder()732*5f7ddb14SDimitry Andric void Demangler::demangleOptionalBinder() {
733*5f7ddb14SDimitry Andric uint64_t Binder = parseOptionalBase62Number('G');
734*5f7ddb14SDimitry Andric if (Error || Binder == 0)
735*5f7ddb14SDimitry Andric return;
736*5f7ddb14SDimitry Andric
737*5f7ddb14SDimitry Andric // In valid inputs each bound lifetime is referenced later. Referencing a
738*5f7ddb14SDimitry Andric // lifetime requires at least one byte of input. Reject inputs that are too
739*5f7ddb14SDimitry Andric // short to reference all bound lifetimes. Otherwise demangling of invalid
740*5f7ddb14SDimitry Andric // binders could generate excessive amounts of output.
741*5f7ddb14SDimitry Andric if (Binder >= Input.size() - BoundLifetimes) {
742*5f7ddb14SDimitry Andric Error = true;
743*5f7ddb14SDimitry Andric return;
744*5f7ddb14SDimitry Andric }
745*5f7ddb14SDimitry Andric
746*5f7ddb14SDimitry Andric print("for<");
747*5f7ddb14SDimitry Andric for (size_t I = 0; I != Binder; ++I) {
748*5f7ddb14SDimitry Andric BoundLifetimes += 1;
749*5f7ddb14SDimitry Andric if (I > 0)
750*5f7ddb14SDimitry Andric print(", ");
751*5f7ddb14SDimitry Andric printLifetime(1);
752*5f7ddb14SDimitry Andric }
753*5f7ddb14SDimitry Andric print("> ");
754*5f7ddb14SDimitry Andric }
755*5f7ddb14SDimitry Andric
756*5f7ddb14SDimitry Andric // <const> = <basic-type> <const-data>
757*5f7ddb14SDimitry Andric // | "p" // placeholder
758*5f7ddb14SDimitry Andric // | <backref>
demangleConst()759*5f7ddb14SDimitry Andric void Demangler::demangleConst() {
760*5f7ddb14SDimitry Andric if (Error || RecursionLevel >= MaxRecursionLevel) {
761*5f7ddb14SDimitry Andric Error = true;
762*5f7ddb14SDimitry Andric return;
763*5f7ddb14SDimitry Andric }
764*5f7ddb14SDimitry Andric SwapAndRestore<size_t> SaveRecursionLevel(RecursionLevel, RecursionLevel + 1);
765*5f7ddb14SDimitry Andric
766*5f7ddb14SDimitry Andric char C = consume();
767*5f7ddb14SDimitry Andric BasicType Type;
768*5f7ddb14SDimitry Andric if (parseBasicType(C, Type)) {
769*5f7ddb14SDimitry Andric switch (Type) {
770*5f7ddb14SDimitry Andric case BasicType::I8:
771*5f7ddb14SDimitry Andric case BasicType::I16:
772*5f7ddb14SDimitry Andric case BasicType::I32:
773*5f7ddb14SDimitry Andric case BasicType::I64:
774*5f7ddb14SDimitry Andric case BasicType::I128:
775*5f7ddb14SDimitry Andric case BasicType::ISize:
776*5f7ddb14SDimitry Andric case BasicType::U8:
777*5f7ddb14SDimitry Andric case BasicType::U16:
778*5f7ddb14SDimitry Andric case BasicType::U32:
779*5f7ddb14SDimitry Andric case BasicType::U64:
780*5f7ddb14SDimitry Andric case BasicType::U128:
781*5f7ddb14SDimitry Andric case BasicType::USize:
782*5f7ddb14SDimitry Andric demangleConstInt();
783*5f7ddb14SDimitry Andric break;
784*5f7ddb14SDimitry Andric case BasicType::Bool:
785*5f7ddb14SDimitry Andric demangleConstBool();
786*5f7ddb14SDimitry Andric break;
787*5f7ddb14SDimitry Andric case BasicType::Char:
788*5f7ddb14SDimitry Andric demangleConstChar();
789*5f7ddb14SDimitry Andric break;
790*5f7ddb14SDimitry Andric case BasicType::Placeholder:
791*5f7ddb14SDimitry Andric print('_');
792*5f7ddb14SDimitry Andric break;
793*5f7ddb14SDimitry Andric default:
794*5f7ddb14SDimitry Andric Error = true;
795*5f7ddb14SDimitry Andric break;
796*5f7ddb14SDimitry Andric }
797*5f7ddb14SDimitry Andric } else if (C == 'B') {
798*5f7ddb14SDimitry Andric demangleBackref([&] { demangleConst(); });
799*5f7ddb14SDimitry Andric } else {
800*5f7ddb14SDimitry Andric Error = true;
801*5f7ddb14SDimitry Andric }
802*5f7ddb14SDimitry Andric }
803*5f7ddb14SDimitry Andric
804*5f7ddb14SDimitry Andric // <const-data> = ["n"] <hex-number>
demangleConstInt()805*5f7ddb14SDimitry Andric void Demangler::demangleConstInt() {
806*5f7ddb14SDimitry Andric if (consumeIf('n'))
807*5f7ddb14SDimitry Andric print('-');
808*5f7ddb14SDimitry Andric
809*5f7ddb14SDimitry Andric StringView HexDigits;
810*5f7ddb14SDimitry Andric uint64_t Value = parseHexNumber(HexDigits);
811*5f7ddb14SDimitry Andric if (HexDigits.size() <= 16) {
812*5f7ddb14SDimitry Andric printDecimalNumber(Value);
813*5f7ddb14SDimitry Andric } else {
814*5f7ddb14SDimitry Andric print("0x");
815*5f7ddb14SDimitry Andric print(HexDigits);
816*5f7ddb14SDimitry Andric }
817*5f7ddb14SDimitry Andric }
818*5f7ddb14SDimitry Andric
819*5f7ddb14SDimitry Andric // <const-data> = "0_" // false
820*5f7ddb14SDimitry Andric // | "1_" // true
demangleConstBool()821*5f7ddb14SDimitry Andric void Demangler::demangleConstBool() {
822*5f7ddb14SDimitry Andric StringView HexDigits;
823*5f7ddb14SDimitry Andric parseHexNumber(HexDigits);
824*5f7ddb14SDimitry Andric if (HexDigits == "0")
825*5f7ddb14SDimitry Andric print("false");
826*5f7ddb14SDimitry Andric else if (HexDigits == "1")
827*5f7ddb14SDimitry Andric print("true");
828*5f7ddb14SDimitry Andric else
829*5f7ddb14SDimitry Andric Error = true;
830*5f7ddb14SDimitry Andric }
831*5f7ddb14SDimitry Andric
832*5f7ddb14SDimitry Andric /// Returns true if CodePoint represents a printable ASCII character.
isAsciiPrintable(uint64_t CodePoint)833*5f7ddb14SDimitry Andric static bool isAsciiPrintable(uint64_t CodePoint) {
834*5f7ddb14SDimitry Andric return 0x20 <= CodePoint && CodePoint <= 0x7e;
835*5f7ddb14SDimitry Andric }
836*5f7ddb14SDimitry Andric
837*5f7ddb14SDimitry Andric // <const-data> = <hex-number>
demangleConstChar()838*5f7ddb14SDimitry Andric void Demangler::demangleConstChar() {
839*5f7ddb14SDimitry Andric StringView HexDigits;
840*5f7ddb14SDimitry Andric uint64_t CodePoint = parseHexNumber(HexDigits);
841*5f7ddb14SDimitry Andric if (Error || HexDigits.size() > 6) {
842*5f7ddb14SDimitry Andric Error = true;
843*5f7ddb14SDimitry Andric return;
844*5f7ddb14SDimitry Andric }
845*5f7ddb14SDimitry Andric
846*5f7ddb14SDimitry Andric print("'");
847*5f7ddb14SDimitry Andric switch (CodePoint) {
848*5f7ddb14SDimitry Andric case '\t':
849*5f7ddb14SDimitry Andric print(R"(\t)");
850*5f7ddb14SDimitry Andric break;
851*5f7ddb14SDimitry Andric case '\r':
852*5f7ddb14SDimitry Andric print(R"(\r)");
853*5f7ddb14SDimitry Andric break;
854*5f7ddb14SDimitry Andric case '\n':
855*5f7ddb14SDimitry Andric print(R"(\n)");
856*5f7ddb14SDimitry Andric break;
857*5f7ddb14SDimitry Andric case '\\':
858*5f7ddb14SDimitry Andric print(R"(\\)");
859*5f7ddb14SDimitry Andric break;
860*5f7ddb14SDimitry Andric case '"':
861*5f7ddb14SDimitry Andric print(R"(")");
862*5f7ddb14SDimitry Andric break;
863*5f7ddb14SDimitry Andric case '\'':
864*5f7ddb14SDimitry Andric print(R"(\')");
865*5f7ddb14SDimitry Andric break;
866*5f7ddb14SDimitry Andric default:
867*5f7ddb14SDimitry Andric if (isAsciiPrintable(CodePoint)) {
868*5f7ddb14SDimitry Andric char C = CodePoint;
869*5f7ddb14SDimitry Andric print(C);
870*5f7ddb14SDimitry Andric } else {
871*5f7ddb14SDimitry Andric print(R"(\u{)");
872*5f7ddb14SDimitry Andric print(HexDigits);
873*5f7ddb14SDimitry Andric print('}');
874*5f7ddb14SDimitry Andric }
875*5f7ddb14SDimitry Andric break;
876*5f7ddb14SDimitry Andric }
877*5f7ddb14SDimitry Andric print('\'');
878*5f7ddb14SDimitry Andric }
879*5f7ddb14SDimitry Andric
880*5f7ddb14SDimitry Andric // <undisambiguated-identifier> = ["u"] <decimal-number> ["_"] <bytes>
parseIdentifier()881*5f7ddb14SDimitry Andric Identifier Demangler::parseIdentifier() {
882*5f7ddb14SDimitry Andric bool Punycode = consumeIf('u');
883*5f7ddb14SDimitry Andric uint64_t Bytes = parseDecimalNumber();
884*5f7ddb14SDimitry Andric
885*5f7ddb14SDimitry Andric // Underscore resolves the ambiguity when identifier starts with a decimal
886*5f7ddb14SDimitry Andric // digit or another underscore.
887*5f7ddb14SDimitry Andric consumeIf('_');
888*5f7ddb14SDimitry Andric
889*5f7ddb14SDimitry Andric if (Error || Bytes > Input.size() - Position) {
890*5f7ddb14SDimitry Andric Error = true;
891*5f7ddb14SDimitry Andric return {};
892*5f7ddb14SDimitry Andric }
893*5f7ddb14SDimitry Andric StringView S = Input.substr(Position, Bytes);
894*5f7ddb14SDimitry Andric Position += Bytes;
895*5f7ddb14SDimitry Andric
896*5f7ddb14SDimitry Andric if (!std::all_of(S.begin(), S.end(), isValid)) {
897*5f7ddb14SDimitry Andric Error = true;
898*5f7ddb14SDimitry Andric return {};
899*5f7ddb14SDimitry Andric }
900*5f7ddb14SDimitry Andric
901*5f7ddb14SDimitry Andric return {S, Punycode};
902*5f7ddb14SDimitry Andric }
903*5f7ddb14SDimitry Andric
904*5f7ddb14SDimitry Andric // Parses optional base 62 number. The presence of a number is determined using
905*5f7ddb14SDimitry Andric // Tag. Returns 0 when tag is absent and parsed value + 1 otherwise
906*5f7ddb14SDimitry Andric //
907*5f7ddb14SDimitry Andric // This function is indended for parsing disambiguators and binders which when
908*5f7ddb14SDimitry Andric // not present have their value interpreted as 0, and otherwise as decoded
909*5f7ddb14SDimitry Andric // value + 1. For example for binders, value for "G_" is 1, for "G0_" value is
910*5f7ddb14SDimitry Andric // 2. When "G" is absent value is 0.
parseOptionalBase62Number(char Tag)911*5f7ddb14SDimitry Andric uint64_t Demangler::parseOptionalBase62Number(char Tag) {
912*5f7ddb14SDimitry Andric if (!consumeIf(Tag))
913*5f7ddb14SDimitry Andric return 0;
914*5f7ddb14SDimitry Andric
915*5f7ddb14SDimitry Andric uint64_t N = parseBase62Number();
916*5f7ddb14SDimitry Andric if (Error || !addAssign(N, 1))
917*5f7ddb14SDimitry Andric return 0;
918*5f7ddb14SDimitry Andric
919*5f7ddb14SDimitry Andric return N;
920*5f7ddb14SDimitry Andric }
921*5f7ddb14SDimitry Andric
922*5f7ddb14SDimitry Andric // Parses base 62 number with <0-9a-zA-Z> as digits. Number is terminated by
923*5f7ddb14SDimitry Andric // "_". All values are offset by 1, so that "_" encodes 0, "0_" encodes 1,
924*5f7ddb14SDimitry Andric // "1_" encodes 2, etc.
925*5f7ddb14SDimitry Andric //
926*5f7ddb14SDimitry Andric // <base-62-number> = {<0-9a-zA-Z>} "_"
parseBase62Number()927*5f7ddb14SDimitry Andric uint64_t Demangler::parseBase62Number() {
928*5f7ddb14SDimitry Andric if (consumeIf('_'))
929*5f7ddb14SDimitry Andric return 0;
930*5f7ddb14SDimitry Andric
931*5f7ddb14SDimitry Andric uint64_t Value = 0;
932*5f7ddb14SDimitry Andric
933*5f7ddb14SDimitry Andric while (true) {
934*5f7ddb14SDimitry Andric uint64_t Digit;
935*5f7ddb14SDimitry Andric char C = consume();
936*5f7ddb14SDimitry Andric
937*5f7ddb14SDimitry Andric if (C == '_') {
938*5f7ddb14SDimitry Andric break;
939*5f7ddb14SDimitry Andric } else if (isDigit(C)) {
940*5f7ddb14SDimitry Andric Digit = C - '0';
941*5f7ddb14SDimitry Andric } else if (isLower(C)) {
942*5f7ddb14SDimitry Andric Digit = 10 + (C - 'a');
943*5f7ddb14SDimitry Andric } else if (isUpper(C)) {
944*5f7ddb14SDimitry Andric Digit = 10 + 26 + (C - 'A');
945*5f7ddb14SDimitry Andric } else {
946*5f7ddb14SDimitry Andric Error = true;
947*5f7ddb14SDimitry Andric return 0;
948*5f7ddb14SDimitry Andric }
949*5f7ddb14SDimitry Andric
950*5f7ddb14SDimitry Andric if (!mulAssign(Value, 62))
951*5f7ddb14SDimitry Andric return 0;
952*5f7ddb14SDimitry Andric
953*5f7ddb14SDimitry Andric if (!addAssign(Value, Digit))
954*5f7ddb14SDimitry Andric return 0;
955*5f7ddb14SDimitry Andric }
956*5f7ddb14SDimitry Andric
957*5f7ddb14SDimitry Andric if (!addAssign(Value, 1))
958*5f7ddb14SDimitry Andric return 0;
959*5f7ddb14SDimitry Andric
960*5f7ddb14SDimitry Andric return Value;
961*5f7ddb14SDimitry Andric }
962*5f7ddb14SDimitry Andric
963*5f7ddb14SDimitry Andric // Parses a decimal number that had been encoded without any leading zeros.
964*5f7ddb14SDimitry Andric //
965*5f7ddb14SDimitry Andric // <decimal-number> = "0"
966*5f7ddb14SDimitry Andric // | <1-9> {<0-9>}
parseDecimalNumber()967*5f7ddb14SDimitry Andric uint64_t Demangler::parseDecimalNumber() {
968*5f7ddb14SDimitry Andric char C = look();
969*5f7ddb14SDimitry Andric if (!isDigit(C)) {
970*5f7ddb14SDimitry Andric Error = true;
971*5f7ddb14SDimitry Andric return 0;
972*5f7ddb14SDimitry Andric }
973*5f7ddb14SDimitry Andric
974*5f7ddb14SDimitry Andric if (C == '0') {
975*5f7ddb14SDimitry Andric consume();
976*5f7ddb14SDimitry Andric return 0;
977*5f7ddb14SDimitry Andric }
978*5f7ddb14SDimitry Andric
979*5f7ddb14SDimitry Andric uint64_t Value = 0;
980*5f7ddb14SDimitry Andric
981*5f7ddb14SDimitry Andric while (isDigit(look())) {
982*5f7ddb14SDimitry Andric if (!mulAssign(Value, 10)) {
983*5f7ddb14SDimitry Andric Error = true;
984*5f7ddb14SDimitry Andric return 0;
985*5f7ddb14SDimitry Andric }
986*5f7ddb14SDimitry Andric
987*5f7ddb14SDimitry Andric uint64_t D = consume() - '0';
988*5f7ddb14SDimitry Andric if (!addAssign(Value, D))
989*5f7ddb14SDimitry Andric return 0;
990*5f7ddb14SDimitry Andric }
991*5f7ddb14SDimitry Andric
992*5f7ddb14SDimitry Andric return Value;
993*5f7ddb14SDimitry Andric }
994*5f7ddb14SDimitry Andric
995*5f7ddb14SDimitry Andric // Parses a hexadecimal number with <0-9a-f> as a digits. Returns the parsed
996*5f7ddb14SDimitry Andric // value and stores hex digits in HexDigits. The return value is unspecified if
997*5f7ddb14SDimitry Andric // HexDigits.size() > 16.
998*5f7ddb14SDimitry Andric //
999*5f7ddb14SDimitry Andric // <hex-number> = "0_"
1000*5f7ddb14SDimitry Andric // | <1-9a-f> {<0-9a-f>} "_"
parseHexNumber(StringView & HexDigits)1001*5f7ddb14SDimitry Andric uint64_t Demangler::parseHexNumber(StringView &HexDigits) {
1002*5f7ddb14SDimitry Andric size_t Start = Position;
1003*5f7ddb14SDimitry Andric uint64_t Value = 0;
1004*5f7ddb14SDimitry Andric
1005*5f7ddb14SDimitry Andric if (!isHexDigit(look()))
1006*5f7ddb14SDimitry Andric Error = true;
1007*5f7ddb14SDimitry Andric
1008*5f7ddb14SDimitry Andric if (consumeIf('0')) {
1009*5f7ddb14SDimitry Andric if (!consumeIf('_'))
1010*5f7ddb14SDimitry Andric Error = true;
1011*5f7ddb14SDimitry Andric } else {
1012*5f7ddb14SDimitry Andric while (!Error && !consumeIf('_')) {
1013*5f7ddb14SDimitry Andric char C = consume();
1014*5f7ddb14SDimitry Andric Value *= 16;
1015*5f7ddb14SDimitry Andric if (isDigit(C))
1016*5f7ddb14SDimitry Andric Value += C - '0';
1017*5f7ddb14SDimitry Andric else if ('a' <= C && C <= 'f')
1018*5f7ddb14SDimitry Andric Value += 10 + (C - 'a');
1019*5f7ddb14SDimitry Andric else
1020*5f7ddb14SDimitry Andric Error = true;
1021*5f7ddb14SDimitry Andric }
1022*5f7ddb14SDimitry Andric }
1023*5f7ddb14SDimitry Andric
1024*5f7ddb14SDimitry Andric if (Error) {
1025*5f7ddb14SDimitry Andric HexDigits = StringView();
1026*5f7ddb14SDimitry Andric return 0;
1027*5f7ddb14SDimitry Andric }
1028*5f7ddb14SDimitry Andric
1029*5f7ddb14SDimitry Andric size_t End = Position - 1;
1030*5f7ddb14SDimitry Andric assert(Start < End);
1031*5f7ddb14SDimitry Andric HexDigits = Input.substr(Start, End - Start);
1032*5f7ddb14SDimitry Andric return Value;
1033*5f7ddb14SDimitry Andric }
1034*5f7ddb14SDimitry Andric
print(char C)1035*5f7ddb14SDimitry Andric void Demangler::print(char C) {
1036*5f7ddb14SDimitry Andric if (Error || !Print)
1037*5f7ddb14SDimitry Andric return;
1038*5f7ddb14SDimitry Andric
1039*5f7ddb14SDimitry Andric Output += C;
1040*5f7ddb14SDimitry Andric }
1041*5f7ddb14SDimitry Andric
print(StringView S)1042*5f7ddb14SDimitry Andric void Demangler::print(StringView S) {
1043*5f7ddb14SDimitry Andric if (Error || !Print)
1044*5f7ddb14SDimitry Andric return;
1045*5f7ddb14SDimitry Andric
1046*5f7ddb14SDimitry Andric Output += S;
1047*5f7ddb14SDimitry Andric }
1048*5f7ddb14SDimitry Andric
printDecimalNumber(uint64_t N)1049*5f7ddb14SDimitry Andric void Demangler::printDecimalNumber(uint64_t N) {
1050*5f7ddb14SDimitry Andric if (Error || !Print)
1051*5f7ddb14SDimitry Andric return;
1052*5f7ddb14SDimitry Andric
1053*5f7ddb14SDimitry Andric Output << N;
1054*5f7ddb14SDimitry Andric }
1055*5f7ddb14SDimitry Andric
1056*5f7ddb14SDimitry Andric // Prints a lifetime. An index 0 always represents an erased lifetime. Indices
1057*5f7ddb14SDimitry Andric // starting from 1, are De Bruijn indices, referring to higher-ranked lifetimes
1058*5f7ddb14SDimitry Andric // bound by one of the enclosing binders.
printLifetime(uint64_t Index)1059*5f7ddb14SDimitry Andric void Demangler::printLifetime(uint64_t Index) {
1060*5f7ddb14SDimitry Andric if (Index == 0) {
1061*5f7ddb14SDimitry Andric print("'_");
1062*5f7ddb14SDimitry Andric return;
1063*5f7ddb14SDimitry Andric }
1064*5f7ddb14SDimitry Andric
1065*5f7ddb14SDimitry Andric if (Index - 1 >= BoundLifetimes) {
1066*5f7ddb14SDimitry Andric Error = true;
1067*5f7ddb14SDimitry Andric return;
1068*5f7ddb14SDimitry Andric }
1069*5f7ddb14SDimitry Andric
1070*5f7ddb14SDimitry Andric uint64_t Depth = BoundLifetimes - Index;
1071*5f7ddb14SDimitry Andric print('\'');
1072*5f7ddb14SDimitry Andric if (Depth < 26) {
1073*5f7ddb14SDimitry Andric char C = 'a' + Depth;
1074*5f7ddb14SDimitry Andric print(C);
1075*5f7ddb14SDimitry Andric } else {
1076*5f7ddb14SDimitry Andric print('z');
1077*5f7ddb14SDimitry Andric printDecimalNumber(Depth - 26 + 1);
1078*5f7ddb14SDimitry Andric }
1079*5f7ddb14SDimitry Andric }
1080*5f7ddb14SDimitry Andric
look() const1081*5f7ddb14SDimitry Andric char Demangler::look() const {
1082*5f7ddb14SDimitry Andric if (Error || Position >= Input.size())
1083*5f7ddb14SDimitry Andric return 0;
1084*5f7ddb14SDimitry Andric
1085*5f7ddb14SDimitry Andric return Input[Position];
1086*5f7ddb14SDimitry Andric }
1087*5f7ddb14SDimitry Andric
consume()1088*5f7ddb14SDimitry Andric char Demangler::consume() {
1089*5f7ddb14SDimitry Andric if (Error || Position >= Input.size()) {
1090*5f7ddb14SDimitry Andric Error = true;
1091*5f7ddb14SDimitry Andric return 0;
1092*5f7ddb14SDimitry Andric }
1093*5f7ddb14SDimitry Andric
1094*5f7ddb14SDimitry Andric return Input[Position++];
1095*5f7ddb14SDimitry Andric }
1096*5f7ddb14SDimitry Andric
consumeIf(char Prefix)1097*5f7ddb14SDimitry Andric bool Demangler::consumeIf(char Prefix) {
1098*5f7ddb14SDimitry Andric if (Error || Position >= Input.size() || Input[Position] != Prefix)
1099*5f7ddb14SDimitry Andric return false;
1100*5f7ddb14SDimitry Andric
1101*5f7ddb14SDimitry Andric Position += 1;
1102*5f7ddb14SDimitry Andric return true;
1103*5f7ddb14SDimitry Andric }
1104*5f7ddb14SDimitry Andric
1105*5f7ddb14SDimitry Andric /// Computes A + B. When computation wraps around sets the error and returns
1106*5f7ddb14SDimitry Andric /// false. Otherwise assigns the result to A and returns true.
addAssign(uint64_t & A,uint64_t B)1107*5f7ddb14SDimitry Andric bool Demangler::addAssign(uint64_t &A, uint64_t B) {
1108*5f7ddb14SDimitry Andric if (A > std::numeric_limits<uint64_t>::max() - B) {
1109*5f7ddb14SDimitry Andric Error = true;
1110*5f7ddb14SDimitry Andric return false;
1111*5f7ddb14SDimitry Andric }
1112*5f7ddb14SDimitry Andric
1113*5f7ddb14SDimitry Andric A += B;
1114*5f7ddb14SDimitry Andric return true;
1115*5f7ddb14SDimitry Andric }
1116*5f7ddb14SDimitry Andric
1117*5f7ddb14SDimitry Andric /// Computes A * B. When computation wraps around sets the error and returns
1118*5f7ddb14SDimitry Andric /// false. Otherwise assigns the result to A and returns true.
mulAssign(uint64_t & A,uint64_t B)1119*5f7ddb14SDimitry Andric bool Demangler::mulAssign(uint64_t &A, uint64_t B) {
1120*5f7ddb14SDimitry Andric if (B != 0 && A > std::numeric_limits<uint64_t>::max() / B) {
1121*5f7ddb14SDimitry Andric Error = true;
1122*5f7ddb14SDimitry Andric return false;
1123*5f7ddb14SDimitry Andric }
1124*5f7ddb14SDimitry Andric
1125*5f7ddb14SDimitry Andric A *= B;
1126*5f7ddb14SDimitry Andric return true;
1127*5f7ddb14SDimitry Andric }
1128