26 using llvm::itanium_demangle::OutputBuffer;
27 using llvm::itanium_demangle::ScopedOverride;
28 using llvm::itanium_demangle::StringView;
36 bool empty()
const {
return Name.empty(); }
39 enum class BasicType {
68 enum class LeaveGenericsOpen {
75 size_t MaxRecursionLevel;
77 size_t RecursionLevel;
78 size_t BoundLifetimes;
93 Demangler(
size_t MaxRecursionLevel = 500);
95 bool demangle(StringView MangledName);
98 bool demanglePath(IsInType
Type,
99 LeaveGenericsOpen LeaveOpen = LeaveGenericsOpen::No);
100 void demangleImplPath(IsInType InType);
101 void demangleGenericArg();
103 void demangleFnSig();
104 void demangleDynBounds();
105 void demangleDynTrait();
106 void demangleOptionalBinder();
107 void demangleConst();
108 void demangleConstInt();
109 void demangleConstBool();
110 void demangleConstChar();
112 template <
typename Callable>
void demangleBackref(Callable
Demangler) {
113 uint64_t Backref = parseBase62Number();
114 if (
Error || Backref >= Position) {
122 ScopedOverride<size_t> SavePosition(Position, Position);
131 uint64_t parseHexNumber(StringView &HexDigits);
136 void printBasicType(BasicType);
138 void printIdentifier(Identifier Ident);
142 bool consumeIf(
char Prefix);
151 if (MangledName ==
nullptr)
155 StringView Mangled(MangledName);
156 if (!Mangled.startsWith(
"_R"))
163 if (!
D.demangle(Mangled)) {
164 std::free(
D.Output.getBuffer());
170 return D.Output.getBuffer();
174 : MaxRecursionLevel(MaxRecursionLevel) {}
176 static inline bool isDigit(
const char C) {
return '0' <=
C &&
C <=
'9'; }
179 return (
'0' <=
C &&
C <=
'9') || (
'a' <=
C &&
C <=
'f');
182 static inline bool isLower(
const char C) {
return 'a' <=
C &&
C <=
'z'; }
184 static inline bool isUpper(
const char C) {
return 'A' <=
C &&
C <=
'Z'; }
203 if (!Mangled.consumeFront(
"_R")) {
207 size_t Dot = Mangled.find(
'.');
208 Input = Mangled.substr(0, Dot);
209 StringView Suffix = Mangled.dropFront(Dot);
211 demanglePath(IsInType::No);
213 if (Position !=
Input.size()) {
214 ScopedOverride<bool> SavePrint(Print,
false);
215 demanglePath(IsInType::No);
218 if (Position !=
Input.size())
221 if (!Suffix.empty()) {
247 bool Demangler::demanglePath(IsInType InType, LeaveGenericsOpen LeaveOpen) {
248 if (
Error || RecursionLevel >= MaxRecursionLevel) {
252 ScopedOverride<size_t> SaveRecursionLevel(RecursionLevel, RecursionLevel + 1);
256 parseOptionalBase62Number(
's');
257 printIdentifier(parseIdentifier());
261 demangleImplPath(InType);
268 demangleImplPath(InType);
272 demanglePath(IsInType::Yes);
280 demanglePath(IsInType::Yes);
290 demanglePath(InType);
292 uint64_t Disambiguator = parseOptionalBase62Number(
's');
304 if (!Ident.empty()) {
306 printIdentifier(Ident);
309 printDecimalNumber(Disambiguator);
313 if (!Ident.empty()) {
315 printIdentifier(Ident);
321 demanglePath(InType);
323 if (InType == IsInType::No)
326 for (
size_t I = 0; !
Error && !consumeIf(
'E'); ++
I) {
329 demangleGenericArg();
331 if (LeaveOpen == LeaveGenericsOpen::Yes)
339 demangleBackref([&] { IsOpen = demanglePath(InType, LeaveOpen); });
352 void Demangler::demangleImplPath(IsInType InType) {
353 ScopedOverride<bool> SavePrint(Print,
false);
354 parseOptionalBase62Number(
's');
355 demanglePath(InType);
362 void Demangler::demangleGenericArg() {
364 printLifetime(parseBase62Number());
365 else if (consumeIf(
'K'))
401 Type = BasicType::Char;
404 Type = BasicType::F64;
407 Type = BasicType::Str;
410 Type = BasicType::F32;
413 Type = BasicType::U8;
416 Type = BasicType::ISize;
419 Type = BasicType::USize;
425 Type = BasicType::U32;
428 Type = BasicType::I128;
431 Type = BasicType::U128;
434 Type = BasicType::Placeholder;
440 Type = BasicType::U16;
443 Type = BasicType::Unit;
455 Type = BasicType::Never;
462 void Demangler::printBasicType(BasicType
Type) {
467 case BasicType::Char:
482 case BasicType::I128:
485 case BasicType::ISize:
500 case BasicType::U128:
503 case BasicType::USize:
515 case BasicType::Placeholder:
518 case BasicType::Unit:
524 case BasicType::Never:
542 void Demangler::demangleType() {
543 if (
Error || RecursionLevel >= MaxRecursionLevel) {
547 ScopedOverride<size_t> SaveRecursionLevel(RecursionLevel, RecursionLevel + 1);
549 size_t Start = Position;
553 return printBasicType(
Type);
571 for (; !
Error && !consumeIf(
'E'); ++
I) {
584 if (consumeIf(
'L')) {
585 if (
auto Lifetime = parseBase62Number()) {
586 printLifetime(Lifetime);
607 if (consumeIf(
'L')) {
608 if (
auto Lifetime = parseBase62Number()) {
610 printLifetime(Lifetime);
617 demangleBackref([&] { demangleType(); });
621 demanglePath(IsInType::Yes);
629 void Demangler::demangleFnSig() {
630 ScopedOverride<size_t> SaveBoundLifetimes(BoundLifetimes, BoundLifetimes);
631 demangleOptionalBinder();
636 if (consumeIf(
'K')) {
638 if (consumeIf(
'C')) {
644 for (
char C : Ident.Name) {
655 for (
size_t I = 0; !
Error && !consumeIf(
'E'); ++
I) {
662 if (consumeIf(
'u')) {
671 void Demangler::demangleDynBounds() {
672 ScopedOverride<size_t> SaveBoundLifetimes(BoundLifetimes, BoundLifetimes);
674 demangleOptionalBinder();
675 for (
size_t I = 0; !
Error && !consumeIf(
'E'); ++
I) {
684 void Demangler::demangleDynTrait() {
685 bool IsOpen = demanglePath(IsInType::Yes, LeaveGenericsOpen::Yes);
686 while (!
Error && consumeIf(
'p')) {
704 void Demangler::demangleOptionalBinder() {
705 uint64_t Binder = parseOptionalBase62Number(
'G');
706 if (
Error || Binder == 0)
713 if (Binder >=
Input.size() - BoundLifetimes) {
719 for (
size_t I = 0;
I != Binder; ++
I) {
731 void Demangler::demangleConst() {
732 if (
Error || RecursionLevel >= MaxRecursionLevel) {
736 ScopedOverride<size_t> SaveRecursionLevel(RecursionLevel, RecursionLevel + 1);
746 case BasicType::I128:
747 case BasicType::ISize:
752 case BasicType::U128:
753 case BasicType::USize:
759 case BasicType::Char:
762 case BasicType::Placeholder:
769 }
else if (
C ==
'B') {
770 demangleBackref([&] { demangleConst(); });
777 void Demangler::demangleConstInt() {
781 StringView HexDigits;
783 if (HexDigits.size() <= 16) {
784 printDecimalNumber(
Value);
793 void Demangler::demangleConstBool() {
794 StringView HexDigits;
795 parseHexNumber(HexDigits);
796 if (HexDigits ==
"0")
798 else if (HexDigits ==
"1")
806 return 0x20 <= CodePoint && CodePoint <= 0x7e;
810 void Demangler::demangleConstChar() {
811 StringView HexDigits;
812 uint64_t CodePoint = parseHexNumber(HexDigits);
813 if (
Error || HexDigits.size() > 6) {
854 bool Punycode = consumeIf(
'u');
855 uint64_t Bytes = parseDecimalNumber();
861 if (
Error || Bytes >
Input.size() - Position) {
865 StringView
S =
Input.substr(Position, Bytes);
873 return {
S, Punycode};
883 uint64_t Demangler::parseOptionalBase62Number(
char Tag) {
888 if (
Error || !addAssign(
N, 1))
899 uint64_t Demangler::parseBase62Number() {
914 Digit = 10 + (
C -
'a');
916 Digit = 10 + 26 + (
C -
'A');
922 if (!mulAssign(
Value, 62))
925 if (!addAssign(
Value, Digit))
929 if (!addAssign(
Value, 1))
939 uint64_t Demangler::parseDecimalNumber() {
954 if (!mulAssign(
Value, 10)) {
973 uint64_t Demangler::parseHexNumber(StringView &HexDigits) {
974 size_t Start = Position;
980 if (consumeIf(
'0')) {
984 while (!
Error && !consumeIf(
'_')) {
989 else if (
'a' <=
C &&
C <=
'f')
997 HexDigits = StringView();
1001 size_t End = Position - 1;
1003 HexDigits =
Input.substr(Start, End - Start);
1008 if (
Error || !Print)
1015 if (
Error || !Print)
1021 void Demangler::printDecimalNumber(
uint64_t N) {
1022 if (
Error || !Print)
1037 if (
Index - 1 >= BoundLifetimes) {
1049 printDecimalNumber(
Depth - 26 + 1);
1053 static inline bool decodePunycodeDigit(
char C,
size_t &
Value) {
1067 static void removeNullBytes(OutputBuffer &Output,
size_t StartIdx) {
1068 char *Buffer =
Output.getBuffer();
1069 char *Start = Buffer + StartIdx;
1070 char *End = Buffer +
Output.getCurrentPosition();
1076 static inline bool encodeUTF8(
size_t CodePoint,
char *Output) {
1077 if (0xD800 <= CodePoint && CodePoint <= 0xDFFF)
1080 if (CodePoint <= 0x7F) {
1085 if (CodePoint <= 0x7FF) {
1086 Output[0] = 0xC0 | ((CodePoint >> 6) & 0x3F);
1087 Output[1] = 0x80 | (CodePoint & 0x3F);
1091 if (CodePoint <= 0xFFFF) {
1092 Output[0] = 0xE0 | (CodePoint >> 12);
1093 Output[1] = 0x80 | ((CodePoint >> 6) & 0x3F);
1094 Output[2] = 0x80 | (CodePoint & 0x3F);
1098 if (CodePoint <= 0x10FFFF) {
1099 Output[0] = 0xF0 | (CodePoint >> 18);
1100 Output[1] = 0x80 | ((CodePoint >> 12) & 0x3F);
1101 Output[2] = 0x80 | ((CodePoint >> 6) & 0x3F);
1102 Output[3] = 0x80 | (CodePoint & 0x3F);
1111 static bool decodePunycode(StringView Input, OutputBuffer &Output) {
1112 size_t OutputSize =
Output.getCurrentPosition();
1113 size_t InputIdx = 0;
1117 for (
size_t I = 0;
I !=
Input.size(); ++
I)
1118 if (Input[
I] ==
'_')
1123 for (; InputIdx != DelimiterPos; ++InputIdx) {
1124 char C =
Input[InputIdx];
1143 auto Adapt = [&](
size_t Delta,
size_t NumPoints) {
1145 Delta += Delta / NumPoints;
1149 while (Delta > (
Base - TMin) * TMax / 2) {
1150 Delta /=
Base - TMin;
1153 return K + (((
Base - TMin + 1) * Delta) / (Delta + Skew));
1157 for (
size_t I = 0; InputIdx !=
Input.size();
I += 1) {
1161 for (
size_t K =
Base;
true; K +=
Base) {
1162 if (InputIdx ==
Input.size())
1164 char C =
Input[InputIdx++];
1166 if (!decodePunycodeDigit(
C, Digit))
1169 if (Digit > (Max -
I) /
W)
1176 else if (K >= Bias + TMax)
1184 if (
W > Max / (
Base -
T))
1188 size_t NumPoints = (
Output.getCurrentPosition() - OutputSize) / 4 + 1;
1189 Bias = Adapt(
I - OldI, NumPoints);
1191 if (
I / NumPoints > Max -
N)
1203 removeNullBytes(Output, OutputSize);
1207 void Demangler::printIdentifier(
Identifier Ident) {
1208 if (
Error || !Print)
1211 if (Ident.Punycode) {
1212 if (!decodePunycode(Ident.Name, Output))
1219 char Demangler::look()
const {
1223 return Input[Position];
1232 return Input[Position++];
1235 bool Demangler::consumeIf(
char Prefix) {