17310403eSTomasz Miąsko //===--- RustDemangle.cpp ---------------------------------------*- C++ -*-===// 27310403eSTomasz Miąsko // 37310403eSTomasz Miąsko // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 47310403eSTomasz Miąsko // See https://llvm.org/LICENSE.txt for license information. 57310403eSTomasz Miąsko // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 67310403eSTomasz Miąsko // 77310403eSTomasz Miąsko //===----------------------------------------------------------------------===// 87310403eSTomasz Miąsko // 97310403eSTomasz Miąsko // This file defines a demangler for Rust v0 mangled symbols as specified in 107310403eSTomasz Miąsko // https://rust-lang.github.io/rfcs/2603-rust-symbol-name-mangling-v0.html 117310403eSTomasz Miąsko // 127310403eSTomasz Miąsko //===----------------------------------------------------------------------===// 137310403eSTomasz Miąsko 147310403eSTomasz Miąsko #include "llvm/Demangle/RustDemangle.h" 157310403eSTomasz Miąsko #include "llvm/Demangle/Demangle.h" 167310403eSTomasz Miąsko 177310403eSTomasz Miąsko #include <algorithm> 187310403eSTomasz Miąsko #include <cassert> 197310403eSTomasz Miąsko #include <cstring> 207310403eSTomasz Miąsko #include <limits> 217310403eSTomasz Miąsko 227310403eSTomasz Miąsko using namespace llvm; 237310403eSTomasz Miąsko using namespace rust_demangle; 247310403eSTomasz Miąsko 257310403eSTomasz Miąsko char *llvm::rustDemangle(const char *MangledName, char *Buf, size_t *N, 267310403eSTomasz Miąsko int *Status) { 277310403eSTomasz Miąsko if (MangledName == nullptr || (Buf != nullptr && N == nullptr)) { 287310403eSTomasz Miąsko if (Status != nullptr) 297310403eSTomasz Miąsko *Status = demangle_invalid_args; 307310403eSTomasz Miąsko return nullptr; 317310403eSTomasz Miąsko } 327310403eSTomasz Miąsko 337310403eSTomasz Miąsko // Return early if mangled name doesn't look like a Rust symbol. 347310403eSTomasz Miąsko StringView Mangled(MangledName); 357310403eSTomasz Miąsko if (!Mangled.startsWith("_R")) { 367310403eSTomasz Miąsko if (Status != nullptr) 377310403eSTomasz Miąsko *Status = demangle_invalid_mangled_name; 387310403eSTomasz Miąsko return nullptr; 397310403eSTomasz Miąsko } 407310403eSTomasz Miąsko 417310403eSTomasz Miąsko Demangler D; 427310403eSTomasz Miąsko if (!initializeOutputStream(nullptr, nullptr, D.Output, 1024)) { 437310403eSTomasz Miąsko if (Status != nullptr) 447310403eSTomasz Miąsko *Status = demangle_memory_alloc_failure; 457310403eSTomasz Miąsko return nullptr; 467310403eSTomasz Miąsko } 477310403eSTomasz Miąsko 487310403eSTomasz Miąsko if (!D.demangle(Mangled)) { 497310403eSTomasz Miąsko if (Status != nullptr) 507310403eSTomasz Miąsko *Status = demangle_invalid_mangled_name; 517310403eSTomasz Miąsko std::free(D.Output.getBuffer()); 527310403eSTomasz Miąsko return nullptr; 537310403eSTomasz Miąsko } 547310403eSTomasz Miąsko 557310403eSTomasz Miąsko D.Output += '\0'; 567310403eSTomasz Miąsko char *Demangled = D.Output.getBuffer(); 577310403eSTomasz Miąsko size_t DemangledLen = D.Output.getCurrentPosition(); 587310403eSTomasz Miąsko 597310403eSTomasz Miąsko if (Buf != nullptr) { 607310403eSTomasz Miąsko if (DemangledLen <= *N) { 617310403eSTomasz Miąsko std::memcpy(Buf, Demangled, DemangledLen); 627310403eSTomasz Miąsko std::free(Demangled); 637310403eSTomasz Miąsko Demangled = Buf; 647310403eSTomasz Miąsko } else { 657310403eSTomasz Miąsko std::free(Buf); 667310403eSTomasz Miąsko } 677310403eSTomasz Miąsko } 687310403eSTomasz Miąsko 697310403eSTomasz Miąsko if (N != nullptr) 707310403eSTomasz Miąsko *N = DemangledLen; 717310403eSTomasz Miąsko 727310403eSTomasz Miąsko if (Status != nullptr) 737310403eSTomasz Miąsko *Status = demangle_success; 747310403eSTomasz Miąsko 757310403eSTomasz Miąsko return Demangled; 767310403eSTomasz Miąsko } 777310403eSTomasz Miąsko 787310403eSTomasz Miąsko Demangler::Demangler(size_t MaxRecursionLevel) 797310403eSTomasz Miąsko : MaxRecursionLevel(MaxRecursionLevel) {} 807310403eSTomasz Miąsko 817310403eSTomasz Miąsko static inline bool isDigit(const char C) { return '0' <= C && C <= '9'; } 827310403eSTomasz Miąsko 83cd74dd17STomasz Miąsko static inline bool isHexDigit(const char C) { 84cd74dd17STomasz Miąsko return ('0' <= C && C <= '9') || ('a' <= C && C <= 'f'); 85cd74dd17STomasz Miąsko } 86cd74dd17STomasz Miąsko 877310403eSTomasz Miąsko static inline bool isLower(const char C) { return 'a' <= C && C <= 'z'; } 887310403eSTomasz Miąsko 897310403eSTomasz Miąsko static inline bool isUpper(const char C) { return 'A' <= C && C <= 'Z'; } 907310403eSTomasz Miąsko 917310403eSTomasz Miąsko /// Returns true if C is a valid mangled character: <0-9a-zA-Z_>. 927310403eSTomasz Miąsko static inline bool isValid(const char C) { 937310403eSTomasz Miąsko return isDigit(C) || isLower(C) || isUpper(C) || C == '_'; 947310403eSTomasz Miąsko } 957310403eSTomasz Miąsko 967310403eSTomasz Miąsko // Demangles Rust v0 mangled symbol. Returns true when successful, and false 977310403eSTomasz Miąsko // otherwise. The demangled symbol is stored in Output field. It is 987310403eSTomasz Miąsko // responsibility of the caller to free the memory behind the output stream. 997310403eSTomasz Miąsko // 1007310403eSTomasz Miąsko // <symbol-name> = "_R" <path> [<instantiating-crate>] 1017310403eSTomasz Miąsko bool Demangler::demangle(StringView Mangled) { 1027310403eSTomasz Miąsko Position = 0; 1037310403eSTomasz Miąsko Error = false; 104f0f2a8b2STomasz Miąsko Print = true; 1057310403eSTomasz Miąsko RecursionLevel = 0; 106*a67a234eSTomasz Miąsko BoundLifetimes = 0; 1077310403eSTomasz Miąsko 1087310403eSTomasz Miąsko if (!Mangled.consumeFront("_R")) { 1097310403eSTomasz Miąsko Error = true; 1107310403eSTomasz Miąsko return false; 1117310403eSTomasz Miąsko } 1127310403eSTomasz Miąsko Input = Mangled; 1137310403eSTomasz Miąsko 11457f40886STomasz Miąsko demanglePath(rust_demangle::InType::No); 1157310403eSTomasz Miąsko 1167310403eSTomasz Miąsko // FIXME parse optional <instantiating-crate>. 1177310403eSTomasz Miąsko 1187310403eSTomasz Miąsko if (Position != Input.size()) 1197310403eSTomasz Miąsko Error = true; 1207310403eSTomasz Miąsko 1217310403eSTomasz Miąsko return !Error; 1227310403eSTomasz Miąsko } 1237310403eSTomasz Miąsko 12406833297STomasz Miąsko // Demangles a path. InType indicates whether a path is inside a type. 12506833297STomasz Miąsko // 1267310403eSTomasz Miąsko // <path> = "C" <identifier> // crate root 1277310403eSTomasz Miąsko // | "M" <impl-path> <type> // <T> (inherent impl) 1287310403eSTomasz Miąsko // | "X" <impl-path> <type> <path> // <T as Trait> (trait impl) 1297310403eSTomasz Miąsko // | "Y" <type> <path> // <T as Trait> (trait definition) 1307310403eSTomasz Miąsko // | "N" <ns> <path> <identifier> // ...::ident (nested path) 1317310403eSTomasz Miąsko // | "I" <path> {<generic-arg>} "E" // ...<T, U> (generic args) 1327310403eSTomasz Miąsko // | <backref> 1337310403eSTomasz Miąsko // <identifier> = [<disambiguator>] <undisambiguated-identifier> 1347310403eSTomasz Miąsko // <ns> = "C" // closure 1357310403eSTomasz Miąsko // | "S" // shim 1367310403eSTomasz Miąsko // | <A-Z> // other special namespaces 1377310403eSTomasz Miąsko // | <a-z> // internal namespaces 13806833297STomasz Miąsko void Demangler::demanglePath(InType InType) { 1397310403eSTomasz Miąsko if (Error || RecursionLevel >= MaxRecursionLevel) { 1407310403eSTomasz Miąsko Error = true; 1417310403eSTomasz Miąsko return; 1427310403eSTomasz Miąsko } 14378e94915STomasz Miąsko SwapAndRestore<size_t> SaveRecursionLevel(RecursionLevel, RecursionLevel + 1); 1447310403eSTomasz Miąsko 1457310403eSTomasz Miąsko switch (consume()) { 1467310403eSTomasz Miąsko case 'C': { 1477310403eSTomasz Miąsko parseOptionalBase62Number('s'); 1487310403eSTomasz Miąsko Identifier Ident = parseIdentifier(); 1497310403eSTomasz Miąsko print(Ident.Name); 1507310403eSTomasz Miąsko break; 1517310403eSTomasz Miąsko } 152f0f2a8b2STomasz Miąsko case 'M': { 15306833297STomasz Miąsko demangleImplPath(InType); 154f0f2a8b2STomasz Miąsko print("<"); 155f0f2a8b2STomasz Miąsko demangleType(); 156f0f2a8b2STomasz Miąsko print(">"); 157f0f2a8b2STomasz Miąsko break; 158f0f2a8b2STomasz Miąsko } 1599fa13800STomasz Miąsko case 'X': { 16006833297STomasz Miąsko demangleImplPath(InType); 1619fa13800STomasz Miąsko print("<"); 1629fa13800STomasz Miąsko demangleType(); 1639fa13800STomasz Miąsko print(" as "); 16457f40886STomasz Miąsko demanglePath(rust_demangle::InType::Yes); 1659fa13800STomasz Miąsko print(">"); 1669fa13800STomasz Miąsko break; 1679fa13800STomasz Miąsko } 168f933f7fbSTomasz Miąsko case 'Y': { 169f933f7fbSTomasz Miąsko print("<"); 170f933f7fbSTomasz Miąsko demangleType(); 171f933f7fbSTomasz Miąsko print(" as "); 17257f40886STomasz Miąsko demanglePath(rust_demangle::InType::Yes); 173f933f7fbSTomasz Miąsko print(">"); 174f933f7fbSTomasz Miąsko break; 175f933f7fbSTomasz Miąsko } 1767310403eSTomasz Miąsko case 'N': { 1777310403eSTomasz Miąsko char NS = consume(); 1787310403eSTomasz Miąsko if (!isLower(NS) && !isUpper(NS)) { 1797310403eSTomasz Miąsko Error = true; 1807310403eSTomasz Miąsko break; 1817310403eSTomasz Miąsko } 18206833297STomasz Miąsko demanglePath(InType); 1837310403eSTomasz Miąsko 18478e94915STomasz Miąsko uint64_t Disambiguator = parseOptionalBase62Number('s'); 1857310403eSTomasz Miąsko Identifier Ident = parseIdentifier(); 1867310403eSTomasz Miąsko 18778e94915STomasz Miąsko if (isUpper(NS)) { 18878e94915STomasz Miąsko // Special namespaces 18978e94915STomasz Miąsko print("::{"); 19078e94915STomasz Miąsko if (NS == 'C') 19178e94915STomasz Miąsko print("closure"); 19278e94915STomasz Miąsko else if (NS == 'S') 19378e94915STomasz Miąsko print("shim"); 19478e94915STomasz Miąsko else 19578e94915STomasz Miąsko print(NS); 1967310403eSTomasz Miąsko if (!Ident.empty()) { 19778e94915STomasz Miąsko print(":"); 19878e94915STomasz Miąsko print(Ident.Name); 19978e94915STomasz Miąsko } 20078e94915STomasz Miąsko print('#'); 20178e94915STomasz Miąsko printDecimalNumber(Disambiguator); 20278e94915STomasz Miąsko print('}'); 20378e94915STomasz Miąsko } else { 20478e94915STomasz Miąsko // Implementation internal namespaces. 20578e94915STomasz Miąsko if (!Ident.empty()) { 2067310403eSTomasz Miąsko print("::"); 2077310403eSTomasz Miąsko print(Ident.Name); 2087310403eSTomasz Miąsko } 20978e94915STomasz Miąsko } 2107310403eSTomasz Miąsko break; 2117310403eSTomasz Miąsko } 2122961f863STomasz Miąsko case 'I': { 21306833297STomasz Miąsko demanglePath(InType); 21406833297STomasz Miąsko // Omit "::" when in a type, where it is optional. 21557f40886STomasz Miąsko if (InType == rust_demangle::InType::No) 21606833297STomasz Miąsko print("::"); 21706833297STomasz Miąsko print("<"); 2182961f863STomasz Miąsko for (size_t I = 0; !Error && !consumeIf('E'); ++I) { 2192961f863STomasz Miąsko if (I > 0) 2202961f863STomasz Miąsko print(", "); 2212961f863STomasz Miąsko demangleGenericArg(); 2222961f863STomasz Miąsko } 2232961f863STomasz Miąsko print(">"); 2242961f863STomasz Miąsko break; 2252961f863STomasz Miąsko } 2267310403eSTomasz Miąsko default: 2277310403eSTomasz Miąsko // FIXME parse remaining productions. 2287310403eSTomasz Miąsko Error = true; 2297310403eSTomasz Miąsko break; 2307310403eSTomasz Miąsko } 2317310403eSTomasz Miąsko } 2327310403eSTomasz Miąsko 233f0f2a8b2STomasz Miąsko // <impl-path> = [<disambiguator>] <path> 234f0f2a8b2STomasz Miąsko // <disambiguator> = "s" <base-62-number> 23506833297STomasz Miąsko void Demangler::demangleImplPath(InType InType) { 236f0f2a8b2STomasz Miąsko SwapAndRestore<bool> SavePrint(Print, false); 237f0f2a8b2STomasz Miąsko parseOptionalBase62Number('s'); 23806833297STomasz Miąsko demanglePath(InType); 239f0f2a8b2STomasz Miąsko } 240f0f2a8b2STomasz Miąsko 2412961f863STomasz Miąsko // <generic-arg> = <lifetime> 2422961f863STomasz Miąsko // | <type> 2432961f863STomasz Miąsko // | "K" <const> 2442961f863STomasz Miąsko // <lifetime> = "L" <base-62-number> 2452961f863STomasz Miąsko void Demangler::demangleGenericArg() { 246*a67a234eSTomasz Miąsko if (consumeIf('L')) 247*a67a234eSTomasz Miąsko printLifetime(parseBase62Number()); 248*a67a234eSTomasz Miąsko else if (consumeIf('K')) 249cd74dd17STomasz Miąsko demangleConst(); 250cd74dd17STomasz Miąsko else 2512961f863STomasz Miąsko demangleType(); 2522961f863STomasz Miąsko } 2532961f863STomasz Miąsko 2542961f863STomasz Miąsko // <basic-type> = "a" // i8 2552961f863STomasz Miąsko // | "b" // bool 2562961f863STomasz Miąsko // | "c" // char 2572961f863STomasz Miąsko // | "d" // f64 2582961f863STomasz Miąsko // | "e" // str 2592961f863STomasz Miąsko // | "f" // f32 2602961f863STomasz Miąsko // | "h" // u8 2612961f863STomasz Miąsko // | "i" // isize 2622961f863STomasz Miąsko // | "j" // usize 2632961f863STomasz Miąsko // | "l" // i32 2642961f863STomasz Miąsko // | "m" // u32 2652961f863STomasz Miąsko // | "n" // i128 2662961f863STomasz Miąsko // | "o" // u128 2672961f863STomasz Miąsko // | "s" // i16 2682961f863STomasz Miąsko // | "t" // u16 2692961f863STomasz Miąsko // | "u" // () 2702961f863STomasz Miąsko // | "v" // ... 2712961f863STomasz Miąsko // | "x" // i64 2722961f863STomasz Miąsko // | "y" // u64 2732961f863STomasz Miąsko // | "z" // ! 2742961f863STomasz Miąsko // | "p" // placeholder (e.g. for generic params), shown as _ 275cd74dd17STomasz Miąsko static bool parseBasicType(char C, BasicType &Type) { 276cd74dd17STomasz Miąsko switch (C) { 277cd74dd17STomasz Miąsko case 'a': 278cd74dd17STomasz Miąsko Type = BasicType::I8; 279cd74dd17STomasz Miąsko return true; 280cd74dd17STomasz Miąsko case 'b': 281cd74dd17STomasz Miąsko Type = BasicType::Bool; 282cd74dd17STomasz Miąsko return true; 283cd74dd17STomasz Miąsko case 'c': 284cd74dd17STomasz Miąsko Type = BasicType::Char; 285cd74dd17STomasz Miąsko return true; 286cd74dd17STomasz Miąsko case 'd': 287cd74dd17STomasz Miąsko Type = BasicType::F64; 288cd74dd17STomasz Miąsko return true; 289cd74dd17STomasz Miąsko case 'e': 290cd74dd17STomasz Miąsko Type = BasicType::Str; 291cd74dd17STomasz Miąsko return true; 292cd74dd17STomasz Miąsko case 'f': 293cd74dd17STomasz Miąsko Type = BasicType::F32; 294cd74dd17STomasz Miąsko return true; 295cd74dd17STomasz Miąsko case 'h': 296cd74dd17STomasz Miąsko Type = BasicType::U8; 297cd74dd17STomasz Miąsko return true; 298cd74dd17STomasz Miąsko case 'i': 299cd74dd17STomasz Miąsko Type = BasicType::ISize; 300cd74dd17STomasz Miąsko return true; 301cd74dd17STomasz Miąsko case 'j': 302cd74dd17STomasz Miąsko Type = BasicType::USize; 303cd74dd17STomasz Miąsko return true; 304cd74dd17STomasz Miąsko case 'l': 305cd74dd17STomasz Miąsko Type = BasicType::I32; 306cd74dd17STomasz Miąsko return true; 307cd74dd17STomasz Miąsko case 'm': 308cd74dd17STomasz Miąsko Type = BasicType::U32; 309cd74dd17STomasz Miąsko return true; 310cd74dd17STomasz Miąsko case 'n': 311cd74dd17STomasz Miąsko Type = BasicType::I128; 312cd74dd17STomasz Miąsko return true; 313cd74dd17STomasz Miąsko case 'o': 314cd74dd17STomasz Miąsko Type = BasicType::U128; 315cd74dd17STomasz Miąsko return true; 316cd74dd17STomasz Miąsko case 'p': 317cd74dd17STomasz Miąsko Type = BasicType::Placeholder; 318cd74dd17STomasz Miąsko return true; 319cd74dd17STomasz Miąsko case 's': 320cd74dd17STomasz Miąsko Type = BasicType::I16; 321cd74dd17STomasz Miąsko return true; 322cd74dd17STomasz Miąsko case 't': 323cd74dd17STomasz Miąsko Type = BasicType::U16; 324cd74dd17STomasz Miąsko return true; 325cd74dd17STomasz Miąsko case 'u': 326cd74dd17STomasz Miąsko Type = BasicType::Unit; 327cd74dd17STomasz Miąsko return true; 328cd74dd17STomasz Miąsko case 'v': 329cd74dd17STomasz Miąsko Type = BasicType::Variadic; 330cd74dd17STomasz Miąsko return true; 331cd74dd17STomasz Miąsko case 'x': 332cd74dd17STomasz Miąsko Type = BasicType::I64; 333cd74dd17STomasz Miąsko return true; 334cd74dd17STomasz Miąsko case 'y': 335cd74dd17STomasz Miąsko Type = BasicType::U64; 336cd74dd17STomasz Miąsko return true; 337cd74dd17STomasz Miąsko case 'z': 338cd74dd17STomasz Miąsko Type = BasicType::Never; 339cd74dd17STomasz Miąsko return true; 340cd74dd17STomasz Miąsko default: 341cd74dd17STomasz Miąsko return false; 342cd74dd17STomasz Miąsko } 343cd74dd17STomasz Miąsko } 344cd74dd17STomasz Miąsko 345cd74dd17STomasz Miąsko void Demangler::printBasicType(BasicType Type) { 346cd74dd17STomasz Miąsko switch (Type) { 347cd74dd17STomasz Miąsko case BasicType::Bool: 348cd74dd17STomasz Miąsko print("bool"); 349cd74dd17STomasz Miąsko break; 350cd74dd17STomasz Miąsko case BasicType::Char: 351cd74dd17STomasz Miąsko print("char"); 352cd74dd17STomasz Miąsko break; 353cd74dd17STomasz Miąsko case BasicType::I8: 354cd74dd17STomasz Miąsko print("i8"); 355cd74dd17STomasz Miąsko break; 356cd74dd17STomasz Miąsko case BasicType::I16: 357cd74dd17STomasz Miąsko print("i16"); 358cd74dd17STomasz Miąsko break; 359cd74dd17STomasz Miąsko case BasicType::I32: 360cd74dd17STomasz Miąsko print("i32"); 361cd74dd17STomasz Miąsko break; 362cd74dd17STomasz Miąsko case BasicType::I64: 363cd74dd17STomasz Miąsko print("i64"); 364cd74dd17STomasz Miąsko break; 365cd74dd17STomasz Miąsko case BasicType::I128: 366cd74dd17STomasz Miąsko print("i128"); 367cd74dd17STomasz Miąsko break; 368cd74dd17STomasz Miąsko case BasicType::ISize: 369cd74dd17STomasz Miąsko print("isize"); 370cd74dd17STomasz Miąsko break; 371cd74dd17STomasz Miąsko case BasicType::U8: 372cd74dd17STomasz Miąsko print("u8"); 373cd74dd17STomasz Miąsko break; 374cd74dd17STomasz Miąsko case BasicType::U16: 375cd74dd17STomasz Miąsko print("u16"); 376cd74dd17STomasz Miąsko break; 377cd74dd17STomasz Miąsko case BasicType::U32: 378cd74dd17STomasz Miąsko print("u32"); 379cd74dd17STomasz Miąsko break; 380cd74dd17STomasz Miąsko case BasicType::U64: 381cd74dd17STomasz Miąsko print("u64"); 382cd74dd17STomasz Miąsko break; 383cd74dd17STomasz Miąsko case BasicType::U128: 384cd74dd17STomasz Miąsko print("u128"); 385cd74dd17STomasz Miąsko break; 386cd74dd17STomasz Miąsko case BasicType::USize: 387cd74dd17STomasz Miąsko print("usize"); 388cd74dd17STomasz Miąsko break; 389cd74dd17STomasz Miąsko case BasicType::F32: 390cd74dd17STomasz Miąsko print("f32"); 391cd74dd17STomasz Miąsko break; 392cd74dd17STomasz Miąsko case BasicType::F64: 393cd74dd17STomasz Miąsko print("f64"); 394cd74dd17STomasz Miąsko break; 395cd74dd17STomasz Miąsko case BasicType::Str: 396cd74dd17STomasz Miąsko print("str"); 397cd74dd17STomasz Miąsko break; 398cd74dd17STomasz Miąsko case BasicType::Placeholder: 399cd74dd17STomasz Miąsko print("_"); 400cd74dd17STomasz Miąsko break; 401cd74dd17STomasz Miąsko case BasicType::Unit: 402cd74dd17STomasz Miąsko print("()"); 403cd74dd17STomasz Miąsko break; 404cd74dd17STomasz Miąsko case BasicType::Variadic: 405cd74dd17STomasz Miąsko print("..."); 406cd74dd17STomasz Miąsko break; 407cd74dd17STomasz Miąsko case BasicType::Never: 408cd74dd17STomasz Miąsko print("!"); 409cd74dd17STomasz Miąsko break; 410cd74dd17STomasz Miąsko } 4112961f863STomasz Miąsko } 4122961f863STomasz Miąsko 4132961f863STomasz Miąsko // <type> = | <basic-type> 4142961f863STomasz Miąsko // | <path> // named type 4152961f863STomasz Miąsko // | "A" <type> <const> // [T; N] 4162961f863STomasz Miąsko // | "S" <type> // [T] 4172961f863STomasz Miąsko // | "T" {<type>} "E" // (T1, T2, T3, ...) 4182961f863STomasz Miąsko // | "R" [<lifetime>] <type> // &T 4192961f863STomasz Miąsko // | "Q" [<lifetime>] <type> // &mut T 4202961f863STomasz Miąsko // | "P" <type> // *const T 4212961f863STomasz Miąsko // | "O" <type> // *mut T 4222961f863STomasz Miąsko // | "F" <fn-sig> // fn(...) -> ... 4232961f863STomasz Miąsko // | "D" <dyn-bounds> <lifetime> // dyn Trait<Assoc = X> + Send + 'a 4242961f863STomasz Miąsko // | <backref> // backref 4252961f863STomasz Miąsko void Demangler::demangleType() { 426b42400ccSTomasz Miąsko size_t Start = Position; 42706833297STomasz Miąsko 428b42400ccSTomasz Miąsko char C = consume(); 429b42400ccSTomasz Miąsko BasicType Type; 430b42400ccSTomasz Miąsko if (parseBasicType(C, Type)) 431b42400ccSTomasz Miąsko return printBasicType(Type); 432b42400ccSTomasz Miąsko 433b42400ccSTomasz Miąsko switch (C) { 434b42400ccSTomasz Miąsko case 'A': 435b42400ccSTomasz Miąsko print("["); 436b42400ccSTomasz Miąsko demangleType(); 437b42400ccSTomasz Miąsko print("; "); 438b42400ccSTomasz Miąsko demangleConst(); 439b42400ccSTomasz Miąsko print("]"); 440b42400ccSTomasz Miąsko break; 441a84c65c2STomasz Miąsko case 'S': 442a84c65c2STomasz Miąsko print("["); 443a84c65c2STomasz Miąsko demangleType(); 444a84c65c2STomasz Miąsko print("]"); 445a84c65c2STomasz Miąsko break; 446774de7a0STomasz Miąsko case 'T': { 447774de7a0STomasz Miąsko print("("); 448774de7a0STomasz Miąsko size_t I = 0; 449774de7a0STomasz Miąsko for (; !Error && !consumeIf('E'); ++I) { 450774de7a0STomasz Miąsko if (I > 0) 451774de7a0STomasz Miąsko print(", "); 452774de7a0STomasz Miąsko demangleType(); 453774de7a0STomasz Miąsko } 454774de7a0STomasz Miąsko if (I == 1) 455774de7a0STomasz Miąsko print(","); 456774de7a0STomasz Miąsko print(")"); 457774de7a0STomasz Miąsko break; 458774de7a0STomasz Miąsko } 459e4fa6c95STomasz Miąsko case 'R': 460e4fa6c95STomasz Miąsko case 'Q': 461*a67a234eSTomasz Miąsko print('&'); 462*a67a234eSTomasz Miąsko if (consumeIf('L')) { 463*a67a234eSTomasz Miąsko if (auto Lifetime = parseBase62Number()) { 464*a67a234eSTomasz Miąsko printLifetime(Lifetime); 465*a67a234eSTomasz Miąsko print(' '); 466*a67a234eSTomasz Miąsko } 467*a67a234eSTomasz Miąsko } 468*a67a234eSTomasz Miąsko if (C == 'Q') 469*a67a234eSTomasz Miąsko print("mut "); 470e4fa6c95STomasz Miąsko demangleType(); 471e4fa6c95STomasz Miąsko break; 4726aac5633STomasz Miąsko case 'P': 4736aac5633STomasz Miąsko print("*const "); 4746aac5633STomasz Miąsko demangleType(); 4756aac5633STomasz Miąsko break; 4766aac5633STomasz Miąsko case 'O': 4776aac5633STomasz Miąsko print("*mut "); 4786aac5633STomasz Miąsko demangleType(); 4796aac5633STomasz Miąsko break; 48075cc1cf0STomasz Miąsko case 'F': 48175cc1cf0STomasz Miąsko demangleFnSig(); 48275cc1cf0STomasz Miąsko break; 483b42400ccSTomasz Miąsko default: 484b42400ccSTomasz Miąsko Position = Start; 48557f40886STomasz Miąsko demanglePath(rust_demangle::InType::Yes); 486b42400ccSTomasz Miąsko break; 487b42400ccSTomasz Miąsko } 488cd74dd17STomasz Miąsko } 489cd74dd17STomasz Miąsko 49075cc1cf0STomasz Miąsko // <fn-sig> := [<binder>] ["U"] ["K" <abi>] {<type>} "E" <type> 49175cc1cf0STomasz Miąsko // <abi> = "C" 49275cc1cf0STomasz Miąsko // | <undisambiguated-identifier> 49375cc1cf0STomasz Miąsko void Demangler::demangleFnSig() { 494*a67a234eSTomasz Miąsko SwapAndRestore<size_t> SaveBoundLifetimes(BoundLifetimes, BoundLifetimes); 495*a67a234eSTomasz Miąsko demangleOptionalBinder(); 49675cc1cf0STomasz Miąsko 49775cc1cf0STomasz Miąsko if (consumeIf('U')) 49875cc1cf0STomasz Miąsko print("unsafe "); 49975cc1cf0STomasz Miąsko 50075cc1cf0STomasz Miąsko if (consumeIf('K')) { 50175cc1cf0STomasz Miąsko print("extern \""); 50275cc1cf0STomasz Miąsko if (consumeIf('C')) { 50375cc1cf0STomasz Miąsko print("C"); 50475cc1cf0STomasz Miąsko } else { 50575cc1cf0STomasz Miąsko Identifier Ident = parseIdentifier(); 50675cc1cf0STomasz Miąsko for (char C : Ident.Name) { 50775cc1cf0STomasz Miąsko // When mangling ABI string, the "-" is replaced with "_". 50875cc1cf0STomasz Miąsko if (C == '_') 50975cc1cf0STomasz Miąsko C = '-'; 51075cc1cf0STomasz Miąsko print(C); 51175cc1cf0STomasz Miąsko } 51275cc1cf0STomasz Miąsko } 51375cc1cf0STomasz Miąsko print("\" "); 51475cc1cf0STomasz Miąsko } 51575cc1cf0STomasz Miąsko 51675cc1cf0STomasz Miąsko print("fn("); 51775cc1cf0STomasz Miąsko for (size_t I = 0; !Error && !consumeIf('E'); ++I) { 51875cc1cf0STomasz Miąsko if (I > 0) 51975cc1cf0STomasz Miąsko print(", "); 52075cc1cf0STomasz Miąsko demangleType(); 52175cc1cf0STomasz Miąsko } 52275cc1cf0STomasz Miąsko print(")"); 52375cc1cf0STomasz Miąsko 52475cc1cf0STomasz Miąsko if (consumeIf('u')) { 52575cc1cf0STomasz Miąsko // Skip the unit type from the output. 52675cc1cf0STomasz Miąsko } else { 52775cc1cf0STomasz Miąsko print(" -> "); 52875cc1cf0STomasz Miąsko demangleType(); 52975cc1cf0STomasz Miąsko } 53075cc1cf0STomasz Miąsko } 53175cc1cf0STomasz Miąsko 532*a67a234eSTomasz Miąsko // Demangles optional binder and updates the number of bound lifetimes. 533*a67a234eSTomasz Miąsko // 534*a67a234eSTomasz Miąsko // <binder> = "G" <base-62-number> 535*a67a234eSTomasz Miąsko void Demangler::demangleOptionalBinder() { 536*a67a234eSTomasz Miąsko uint64_t Binder = parseOptionalBase62Number('G'); 537*a67a234eSTomasz Miąsko if (Error || Binder == 0) 538*a67a234eSTomasz Miąsko return; 539*a67a234eSTomasz Miąsko 540*a67a234eSTomasz Miąsko // In valid inputs each bound lifetime is referenced later. Referencing a 541*a67a234eSTomasz Miąsko // lifetime requires at least one byte of input. Reject inputs that are too 542*a67a234eSTomasz Miąsko // short to reference all bound lifetimes. Otherwise demangling of invalid 543*a67a234eSTomasz Miąsko // binders could generate excessive amounts of output. 544*a67a234eSTomasz Miąsko if (Binder >= Input.size() - BoundLifetimes) { 545*a67a234eSTomasz Miąsko Error = true; 546*a67a234eSTomasz Miąsko return; 547*a67a234eSTomasz Miąsko } 548*a67a234eSTomasz Miąsko 549*a67a234eSTomasz Miąsko print("for<"); 550*a67a234eSTomasz Miąsko for (size_t I = 0; I != Binder; ++I) { 551*a67a234eSTomasz Miąsko BoundLifetimes += 1; 552*a67a234eSTomasz Miąsko if (I > 0) 553*a67a234eSTomasz Miąsko print(", "); 554*a67a234eSTomasz Miąsko printLifetime(1); 555*a67a234eSTomasz Miąsko } 556*a67a234eSTomasz Miąsko print("> "); 557*a67a234eSTomasz Miąsko } 558*a67a234eSTomasz Miąsko 559cd74dd17STomasz Miąsko // <const> = <basic-type> <const-data> 560cd74dd17STomasz Miąsko // | "p" // placeholder 561cd74dd17STomasz Miąsko // | <backref> 562cd74dd17STomasz Miąsko void Demangler::demangleConst() { 563cd74dd17STomasz Miąsko BasicType Type; 564cd74dd17STomasz Miąsko if (parseBasicType(consume(), Type)) { 565cd74dd17STomasz Miąsko switch (Type) { 566cd74dd17STomasz Miąsko case BasicType::I8: 567cd74dd17STomasz Miąsko case BasicType::I16: 568cd74dd17STomasz Miąsko case BasicType::I32: 569cd74dd17STomasz Miąsko case BasicType::I64: 570cd74dd17STomasz Miąsko case BasicType::I128: 571cd74dd17STomasz Miąsko case BasicType::ISize: 572cd74dd17STomasz Miąsko case BasicType::U8: 573cd74dd17STomasz Miąsko case BasicType::U16: 574cd74dd17STomasz Miąsko case BasicType::U32: 575cd74dd17STomasz Miąsko case BasicType::U64: 576cd74dd17STomasz Miąsko case BasicType::U128: 577cd74dd17STomasz Miąsko case BasicType::USize: 578cd74dd17STomasz Miąsko demangleConstInt(); 579cd74dd17STomasz Miąsko break; 580fc0f2bb9STomasz Miąsko case BasicType::Bool: 581fc0f2bb9STomasz Miąsko demangleConstBool(); 582fc0f2bb9STomasz Miąsko break; 5832ba49f6aSTomasz Miąsko case BasicType::Char: 5842ba49f6aSTomasz Miąsko demangleConstChar(); 5852ba49f6aSTomasz Miąsko break; 586cd74dd17STomasz Miąsko case BasicType::Placeholder: 587cd74dd17STomasz Miąsko print('_'); 588cd74dd17STomasz Miąsko break; 589cd74dd17STomasz Miąsko default: 5902ba49f6aSTomasz Miąsko // FIXME demangle backreferences. 5912961f863STomasz Miąsko Error = true; 592cd74dd17STomasz Miąsko break; 593cd74dd17STomasz Miąsko } 594cd74dd17STomasz Miąsko } else { 595cd74dd17STomasz Miąsko Error = true; 596cd74dd17STomasz Miąsko } 597cd74dd17STomasz Miąsko } 598cd74dd17STomasz Miąsko 599cd74dd17STomasz Miąsko // <const-data> = ["n"] <hex-number> 600cd74dd17STomasz Miąsko void Demangler::demangleConstInt() { 601cd74dd17STomasz Miąsko if (consumeIf('n')) 602cd74dd17STomasz Miąsko print('-'); 603cd74dd17STomasz Miąsko 604cd74dd17STomasz Miąsko StringView HexDigits; 605cd74dd17STomasz Miąsko uint64_t Value = parseHexNumber(HexDigits); 606cd74dd17STomasz Miąsko if (HexDigits.size() <= 16) { 607cd74dd17STomasz Miąsko printDecimalNumber(Value); 608cd74dd17STomasz Miąsko } else { 609cd74dd17STomasz Miąsko print("0x"); 610cd74dd17STomasz Miąsko print(HexDigits); 6112961f863STomasz Miąsko } 6122961f863STomasz Miąsko } 6132961f863STomasz Miąsko 614fc0f2bb9STomasz Miąsko // <const-data> = "0_" // false 615fc0f2bb9STomasz Miąsko // | "1_" // true 616fc0f2bb9STomasz Miąsko void Demangler::demangleConstBool() { 617fc0f2bb9STomasz Miąsko StringView HexDigits; 618fc0f2bb9STomasz Miąsko parseHexNumber(HexDigits); 619fc0f2bb9STomasz Miąsko if (HexDigits == "0") 620fc0f2bb9STomasz Miąsko print("false"); 621fc0f2bb9STomasz Miąsko else if (HexDigits == "1") 622fc0f2bb9STomasz Miąsko print("true"); 623fc0f2bb9STomasz Miąsko else 624fc0f2bb9STomasz Miąsko Error = true; 625fc0f2bb9STomasz Miąsko } 626fc0f2bb9STomasz Miąsko 6272ba49f6aSTomasz Miąsko /// Returns true if CodePoint represents a printable ASCII character. 6282ba49f6aSTomasz Miąsko static bool isAsciiPrintable(uint64_t CodePoint) { 6292ba49f6aSTomasz Miąsko return 0x20 <= CodePoint && CodePoint <= 0x7e; 6302ba49f6aSTomasz Miąsko } 6312ba49f6aSTomasz Miąsko 6322ba49f6aSTomasz Miąsko // <const-data> = <hex-number> 6332ba49f6aSTomasz Miąsko void Demangler::demangleConstChar() { 6342ba49f6aSTomasz Miąsko StringView HexDigits; 6352ba49f6aSTomasz Miąsko uint64_t CodePoint = parseHexNumber(HexDigits); 6362ba49f6aSTomasz Miąsko if (Error || HexDigits.size() > 6) { 6372ba49f6aSTomasz Miąsko Error = true; 6382ba49f6aSTomasz Miąsko return; 6392ba49f6aSTomasz Miąsko } 6402ba49f6aSTomasz Miąsko 6412ba49f6aSTomasz Miąsko print("'"); 6422ba49f6aSTomasz Miąsko switch (CodePoint) { 6432ba49f6aSTomasz Miąsko case '\t': 6442ba49f6aSTomasz Miąsko print(R"(\t)"); 6452ba49f6aSTomasz Miąsko break; 6462ba49f6aSTomasz Miąsko case '\r': 6472ba49f6aSTomasz Miąsko print(R"(\r)"); 6482ba49f6aSTomasz Miąsko break; 6492ba49f6aSTomasz Miąsko case '\n': 6502ba49f6aSTomasz Miąsko print(R"(\n)"); 6512ba49f6aSTomasz Miąsko break; 6522ba49f6aSTomasz Miąsko case '\\': 6532ba49f6aSTomasz Miąsko print(R"(\\)"); 6542ba49f6aSTomasz Miąsko break; 6552ba49f6aSTomasz Miąsko case '"': 6562ba49f6aSTomasz Miąsko print(R"(")"); 6572ba49f6aSTomasz Miąsko break; 6582ba49f6aSTomasz Miąsko case '\'': 6592ba49f6aSTomasz Miąsko print(R"(\')"); 6602ba49f6aSTomasz Miąsko break; 6612ba49f6aSTomasz Miąsko default: 6622ba49f6aSTomasz Miąsko if (isAsciiPrintable(CodePoint)) { 6632ba49f6aSTomasz Miąsko char C = CodePoint; 6642ba49f6aSTomasz Miąsko print(C); 6652ba49f6aSTomasz Miąsko } else { 6662ba49f6aSTomasz Miąsko print(R"(\u{)"); 6672ba49f6aSTomasz Miąsko print(HexDigits); 6682ba49f6aSTomasz Miąsko print('}'); 6692ba49f6aSTomasz Miąsko } 6702ba49f6aSTomasz Miąsko break; 6712ba49f6aSTomasz Miąsko } 6722ba49f6aSTomasz Miąsko print('\''); 6732ba49f6aSTomasz Miąsko } 6742ba49f6aSTomasz Miąsko 6757310403eSTomasz Miąsko // <undisambiguated-identifier> = ["u"] <decimal-number> ["_"] <bytes> 6767310403eSTomasz Miąsko Identifier Demangler::parseIdentifier() { 6777310403eSTomasz Miąsko bool Punycode = consumeIf('u'); 6787310403eSTomasz Miąsko uint64_t Bytes = parseDecimalNumber(); 6797310403eSTomasz Miąsko 6807310403eSTomasz Miąsko // Underscore resolves the ambiguity when identifier starts with a decimal 6817310403eSTomasz Miąsko // digit or another underscore. 6827310403eSTomasz Miąsko consumeIf('_'); 6837310403eSTomasz Miąsko 6847310403eSTomasz Miąsko if (Error || Bytes > Input.size() - Position) { 6857310403eSTomasz Miąsko Error = true; 6867310403eSTomasz Miąsko return {}; 6877310403eSTomasz Miąsko } 6887310403eSTomasz Miąsko StringView S = Input.substr(Position, Bytes); 6897310403eSTomasz Miąsko Position += Bytes; 6907310403eSTomasz Miąsko 6917310403eSTomasz Miąsko if (!std::all_of(S.begin(), S.end(), isValid)) { 6927310403eSTomasz Miąsko Error = true; 6937310403eSTomasz Miąsko return {}; 6947310403eSTomasz Miąsko } 6957310403eSTomasz Miąsko 6967310403eSTomasz Miąsko return {S, Punycode}; 6977310403eSTomasz Miąsko } 6987310403eSTomasz Miąsko 6997310403eSTomasz Miąsko // Parses optional base 62 number. The presence of a number is determined using 700*a67a234eSTomasz Miąsko // Tag. Returns 0 when tag is absent and parsed value + 1 otherwise 701*a67a234eSTomasz Miąsko // 702*a67a234eSTomasz Miąsko // This function is indended for parsing disambiguators and binders which when 703*a67a234eSTomasz Miąsko // not present have their value interpreted as 0, and otherwise as decoded 704*a67a234eSTomasz Miąsko // value + 1. For example for binders, value for "G_" is 1, for "G0_" value is 705*a67a234eSTomasz Miąsko // 2. When "G" is absent value is 0. 70678e94915STomasz Miąsko uint64_t Demangler::parseOptionalBase62Number(char Tag) { 70778e94915STomasz Miąsko if (!consumeIf(Tag)) 70878e94915STomasz Miąsko return 0; 70978e94915STomasz Miąsko 71078e94915STomasz Miąsko uint64_t N = parseBase62Number(); 71178e94915STomasz Miąsko if (Error || !addAssign(N, 1)) 71278e94915STomasz Miąsko return 0; 71378e94915STomasz Miąsko 71478e94915STomasz Miąsko return N; 7157310403eSTomasz Miąsko } 7167310403eSTomasz Miąsko 7177310403eSTomasz Miąsko // Parses base 62 number with <0-9a-zA-Z> as digits. Number is terminated by 7187310403eSTomasz Miąsko // "_". All values are offset by 1, so that "_" encodes 0, "0_" encodes 1, 7197310403eSTomasz Miąsko // "1_" encodes 2, etc. 7207310403eSTomasz Miąsko // 7217310403eSTomasz Miąsko // <base-62-number> = {<0-9a-zA-Z>} "_" 7227310403eSTomasz Miąsko uint64_t Demangler::parseBase62Number() { 7237310403eSTomasz Miąsko if (consumeIf('_')) 7247310403eSTomasz Miąsko return 0; 7257310403eSTomasz Miąsko 7267310403eSTomasz Miąsko uint64_t Value = 0; 7277310403eSTomasz Miąsko 7287310403eSTomasz Miąsko while (true) { 7297310403eSTomasz Miąsko uint64_t Digit; 7307310403eSTomasz Miąsko char C = consume(); 7317310403eSTomasz Miąsko 7327310403eSTomasz Miąsko if (C == '_') { 7337310403eSTomasz Miąsko break; 7347310403eSTomasz Miąsko } else if (isDigit(C)) { 7357310403eSTomasz Miąsko Digit = C - '0'; 7367310403eSTomasz Miąsko } else if (isLower(C)) { 7377310403eSTomasz Miąsko Digit = 10 + (C - 'a'); 7387310403eSTomasz Miąsko } else if (isUpper(C)) { 7397310403eSTomasz Miąsko Digit = 10 + 26 + (C - 'A'); 7407310403eSTomasz Miąsko } else { 7417310403eSTomasz Miąsko Error = true; 7427310403eSTomasz Miąsko return 0; 7437310403eSTomasz Miąsko } 7447310403eSTomasz Miąsko 7457310403eSTomasz Miąsko if (!mulAssign(Value, 62)) 7467310403eSTomasz Miąsko return 0; 7477310403eSTomasz Miąsko 7487310403eSTomasz Miąsko if (!addAssign(Value, Digit)) 7497310403eSTomasz Miąsko return 0; 7507310403eSTomasz Miąsko } 7517310403eSTomasz Miąsko 7527310403eSTomasz Miąsko if (!addAssign(Value, 1)) 7537310403eSTomasz Miąsko return 0; 7547310403eSTomasz Miąsko 7557310403eSTomasz Miąsko return Value; 7567310403eSTomasz Miąsko } 7577310403eSTomasz Miąsko 7587310403eSTomasz Miąsko // Parses a decimal number that had been encoded without any leading zeros. 7597310403eSTomasz Miąsko // 7607310403eSTomasz Miąsko // <decimal-number> = "0" 7617310403eSTomasz Miąsko // | <1-9> {<0-9>} 7627310403eSTomasz Miąsko uint64_t Demangler::parseDecimalNumber() { 7637310403eSTomasz Miąsko char C = look(); 7647310403eSTomasz Miąsko if (!isDigit(C)) { 7657310403eSTomasz Miąsko Error = true; 7667310403eSTomasz Miąsko return 0; 7677310403eSTomasz Miąsko } 7687310403eSTomasz Miąsko 7697310403eSTomasz Miąsko if (C == '0') { 7707310403eSTomasz Miąsko consume(); 7717310403eSTomasz Miąsko return 0; 7727310403eSTomasz Miąsko } 7737310403eSTomasz Miąsko 7747310403eSTomasz Miąsko uint64_t Value = 0; 7757310403eSTomasz Miąsko 7767310403eSTomasz Miąsko while (isDigit(look())) { 7777310403eSTomasz Miąsko if (!mulAssign(Value, 10)) { 7787310403eSTomasz Miąsko Error = true; 7797310403eSTomasz Miąsko return 0; 7807310403eSTomasz Miąsko } 7817310403eSTomasz Miąsko 7827310403eSTomasz Miąsko uint64_t D = consume() - '0'; 7837310403eSTomasz Miąsko if (!addAssign(Value, D)) 7847310403eSTomasz Miąsko return 0; 7857310403eSTomasz Miąsko } 7867310403eSTomasz Miąsko 7877310403eSTomasz Miąsko return Value; 7887310403eSTomasz Miąsko } 789cd74dd17STomasz Miąsko 790cd74dd17STomasz Miąsko // Parses a hexadecimal number with <0-9a-f> as a digits. Returns the parsed 791cd74dd17STomasz Miąsko // value and stores hex digits in HexDigits. The return value is unspecified if 792cd74dd17STomasz Miąsko // HexDigits.size() > 16. 793cd74dd17STomasz Miąsko // 794cd74dd17STomasz Miąsko // <hex-number> = "0_" 795cd74dd17STomasz Miąsko // | <1-9a-f> {<0-9a-f>} "_" 796cd74dd17STomasz Miąsko uint64_t Demangler::parseHexNumber(StringView &HexDigits) { 797cd74dd17STomasz Miąsko size_t Start = Position; 798cd74dd17STomasz Miąsko uint64_t Value = 0; 799cd74dd17STomasz Miąsko 800cd74dd17STomasz Miąsko if (!isHexDigit(look())) 801cd74dd17STomasz Miąsko Error = true; 802cd74dd17STomasz Miąsko 803cd74dd17STomasz Miąsko if (consumeIf('0')) { 804cd74dd17STomasz Miąsko if (!consumeIf('_')) 805cd74dd17STomasz Miąsko Error = true; 806cd74dd17STomasz Miąsko } else { 807cd74dd17STomasz Miąsko while (!Error && !consumeIf('_')) { 808cd74dd17STomasz Miąsko char C = consume(); 809cd74dd17STomasz Miąsko Value *= 16; 810cd74dd17STomasz Miąsko if (isDigit(C)) 811cd74dd17STomasz Miąsko Value += C - '0'; 812cd74dd17STomasz Miąsko else if ('a' <= C && C <= 'f') 813cd74dd17STomasz Miąsko Value += 10 + (C - 'a'); 814cd74dd17STomasz Miąsko else 815cd74dd17STomasz Miąsko Error = true; 816cd74dd17STomasz Miąsko } 817cd74dd17STomasz Miąsko } 818cd74dd17STomasz Miąsko 819cd74dd17STomasz Miąsko if (Error) { 820cd74dd17STomasz Miąsko HexDigits = StringView(); 821cd74dd17STomasz Miąsko return 0; 822cd74dd17STomasz Miąsko } 823cd74dd17STomasz Miąsko 824cd74dd17STomasz Miąsko size_t End = Position - 1; 825cd74dd17STomasz Miąsko assert(Start < End); 826cd74dd17STomasz Miąsko HexDigits = Input.substr(Start, End - Start); 827cd74dd17STomasz Miąsko return Value; 828cd74dd17STomasz Miąsko } 829*a67a234eSTomasz Miąsko 830*a67a234eSTomasz Miąsko // Prints a lifetime. An index 0 always represents an erased lifetime. Indices 831*a67a234eSTomasz Miąsko // starting from 1, are De Bruijn indices, referring to higher-ranked lifetimes 832*a67a234eSTomasz Miąsko // bound by one of the enclosing binders. 833*a67a234eSTomasz Miąsko void Demangler::printLifetime(uint64_t Index) { 834*a67a234eSTomasz Miąsko if (Index == 0) { 835*a67a234eSTomasz Miąsko print("'_"); 836*a67a234eSTomasz Miąsko return; 837*a67a234eSTomasz Miąsko } 838*a67a234eSTomasz Miąsko 839*a67a234eSTomasz Miąsko if (Index - 1 >= BoundLifetimes) { 840*a67a234eSTomasz Miąsko Error = true; 841*a67a234eSTomasz Miąsko return; 842*a67a234eSTomasz Miąsko } 843*a67a234eSTomasz Miąsko 844*a67a234eSTomasz Miąsko uint64_t Depth = BoundLifetimes - Index; 845*a67a234eSTomasz Miąsko print('\''); 846*a67a234eSTomasz Miąsko if (Depth < 26) { 847*a67a234eSTomasz Miąsko char C = 'a' + Depth; 848*a67a234eSTomasz Miąsko print(C); 849*a67a234eSTomasz Miąsko } else { 850*a67a234eSTomasz Miąsko print('z'); 851*a67a234eSTomasz Miąsko printDecimalNumber(Depth - 26 + 1); 852*a67a234eSTomasz Miąsko } 853*a67a234eSTomasz Miąsko } 854