26using llvm::itanium_demangle::OutputBuffer;
27using llvm::itanium_demangle::ScopedOverride;
32 std::string_view
Name;
35 bool empty()
const {
return Name.empty(); }
67enum class LeaveGenericsOpen {
74 size_t MaxRecursionLevel;
76 size_t RecursionLevel;
77 size_t BoundLifetimes;
79 std::string_view Input;
92 Demangler(
size_t MaxRecursionLevel = 500);
94 bool demangle(std::string_view MangledName);
97 bool demanglePath(IsInType
Type,
98 LeaveGenericsOpen LeaveOpen = LeaveGenericsOpen::No);
99 void demangleImplPath(IsInType InType);
100 void demangleGenericArg();
102 void demangleFnSig();
103 void demangleDynBounds();
104 void demangleDynTrait();
105 void demangleOptionalBinder();
106 void demangleConst();
107 void demangleConstInt();
108 void demangleConstBool();
109 void demangleConstChar();
111 template <
typename Callable>
void demangleBackref(Callable Demangler) {
112 uint64_t Backref = parseBase62Number();
113 if (
Error || Backref >= Position) {
130 uint64_t parseHexNumber(std::string_view &HexDigits);
133 void print(std::string_view S);
135 void printBasicType(BasicType);
137 void printIdentifier(Identifier Ident);
141 bool consumeIf(
char Prefix);
150 if (MangledName ==
nullptr)
154 std::string_view Mangled(MangledName);
155 if (!llvm::itanium_demangle::starts_with(Mangled,
"_R"))
159 if (!
D.demangle(Mangled)) {
160 std::free(
D.Output.getBuffer());
166 return D.Output.getBuffer();
169Demangler::Demangler(
size_t MaxRecursionLevel)
170 : MaxRecursionLevel(MaxRecursionLevel) {}
172static inline bool isDigit(
const char C) {
return '0' <=
C &&
C <=
'9'; }
175 return (
'0' <=
C &&
C <=
'9') || (
'a' <=
C &&
C <=
'f');
178static inline bool isLower(
const char C) {
return 'a' <=
C &&
C <=
'z'; }
180static inline bool isUpper(
const char C) {
return 'A' <=
C &&
C <=
'Z'; }
192bool Demangler::demangle(std::string_view Mangled) {
199 if (!llvm::itanium_demangle::starts_with(Mangled,
"_R")) {
204 size_t Dot =
Mangled.find(
'.');
205 Input = Dot == std::string_view::npos ?
Mangled :
Mangled.substr(0, Dot);
207 demanglePath(IsInType::No);
209 if (Position != Input.size()) {
211 demanglePath(IsInType::No);
214 if (Position != Input.size())
217 if (Dot != std::string_view::npos) {
243bool Demangler::demanglePath(IsInType InType, LeaveGenericsOpen LeaveOpen) {
244 if (
Error || RecursionLevel >= MaxRecursionLevel) {
252 parseOptionalBase62Number(
's');
253 printIdentifier(parseIdentifier());
257 demangleImplPath(InType);
264 demangleImplPath(InType);
268 demanglePath(IsInType::Yes);
276 demanglePath(IsInType::Yes);
286 demanglePath(InType);
288 uint64_t Disambiguator = parseOptionalBase62Number(
's');
300 if (!Ident.empty()) {
302 printIdentifier(Ident);
305 printDecimalNumber(Disambiguator);
309 if (!Ident.empty()) {
311 printIdentifier(Ident);
317 demanglePath(InType);
319 if (InType == IsInType::No)
322 for (
size_t I = 0; !
Error && !consumeIf(
'E'); ++
I) {
325 demangleGenericArg();
327 if (LeaveOpen == LeaveGenericsOpen::Yes)
335 demangleBackref([&] { IsOpen = demanglePath(InType, LeaveOpen); });
348void Demangler::demangleImplPath(IsInType InType) {
350 parseOptionalBase62Number(
's');
351 demanglePath(InType);
358void Demangler::demangleGenericArg() {
360 printLifetime(parseBase62Number());
361 else if (consumeIf(
'K'))
391 Type = BasicType::I8;
394 Type = BasicType::Bool;
397 Type = BasicType::Char;
400 Type = BasicType::F64;
403 Type = BasicType::Str;
406 Type = BasicType::F32;
409 Type = BasicType::U8;
412 Type = BasicType::ISize;
415 Type = BasicType::USize;
418 Type = BasicType::I32;
421 Type = BasicType::U32;
424 Type = BasicType::I128;
427 Type = BasicType::U128;
430 Type = BasicType::Placeholder;
433 Type = BasicType::I16;
436 Type = BasicType::U16;
439 Type = BasicType::Unit;
442 Type = BasicType::Variadic;
445 Type = BasicType::I64;
448 Type = BasicType::U64;
451 Type = BasicType::Never;
458void Demangler::printBasicType(BasicType
Type) {
460 case BasicType::Bool:
463 case BasicType::Char:
478 case BasicType::I128:
481 case BasicType::ISize:
496 case BasicType::U128:
499 case BasicType::USize:
511 case BasicType::Placeholder:
514 case BasicType::Unit:
517 case BasicType::Variadic:
520 case BasicType::Never:
538void Demangler::demangleType() {
539 if (
Error || RecursionLevel >= MaxRecursionLevel) {
545 size_t Start = Position;
549 return printBasicType(
Type);
567 for (; !
Error && !consumeIf(
'E'); ++
I) {
580 if (consumeIf(
'L')) {
581 if (
auto Lifetime = parseBase62Number()) {
582 printLifetime(Lifetime);
603 if (consumeIf(
'L')) {
604 if (
auto Lifetime = parseBase62Number()) {
606 printLifetime(Lifetime);
613 demangleBackref([&] { demangleType(); });
617 demanglePath(IsInType::Yes);
625void Demangler::demangleFnSig() {
627 demangleOptionalBinder();
632 if (consumeIf(
'K')) {
634 if (consumeIf(
'C')) {
640 for (
char C : Ident.Name) {
651 for (
size_t I = 0; !
Error && !consumeIf(
'E'); ++
I) {
658 if (consumeIf(
'u')) {
667void Demangler::demangleDynBounds() {
670 demangleOptionalBinder();
671 for (
size_t I = 0; !
Error && !consumeIf(
'E'); ++
I) {
680void Demangler::demangleDynTrait() {
681 bool IsOpen = demanglePath(IsInType::Yes, LeaveGenericsOpen::Yes);
682 while (!
Error && consumeIf(
'p')) {
700void Demangler::demangleOptionalBinder() {
701 uint64_t Binder = parseOptionalBase62Number(
'G');
702 if (
Error || Binder == 0)
709 if (Binder >= Input.size() - BoundLifetimes) {
715 for (
size_t I = 0;
I != Binder; ++
I) {
727void Demangler::demangleConst() {
728 if (
Error || RecursionLevel >= MaxRecursionLevel) {
742 case BasicType::I128:
743 case BasicType::ISize:
748 case BasicType::U128:
749 case BasicType::USize:
752 case BasicType::Bool:
755 case BasicType::Char:
758 case BasicType::Placeholder:
765 }
else if (
C ==
'B') {
766 demangleBackref([&] { demangleConst(); });
773void Demangler::demangleConstInt() {
777 std::string_view HexDigits;
779 if (HexDigits.size() <= 16) {
780 printDecimalNumber(
Value);
789void Demangler::demangleConstBool() {
790 std::string_view HexDigits;
791 parseHexNumber(HexDigits);
792 if (HexDigits ==
"0")
794 else if (HexDigits ==
"1")
802 return 0x20 <= CodePoint && CodePoint <= 0x7e;
806void Demangler::demangleConstChar() {
807 std::string_view HexDigits;
808 uint64_t CodePoint = parseHexNumber(HexDigits);
809 if (
Error || HexDigits.size() > 6) {
850 bool Punycode = consumeIf(
'u');
851 uint64_t Bytes = parseDecimalNumber();
857 if (
Error || Bytes > Input.size() - Position) {
861 std::string_view S = Input.substr(Position, Bytes);
864 if (!std::all_of(S.begin(), S.end(),
isValid)) {
869 return {S, Punycode};
879uint64_t Demangler::parseOptionalBase62Number(
char Tag) {
884 if (
Error || !addAssign(
N, 1))
895uint64_t Demangler::parseBase62Number() {
910 Digit = 10 + (
C -
'a');
912 Digit = 10 + 26 + (
C -
'A');
918 if (!mulAssign(
Value, 62))
921 if (!addAssign(
Value, Digit))
925 if (!addAssign(
Value, 1))
935uint64_t Demangler::parseDecimalNumber() {
950 if (!mulAssign(
Value, 10)) {
969uint64_t Demangler::parseHexNumber(std::string_view &HexDigits) {
970 size_t Start = Position;
976 if (consumeIf(
'0')) {
980 while (!
Error && !consumeIf(
'_')) {
985 else if (
'a' <=
C &&
C <=
'f')
993 HexDigits = std::string_view();
997 size_t End = Position - 1;
999 HexDigits = Input.substr(Start,
End - Start);
1003void Demangler::print(
char C) {
1004 if (
Error || !Print)
1010void Demangler::print(std::string_view S) {
1011 if (
Error || !Print)
1017void Demangler::printDecimalNumber(
uint64_t N) {
1018 if (
Error || !Print)
1033 if (
Index - 1 >= BoundLifetimes) {
1045 printDecimalNumber(
Depth - 26 + 1);
1049static inline bool decodePunycodeDigit(
char C,
size_t &
Value) {
1063static void removeNullBytes(
OutputBuffer &Output,
size_t StartIdx) {
1065 char *Start = Buffer + StartIdx;
1072static inline bool encodeUTF8(
size_t CodePoint,
char *Output) {
1073 if (0xD800 <= CodePoint && CodePoint <= 0xDFFF)
1076 if (CodePoint <= 0x7F) {
1077 Output[0] = CodePoint;
1081 if (CodePoint <= 0x7FF) {
1082 Output[0] = 0xC0 | ((CodePoint >> 6) & 0x3F);
1083 Output[1] = 0x80 | (CodePoint & 0x3F);
1087 if (CodePoint <= 0xFFFF) {
1088 Output[0] = 0xE0 | (CodePoint >> 12);
1089 Output[1] = 0x80 | ((CodePoint >> 6) & 0x3F);
1090 Output[2] = 0x80 | (CodePoint & 0x3F);
1094 if (CodePoint <= 0x10FFFF) {
1095 Output[0] = 0xF0 | (CodePoint >> 18);
1096 Output[1] = 0x80 | ((CodePoint >> 12) & 0x3F);
1097 Output[2] = 0x80 | ((CodePoint >> 6) & 0x3F);
1098 Output[3] = 0x80 | (CodePoint & 0x3F);
1107static bool decodePunycode(std::string_view Input,
OutputBuffer &Output) {
1109 size_t InputIdx = 0;
1112 size_t DelimiterPos = std::string_view::npos;
1113 for (
size_t I = 0;
I != Input.size(); ++
I)
1114 if (Input[
I] ==
'_')
1117 if (DelimiterPos != std::string_view::npos) {
1119 for (; InputIdx != DelimiterPos; ++InputIdx) {
1120 char C = Input[InputIdx];
1125 Output += std::string_view(
UTF8, 4);
1139 auto Adapt = [&](
size_t Delta,
size_t NumPoints) {
1141 Delta += Delta / NumPoints;
1145 while (Delta > (
Base - TMin) * TMax / 2) {
1146 Delta /=
Base - TMin;
1149 return K + (((
Base - TMin + 1) * Delta) / (Delta + Skew));
1153 for (
size_t I = 0; InputIdx != Input.size();
I += 1) {
1156 size_t Max = std::numeric_limits<size_t>::max();
1157 for (
size_t K =
Base;
true;
K +=
Base) {
1158 if (InputIdx == Input.size())
1160 char C = Input[InputIdx++];
1162 if (!decodePunycodeDigit(
C, Digit))
1165 if (Digit > (Max -
I) / W)
1172 else if (K >= Bias + TMax)
1180 if (W > Max / (
Base -
T))
1185 Bias = Adapt(
I - OldI, NumPoints);
1187 if (
I / NumPoints > Max -
N)
1199 removeNullBytes(Output, OutputSize);
1203void Demangler::printIdentifier(Identifier Ident) {
1204 if (
Error || !Print)
1207 if (Ident.Punycode) {
1208 if (!decodePunycode(Ident.Name, Output))
1215char Demangler::look()
const {
1216 if (
Error || Position >= Input.size())
1219 return Input[Position];
1222char Demangler::consume() {
1223 if (
Error || Position >= Input.size()) {
1228 return Input[Position++];
1231bool Demangler::consumeIf(
char Prefix) {
1232 if (
Error || Position >= Input.size() || Input[Position] != Prefix)
1242 if (
A > std::numeric_limits<uint64_t>::max() -
B) {
1254 if (
B != 0 &&
A > std::numeric_limits<uint64_t>::max() /
B) {
static void print(raw_ostream &Out, object::Archive::Kind Kind, T Val)
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
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 isDigit(const char C)
static bool isAsciiPrintable(uint64_t CodePoint)
Returns true if CodePoint represents a printable ASCII character.
static bool isHexDigit(const char C)
static bool isLower(const char C)
static bool parseBasicType(char C, BasicType &Type)
static bool isUpper(const char C)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
static void encodeUTF8(uint32_t UnicodeScalarValue, SmallVectorImpl< char > &Result)
encodeUTF8 - Encode UnicodeScalarValue in UTF-8 and append it to result.
void setCurrentPosition(size_t NewPos)
size_t getCurrentPosition() const
void insert(size_t Pos, const char *S, size_t N)
Lightweight error class with error context and mandatory checking.
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.
std::string demangle(const std::string &MangledName)
Attempt to demangle a string using different demangling schemes.
@ Never
Never set the bit.
char * rustDemangle(const char *MangledName)