diff --git a/llvm/include/llvm/Demangle/RustDemangle.h b/llvm/include/llvm/Demangle/RustDemangle.h --- a/llvm/include/llvm/Demangle/RustDemangle.h +++ b/llvm/include/llvm/Demangle/RustDemangle.h @@ -54,11 +54,14 @@ void demanglePath(); void demangleGenericArg(); void demangleType(); + void demangleConst(); + void demangleConstInt(); Identifier parseIdentifier(); uint64_t parseOptionalBase62Number(char Tag); uint64_t parseBase62Number(); uint64_t parseDecimalNumber(); + uint64_t parseHexNumber(StringView &HexDigits); void print(char C) { if (Error) diff --git a/llvm/lib/Demangle/RustDemangle.cpp b/llvm/lib/Demangle/RustDemangle.cpp --- a/llvm/lib/Demangle/RustDemangle.cpp +++ b/llvm/lib/Demangle/RustDemangle.cpp @@ -200,8 +200,12 @@ // | "K" // = "L" void Demangler::demangleGenericArg() { - // FIXME parse remaining productions - demangleType(); + if (consumeIf('L')) + Error = true; // FIXME demangle lifetimes. + else if (consumeIf('K')) + demangleConst(); + else + demangleType(); } static const char *const BasicTypes[] = { @@ -281,6 +285,53 @@ } } +// = +// | "p" // placeholder +// | +// = ["n"] {} "_" +void Demangler::demangleConst() { + char Type = consume(); + switch (Type) { + case 'a': // i8 + case 'h': // u8 + case 'i': // isize + case 'j': // usize + case 'l': // i32 + case 'm': // u32 + case 'n': // i128 + case 'o': // u128 + case 's': // i16 + case 't': // u16 + case 'x': // i64 + case 'y': // u64 + demangleConstInt(); + break; + case 'p': // placeholder + print('_'); + break; + default: + // FIXME demangle backreferences, bool constants, and char constants. + Error = true; + break; + } +} + +void Demangler::demangleConstInt() { + bool IsNegative = consumeIf('n'); + StringView HexDigits; + uint64_t Value = parseHexNumber(HexDigits); + + if (IsNegative) + print('-'); + + if (HexDigits.size() <= 16) { + printDecimalNumber(Value); + } else { + print("0x"); + print(HexDigits); + } +} + // = ["u"] ["_"] Identifier Demangler::parseIdentifier() { bool Punycode = consumeIf('u'); @@ -390,3 +441,36 @@ return Value; } + +// Parses a hexadecimal number with <0-9a-f> as a digits. Returns the parsed +// value and stores hex digits in HexDigits. The resulting value might be not +// representable in uint64_t, so check the length of hex digits (<= 16), before +// using the returned value. +// +// = {<0-9a-f>} "_" +uint64_t Demangler::parseHexNumber(StringView &HexDigits) { + size_t Start = Position; + uint64_t Value = 0; + + 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) { + Value = 0; + HexDigits = StringView(); + return Value; + } + + assert(Start < Position); + size_t N = Position - 1 - Start; + HexDigits = Input.substr(Start, N); + return Value; +} diff --git a/llvm/test/Demangle/rust.test b/llvm/test/Demangle/rust.test --- a/llvm/test/Demangle/rust.test +++ b/llvm/test/Demangle/rust.test @@ -44,6 +44,11 @@ CHECK: generic::<_, _, _> _RIC7genericpppE +; Generic const arguments + +CHECK: generic_const::<_> + _RIC13generic_constKpE + ; Basic types CHECK: basic:: @@ -109,6 +114,76 @@ CHECK: basic:: _RIC5basiczE +; Integer constants. Test value demangling. + +CHECK: integer::<0> + _RIC7integerKi0_E + +CHECK: integer::<1> + _RIC7integerKi1_E + +CHECK: integer::<-1> + _RIC7integerKin1_E + +CHECK: integer::<-15> + _RIC7integerKinf_E + +CHECK: integer::<-16> + _RIC7integerKin10_E + +CHECK: integer::<-17> + _RIC7integerKin11_E + +CHECK: integer::<127> + _RIC7integerKi7f_E + +CHECK: integer::<18446744073709551615> + _RIC7integerKoffffffffffffffff_E + +CHECK: integer::<0x10000000000000000> + _RIC7integerKo10000000000000000_E + +CHECK: integer::<-0x123456789abcdef01> + _RIC7integerKnn123456789abcdef01_E + +; Integer constants. Test all integer types. + +CHECK: integer::<0, i8> + _RIC7integerKa0_aE + +CHECK: integer::<0, u8> + _RIC7integerKh0_hE + +CHECK: integer::<0, isize> + _RIC7integerKi0_iE + +CHECK: integer::<0, usize> + _RIC7integerKj0_jE + +CHECK: integer::<0, i32> + _RIC7integerKl0_lE + +CHECK: integer::<0, u32> + _RIC7integerKm0_mE + +CHECK: integer::<0, i128> + _RIC7integerKn0_nE + +CHECK: integer::<0, u128> + _RIC7integerKo0_oE + +CHECK: integer::<0, i16> + _RIC7integerKs0_sE + +CHECK: integer::<0, u16> + _RIC7integerKt0_tE + +CHECK: integer::<0, i64> + _RIC7integerKx0_xE + +CHECK: integer::<0, u64> + _RIC7integerKy0_yE + ; Invalid mangled characters CHECK: _RNvC2a.1c