diff options
author | Tomasz Miąsko <tomasz.miasko@gmail.com> | 2021-06-23 15:59:24 +0200 |
---|---|---|
committer | Tomasz Miąsko <tomasz.miasko@gmail.com> | 2021-06-23 18:28:16 +0200 |
commit | 6cc6ada143236f16faf8b383d73e00e709fa6a9f (patch) | |
tree | e60e7eae3096cfd311f7fb08bc7768f2a05aedda /llvm/lib/Demangle/RustDemangle.cpp | |
parent | b58dfd87da5cb19693764869a9a158f88c3d4bde (diff) | |
download | llvm-6cc6ada143236f16faf8b383d73e00e709fa6a9f.zip llvm-6cc6ada143236f16faf8b383d73e00e709fa6a9f.tar.gz llvm-6cc6ada143236f16faf8b383d73e00e709fa6a9f.tar.bz2 |
[Demangle][Rust] Hide implementation details NFC
Move content of the "public" header into the implementation file.
This also renames two enumerations that were previously used through
`rust_demangle::` scope, to avoid breaking a build bot with older
version of GCC that rejects uses of enumerator through `E::A` if there
is a variable with the same name as enumeration `E` in the scope.
Reviewed By: dblaikie
Differential Revision: https://reviews.llvm.org/D104362
Diffstat (limited to 'llvm/lib/Demangle/RustDemangle.cpp')
-rw-r--r-- | llvm/lib/Demangle/RustDemangle.cpp | 217 |
1 files changed, 205 insertions, 12 deletions
diff --git a/llvm/lib/Demangle/RustDemangle.cpp b/llvm/lib/Demangle/RustDemangle.cpp index 39db8fd..f916300 100644 --- a/llvm/lib/Demangle/RustDemangle.cpp +++ b/llvm/lib/Demangle/RustDemangle.cpp @@ -11,16 +11,140 @@ // //===----------------------------------------------------------------------===// -#include "llvm/Demangle/RustDemangle.h" #include "llvm/Demangle/Demangle.h" +#include "llvm/Demangle/StringView.h" +#include "llvm/Demangle/Utility.h" #include <algorithm> #include <cassert> +#include <cstdint> #include <cstring> #include <limits> using namespace llvm; -using namespace rust_demangle; + +using llvm::itanium_demangle::OutputStream; +using llvm::itanium_demangle::StringView; +using llvm::itanium_demangle::SwapAndRestore; + +namespace { + +struct Identifier { + StringView Name; + bool Punycode; + + bool empty() const { return Name.empty(); } +}; + +enum class BasicType { + Bool, + Char, + I8, + I16, + I32, + I64, + I128, + ISize, + U8, + U16, + U32, + U64, + U128, + USize, + F32, + F64, + Str, + Placeholder, + Unit, + Variadic, + Never, +}; + +enum class IsInType { + No, + Yes, +}; + +enum class LeaveGenericsOpen { + No, + Yes, +}; + +class Demangler { + // Maximum recursion level. Used to avoid stack overflow. + size_t MaxRecursionLevel; + // Current recursion level. + size_t RecursionLevel; + size_t BoundLifetimes; + // Input string that is being demangled with "_R" prefix removed. + StringView Input; + // Position in the input string. + size_t Position; + // When true, print methods append the output to the stream. + // When false, the output is suppressed. + bool Print; + // True if an error occurred. + bool Error; + +public: + // Demangled output. + OutputStream Output; + + Demangler(size_t MaxRecursionLevel = 500); + + bool demangle(StringView MangledName); + +private: + bool demanglePath(IsInType Type, + LeaveGenericsOpen LeaveOpen = LeaveGenericsOpen::No); + void demangleImplPath(IsInType InType); + void demangleGenericArg(); + void demangleType(); + void demangleFnSig(); + void demangleDynBounds(); + void demangleDynTrait(); + void demangleOptionalBinder(); + void demangleConst(); + void demangleConstInt(); + void demangleConstBool(); + void demangleConstChar(); + + template <typename Callable> void demangleBackref(Callable Demangler) { + uint64_t Backref = parseBase62Number(); + if (Error || Backref >= Position) { + Error = true; + return; + } + + if (!Print) + return; + + SwapAndRestore<size_t> SavePosition(Position, Position); + Position = Backref; + Demangler(); + } + + Identifier parseIdentifier(); + uint64_t parseOptionalBase62Number(char Tag); + uint64_t parseBase62Number(); + uint64_t parseDecimalNumber(); + uint64_t parseHexNumber(StringView &HexDigits); + + void print(char C); + void print(StringView S); + void printDecimalNumber(uint64_t N); + void printBasicType(BasicType); + void printLifetime(uint64_t Index); + + char look() const; + char consume(); + bool consumeIf(char Prefix); + + bool addAssign(uint64_t &A, uint64_t B); + bool mulAssign(uint64_t &A, uint64_t B); +}; + +} // namespace char *llvm::rustDemangle(const char *MangledName, char *Buf, size_t *N, int *Status) { @@ -113,11 +237,11 @@ bool Demangler::demangle(StringView Mangled) { Input = Mangled.substr(0, Dot); StringView Suffix = Mangled.dropFront(Dot); - demanglePath(rust_demangle::InType::No); + demanglePath(IsInType::No); if (Position != Input.size()) { SwapAndRestore<bool> SavePrint(Print, false); - demanglePath(InType::No); + demanglePath(IsInType::No); } if (Position != Input.size()) @@ -149,7 +273,7 @@ bool Demangler::demangle(StringView Mangled) { // | "S" // shim // | <A-Z> // other special namespaces // | <a-z> // internal namespaces -bool Demangler::demanglePath(InType InType, LeaveOpen LeaveOpen) { +bool Demangler::demanglePath(IsInType InType, LeaveGenericsOpen LeaveOpen) { if (Error || RecursionLevel >= MaxRecursionLevel) { Error = true; return false; @@ -175,7 +299,7 @@ bool Demangler::demanglePath(InType InType, LeaveOpen LeaveOpen) { print("<"); demangleType(); print(" as "); - demanglePath(rust_demangle::InType::Yes); + demanglePath(IsInType::Yes); print(">"); break; } @@ -183,7 +307,7 @@ bool Demangler::demanglePath(InType InType, LeaveOpen LeaveOpen) { print("<"); demangleType(); print(" as "); - demanglePath(rust_demangle::InType::Yes); + demanglePath(IsInType::Yes); print(">"); break; } @@ -226,7 +350,7 @@ bool Demangler::demanglePath(InType InType, LeaveOpen LeaveOpen) { case 'I': { demanglePath(InType); // Omit "::" when in a type, where it is optional. - if (InType == rust_demangle::InType::No) + if (InType == IsInType::No) print("::"); print("<"); for (size_t I = 0; !Error && !consumeIf('E'); ++I) { @@ -234,7 +358,7 @@ bool Demangler::demanglePath(InType InType, LeaveOpen LeaveOpen) { print(", "); demangleGenericArg(); } - if (LeaveOpen == rust_demangle::LeaveOpen::Yes) + if (LeaveOpen == LeaveGenericsOpen::Yes) return true; else print(">"); @@ -255,7 +379,7 @@ bool Demangler::demanglePath(InType InType, LeaveOpen LeaveOpen) { // <impl-path> = [<disambiguator>] <path> // <disambiguator> = "s" <base-62-number> -void Demangler::demangleImplPath(InType InType) { +void Demangler::demangleImplPath(IsInType InType) { SwapAndRestore<bool> SavePrint(Print, false); parseOptionalBase62Number('s'); demanglePath(InType); @@ -524,7 +648,7 @@ void Demangler::demangleType() { break; default: Position = Start; - demanglePath(rust_demangle::InType::Yes); + demanglePath(IsInType::Yes); break; } } @@ -586,7 +710,7 @@ void Demangler::demangleDynBounds() { // <dyn-trait> = <path> {<dyn-trait-assoc-binding>} // <dyn-trait-assoc-binding> = "p" <undisambiguated-identifier> <type> void Demangler::demangleDynTrait() { - bool IsOpen = demanglePath(InType::Yes, LeaveOpen::Yes); + bool IsOpen = demanglePath(IsInType::Yes, LeaveGenericsOpen::Yes); while (!Error && consumeIf('p')) { if (!IsOpen) { IsOpen = true; @@ -908,6 +1032,27 @@ uint64_t Demangler::parseHexNumber(StringView &HexDigits) { return Value; } +void Demangler::print(char C) { + if (Error || !Print) + return; + + Output += C; +} + +void Demangler::print(StringView S) { + if (Error || !Print) + return; + + Output += S; +} + +void Demangler::printDecimalNumber(uint64_t N) { + if (Error || !Print) + return; + + Output << N; +} + // 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. @@ -932,3 +1077,51 @@ void Demangler::printLifetime(uint64_t Index) { printDecimalNumber(Depth - 26 + 1); } } + +char Demangler::look() const { + if (Error || Position >= Input.size()) + return 0; + + return Input[Position]; +} + +char Demangler::consume() { + if (Error || Position >= Input.size()) { + Error = true; + return 0; + } + + return Input[Position++]; +} + +bool Demangler::consumeIf(char Prefix) { + if (Error || Position >= Input.size() || Input[Position] != Prefix) + return false; + + Position += 1; + return true; +} + +/// Computes A + B. When computation wraps around sets the error and returns +/// false. Otherwise assigns the result to A and returns true. +bool Demangler::addAssign(uint64_t &A, uint64_t B) { + if (A > std::numeric_limits<uint64_t>::max() - B) { + Error = true; + return false; + } + + A += B; + return true; +} + +/// Computes A * B. When computation wraps around sets the error and returns +/// false. Otherwise assigns the result to A and returns true. +bool Demangler::mulAssign(uint64_t &A, uint64_t B) { + if (B != 0 && A > std::numeric_limits<uint64_t>::max() / B) { + Error = true; + return false; + } + + A *= B; + return true; +} |