26using llvm::itanium_demangle::OutputBuffer;
27using llvm::itanium_demangle::ScopedOverride;
28using llvm::itanium_demangle::StringView;
36 bool empty()
const {
return Name.empty(); }
68enum class LeaveGenericsOpen {
75 size_t MaxRecursionLevel;
77 size_t RecursionLevel;
78 size_t BoundLifetimes;
93 Demangler(
size_t MaxRecursionLevel = 500);
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) {
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"))
160 if (!
D.demangle(Mangled)) {
161 std::free(
D.Output.getBuffer());
167 return D.Output.getBuffer();
170Demangler::Demangler(
size_t MaxRecursionLevel)
171 : MaxRecursionLevel(MaxRecursionLevel) {}
173static inline bool isDigit(
const char C) {
return '0' <=
C &&
C <=
'9'; }
176 return (
'0' <=
C &&
C <=
'9') || (
'a' <=
C &&
C <=
'f');
179static inline bool isLower(
const char C) {
return 'a' <=
C &&
C <=
'z'; }
181static inline bool isUpper(
const char C) {
return 'A' <=
C &&
C <=
'Z'; }
204 size_t Dot = Mangled.
find(
'.');
205 Input = Mangled.
substr(0, Dot);
208 demanglePath(IsInType::No);
210 if (Position != Input.
size()) {
212 demanglePath(IsInType::No);
215 if (Position != Input.
size())
218 if (!Suffix.
empty()) {
244bool Demangler::demanglePath(IsInType InType, LeaveGenericsOpen LeaveOpen) {
245 if (
Error || RecursionLevel >= MaxRecursionLevel) {
253 parseOptionalBase62Number(
's');
254 printIdentifier(parseIdentifier());
258 demangleImplPath(InType);
265 demangleImplPath(InType);
269 demanglePath(IsInType::Yes);
277 demanglePath(IsInType::Yes);
287 demanglePath(InType);
289 uint64_t Disambiguator = parseOptionalBase62Number(
's');
301 if (!Ident.empty()) {
303 printIdentifier(Ident);
306 printDecimalNumber(Disambiguator);
310 if (!Ident.empty()) {
312 printIdentifier(Ident);
318 demanglePath(InType);
320 if (InType == IsInType::No)
323 for (
size_t I = 0; !
Error && !consumeIf(
'E'); ++
I) {
326 demangleGenericArg();
328 if (LeaveOpen == LeaveGenericsOpen::Yes)
336 demangleBackref([&] { IsOpen = demanglePath(InType, LeaveOpen); });
349void Demangler::demangleImplPath(IsInType InType) {
351 parseOptionalBase62Number(
's');
352 demanglePath(InType);
359void Demangler::demangleGenericArg() {
361 printLifetime(parseBase62Number());
362 else if (consumeIf(
'K'))
392 Type = BasicType::I8;
395 Type = BasicType::Bool;
398 Type = BasicType::Char;
401 Type = BasicType::F64;
404 Type = BasicType::Str;
407 Type = BasicType::F32;
410 Type = BasicType::U8;
413 Type = BasicType::ISize;
416 Type = BasicType::USize;
419 Type = BasicType::I32;
422 Type = BasicType::U32;
425 Type = BasicType::I128;
428 Type = BasicType::U128;
431 Type = BasicType::Placeholder;
434 Type = BasicType::I16;
437 Type = BasicType::U16;
440 Type = BasicType::Unit;
443 Type = BasicType::Variadic;
446 Type = BasicType::I64;
449 Type = BasicType::U64;
452 Type = BasicType::Never;
459void Demangler::printBasicType(BasicType
Type) {
461 case BasicType::Bool:
464 case BasicType::Char:
479 case BasicType::I128:
482 case BasicType::ISize:
497 case BasicType::U128:
500 case BasicType::USize:
512 case BasicType::Placeholder:
515 case BasicType::Unit:
518 case BasicType::Variadic:
521 case BasicType::Never:
539void Demangler::demangleType() {
540 if (
Error || RecursionLevel >= MaxRecursionLevel) {
546 size_t Start = Position;
550 return printBasicType(
Type);
568 for (; !
Error && !consumeIf(
'E'); ++
I) {
581 if (consumeIf(
'L')) {
582 if (
auto Lifetime = parseBase62Number()) {
583 printLifetime(Lifetime);
604 if (consumeIf(
'L')) {
605 if (
auto Lifetime = parseBase62Number()) {
607 printLifetime(Lifetime);
614 demangleBackref([&] { demangleType(); });
618 demanglePath(IsInType::Yes);
626void Demangler::demangleFnSig() {
628 demangleOptionalBinder();
633 if (consumeIf(
'K')) {
635 if (consumeIf(
'C')) {
641 for (
char C : Ident.Name) {
652 for (
size_t I = 0; !
Error && !consumeIf(
'E'); ++
I) {
659 if (consumeIf(
'u')) {
668void Demangler::demangleDynBounds() {
671 demangleOptionalBinder();
672 for (
size_t I = 0; !
Error && !consumeIf(
'E'); ++
I) {
681void Demangler::demangleDynTrait() {
682 bool IsOpen = demanglePath(IsInType::Yes, LeaveGenericsOpen::Yes);
683 while (!
Error && consumeIf(
'p')) {
701void Demangler::demangleOptionalBinder() {
702 uint64_t Binder = parseOptionalBase62Number(
'G');
703 if (
Error || Binder == 0)
710 if (Binder >= Input.
size() - BoundLifetimes) {
716 for (
size_t I = 0;
I != Binder; ++
I) {
728void Demangler::demangleConst() {
729 if (
Error || RecursionLevel >= MaxRecursionLevel) {
743 case BasicType::I128:
744 case BasicType::ISize:
749 case BasicType::U128:
750 case BasicType::USize:
753 case BasicType::Bool:
756 case BasicType::Char:
759 case BasicType::Placeholder:
766 }
else if (
C ==
'B') {
767 demangleBackref([&] { demangleConst(); });
774void Demangler::demangleConstInt() {
780 if (HexDigits.
size() <= 16) {
781 printDecimalNumber(
Value);
790void Demangler::demangleConstBool() {
792 parseHexNumber(HexDigits);
793 if (HexDigits ==
"0")
795 else if (HexDigits ==
"1")
803 return 0x20 <= CodePoint && CodePoint <= 0x7e;
807void Demangler::demangleConstChar() {
809 uint64_t CodePoint = parseHexNumber(HexDigits);
851 bool Punycode = consumeIf(
'u');
852 uint64_t Bytes = parseDecimalNumber();
858 if (
Error || Bytes > Input.
size() - Position) {
870 return {S, Punycode};
880uint64_t Demangler::parseOptionalBase62Number(
char Tag) {
885 if (
Error || !addAssign(
N, 1))
896uint64_t Demangler::parseBase62Number() {
911 Digit = 10 + (
C -
'a');
913 Digit = 10 + 26 + (
C -
'A');
919 if (!mulAssign(
Value, 62))
922 if (!addAssign(
Value, Digit))
926 if (!addAssign(
Value, 1))
936uint64_t Demangler::parseDecimalNumber() {
951 if (!mulAssign(
Value, 10)) {
971 size_t Start = Position;
977 if (consumeIf(
'0')) {
981 while (!
Error && !consumeIf(
'_')) {
986 else if (
'a' <=
C &&
C <=
'f')
998 size_t End = Position - 1;
1000 HexDigits = Input.
substr(Start, End - Start);
1004void Demangler::print(
char C) {
1005 if (
Error || !Print)
1012 if (
Error || !Print)
1018void Demangler::printDecimalNumber(
uint64_t N) {
1019 if (
Error || !Print)
1034 if (
Index - 1 >= BoundLifetimes) {
1046 printDecimalNumber(
Depth - 26 + 1);
1050static inline bool decodePunycodeDigit(
char C,
size_t &
Value) {
1064static void removeNullBytes(
OutputBuffer &Output,
size_t StartIdx) {
1066 char *Start = Buffer + StartIdx;
1073static inline bool encodeUTF8(
size_t CodePoint,
char *Output) {
1074 if (0xD800 <= CodePoint && CodePoint <= 0xDFFF)
1077 if (CodePoint <= 0x7F) {
1078 Output[0] = CodePoint;
1082 if (CodePoint <= 0x7FF) {
1083 Output[0] = 0xC0 | ((CodePoint >> 6) & 0x3F);
1084 Output[1] = 0x80 | (CodePoint & 0x3F);
1088 if (CodePoint <= 0xFFFF) {
1089 Output[0] = 0xE0 | (CodePoint >> 12);
1090 Output[1] = 0x80 | ((CodePoint >> 6) & 0x3F);
1091 Output[2] = 0x80 | (CodePoint & 0x3F);
1095 if (CodePoint <= 0x10FFFF) {
1096 Output[0] = 0xF0 | (CodePoint >> 18);
1097 Output[1] = 0x80 | ((CodePoint >> 12) & 0x3F);
1098 Output[2] = 0x80 | ((CodePoint >> 6) & 0x3F);
1099 Output[3] = 0x80 | (CodePoint & 0x3F);
1110 size_t InputIdx = 0;
1114 for (
size_t I = 0;
I != Input.
size(); ++
I)
1115 if (Input[
I] ==
'_')
1120 for (; InputIdx != DelimiterPos; ++InputIdx) {
1121 char C = Input[InputIdx];
1140 auto Adapt = [&](
size_t Delta,
size_t NumPoints) {
1142 Delta += Delta / NumPoints;
1146 while (Delta > (
Base - TMin) * TMax / 2) {
1147 Delta /=
Base - TMin;
1150 return K + (((
Base - TMin + 1) * Delta) / (Delta + Skew));
1154 for (
size_t I = 0; InputIdx != Input.
size();
I += 1) {
1157 size_t Max = std::numeric_limits<size_t>::max();
1158 for (
size_t K =
Base;
true; K +=
Base) {
1159 if (InputIdx == Input.
size())
1161 char C = Input[InputIdx++];
1163 if (!decodePunycodeDigit(
C, Digit))
1166 if (Digit > (Max -
I) / W)
1173 else if (K >= Bias + TMax)
1181 if (W > Max / (
Base -
T))
1186 Bias = Adapt(
I - OldI, NumPoints);
1188 if (
I / NumPoints > Max -
N)
1200 removeNullBytes(Output, OutputSize);
1204void Demangler::printIdentifier(Identifier Ident) {
1205 if (
Error || !Print)
1208 if (Ident.Punycode) {
1209 if (!decodePunycode(Ident.Name, Output))
1216char Demangler::look()
const {
1220 return Input[Position];
1223char Demangler::consume() {
1224 if (
Error || Position >= Input.
size()) {
1229 return Input[Position++];
1232bool Demangler::consumeIf(
char Prefix) {
1233 if (
Error || Position >= Input.
size() || Input[Position] != Prefix)
1243 if (
A > std::numeric_limits<uint64_t>::max() -
B) {
1255 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)
bool consumeFront(char C)
StringView substr(size_t Pos, size_t Len=npos) const
StringView dropFront(size_t N=1) const
const char * begin() const
size_t find(char C, size_t From=0) const
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)