LLVM  13.0.0git
RustDemangle.cpp
Go to the documentation of this file.
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 
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)
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)
38  return nullptr;
39  }
40 
41  Demangler D;
42  if (!initializeOutputStream(nullptr, nullptr, D.Output, 1024)) {
43  if (Status != nullptr)
45  return nullptr;
46  }
47 
48  if (!D.demangle(Mangled)) {
49  if (Status != nullptr)
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)
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.
222  print("::");
223  print("<");
224  for (size_t I = 0; !Error && !consumeIf('E'); ++I) {
225  if (I > 0)
226  print(", ");
227  demangleGenericArg();
228  }
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':
294  return true;
295  case 'b':
297  return true;
298  case 'c':
300  return true;
301  case 'd':
303  return true;
304  case 'e':
306  return true;
307  case 'f':
309  return true;
310  case 'h':
312  return true;
313  case 'i':
315  return true;
316  case 'j':
318  return true;
319  case 'l':
321  return true;
322  case 'm':
324  return true;
325  case 'n':
327  return true;
328  case 'o':
330  return true;
331  case 'p':
333  return true;
334  case 's':
336  return true;
337  case 't':
339  return true;
340  case 'u':
342  return true;
343  case 'v':
345  return true;
346  case 'x':
348  return true;
349  case 'y':
351  return true;
352  case 'z':
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;
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;
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 }
llvm::rust_demangle::BasicType::F64
@ F64
llvm
Definition: AllocatorList.h:23
llvm::rust_demangle::BasicType::U128
@ U128
llvm::rust_demangle::BasicType::U32
@ U32
llvm::rust_demangle::Demangler::Demangler
Demangler(size_t MaxRecursionLevel=500)
Definition: RustDemangle.cpp:78
llvm::Depth
@ Depth
Definition: SIMachineScheduler.h:34
llvm::Type
The instances of the Type class are immutable: once they are created, they are never changed.
Definition: Type.h:46
llvm::rust_demangle::BasicType::U16
@ U16
llvm::rust_demangle::InType
InType
Definition: RustDemangle.h:55
llvm::rust_demangle::Demangler::demangle
bool demangle(StringView MangledName)
Definition: RustDemangle.cpp:101
llvm::rust_demangle::BasicType::I32
@ I32
llvm::rust_demangle::BasicType::Unit
@ Unit
llvm::rust_demangle::BasicType::Bool
@ Bool
llvm::all_of
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
Definition: STLExtras.h:1482
llvm::rust_demangle::LeaveOpen
LeaveOpen
Definition: RustDemangle.h:60
llvm::rust_demangle::BasicType::F32
@ F32
llvm::rust_demangle::BasicType::Placeholder
@ Placeholder
llvm::rust_demangle::BasicType::Never
@ Never
parseBasicType
static bool parseBasicType(char C, BasicType &Type)
Definition: RustDemangle.cpp:290
llvm::rust_demangle::BasicType::I8
@ I8
C
(vector float) vec_cmpeq(*A, *B) C
Definition: README_ALTIVEC.txt:86
llvm::rust_demangle::BasicType::Str
@ Str
llvm::rust_demangle::BasicType::I128
@ I128
llvm::rust_demangle::Identifier::empty
bool empty() const
Definition: RustDemangle.h:28
llvm::rust_demangle::BasicType
BasicType
Definition: RustDemangle.h:31
isLower
static bool isLower(const char C)
Definition: RustDemangle.cpp:87
llvm::rust_demangle::BasicType::I16
@ I16
llvm::demangle_success
@ demangle_success
Definition: Demangle.h:28
llvm::demangle_invalid_args
@ demangle_invalid_args
Definition: Demangle.h:25
llvm::rust_demangle::BasicType::I64
@ I64
Index
uint32_t Index
Definition: ELFObjHandler.cpp:84
D
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
isAsciiPrintable
static bool isAsciiPrintable(uint64_t CodePoint)
Returns true if CodePoint represents a printable ASCII character.
Definition: RustDemangle.cpp:701
I
#define I(x, y, z)
Definition: MD5.cpp:59
llvm::rust_demangle::BasicType::USize
@ USize
llvm::rust_demangle::BasicType::Variadic
@ Variadic
llvm::rust_demangle::BasicType::Char
@ Char
assert
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
llvm::demangle_memory_alloc_failure
@ demangle_memory_alloc_failure
Definition: Demangle.h:27
memcpy
<%struct.s * > cast struct s *S to sbyte *< sbyte * > sbyte uint cast struct s *agg result to sbyte *< sbyte * > sbyte uint cast struct s *memtmp to sbyte *< sbyte * > sbyte uint ret void llc ends up issuing two memcpy or custom lower memcpy(of small size) to be ldmia/stmia. I think option 2 is better but the current register allocator cannot allocate a chunk of registers at a time. A feasible temporary solution is to use specific physical registers at the lowering time for small(<
llvm::rust_demangle::InType::Yes
@ Yes
Status
Definition: SIModeRegister.cpp:28
llvm::demangle_invalid_mangled_name
@ demangle_invalid_mangled_name
Definition: Demangle.h:26
llvm::rust_demangle::Identifier
Definition: RustDemangle.h:24
isDigit
static bool isDigit(const char C)
Definition: RustDemangle.cpp:81
Demangle.h
llvm::rust_demangle::LeaveOpen::Yes
@ Yes
llvm::rust_demangle::InType::No
@ No
S
add sub stmia L5 ldr r0 bl L_printf $stub Instead of a and a wouldn t it be better to do three moves *Return an aggregate type is even return S
Definition: README.txt:210
RustDemangle.h
llvm::GraphProgram::Name
Name
Definition: GraphWriter.h:52
llvm::Error
Lightweight error class with error context and mandatory checking.
Definition: Error.h:157
llvm::TargetStackID::Value
Value
Definition: TargetFrameLowering.h:27
llvm::rust_demangle::Identifier::Name
StringView Name
Definition: RustDemangle.h:25
llvm::rust_demangle::BasicType::ISize
@ ISize
llvm::rust_demangle::BasicType::U8
@ U8
isValid
static bool isValid(const char C)
Returns true if C is a valid mangled character: <0-9a-zA-Z_>.
Definition: RustDemangle.cpp:92
N
#define N
isHexDigit
static bool isHexDigit(const char C)
Definition: RustDemangle.cpp:83
isUpper
static bool isUpper(const char C)
Definition: RustDemangle.cpp:89
initializeOutputStream
bool initializeOutputStream(char *Buf, size_t *N, OutputStream &S, size_t InitSize)
Definition: Utility.h:174
llvm::Value
LLVM Value Representation.
Definition: Value.h:75
llvm::rust_demangle::Demangler
Definition: RustDemangle.h:65
llvm::rust_demangle::BasicType::U64
@ U64
llvm::rustDemangle
char * rustDemangle(const char *MangledName, char *Buf, size_t *N, int *Status)
Definition: RustDemangle.cpp:25