27using llvm::itanium_demangle::OutputBuffer;
28using llvm::itanium_demangle::ScopedOverride;
29using llvm::itanium_demangle::starts_with;
34 std::string_view Name;
37 bool empty()
const {
return Name.empty(); }
69enum class LeaveGenericsOpen {
76 size_t MaxRecursionLevel;
78 size_t RecursionLevel;
79 size_t BoundLifetimes;
81 std::string_view Input;
94 Demangler(
size_t MaxRecursionLevel = 500);
96 bool demangle(std::string_view MangledName);
99 bool demanglePath(IsInType
Type,
100 LeaveGenericsOpen LeaveOpen = LeaveGenericsOpen::No);
101 void demangleImplPath(IsInType InType);
102 void demangleGenericArg();
104 void demangleFnSig();
105 void demangleDynBounds();
106 void demangleDynTrait();
107 void demangleOptionalBinder();
108 void demangleConst();
109 void demangleConstInt();
110 void demangleConstBool();
111 void demangleConstChar();
113 template <
typename Callable>
void demangleBackref(Callable
Demangler) {
114 uint64_t Backref = parseBase62Number();
115 if (
Error || Backref >= Position) {
123 ScopedOverride<size_t> SavePosition(Position, Position);
129 uint64_t parseOptionalBase62Number(
char Tag);
130 uint64_t parseBase62Number();
131 uint64_t parseDecimalNumber();
132 uint64_t parseHexNumber(std::string_view &HexDigits);
135 void print(std::string_view S);
136 void printDecimalNumber(uint64_t
N);
137 void printBasicType(BasicType);
138 void printLifetime(uint64_t Index);
139 void printIdentifier(Identifier Ident);
143 bool consumeIf(
char Prefix);
145 bool addAssign(uint64_t &
A, uint64_t
B);
146 bool mulAssign(uint64_t &
A, uint64_t
B);
153 if (MangledName.empty() || !
starts_with(MangledName,
"_R"))
157 if (!
D.demangle(MangledName)) {
158 std::free(
D.Output.getBuffer());
164 return D.Output.getBuffer();
167Demangler::Demangler(
size_t MaxRecursionLevel)
168 : MaxRecursionLevel(MaxRecursionLevel) {}
170static inline bool isDigit(
const char C) {
return '0' <=
C &&
C <=
'9'; }
173 return (
'0' <=
C &&
C <=
'9') || (
'a' <=
C &&
C <=
'f');
176static inline bool isLower(
const char C) {
return 'a' <=
C &&
C <=
'z'; }
178static inline bool isUpper(
const char C) {
return 'A' <=
C &&
C <=
'Z'; }
190bool Demangler::demangle(std::string_view Mangled) {
202 size_t Dot =
Mangled.find(
'.');
203 Input = Dot == std::string_view::npos ?
Mangled :
Mangled.substr(0, Dot);
205 demanglePath(IsInType::No);
207 if (Position != Input.size()) {
208 ScopedOverride<bool> SavePrint(Print,
false);
209 demanglePath(IsInType::No);
212 if (Position != Input.size())
215 if (Dot != std::string_view::npos) {
241bool Demangler::demanglePath(IsInType InType, LeaveGenericsOpen LeaveOpen) {
242 if (
Error || RecursionLevel >= MaxRecursionLevel) {
246 ScopedOverride<size_t> SaveRecursionLevel(RecursionLevel, RecursionLevel + 1);
250 parseOptionalBase62Number(
's');
251 printIdentifier(parseIdentifier());
255 demangleImplPath(InType);
262 demangleImplPath(InType);
266 demanglePath(IsInType::Yes);
274 demanglePath(IsInType::Yes);
284 demanglePath(InType);
286 uint64_t Disambiguator = parseOptionalBase62Number(
's');
298 if (!Ident.empty()) {
300 printIdentifier(Ident);
303 printDecimalNumber(Disambiguator);
307 if (!Ident.empty()) {
309 printIdentifier(Ident);
315 demanglePath(InType);
317 if (InType == IsInType::No)
320 for (
size_t I = 0; !
Error && !consumeIf(
'E'); ++
I) {
323 demangleGenericArg();
325 if (LeaveOpen == LeaveGenericsOpen::Yes)
333 demangleBackref([&] { IsOpen = demanglePath(InType, LeaveOpen); });
346void Demangler::demangleImplPath(IsInType InType) {
347 ScopedOverride<bool> SavePrint(Print,
false);
348 parseOptionalBase62Number(
's');
349 demanglePath(InType);
356void Demangler::demangleGenericArg() {
358 printLifetime(parseBase62Number());
359 else if (consumeIf(
'K'))
389 Type = BasicType::I8;
392 Type = BasicType::Bool;
395 Type = BasicType::Char;
398 Type = BasicType::F64;
401 Type = BasicType::Str;
404 Type = BasicType::F32;
407 Type = BasicType::U8;
410 Type = BasicType::ISize;
413 Type = BasicType::USize;
416 Type = BasicType::I32;
419 Type = BasicType::U32;
422 Type = BasicType::I128;
425 Type = BasicType::U128;
428 Type = BasicType::Placeholder;
431 Type = BasicType::I16;
434 Type = BasicType::U16;
437 Type = BasicType::Unit;
440 Type = BasicType::Variadic;
443 Type = BasicType::I64;
446 Type = BasicType::U64;
449 Type = BasicType::Never;
456void Demangler::printBasicType(BasicType
Type) {
458 case BasicType::Bool:
461 case BasicType::Char:
476 case BasicType::I128:
479 case BasicType::ISize:
494 case BasicType::U128:
497 case BasicType::USize:
509 case BasicType::Placeholder:
512 case BasicType::Unit:
515 case BasicType::Variadic:
518 case BasicType::Never:
536void Demangler::demangleType() {
537 if (
Error || RecursionLevel >= MaxRecursionLevel) {
541 ScopedOverride<size_t> SaveRecursionLevel(RecursionLevel, RecursionLevel + 1);
543 size_t Start = Position;
547 return printBasicType(
Type);
565 for (; !
Error && !consumeIf(
'E'); ++
I) {
578 if (consumeIf(
'L')) {
579 if (
auto Lifetime = parseBase62Number()) {
580 printLifetime(Lifetime);
601 if (consumeIf(
'L')) {
602 if (
auto Lifetime = parseBase62Number()) {
604 printLifetime(Lifetime);
611 demangleBackref([&] { demangleType(); });
615 demanglePath(IsInType::Yes);
623void Demangler::demangleFnSig() {
624 ScopedOverride<size_t> SaveBoundLifetimes(BoundLifetimes, BoundLifetimes);
625 demangleOptionalBinder();
630 if (consumeIf(
'K')) {
632 if (consumeIf(
'C')) {
638 for (
char C : Ident.Name) {
649 for (
size_t I = 0; !
Error && !consumeIf(
'E'); ++
I) {
656 if (consumeIf(
'u')) {
665void Demangler::demangleDynBounds() {
666 ScopedOverride<size_t> SaveBoundLifetimes(BoundLifetimes, BoundLifetimes);
668 demangleOptionalBinder();
669 for (
size_t I = 0; !
Error && !consumeIf(
'E'); ++
I) {
678void Demangler::demangleDynTrait() {
679 bool IsOpen = demanglePath(IsInType::Yes, LeaveGenericsOpen::Yes);
680 while (!
Error && consumeIf(
'p')) {
687 print(parseIdentifier().Name);
698void Demangler::demangleOptionalBinder() {
699 uint64_t Binder = parseOptionalBase62Number(
'G');
700 if (
Error || Binder == 0)
707 if (Binder >= Input.size() - BoundLifetimes) {
713 for (
size_t I = 0;
I != Binder; ++
I) {
725void Demangler::demangleConst() {
726 if (
Error || RecursionLevel >= MaxRecursionLevel) {
730 ScopedOverride<size_t> SaveRecursionLevel(RecursionLevel, RecursionLevel + 1);
740 case BasicType::I128:
741 case BasicType::ISize:
746 case BasicType::U128:
747 case BasicType::USize:
750 case BasicType::Bool:
753 case BasicType::Char:
756 case BasicType::Placeholder:
763 }
else if (
C ==
'B') {
764 demangleBackref([&] { demangleConst(); });
771void Demangler::demangleConstInt() {
775 std::string_view HexDigits;
776 uint64_t
Value = parseHexNumber(HexDigits);
777 if (HexDigits.size() <= 16) {
778 printDecimalNumber(
Value);
787void Demangler::demangleConstBool() {
788 std::string_view HexDigits;
789 parseHexNumber(HexDigits);
790 if (HexDigits ==
"0")
792 else if (HexDigits ==
"1")
800 return 0x20 <= CodePoint && CodePoint <= 0x7e;
804void Demangler::demangleConstChar() {
805 std::string_view HexDigits;
806 uint64_t CodePoint = parseHexNumber(HexDigits);
807 if (
Error || HexDigits.size() > 6) {
848 bool Punycode = consumeIf(
'u');
849 uint64_t Bytes = parseDecimalNumber();
855 if (
Error || Bytes > Input.size() - Position) {
859 std::string_view S = Input.substr(Position, Bytes);
862 if (!std::all_of(S.begin(), S.end(),
isValid)) {
867 return {S, Punycode};
877uint64_t Demangler::parseOptionalBase62Number(
char Tag) {
881 uint64_t
N = parseBase62Number();
882 if (
Error || !addAssign(
N, 1))
893uint64_t Demangler::parseBase62Number() {
908 Digit = 10 + (
C -
'a');
910 Digit = 10 + 26 + (
C -
'A');
916 if (!mulAssign(
Value, 62))
919 if (!addAssign(
Value, Digit))
923 if (!addAssign(
Value, 1))
933uint64_t Demangler::parseDecimalNumber() {
948 if (!mulAssign(
Value, 10)) {
967uint64_t Demangler::parseHexNumber(std::string_view &HexDigits) {
968 size_t Start = Position;
974 if (consumeIf(
'0')) {
978 while (!
Error && !consumeIf(
'_')) {
983 else if (
'a' <=
C &&
C <=
'f')
991 HexDigits = std::string_view();
995 size_t End = Position - 1;
997 HexDigits = Input.substr(Start, End - Start);
1001void Demangler::print(
char C) {
1002 if (
Error || !Print)
1008void Demangler::print(std::string_view S) {
1009 if (
Error || !Print)
1015void Demangler::printDecimalNumber(uint64_t
N) {
1016 if (
Error || !Print)
1025void Demangler::printLifetime(uint64_t Index) {
1031 if (Index - 1 >= BoundLifetimes) {
1043 printDecimalNumber(
Depth - 26 + 1);
1063 char *Start = Buffer + StartIdx;
1071 if (0xD800 <= CodePoint && CodePoint <= 0xDFFF)
1074 if (CodePoint <= 0x7F) {
1075 Output[0] = CodePoint;
1079 if (CodePoint <= 0x7FF) {
1080 Output[0] = 0xC0 | ((CodePoint >> 6) & 0x3F);
1081 Output[1] = 0x80 | (CodePoint & 0x3F);
1085 if (CodePoint <= 0xFFFF) {
1086 Output[0] = 0xE0 | (CodePoint >> 12);
1087 Output[1] = 0x80 | ((CodePoint >> 6) & 0x3F);
1088 Output[2] = 0x80 | (CodePoint & 0x3F);
1092 if (CodePoint <= 0x10FFFF) {
1093 Output[0] = 0xF0 | (CodePoint >> 18);
1094 Output[1] = 0x80 | ((CodePoint >> 12) & 0x3F);
1095 Output[2] = 0x80 | ((CodePoint >> 6) & 0x3F);
1096 Output[3] = 0x80 | (CodePoint & 0x3F);
1107 size_t InputIdx = 0;
1110 size_t DelimiterPos = std::string_view::npos;
1111 for (
size_t I = 0;
I !=
Input.size(); ++
I)
1115 if (DelimiterPos != std::string_view::npos) {
1117 for (; InputIdx != DelimiterPos; ++InputIdx) {
1118 char C =
Input[InputIdx];
1123 Output += std::string_view(
UTF8, 4);
1137 auto Adapt = [&](
size_t Delta,
size_t NumPoints) {
1139 Delta += Delta / NumPoints;
1143 while (Delta > (
Base - TMin) * TMax / 2) {
1144 Delta /=
Base - TMin;
1147 return K + (((
Base - TMin + 1) * Delta) / (Delta + Skew));
1151 for (
size_t I = 0; InputIdx !=
Input.size();
I += 1) {
1154 size_t Max = std::numeric_limits<size_t>::max();
1155 for (
size_t K =
Base;
true; K +=
Base) {
1156 if (InputIdx ==
Input.size())
1158 char C =
Input[InputIdx++];
1163 if (Digit > (Max -
I) / W)
1170 else if (K >= Bias + TMax)
1178 if (W > Max / (
Base -
T))
1183 Bias = Adapt(
I - OldI, NumPoints);
1185 if (
I / NumPoints > Max -
N)
1201void Demangler::printIdentifier(Identifier Ident) {
1202 if (
Error || !Print)
1205 if (Ident.Punycode) {
1213char Demangler::look()
const {
1214 if (
Error || Position >= Input.size())
1217 return Input[Position];
1220char Demangler::consume() {
1221 if (
Error || Position >= Input.size()) {
1226 return Input[Position++];
1229bool Demangler::consumeIf(
char Prefix) {
1230 if (
Error || Position >= Input.size() || Input[Position] != Prefix)
1239bool Demangler::addAssign(uint64_t &
A, uint64_t
B) {
1240 if (
A > std::numeric_limits<uint64_t>::max() -
B) {
1251bool Demangler::mulAssign(uint64_t &
A, uint64_t
B) {
1252 if (
B != 0 &&
A > std::numeric_limits<uint64_t>::max() /
B) {
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static void print(raw_ostream &Out, object::Archive::Kind Kind, T Val)
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
itanium_demangle::ManglingParser< DefaultAllocator > Demangler
static bool isValid(const char C)
Returns true if C is a valid mangled character: <0-9a-zA-Z_>.
static bool decodePunycodeDigit(char C, size_t &Value)
static bool isAsciiPrintable(uint64_t CodePoint)
Returns true if CodePoint represents a printable ASCII character.
static void removeNullBytes(OutputBuffer &Output, size_t StartIdx)
static bool encodeUTF8(size_t CodePoint, char *Output)
static bool decodePunycode(std::string_view Input, OutputBuffer &Output)
static bool parseBasicType(char C, BasicType &Type)
void setCurrentPosition(size_t NewPos)
size_t getCurrentPosition() const
void insert(size_t Pos, const char *S, size_t N)
The instances of the Type class are immutable: once they are created, they are never changed.
LLVM Value Representation.
@ C
The default llvm calling convention, compatible with C.
Print(const T &, const DataFlowGraph &) -> Print< T >
This is an optimization pass for GlobalISel generic memory operations.
FunctionAddr VTableAddr Value
Printable print(const GCNRegPressure &RP, const GCNSubtarget *ST=nullptr, unsigned DynamicVGPRBlockSize=0)
bool isLower(char C)
Checks if character C is a lowercase letter as classified by "C" locale.
bool isUpper(char C)
Checks if character C is a uppercase letter as classified by "C" locale.
@ Never
Never set the bit.
bool isDigit(char C)
Checks if character C is one of the 10 decimal digits.
DEMANGLE_ABI char * rustDemangle(std::string_view MangledName)
bool isHexDigit(char C)
Checks if character C is a hexadecimal numeric character.
DEMANGLE_ABI std::string demangle(std::string_view MangledName)
Attempt to demangle a string using different demangling schemes.