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