diff options
author | Tomasz Miąsko <tomasz.miasko@gmail.com> | 2021-05-14 00:00:00 +0000 |
---|---|---|
committer | Tomasz Miąsko <tomasz.miasko@gmail.com> | 2021-05-14 19:47:19 +0200 |
commit | cd74dd178b98b658a61028df112dd4ca1a552561 (patch) | |
tree | 64b2691e9754a512e1adda0cb2ba67f798d0413c /llvm/lib/Demangle/RustDemangle.cpp | |
parent | 653fa0b46ae34c06495b542414b704b30381cd02 (diff) | |
download | llvm-cd74dd178b98b658a61028df112dd4ca1a552561.zip llvm-cd74dd178b98b658a61028df112dd4ca1a552561.tar.gz llvm-cd74dd178b98b658a61028df112dd4ca1a552561.tar.bz2 |
[Demangle][Rust] Parse integer constants
Reviewed By: dblaikie
Differential Revision: https://reviews.llvm.org/D102179
Diffstat (limited to 'llvm/lib/Demangle/RustDemangle.cpp')
-rw-r--r-- | llvm/lib/Demangle/RustDemangle.cpp | 274 |
1 files changed, 236 insertions, 38 deletions
diff --git a/llvm/lib/Demangle/RustDemangle.cpp b/llvm/lib/Demangle/RustDemangle.cpp index 2687978..1bc9d47 100644 --- a/llvm/lib/Demangle/RustDemangle.cpp +++ b/llvm/lib/Demangle/RustDemangle.cpp @@ -80,6 +80,10 @@ Demangler::Demangler(size_t MaxRecursionLevel) static inline bool isDigit(const char C) { return '0' <= C && C <= '9'; } +static inline bool isHexDigit(const char C) { + return ('0' <= C && C <= '9') || ('a' <= C && C <= 'f'); +} + static inline bool isLower(const char C) { return 'a' <= C && C <= 'z'; } static inline bool isUpper(const char C) { return 'A' <= C && C <= 'Z'; } @@ -200,39 +204,13 @@ void Demangler::demanglePath() { // | "K" <const> // <lifetime> = "L" <base-62-number> void Demangler::demangleGenericArg() { - // FIXME parse remaining productions - demangleType(); + if (consumeIf('K')) + demangleConst(); + else + demangleType(); + // FIXME demangle lifetimes. } -static const char *const BasicTypes[] = { - "i8", // a - "bool", // b - "char", // c - "f64", // d - "str", // e - "f32", // f - nullptr, // g - "u8", // h - "isize", // i - "usize", // j - nullptr, // k - "i32", // l - "u32", // m - "i128", // n - "u128", // o - "_", // p - nullptr, // q - nullptr, // r - "i16", // s - "u16", // t - "()", // u - "...", // v - nullptr, // w - "i64", // x - "u64", // y - "!", // z -}; - // <basic-type> = "a" // i8 // | "b" // bool // | "c" // char @@ -254,10 +232,142 @@ static const char *const BasicTypes[] = { // | "y" // u64 // | "z" // ! // | "p" // placeholder (e.g. for generic params), shown as _ -static const char *parseBasicType(char C) { - if (isLower(C)) - return BasicTypes[C - 'a']; - return nullptr; +static bool parseBasicType(char C, BasicType &Type) { + switch (C) { + case 'a': + Type = BasicType::I8; + return true; + case 'b': + Type = BasicType::Bool; + return true; + case 'c': + Type = BasicType::Char; + return true; + case 'd': + Type = BasicType::F64; + return true; + case 'e': + Type = BasicType::Str; + return true; + case 'f': + Type = BasicType::F32; + return true; + case 'h': + Type = BasicType::U8; + return true; + case 'i': + Type = BasicType::ISize; + return true; + case 'j': + Type = BasicType::USize; + return true; + case 'l': + Type = BasicType::I32; + return true; + case 'm': + Type = BasicType::U32; + return true; + case 'n': + Type = BasicType::I128; + return true; + case 'o': + Type = BasicType::U128; + return true; + case 'p': + Type = BasicType::Placeholder; + return true; + case 's': + Type = BasicType::I16; + return true; + case 't': + Type = BasicType::U16; + return true; + case 'u': + Type = BasicType::Unit; + return true; + case 'v': + Type = BasicType::Variadic; + return true; + case 'x': + Type = BasicType::I64; + return true; + case 'y': + Type = BasicType::U64; + return true; + case 'z': + Type = BasicType::Never; + return true; + default: + return false; + } +} + +void Demangler::printBasicType(BasicType Type) { + switch (Type) { + case BasicType::Bool: + print("bool"); + break; + case BasicType::Char: + print("char"); + break; + case BasicType::I8: + print("i8"); + break; + case BasicType::I16: + print("i16"); + break; + case BasicType::I32: + print("i32"); + break; + case BasicType::I64: + print("i64"); + break; + case BasicType::I128: + print("i128"); + break; + case BasicType::ISize: + print("isize"); + break; + case BasicType::U8: + print("u8"); + break; + case BasicType::U16: + print("u16"); + break; + case BasicType::U32: + print("u32"); + break; + case BasicType::U64: + print("u64"); + break; + case BasicType::U128: + print("u128"); + break; + case BasicType::USize: + print("usize"); + break; + case BasicType::F32: + print("f32"); + break; + case BasicType::F64: + print("f64"); + break; + case BasicType::Str: + print("str"); + break; + case BasicType::Placeholder: + print("_"); + break; + case BasicType::Unit: + print("()"); + break; + case BasicType::Variadic: + print("..."); + break; + case BasicType::Never: + print("!"); + break; + } } // <type> = | <basic-type> @@ -273,14 +383,62 @@ static const char *parseBasicType(char C) { // | "D" <dyn-bounds> <lifetime> // dyn Trait<Assoc = X> + Send + 'a // | <backref> // backref void Demangler::demangleType() { - if (const char *BasicType = parseBasicType(consume())) { - print(BasicType); + BasicType Type; + if (parseBasicType(consume(), Type)) + printBasicType(Type); + else + Error = true; // FIXME parse remaining productions. +} + +// <const> = <basic-type> <const-data> +// | "p" // placeholder +// | <backref> +void Demangler::demangleConst() { + BasicType Type; + if (parseBasicType(consume(), Type)) { + switch (Type) { + case BasicType::I8: + case BasicType::I16: + case BasicType::I32: + case BasicType::I64: + case BasicType::I128: + case BasicType::ISize: + case BasicType::U8: + case BasicType::U16: + case BasicType::U32: + case BasicType::U64: + case BasicType::U128: + case BasicType::USize: + demangleConstInt(); + break; + case BasicType::Placeholder: + print('_'); + break; + default: + // FIXME demangle backreferences, bool constants, and char constants. + Error = true; + break; + } } else { - // FIXME parse remaining productions. Error = true; } } +// <const-data> = ["n"] <hex-number> +void Demangler::demangleConstInt() { + if (consumeIf('n')) + print('-'); + + StringView HexDigits; + uint64_t Value = parseHexNumber(HexDigits); + if (HexDigits.size() <= 16) { + printDecimalNumber(Value); + } else { + print("0x"); + print(HexDigits); + } +} + // <undisambiguated-identifier> = ["u"] <decimal-number> ["_"] <bytes> Identifier Demangler::parseIdentifier() { bool Punycode = consumeIf('u'); @@ -390,3 +548,43 @@ uint64_t Demangler::parseDecimalNumber() { return Value; } + +// Parses a hexadecimal number with <0-9a-f> as a digits. Returns the parsed +// value and stores hex digits in HexDigits. The return value is unspecified if +// HexDigits.size() > 16. +// +// <hex-number> = "0_" +// | <1-9a-f> {<0-9a-f>} "_" +uint64_t Demangler::parseHexNumber(StringView &HexDigits) { + size_t Start = Position; + uint64_t Value = 0; + + if (!isHexDigit(look())) + Error = true; + + if (consumeIf('0')) { + if (!consumeIf('_')) + Error = true; + } else { + while (!Error && !consumeIf('_')) { + char C = consume(); + Value *= 16; + if (isDigit(C)) + Value += C - '0'; + else if ('a' <= C && C <= 'f') + Value += 10 + (C - 'a'); + else + Error = true; + } + } + + if (Error) { + HexDigits = StringView(); + return 0; + } + + size_t End = Position - 1; + assert(Start < End); + HexDigits = Input.substr(Start, End - Start); + return Value; +} |