1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-11-22 02:33:06 +01:00

[Demangle][Rust] Parse integer constants

Reviewed By: dblaikie

Differential Revision: https://reviews.llvm.org/D102179
This commit is contained in:
Tomasz Miąsko 2021-05-14 00:00:00 +00:00
parent 72f2c7d2ee
commit 19ed746cf3
3 changed files with 347 additions and 38 deletions

View File

@ -28,6 +28,30 @@ struct Identifier {
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,
};
class Demangler {
// Maximum recursion level. Used to avoid stack overflow.
size_t MaxRecursionLevel;
@ -54,11 +78,14 @@ private:
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)
@ -81,6 +108,8 @@ private:
Output << N;
}
void printBasicType(BasicType);
char look() const {
if (Error || Position >= Input.size())
return 0;

View File

@ -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;
}

View File

@ -44,6 +44,11 @@ CHECK: generic::<_, _>
CHECK: generic::<_, _, _>
_RIC7genericpppE
; Generic const arguments
CHECK: generic_const::<_>
_RIC13generic_constKpE
; Basic types
CHECK: basic::<i8>
@ -109,6 +114,83 @@ CHECK: basic::<u64>
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::<18446744073709551615>
_RIC7integerKoffffffffffffffff_E
CHECK: integer::<0x10000000000000000>
_RIC7integerKo10000000000000000_E
CHECK: integer::<-0x123456789abcdef01>
_RIC7integerKnn123456789abcdef01_E
; Invalid integer constant without any digits:
CHECK: _RIC7integerKi_E
_RIC7integerKi_E
; Invalid integer constants with insignificant leading zeros:
CHECK: _RIC7integerKi00_E
_RIC7integerKi00_E
CHECK: _RIC7integerKi01_E
_RIC7integerKi01_E
; Integer constants. Test all integer types.
CHECK: i8::<0>
_RIC2i8Ka0_E
CHECK: u8::<0>
_RIC2u8Kh0_E
CHECK: isize::<0>
_RIC5isizeKi0_E
CHECK: usize::<0>
_RIC5usizeKj0_E
CHECK: i32::<0>
_RIC3i32Kl0_E
CHECK: u32::<0>
_RIC3u32Km0_E
CHECK: i128::<0>
_RIC4i128Kn0_E
CHECK: u128::<0>
_RIC4u128Ko0_E
CHECK: i16::<0>
_RIC3i16Ks0_E
CHECK: u16::<0>
_RIC3u16Kt0_E
CHECK: i64::<0>
_RIC3i64Kx0_E
CHECK: u64::<0>
_RIC3u64Ky0_E
; Invalid mangled characters
CHECK: _RNvC2a.1c