diff options
author | Tomasz Miąsko <tomasz.miasko@gmail.com> | 2021-06-02 10:26:05 +0200 |
---|---|---|
committer | Tomasz Miąsko <tomasz.miasko@gmail.com> | 2021-06-02 10:36:45 +0200 |
commit | a67a234ec7aaf9b21dd70e56b128ab8d79092a78 (patch) | |
tree | 1acbc033d8e467f0c3c7ba040d660a8c30027ffe /llvm/lib/Demangle/RustDemangle.cpp | |
parent | 3b0a33d0ade8a6bacfb5a843f3263806cd12da0a (diff) | |
download | llvm-a67a234ec7aaf9b21dd70e56b128ab8d79092a78.zip llvm-a67a234ec7aaf9b21dd70e56b128ab8d79092a78.tar.gz llvm-a67a234ec7aaf9b21dd70e56b128ab8d79092a78.tar.bz2 |
[Demangle][Rust] Parse binders
Reviewed By: dblaikie
Differential Revision: https://reviews.llvm.org/D102729
Diffstat (limited to 'llvm/lib/Demangle/RustDemangle.cpp')
-rw-r--r-- | llvm/lib/Demangle/RustDemangle.cpp | 83 |
1 files changed, 73 insertions, 10 deletions
diff --git a/llvm/lib/Demangle/RustDemangle.cpp b/llvm/lib/Demangle/RustDemangle.cpp index d81ee33..d6cf78b 100644 --- a/llvm/lib/Demangle/RustDemangle.cpp +++ b/llvm/lib/Demangle/RustDemangle.cpp @@ -103,6 +103,7 @@ bool Demangler::demangle(StringView Mangled) { Error = false; Print = true; RecursionLevel = 0; + BoundLifetimes = 0; if (!Mangled.consumeFront("_R")) { Error = true; @@ -242,11 +243,12 @@ void Demangler::demangleImplPath(InType InType) { // | "K" <const> // <lifetime> = "L" <base-62-number> void Demangler::demangleGenericArg() { - if (consumeIf('K')) + if (consumeIf('L')) + printLifetime(parseBase62Number()); + else if (consumeIf('K')) demangleConst(); else demangleType(); - // FIXME demangle lifetimes. } // <basic-type> = "a" // i8 @@ -455,13 +457,16 @@ void Demangler::demangleType() { break; } case 'R': - print("&"); - // FIXME demangle [<lifetime>]. - demangleType(); - break; case 'Q': - print("&mut "); - // FIXME demangle [<lifetime>]. + print('&'); + if (consumeIf('L')) { + if (auto Lifetime = parseBase62Number()) { + printLifetime(Lifetime); + print(' '); + } + } + if (C == 'Q') + print("mut "); demangleType(); break; case 'P': @@ -486,7 +491,8 @@ void Demangler::demangleType() { // <abi> = "C" // | <undisambiguated-identifier> void Demangler::demangleFnSig() { - // FIXME demangle binder. + SwapAndRestore<size_t> SaveBoundLifetimes(BoundLifetimes, BoundLifetimes); + demangleOptionalBinder(); if (consumeIf('U')) print("unsafe "); @@ -523,6 +529,33 @@ void Demangler::demangleFnSig() { } } +// Demangles optional binder and updates the number of bound lifetimes. +// +// <binder> = "G" <base-62-number> +void Demangler::demangleOptionalBinder() { + uint64_t Binder = parseOptionalBase62Number('G'); + if (Error || Binder == 0) + return; + + // In valid inputs each bound lifetime is referenced later. Referencing a + // lifetime requires at least one byte of input. Reject inputs that are too + // short to reference all bound lifetimes. Otherwise demangling of invalid + // binders could generate excessive amounts of output. + if (Binder >= Input.size() - BoundLifetimes) { + Error = true; + return; + } + + print("for<"); + for (size_t I = 0; I != Binder; ++I) { + BoundLifetimes += 1; + if (I > 0) + print(", "); + printLifetime(1); + } + print("> "); +} + // <const> = <basic-type> <const-data> // | "p" // placeholder // | <backref> @@ -664,7 +697,12 @@ Identifier Demangler::parseIdentifier() { } // Parses optional base 62 number. The presence of a number is determined using -// Tag. Returns 0 when tag is absent and parsed value + 1 otherwise. +// Tag. Returns 0 when tag is absent and parsed value + 1 otherwise +// +// This function is indended for parsing disambiguators and binders which when +// not present have their value interpreted as 0, and otherwise as decoded +// value + 1. For example for binders, value for "G_" is 1, for "G0_" value is +// 2. When "G" is absent value is 0. uint64_t Demangler::parseOptionalBase62Number(char Tag) { if (!consumeIf(Tag)) return 0; @@ -788,3 +826,28 @@ uint64_t Demangler::parseHexNumber(StringView &HexDigits) { HexDigits = Input.substr(Start, End - Start); return Value; } + +// Prints a lifetime. An index 0 always represents an erased lifetime. Indices +// starting from 1, are De Bruijn indices, referring to higher-ranked lifetimes +// bound by one of the enclosing binders. +void Demangler::printLifetime(uint64_t Index) { + if (Index == 0) { + print("'_"); + return; + } + + if (Index - 1 >= BoundLifetimes) { + Error = true; + return; + } + + uint64_t Depth = BoundLifetimes - Index; + print('\''); + if (Depth < 26) { + char C = 'a' + Depth; + print(C); + } else { + print('z'); + printDecimalNumber(Depth - 26 + 1); + } +} |