LLVM: lib/Demangle/MicrosoftDemangle.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
17
23
24#include
25#include
26#include
27#include <string_view>
28#include
29
30using namespace llvm;
32
34 return !S.empty() && std::isdigit(S.front());
35}
36
41
43 if (!llvm::itanium_demangle::starts_with(S, C))
44 return false;
45 S.remove_prefix(1);
46 return true;
47}
48
49static bool consumeFront(std::string_view &S, std::string_view C) {
50 if (!llvm::itanium_demangle::starts_with(S, C))
51 return false;
52 S.remove_prefix(C.size());
53 return true;
54}
55
56static bool consumeFront(std::string_view &S, std::string_view PrefixA,
57 std::string_view PrefixB, bool A) {
58 const std::string_view &Prefix = A ? PrefixA : PrefixB;
60}
61
62static bool startsWith(std::string_view S, std::string_view PrefixA,
63 std::string_view PrefixB, bool A) {
64 const std::string_view &Prefix = A ? PrefixA : PrefixB;
65 return llvm::itanium_demangle::starts_with(S, Prefix);
66}
67
68bool Demangler::isMemberPointer(std::string_view MangledName, bool &Error) {
70 const char F = MangledName.front();
71 MangledName.remove_prefix(1);
72 switch (F) {
73 case '$':
74
75
76 return false;
77 case 'A':
78
79
80 return false;
81 case 'P':
82 case 'Q':
83 case 'R':
84 case 'S':
85
86
87 break;
88 default:
89
90
92 }
93
94
95
97 if (MangledName[0] != '6' && MangledName[0] != '8') {
99 return false;
100 }
101 return (MangledName[0] == '8');
102 }
103
104
105
109 demanglePointerAuthQualifier(MangledName);
110
111 if (MangledName.empty()) {
113 return false;
114 }
115
116
117 switch (MangledName.front()) {
118 case 'A':
119 case 'B':
120 case 'C':
121 case 'D':
122 return false;
123 case 'Q':
124 case 'R':
125 case 'S':
126 case 'T':
127 return true;
128 default:
130 return false;
131 }
132}
133
170
173 return false;
174
175 size_t End = S.find('?');
176 if (End == std::string_view::npos)
177 return false;
178 std::string_view Candidate = S.substr(0, End);
179 if (Candidate.empty())
180 return false;
181
182
183
184 if (Candidate.size() == 1)
185 return Candidate[0] == '@' || (Candidate[0] >= '0' && Candidate[0] <= '9');
186
187
188 if (Candidate.back() != '@')
189 return false;
190 Candidate.remove_suffix(1);
191
192
193
194
195
196
197
198 if (Candidate[0] < 'B' || Candidate[0] > 'P')
199 return false;
200 Candidate.remove_prefix(1);
201 while (!Candidate.empty()) {
202 if (Candidate[0] < 'A' || Candidate[0] > 'P')
203 return false;
204 Candidate.remove_prefix(1);
205 }
206
207 return true;
208}
209
211 switch (S.front()) {
212 case 'T':
213 case 'U':
214 case 'V':
215 case 'W':
216 return true;
217 }
218 return false;
219}
220
221static bool isCustomType(std::string_view S) { return S[0] == '?'; }
222
224 if (llvm::itanium_demangle::starts_with(S, "$$Q"))
225 return true;
226
227 switch (S.front()) {
228 case 'A':
229 case 'P':
230 case 'Q':
231 case 'R':
232 case 'S':
233 return true;
234 }
235 return false;
236}
237
238static bool isArrayType(std::string_view S) { return S[0] == 'Y'; }
239
241 return llvm::itanium_demangle::starts_with(S, "$$A8@@") ||
242 llvm::itanium_demangle::starts_with(S, "$$A6");
243}
244
253
254static std::pair<Qualifiers, PointerAffinity>
258
259 const char F = MangledName.front();
260 MangledName.remove_prefix(1);
261 switch (F) {
262 case 'A':
264 case 'P':
266 case 'Q':
268 case 'R':
270 case 'S':
273 }
274
275
277}
278
284 for (size_t I = 0; I < Count; ++I) {
286 Head = Head->Next;
287 }
288 return N;
289}
290
291std::string_view Demangler::copyString(std::string_view Borrowed) {
293
294
295 if (Borrowed.size())
296 std::memcpy(Stable, Borrowed.data(), Borrowed.size());
297
298 return {Stable, Borrowed.size()};
299}
300
302Demangler::demangleSpecialTableSymbolNode(std::string_view &MangledName,
304 NamedIdentifierNode *NI = Arena.alloc();
305 switch (K) {
307 NI->Name = "`vftable'";
308 break;
310 NI->Name = "`vbtable'";
311 break;
313 NI->Name = "`local vftable'";
314 break;
316 NI->Name = "`RTTI Complete Object Locator'";
317 break;
318 default:
320 }
321 QualifiedNameNode *QN = demangleNameScopeChain(MangledName, NI);
322 SpecialTableSymbolNode *STSN = Arena.alloc();
323 STSN->Name = QN;
325 if (MangledName.empty()) {
327 return nullptr;
328 }
329 char Front = MangledName.front();
330 MangledName.remove_prefix(1);
331 if (Front != '6' && Front != '7') {
333 return nullptr;
334 }
335
336 std::tie(STSN->Quals, IsMember) = demangleQualifiers(MangledName);
337
338 NodeList *TargetCurrent = nullptr;
339 NodeList *TargetHead = nullptr;
340 size_t Count = 0;
343
345 if (TargetCurrent)
347 else
348 TargetHead = Next;
349
350 TargetCurrent = Next;
351 QualifiedNameNode *QN = demangleFullyQualifiedTypeName(MangledName);
353 return nullptr;
355 TargetCurrent->N = QN;
356 }
357
360
361 return STSN;
362}
363
365Demangler::demangleLocalStaticGuard(std::string_view &MangledName,
366 bool IsThread) {
367 LocalStaticGuardIdentifierNode *LSGI =
368 Arena.alloc();
370 QualifiedNameNode *QN = demangleNameScopeChain(MangledName, LSGI);
371 LocalStaticGuardVariableNode *LSGVN =
372 Arena.alloc();
373 LSGVN->Name = QN;
374
379 else {
381 return nullptr;
382 }
383
384 if (!MangledName.empty())
385 LSGI->ScopeIndex = demangleUnsigned(MangledName);
386 return LSGVN;
387}
388
390 std::string_view Name) {
392 Id->Name = Name;
393 return Id;
394}
395
405
407 std::string_view Name) {
410}
411
414 std::string_view VariableName) {
418 return VSN;
419}
420
422Demangler::demangleUntypedVariable(ArenaAllocator &Arena,
423 std::string_view &MangledName,
424 std::string_view VariableName) {
426 QualifiedNameNode *QN = demangleNameScopeChain(MangledName, NI);
427 VariableSymbolNode *VSN = Arena.alloc();
428 VSN->Name = QN;
430 return VSN;
431
433 return nullptr;
434}
435
437Demangler::demangleRttiBaseClassDescriptorNode(ArenaAllocator &Arena,
438 std::string_view &MangledName) {
439 RttiBaseClassDescriptorNode *RBCDN =
440 Arena.alloc();
441 RBCDN->NVOffset = demangleUnsigned(MangledName);
442 RBCDN->VBPtrOffset = demangleSigned(MangledName);
443 RBCDN->VBTableOffset = demangleUnsigned(MangledName);
444 RBCDN->Flags = demangleUnsigned(MangledName);
446 return nullptr;
447
448 VariableSymbolNode *VSN = Arena.alloc();
449 VSN->Name = demangleNameScopeChain(MangledName, RBCDN);
451 return VSN;
452}
453
455Demangler::demangleInitFiniStub(std::string_view &MangledName,
456 bool IsDestructor) {
457 DynamicStructorIdentifierNode *DSIN =
458 Arena.alloc();
460
461 bool IsKnownStaticDataMember = false;
463 IsKnownStaticDataMember = true;
464
465 SymbolNode *Symbol = demangleDeclarator(MangledName);
467 return nullptr;
468
469 FunctionSymbolNode *FSN = nullptr;
470
472 DSIN->Variable = static_cast<VariableSymbolNode *>(Symbol);
473
474
475
476
477
478 int AtCount = IsKnownStaticDataMember ? 2 : 1;
479 for (int I = 0; I < AtCount; ++I) {
481 continue;
483 return nullptr;
484 }
485
486 FSN = demangleFunctionEncoding(MangledName);
487 if (FSN)
489 } else {
490 if (IsKnownStaticDataMember) {
491
493 return nullptr;
494 }
495
496 FSN = static_cast<FunctionSymbolNode *>(Symbol);
499 }
500
501 return FSN;
502}
503
504SymbolNode *Demangler::demangleSpecialIntrinsic(std::string_view &MangledName) {
506
507 switch (SIK) {
509 return nullptr;
511 return demangleStringLiteral(MangledName);
516 return demangleSpecialTableSymbolNode(MangledName, SIK);
518 return demangleVcallThunkNode(MangledName);
520 return demangleLocalStaticGuard(MangledName, false);
522 return demangleLocalStaticGuard(MangledName, true);
526 break;
528 break;
529 if (!MangledName.empty())
530 break;
532 }
534 return demangleUntypedVariable(Arena, MangledName,
535 "`RTTI Base Class Array'");
537 return demangleUntypedVariable(Arena, MangledName,
538 "`RTTI Class Hierarchy Descriptor'");
540 return demangleRttiBaseClassDescriptorNode(Arena, MangledName);
542 return demangleInitFiniStub(MangledName, false);
544 return demangleInitFiniStub(MangledName, true);
547
548
549 break;
552 }
554 return nullptr;
555}
556
558Demangler::demangleFunctionIdentifierCode(std::string_view &MangledName) {
559 assert(llvm::itanium_demangle::starts_with(MangledName, '?'));
560 MangledName.remove_prefix(1);
561 if (MangledName.empty()) {
563 return nullptr;
564 }
565
567 return demangleFunctionIdentifierCode(
570 return demangleFunctionIdentifierCode(MangledName,
572 return demangleFunctionIdentifierCode(MangledName,
574}
575
577Demangler::demangleStructorIdentifier(std::string_view &MangledName,
578 bool IsDestructor) {
579 StructorIdentifierNode *N = Arena.alloc();
580 N->IsDestructor = IsDestructor;
581 return N;
582}
583
585Demangler::demangleConversionOperatorIdentifier(std::string_view &MangledName) {
586 ConversionOperatorIdentifierNode *N =
587 Arena.alloc();
588 return N;
589}
590
592Demangler::demangleLiteralOperatorIdentifier(std::string_view &MangledName) {
593 LiteralOperatorIdentifierNode *N =
594 Arena.alloc();
595 N->Name = demangleSimpleString(MangledName, false);
596 return N;
597}
598
600Demangler::translateIntrinsicFunctionCode(char CH,
603 if (!(CH >= '0' && CH <= '9') && !(CH >= 'A' && CH <= 'Z')) {
605 return IFK::None;
606 }
607
608
609
610
611 static IFK Basic[36] = {
612 IFK::None,
613 IFK::None,
614 IFK::New,
615 IFK::Delete,
616 IFK::Assign,
617 IFK::RightShift,
618 IFK::LeftShift,
619 IFK::LogicalNot,
620 IFK::Equals,
621 IFK::NotEquals,
622 IFK::ArraySubscript,
623 IFK::None,
624 IFK::Pointer,
625 IFK::Dereference,
626 IFK::Increment,
627 IFK::Decrement,
628 IFK::Minus,
629 IFK::Plus,
630 IFK::BitwiseAnd,
631 IFK::MemberPointer,
632 IFK::Divide,
633 IFK::Modulus,
634 IFK::LessThan,
635 IFK::LessThanEqual,
636 IFK::GreaterThan,
637 IFK::GreaterThanEqual,
638 IFK::Comma,
639 IFK::Parens,
640 IFK::BitwiseNot,
641 IFK::BitwiseXor,
642 IFK::BitwiseOr,
643 IFK::LogicalAnd,
644 IFK::LogicalOr,
645 IFK::TimesEqual,
646 IFK::PlusEqual,
647 IFK::MinusEqual,
648 };
649 static IFK Under[36] = {
650 IFK::DivEqual,
651 IFK::ModEqual,
652 IFK::RshEqual,
653 IFK::LshEqual,
654 IFK::BitwiseAndEqual,
655 IFK::BitwiseOrEqual,
656 IFK::BitwiseXorEqual,
657 IFK::None,
658 IFK::None,
659 IFK::None,
660 IFK::None,
661 IFK::None,
662 IFK::None,
663 IFK::VbaseDtor,
664 IFK::VecDelDtor,
665 IFK::DefaultCtorClosure,
666 IFK::ScalarDelDtor,
667 IFK::VecCtorIter,
668 IFK::VecDtorIter,
669 IFK::VecVbaseCtorIter,
670 IFK::VdispMap,
671 IFK::EHVecCtorIter,
672 IFK::EHVecDtorIter,
673 IFK::EHVecVbaseCtorIter,
674 IFK::CopyCtorClosure,
675 IFK::None,
676 IFK::None,
677 IFK::None,
678 IFK::None,
679 IFK::LocalVftableCtorClosure,
680 IFK::ArrayNew,
681 IFK::ArrayDelete,
682 IFK::None,
683 IFK::None,
684 IFK::None,
685 IFK::None,
686 };
688 IFK::None,
689 IFK::None,
690 IFK::None,
691 IFK::None,
692 IFK::None,
693 IFK::None,
694 IFK::None,
695 IFK::None,
696 IFK::None,
697 IFK::None,
698 IFK::ManVectorCtorIter,
699 IFK::ManVectorDtorIter,
700 IFK::EHVectorCopyCtorIter,
701 IFK::EHVectorVbaseCopyCtorIter,
702 IFK::None,
703 IFK::None,
704 IFK::VectorCopyCtorIter,
705 IFK::VectorVbaseCopyCtorIter,
706 IFK::ManVectorVbaseCopyCtorIter,
707
708 IFK::None,
709 IFK::None,
710 IFK::CoAwait,
711 IFK::Spaceship,
712 IFK::None,
713 IFK::None,
714 IFK::None,
715 IFK::None,
716 IFK::None,
717 IFK::None,
718 IFK::None,
719 IFK::None,
720 IFK::None,
721 IFK::None,
722 IFK::None,
723 IFK::None,
724 IFK::None,
725 };
726
727 int Index = (CH >= '0' && CH <= '9') ? (CH - '0') : (CH - 'A' + 10);
728 switch (Group) {
735 }
737}
738
740Demangler::demangleFunctionIdentifierCode(std::string_view &MangledName,
742 if (MangledName.empty()) {
744 return nullptr;
745 }
746 const char CH = MangledName.front();
747 switch (Group) {
749 MangledName.remove_prefix(1);
750 switch (CH) {
751 case '0':
752 case '1':
753 return demangleStructorIdentifier(MangledName, CH == '1');
754 case 'B':
755 return demangleConversionOperatorIdentifier(MangledName);
756 default:
757 return Arena.alloc(
758 translateIntrinsicFunctionCode(CH, Group));
759 }
761 MangledName.remove_prefix(1);
762 return Arena.alloc(
763 translateIntrinsicFunctionCode(CH, Group));
765 MangledName.remove_prefix(1);
766 switch (CH) {
767 case 'K':
768 return demangleLiteralOperatorIdentifier(MangledName);
769 default:
770 return Arena.alloc(
771 translateIntrinsicFunctionCode(CH, Group));
772 }
773 }
774
776}
777
778SymbolNode *Demangler::demangleEncodedSymbol(std::string_view &MangledName,
780 if (MangledName.empty()) {
782 return nullptr;
783 }
784
785
786 switch (MangledName.front()) {
787 case '0':
788 case '1':
789 case '2':
790 case '3':
791 case '4': {
792 StorageClass SC = demangleVariableStorageClass(MangledName);
793 return demangleVariableEncoding(MangledName, SC);
794 }
795 }
796 FunctionSymbolNode *FSN = demangleFunctionEncoding(MangledName);
797
798 IdentifierNode *UQN = Name->getUnqualifiedIdentifier();
800 ConversionOperatorIdentifierNode *COIN =
801 static_cast<ConversionOperatorIdentifierNode *>(UQN);
802 if (FSN)
804 }
805 return FSN;
806}
807
808SymbolNode *Demangler::demangleDeclarator(std::string_view &MangledName) {
809
810
811 QualifiedNameNode *QN = demangleFullyQualifiedSymbolName(MangledName);
813 return nullptr;
814
815 SymbolNode *Symbol = demangleEncodedSymbol(MangledName, QN);
817 return nullptr;
819
822 ConversionOperatorIdentifierNode *COIN =
823 static_cast<ConversionOperatorIdentifierNode *>(UQN);
826 return nullptr;
827 }
828 }
830}
831
832SymbolNode *Demangler::demangleMD5Name(std::string_view &MangledName) {
833 assert(llvm::itanium_demangle::starts_with(MangledName, "??@"));
834
835
836
837 size_t MD5Last = MangledName.find('@', strlen("??@"));
838 if (MD5Last == std::string_view::npos) {
840 return nullptr;
841 }
842 const char *Start = MangledName.data();
843 const size_t StartSize = MangledName.size();
844 MangledName.remove_prefix(MD5Last + 1);
845
846
847
848
849
850
851
852
853
854
855
857
858 assert(MangledName.size() < StartSize);
859 const size_t Count = StartSize - MangledName.size();
860 std::string_view MD5(Start, Count);
863
864 return S;
865}
866
867SymbolNode *Demangler::demangleTypeinfoName(std::string_view &MangledName) {
868 assert(llvm::itanium_demangle::starts_with(MangledName, '.'));
870
872 if (Error || !MangledName.empty()) {
874 return nullptr;
875 }
877}
878
879
880SymbolNode *Demangler::parse(std::string_view &MangledName) {
881
882
883
884 if (llvm::itanium_demangle::starts_with(MangledName, '.'))
885 return demangleTypeinfoName(MangledName);
886
887 if (llvm::itanium_demangle::starts_with(MangledName, "??@"))
888 return demangleMD5Name(MangledName);
889
890
891 if (!llvm::itanium_demangle::starts_with(MangledName, '?')) {
893 return nullptr;
894 }
895
897
898
899
900 if (SymbolNode *SI = demangleSpecialIntrinsic(MangledName))
901 return SI;
902
903 return demangleDeclarator(MangledName);
904}
905
906TagTypeNode *Demangler::parseTagUniqueName(std::string_view &MangledName) {
909 return nullptr;
910 }
912 if (MangledName.empty()) {
914 return nullptr;
915 }
916
917 return demangleClassType(MangledName);
918}
919
920
921
922
923
924
925
926
928Demangler::demangleVariableEncoding(std::string_view &MangledName,
931
933 VSN->SC = SC;
934
936 return nullptr;
937
938
939
943
946 demanglePointerExtQualifiers(MangledName));
947
948 bool IsMember = false;
949 std::tie(ExtraChildQuals, IsMember) = demangleQualifiers(MangledName);
950
953 demangleFullyQualifiedTypeName(MangledName);
954 (void)BackRefName;
955 }
957
958 break;
959 }
960 default:
961 VSN->Type->Quals = demangleQualifiers(MangledName).first;
962 break;
963 }
964
965 return VSN;
966}
967
968
969
970
971
972
973
974
975
976
977
978
979std::pair<uint64_t, bool>
980Demangler::demangleNumber(std::string_view &MangledName) {
981 bool IsNegative = consumeFront(MangledName, '?');
982
984 uint64_t Ret = MangledName[0] - '0' + 1;
985 MangledName.remove_prefix(1);
986 return {Ret, IsNegative};
987 }
988
989 uint64_t Ret = 0;
990 for (size_t i = 0; i < MangledName.size(); ++i) {
991 char C = MangledName[i];
992 if (C == '@') {
993 MangledName.remove_prefix(i + 1);
994 return {Ret, IsNegative};
995 }
996 if ('A' <= C && C <= 'P') {
997 Ret = (Ret << 4) + (C - 'A');
998 continue;
999 }
1000 break;
1001 }
1002
1004 return {0ULL, false};
1005}
1006
1007uint64_t Demangler::demangleUnsigned(std::string_view &MangledName) {
1008 bool IsNegative = false;
1009 uint64_t Number = 0;
1010 std::tie(Number, IsNegative) = demangleNumber(MangledName);
1011 if (IsNegative)
1014}
1015
1016int64_t Demangler::demangleSigned(std::string_view &MangledName) {
1017 bool IsNegative = false;
1018 uint64_t Number = 0;
1019 std::tie(Number, IsNegative) = demangleNumber(MangledName);
1022 int64_t I = static_cast<int64_t>(Number);
1023 return IsNegative ? -I : I;
1024}
1025
1026
1027
1028void Demangler::memorizeString(std::string_view S) {
1030 return;
1031 for (size_t i = 0; i < Backrefs.NamesCount; ++i)
1032 if (S == Backrefs.Names[i]->Name)
1033 return;
1034 NamedIdentifierNode *N = Arena.alloc();
1035 N->Name = S;
1037}
1038
1040Demangler::demangleBackRefName(std::string_view &MangledName) {
1042
1043 size_t I = MangledName[0] - '0';
1046 return nullptr;
1047 }
1048
1049 MangledName.remove_prefix(1);
1050 return Backrefs.Names[I];
1051}
1052
1053void Demangler::memorizeIdentifier(IdentifierNode *Identifier) {
1054
1055
1056 OutputBuffer OB;
1058 std::string_view Owned = copyString(OB);
1059 memorizeString(Owned);
1060 std::free(OB.getBuffer());
1061}
1062
1064Demangler::demangleTemplateInstantiationName(std::string_view &MangledName,
1066 assert(llvm::itanium_demangle::starts_with(MangledName, "?$"));
1068
1069 BackrefContext OuterContext;
1070 std::swap(OuterContext, Backrefs);
1071
1073 demangleUnqualifiedSymbolName(MangledName, NBB_Simple);
1075 Identifier->TemplateParams = demangleTemplateParameterList(MangledName);
1076
1077 std::swap(OuterContext, Backrefs);
1079 return nullptr;
1080
1082
1083
1084
1088 return nullptr;
1089 }
1090
1091 memorizeIdentifier(Identifier);
1092 }
1093
1095}
1096
1098Demangler::demangleSimpleName(std::string_view &MangledName, bool Memorize) {
1099 std::string_view S = demangleSimpleString(MangledName, Memorize);
1101 return nullptr;
1102
1103 NamedIdentifierNode *Name = Arena.alloc();
1104 Name->Name = S;
1105 return Name;
1106}
1107
1109
1112 return (C <= 'J') ? (C - 'A') : (10 + C - 'K');
1113}
1114
1115uint8_t Demangler::demangleCharLiteral(std::string_view &MangledName) {
1116 assert(!MangledName.empty());
1117 if (!llvm::itanium_demangle::starts_with(MangledName, '?')) {
1118 const uint8_t F = MangledName.front();
1119 MangledName.remove_prefix(1);
1120 return F;
1121 }
1122
1123 MangledName.remove_prefix(1);
1124 if (MangledName.empty())
1125 goto CharLiteralError;
1126
1128
1129 if (MangledName.size() < 2)
1130 goto CharLiteralError;
1131 std::string_view Nibbles = MangledName.substr(0, 2);
1133 goto CharLiteralError;
1134
1137 MangledName.remove_prefix(2);
1138 return (C1 << 4) | C2;
1139 }
1140
1142 const char *Lookup = ",/\\:. \n\t'-";
1143 char C = Lookup[MangledName[0] - '0'];
1144 MangledName.remove_prefix(1);
1145 return C;
1146 }
1147
1148 if (MangledName[0] >= 'a' && MangledName[0] <= 'z') {
1149 char Lookup[26] = {'\xE1', '\xE2', '\xE3', '\xE4', '\xE5', '\xE6', '\xE7',
1150 '\xE8', '\xE9', '\xEA', '\xEB', '\xEC', '\xED', '\xEE',
1151 '\xEF', '\xF0', '\xF1', '\xF2', '\xF3', '\xF4', '\xF5',
1152 '\xF6', '\xF7', '\xF8', '\xF9', '\xFA'};
1153 char C = Lookup[MangledName[0] - 'a'];
1154 MangledName.remove_prefix(1);
1155 return C;
1156 }
1157
1158 if (MangledName[0] >= 'A' && MangledName[0] <= 'Z') {
1159 char Lookup[26] = {'\xC1', '\xC2', '\xC3', '\xC4', '\xC5', '\xC6', '\xC7',
1160 '\xC8', '\xC9', '\xCA', '\xCB', '\xCC', '\xCD', '\xCE',
1161 '\xCF', '\xD0', '\xD1', '\xD2', '\xD3', '\xD4', '\xD5',
1162 '\xD6', '\xD7', '\xD8', '\xD9', '\xDA'};
1163 char C = Lookup[MangledName[0] - 'A'];
1164 MangledName.remove_prefix(1);
1165 return C;
1166 }
1167
1168CharLiteralError:
1170 return '\0';
1171}
1172
1173wchar_t Demangler::demangleWcharLiteral(std::string_view &MangledName) {
1174 uint8_t C1, C2;
1175
1176 C1 = demangleCharLiteral(MangledName);
1177 if (Error || MangledName.empty())
1178 goto WCharLiteralError;
1179 C2 = demangleCharLiteral(MangledName);
1181 goto WCharLiteralError;
1182
1183 return ((wchar_t)C1 << 8) | (wchar_t)C2;
1184
1185WCharLiteralError:
1187 return L'\0';
1188}
1189
1191 assert(Digit <= 15);
1192 *Buffer = (Digit < 10) ? ('0' + Digit) : ('A' + Digit - 10);
1193}
1194
1197
1198
1199
1200
1201
1202
1203 char TempBuffer[17];
1204
1205 ::memset(TempBuffer, 0, sizeof(TempBuffer));
1206 constexpr int MaxPos = sizeof(TempBuffer) - 1;
1207
1208 int Pos = MaxPos - 1;
1209 while (C != 0) {
1210 for (int I = 0; I < 2; ++I) {
1212 C /= 16;
1213 }
1214 }
1215 TempBuffer[Pos--] = 'x';
1217 TempBuffer[Pos--] = '\\';
1218 OB << std::string_view(&TempBuffer[Pos + 1]);
1219}
1220
1222 switch (C) {
1223 case '\0':
1224 OB << "\\0";
1225 return;
1226 case '\'':
1227 OB << "\\\'";
1228 return;
1229 case '\"':
1230 OB << "\\\"";
1231 return;
1232 case '\\':
1233 OB << "\\\\";
1234 return;
1235 case '\a':
1236 OB << "\\a";
1237 return;
1238 case '\b':
1239 OB << "\\b";
1240 return;
1241 case '\f':
1242 OB << "\\f";
1243 return;
1244 case '\n':
1245 OB << "\\n";
1246 return;
1247 case '\r':
1248 OB << "\\r";
1249 return;
1250 case '\t':
1251 OB << "\\t";
1252 return;
1253 case '\v':
1254 OB << "\\v";
1255 return;
1256 default:
1257 break;
1258 }
1259
1260 if (C > 0x1F && C < 0x7F) {
1261
1263 return;
1264 }
1265
1267}
1268
1271 unsigned Count = 0;
1272 while (Length > 0 && *End == 0) {
1274 --End;
1276 }
1278}
1279
1282 unsigned Result = 0;
1283 for (unsigned I = 0; I < Length; ++I) {
1284 if (*StringBytes++ == 0)
1286 }
1288}
1289
1290
1291
1292
1295 assert(NumBytes > 0);
1296
1297
1298 if (NumBytes % 2 == 1)
1299 return 1;
1300
1301
1302
1303
1304 if (NumBytes < 32) {
1306 if (TrailingNulls >= 4 && NumBytes % 4 == 0)
1307 return 4;
1308 if (TrailingNulls >= 2)
1309 return 2;
1310 return 1;
1311 }
1312
1313
1314
1315
1316
1317
1318
1320 if (Nulls >= 2 * NumChars / 3 && NumBytes % 4 == 0)
1321 return 4;
1322 if (Nulls >= NumChars / 3)
1323 return 2;
1324 return 1;
1325}
1326
1328 unsigned CharIndex, unsigned CharBytes) {
1329 assert(CharBytes == 1 || CharBytes == 2 || CharBytes == 4);
1330 unsigned Offset = CharIndex * CharBytes;
1331 unsigned Result = 0;
1332 StringBytes = StringBytes + Offset;
1333 for (unsigned I = 0; I < CharBytes; ++I) {
1334 unsigned C = static_cast<unsigned>(StringBytes[I]);
1336 }
1338}
1339
1341Demangler::demangleVcallThunkNode(std::string_view &MangledName) {
1342 FunctionSymbolNode *FSN = Arena.alloc();
1343 VcallThunkIdentifierNode *VTIN = Arena.alloc();
1346
1347 FSN->Name = demangleNameScopeChain(MangledName, VTIN);
1351 VTIN->OffsetInVTable = demangleUnsigned(MangledName);
1356 return (Error) ? nullptr : FSN;
1357}
1358
1360Demangler::demangleStringLiteral(std::string_view &MangledName) {
1361
1362 OutputBuffer OB;
1363 std::string_view CRC;
1364 uint64_t StringByteSize;
1365 bool IsWcharT = false;
1366 bool IsNegative = false;
1367 size_t CrcEndPos = 0;
1368 char F;
1369
1370 EncodedStringLiteralNode *Result = Arena.alloc();
1371
1372
1374 goto StringLiteralError;
1375 if (MangledName.empty())
1376 goto StringLiteralError;
1377
1378
1379 F = MangledName.front();
1380 MangledName.remove_prefix(1);
1381 switch (F) {
1382 case '1':
1383 IsWcharT = true;
1385 case '0':
1386 break;
1387 default:
1388 goto StringLiteralError;
1389 }
1390
1391
1392 std::tie(StringByteSize, IsNegative) = demangleNumber(MangledName);
1393 if (Error || IsNegative || StringByteSize < (IsWcharT ? 2 : 1))
1394 goto StringLiteralError;
1395
1396
1397 CrcEndPos = MangledName.find('@');
1398 if (CrcEndPos == std::string_view::npos)
1399 goto StringLiteralError;
1400 CRC = MangledName.substr(0, CrcEndPos);
1401 MangledName.remove_prefix(CrcEndPos + 1);
1402 if (MangledName.empty())
1403 goto StringLiteralError;
1404
1405 if (IsWcharT) {
1407 if (StringByteSize > 64)
1408 Result->IsTruncated = true;
1409
1411
1412 if (StringByteSize % 2 != 0)
1413 goto StringLiteralError;
1414 if (StringByteSize == 0)
1415 goto StringLiteralError;
1416 if (MangledName.size() < 2)
1417 goto StringLiteralError;
1418 wchar_t W = demangleWcharLiteral(MangledName);
1419 if (StringByteSize != 2 || Result->IsTruncated)
1421 StringByteSize -= 2;
1423 goto StringLiteralError;
1424 }
1425 } else {
1426
1427
1428 constexpr unsigned MaxStringByteLength = 32 * 4;
1429 uint8_t StringBytes[MaxStringByteLength];
1430
1431 unsigned BytesDecoded = 0;
1433 if (MangledName.size() < 1 || BytesDecoded >= MaxStringByteLength)
1434 goto StringLiteralError;
1435 StringBytes[BytesDecoded++] = demangleCharLiteral(MangledName);
1436 }
1437
1438 if (StringByteSize > BytesDecoded)
1439 Result->IsTruncated = true;
1440
1441 unsigned CharBytes =
1443 assert(StringByteSize % CharBytes == 0);
1444 switch (CharBytes) {
1445 case 1:
1447 break;
1448 case 2:
1450 break;
1451 case 4:
1453 break;
1454 default:
1456 }
1457 const unsigned NumChars = BytesDecoded / CharBytes;
1458 for (unsigned CharIndex = 0; CharIndex < NumChars; ++CharIndex) {
1459 unsigned NextChar =
1461 if (CharIndex + 1 < NumChars || Result->IsTruncated)
1463 }
1464 }
1465
1466 Result->DecodedString = copyString(OB);
1467 std::free(OB.getBuffer());
1469
1470StringLiteralError:
1472 std::free(OB.getBuffer());
1473 return nullptr;
1474}
1475
1476
1477
1478std::string_view Demangler::demangleSimpleString(std::string_view &MangledName,
1479 bool Memorize) {
1480 std::string_view S;
1481 for (size_t i = 0; i < MangledName.size(); ++i) {
1482 if (MangledName[i] != '@')
1483 continue;
1484 if (i == 0)
1485 break;
1486 S = MangledName.substr(0, i);
1487 MangledName.remove_prefix(i + 1);
1488
1489 if (Memorize)
1490 memorizeString(S);
1491 return S;
1492 }
1493
1495 return {};
1496}
1497
1499Demangler::demangleAnonymousNamespaceName(std::string_view &MangledName) {
1500 assert(llvm::itanium_demangle::starts_with(MangledName, "?A"));
1502
1503 NamedIdentifierNode *Node = Arena.alloc();
1504 Node->Name = "`anonymous namespace'";
1505 size_t EndPos = MangledName.find('@');
1506 if (EndPos == std::string_view::npos) {
1508 return nullptr;
1509 }
1510 std::string_view NamespaceKey = MangledName.substr(0, EndPos);
1511 memorizeString(NamespaceKey);
1512 MangledName = MangledName.substr(EndPos + 1);
1513 return Node;
1514}
1515
1517Demangler::demangleLocallyScopedNamePiece(std::string_view &MangledName) {
1519
1520 NamedIdentifierNode *Identifier = Arena.alloc();
1522 uint64_t Number = 0;
1523 bool IsNegative = false;
1524 std::tie(Number, IsNegative) = demangleNumber(MangledName);
1525 assert(!IsNegative);
1526
1527
1529
1533 return nullptr;
1534
1535
1536 OutputBuffer OB;
1537 OB << '`';
1539 OB << '\'';
1540 OB << "::`" << Number << "'";
1541
1543 std::free(OB.getBuffer());
1545}
1546
1547
1549Demangler::demangleFullyQualifiedTypeName(std::string_view &MangledName) {
1551 demangleUnqualifiedTypeName(MangledName, true);
1553 return nullptr;
1555
1556 QualifiedNameNode *QN = demangleNameScopeChain(MangledName, Identifier);
1558 return nullptr;
1560 return QN;
1561}
1562
1563
1564
1565
1567Demangler::demangleFullyQualifiedSymbolName(std::string_view &MangledName) {
1568
1569
1570
1571
1572
1574 demangleUnqualifiedSymbolName(MangledName, NBB_Simple);
1576 return nullptr;
1577
1578 QualifiedNameNode *QN = demangleNameScopeChain(MangledName, Identifier);
1580 return nullptr;
1581
1585 return nullptr;
1586 }
1587 StructorIdentifierNode *SIN =
1588 static_cast<StructorIdentifierNode *>(Identifier);
1590 SIN->Class = static_cast<IdentifierNode *>(ClassNode);
1591 }
1593 return QN;
1594}
1595
1597Demangler::demangleUnqualifiedTypeName(std::string_view &MangledName,
1598 bool Memorize) {
1599
1600
1601
1602
1604 return demangleBackRefName(MangledName);
1605
1606 if (llvm::itanium_demangle::starts_with(MangledName, "?$"))
1607 return demangleTemplateInstantiationName(MangledName, NBB_Template);
1608
1609 return demangleSimpleName(MangledName, Memorize);
1610}
1611
1613Demangler::demangleUnqualifiedSymbolName(std::string_view &MangledName,
1616 return demangleBackRefName(MangledName);
1617 if (llvm::itanium_demangle::starts_with(MangledName, "?$"))
1618 return demangleTemplateInstantiationName(MangledName, NBB);
1619 if (llvm::itanium_demangle::starts_with(MangledName, '?'))
1620 return demangleFunctionIdentifierCode(MangledName);
1621 return demangleSimpleName(MangledName, (NBB & NBB_Simple) != 0);
1622}
1623
1625Demangler::demangleNameScopePiece(std::string_view &MangledName) {
1627 return demangleBackRefName(MangledName);
1628
1629 if (llvm::itanium_demangle::starts_with(MangledName, "?$"))
1630 return demangleTemplateInstantiationName(MangledName, NBB_Template);
1631
1632 if (llvm::itanium_demangle::starts_with(MangledName, "?A"))
1633 return demangleAnonymousNamespaceName(MangledName);
1634
1636 return demangleLocallyScopedNamePiece(MangledName);
1637
1638 return demangleSimpleName(MangledName, true);
1639}
1640
1642Demangler::demangleNameScopeChain(std::string_view &MangledName,
1645
1646 Head->N = UnqualifiedName;
1647
1648 size_t Count = 1;
1652 NewHead->Next = Head;
1653 Head = NewHead;
1654
1655 if (MangledName.empty()) {
1657 return nullptr;
1658 }
1659
1661 IdentifierNode *Elem = demangleNameScopePiece(MangledName);
1663 return nullptr;
1664
1665 Head->N = Elem;
1666 }
1667
1668 QualifiedNameNode *QN = Arena.alloc();
1670 return QN;
1671}
1672
1673FuncClass Demangler::demangleFunctionClass(std::string_view &MangledName) {
1674 const char F = MangledName.front();
1675 MangledName.remove_prefix(1);
1676 switch (F) {
1677 case '9':
1679 case 'A':
1681 case 'B':
1683 case 'C':
1685 case 'D':
1687 case 'E':
1689 case 'F':
1691 case 'G':
1693 case 'H':
1695 case 'I':
1697 case 'J':
1699 case 'K':
1701 case 'L':
1703 case 'M':
1705 case 'N':
1707 case 'O':
1709 case 'P':
1711 case 'Q':
1713 case 'R':
1715 case 'S':
1717 case 'T':
1719 case 'U':
1721 case 'V':
1723 case 'W':
1725 case 'X':
1727 case 'Y':
1729 case 'Z':
1731 case '$': {
1735 if (MangledName.empty())
1736 break;
1737 const char F = MangledName.front();
1738 MangledName.remove_prefix(1);
1739 switch (F) {
1740 case '0':
1742 case '1':
1744 case '2':
1746 case '3':
1748 case '4':
1750 case '5':
1752 }
1753 }
1754 }
1755
1758}
1759
1761Demangler::demangleCallingConvention(std::string_view &MangledName) {
1762 if (MangledName.empty()) {
1765 }
1766
1767 const char F = MangledName.front();
1768 MangledName.remove_prefix(1);
1769 switch (F) {
1770 case 'A':
1771 case 'B':
1773 case 'C':
1774 case 'D':
1776 case 'E':
1777 case 'F':
1779 case 'G':
1780 case 'H':
1782 case 'I':
1783 case 'J':
1785 case 'M':
1786 case 'N':
1788 case 'O':
1789 case 'P':
1791 case 'Q':
1793 case 'S':
1795 case 'W':
1797 }
1798
1800}
1801
1803Demangler::demangleVariableStorageClass(std::string_view &MangledName) {
1804 assert(MangledName.front() >= '0' && MangledName.front() <= '4');
1805
1806 const char F = MangledName.front();
1807 MangledName.remove_prefix(1);
1808 switch (F) {
1809 case '0':
1811 case '1':
1813 case '2':
1815 case '3':
1817 case '4':
1819 }
1821}
1822
1823std::pair<Qualifiers, bool>
1824Demangler::demangleQualifiers(std::string_view &MangledName) {
1825 if (MangledName.empty()) {
1827 return std::make_pair(Q_None, false);
1828 }
1829
1830 const char F = MangledName.front();
1831 MangledName.remove_prefix(1);
1832 switch (F) {
1833
1834 case 'Q':
1835 return std::make_pair(Q_None, true);
1836 case 'R':
1837 return std::make_pair(Q_Const, true);
1838 case 'S':
1839 return std::make_pair(Q_Volatile, true);
1840 case 'T':
1842
1843 case 'A':
1844 return std::make_pair(Q_None, false);
1845 case 'B':
1846 return std::make_pair(Q_Const, false);
1847 case 'C':
1848 return std::make_pair(Q_Volatile, false);
1849 case 'D':
1851 }
1853 return std::make_pair(Q_None, false);
1854}
1855
1856
1857
1858TypeNode *Demangler::demangleType(std::string_view &MangledName,
1863 std::tie(Quals, IsMember) = demangleQualifiers(MangledName);
1866 std::tie(Quals, IsMember) = demangleQualifiers(MangledName);
1867 }
1868
1869 if (MangledName.empty()) {
1871 return nullptr;
1872 }
1873
1874 TypeNode *Ty = nullptr;
1876 Ty = demangleClassType(MangledName);
1878 if (isMemberPointer(MangledName, Error))
1879 Ty = demangleMemberPointerType(MangledName);
1880 else if ()
1881 Ty = demanglePointerType(MangledName);
1882 else
1883 return nullptr;
1885 Ty = demangleArrayType(MangledName);
1888 Ty = demangleFunctionType(MangledName, true);
1889 else {
1890 assert(llvm::itanium_demangle::starts_with(MangledName, "$$A6"));
1892 Ty = demangleFunctionType(MangledName, false);
1893 }
1895 Ty = demangleCustomType(MangledName);
1896 } else {
1897 Ty = demanglePrimitiveType(MangledName);
1898 }
1899
1900 if (!Ty || Error)
1901 return Ty;
1903 return Ty;
1904}
1905
1906bool Demangler::demangleThrowSpecification(std::string_view &MangledName) {
1908 return true;
1910 return false;
1911
1913 return false;
1914}
1915
1917Demangler::demangleFunctionType(std::string_view &MangledName,
1918 bool HasThisQuals) {
1919 FunctionSignatureNode *FTy = Arena.alloc();
1920
1921 if (HasThisQuals) {
1922 FTy->Quals = demanglePointerExtQualifiers(MangledName);
1924 FTy->Quals = Qualifiers(FTy->Quals | demangleQualifiers(MangledName).first);
1925 }
1926
1927
1928 FTy->CallConvention = demangleCallingConvention(MangledName);
1929
1930
1931
1932 bool IsStructor = consumeFront(MangledName, '@');
1933 if (!IsStructor)
1935
1936 FTy->Params = demangleFunctionParameterList(MangledName, FTy->IsVariadic);
1937
1938 FTy->IsNoexcept = demangleThrowSpecification(MangledName);
1939
1940 return FTy;
1941}
1942
1944Demangler::demangleFunctionEncoding(std::string_view &MangledName) {
1948
1949 if (MangledName.empty()) {
1951 return nullptr;
1952 }
1953
1954 FuncClass FC = demangleFunctionClass(MangledName);
1956
1957 FunctionSignatureNode *FSN = nullptr;
1958 ThunkSignatureNode *TTN = nullptr;
1960 TTN = Arena.alloc();
1963 TTN = Arena.alloc();
1967 }
1970 }
1971
1973
1974
1975
1976 FSN = Arena.alloc();
1977 } else {
1979 FSN = demangleFunctionType(MangledName, HasThisQuals);
1980 }
1981
1983 return nullptr;
1984
1985 if (TTN) {
1986 *static_cast<FunctionSignatureNode *>(TTN) = *FSN;
1987 FSN = TTN;
1988 }
1990
1991 FunctionSymbolNode *Symbol = Arena.alloc();
1992 Symbol->Signature = FSN;
1994}
1995
1996CustomTypeNode *Demangler::demangleCustomType(std::string_view &MangledName) {
1997 assert(llvm::itanium_demangle::starts_with(MangledName, '?'));
1998 MangledName.remove_prefix(1);
1999
2000 CustomTypeNode *CTN = Arena.alloc();
2001 CTN->Identifier = demangleUnqualifiedTypeName(MangledName, true);
2005 return nullptr;
2006 return CTN;
2007}
2008
2009
2011Demangler::demanglePrimitiveType(std::string_view &MangledName) {
2014
2015 const char F = MangledName.front();
2016 MangledName.remove_prefix(1);
2017 switch (F) {
2018 case 'X':
2020 case 'D':
2022 case 'C':
2024 case 'E':
2026 case 'F':
2028 case 'G':
2030 case 'H':
2032 case 'I':
2034 case 'J':
2036 case 'K':
2038 case 'M':
2040 case 'N':
2042 case 'O':
2044 case '_': {
2045 if (MangledName.empty()) {
2047 return nullptr;
2048 }
2049 const char F = MangledName.front();
2050 MangledName.remove_prefix(1);
2051 switch (F) {
2052 case 'N':
2054 case 'J':
2056 case 'K':
2058 case 'W':
2060 case 'Q':
2062 case 'S':
2064 case 'U':
2066 case 'P':
2068 case 'T':
2070 }
2071 break;
2072 }
2073 }
2075 return nullptr;
2076}
2077
2078TagTypeNode *Demangler::demangleClassType(std::string_view &MangledName) {
2079 TagTypeNode *TT = nullptr;
2080
2081 const char F = MangledName.front();
2082 MangledName.remove_prefix(1);
2083 switch (F) {
2084 case 'T':
2086 break;
2087 case 'U':
2089 break;
2090 case 'V':
2092 break;
2093 case 'W':
2096 return nullptr;
2097 }
2099 break;
2100 default:
2102 }
2103
2104 TT->QualifiedName = demangleFullyQualifiedTypeName(MangledName);
2105 return TT;
2106}
2107
2108
2109
2110PointerTypeNode *Demangler::demanglePointerType(std::string_view &MangledName) {
2111 PointerTypeNode *Pointer = Arena.alloc();
2112
2115
2117 Pointer->Pointee = demangleFunctionType(MangledName, false);
2119 }
2120
2121 Qualifiers ExtQuals = demanglePointerExtQualifiers(MangledName);
2123
2124 Pointer->PointerAuthQualifier = createPointerAuthQualifier(MangledName);
2125
2128}
2129
2131Demangler::demangleMemberPointerType(std::string_view &MangledName) {
2132 PointerTypeNode *Pointer = Arena.alloc();
2133
2137
2138 Qualifiers ExtQuals = demanglePointerExtQualifiers(MangledName);
2140
2141
2142
2144 Pointer->ClassParent = demangleFullyQualifiedTypeName(MangledName);
2145 Pointer->Pointee = demangleFunctionType(MangledName, true);
2146 } else {
2149 std::tie(PointeeQuals, IsMember) = demangleQualifiers(MangledName);
2151 Pointer->ClassParent = demangleFullyQualifiedTypeName(MangledName);
2152
2155 Pointer->Pointee->Quals = PointeeQuals;
2156 }
2157
2159}
2160
2162Demangler::demanglePointerExtQualifiers(std::string_view &MangledName) {
2170
2171 return Quals;
2172}
2173
2174std::optionalPointerAuthQualifierNode::ArgArray
2175Demangler::demanglePointerAuthQualifier(std::string_view &MangledName) {
2176 if ((MangledName, "__ptrauth"))
2177 return std::nullopt;
2178
2181
2182 for (unsigned I = 0; I < NumArgs; ++I) {
2183 bool IsNegative = false;
2184 uint64_t Value = 0;
2185 std::tie(Value, IsNegative) = demangleNumber(MangledName);
2186 if (IsNegative)
2187 return std::nullopt;
2188
2190 }
2191
2193}
2194
2196Demangler::createPointerAuthQualifier(std::string_view &MangledName) {
2198 std::optionalPointerAuthQualifierNode::ArgArray Vals =
2199 demanglePointerAuthQualifier(MangledName);
2200
2201 if (!Vals)
2202 return nullptr;
2203
2204 PointerAuthQualifierNode *PtrAuthQual =
2205 Arena.alloc();
2206 NodeArrayNode *Array = Arena.alloc();
2208 Array->Count = NumArgs;
2210
2211 for (unsigned I = 0; I < NumArgs; ++I)
2212 Array->Nodes[I] = Arena.alloc((*Vals)[I], false);
2213
2214 return PtrAuthQual;
2215}
2216
2217ArrayTypeNode *Demangler::demangleArrayType(std::string_view &MangledName) {
2218 assert(MangledName.front() == 'Y');
2219 MangledName.remove_prefix(1);
2220
2221 uint64_t Rank = 0;
2222 bool IsNegative = false;
2223 std::tie(Rank, IsNegative) = demangleNumber(MangledName);
2224 if (IsNegative || Rank == 0) {
2226 return nullptr;
2227 }
2228
2229 ArrayTypeNode *ATy = Arena.alloc();
2232
2233 for (uint64_t I = 0; I < Rank; ++I) {
2234 uint64_t D = 0;
2235 std::tie(D, IsNegative) = demangleNumber(MangledName);
2236 if (Error || IsNegative) {
2238 return nullptr;
2239 }
2240 Tail->N = Arena.alloc(D, IsNegative);
2241 if (I + 1 < Rank) {
2244 }
2245 }
2247
2250 std::tie(ATy->Quals, IsMember) = demangleQualifiers(MangledName);
2251 if (IsMember) {
2253 return nullptr;
2254 }
2255 }
2256
2258 return ATy;
2259}
2260
2261
2263Demangler::demangleFunctionParameterList(std::string_view &MangledName,
2264 bool &IsVariadic) {
2265
2267 return nullptr;
2268
2271 size_t Count = 0;
2272 while ( && !llvm::itanium_demangle::starts_with(MangledName, '@') &&
2273 !llvm::itanium_demangle::starts_with(MangledName, 'Z')) {
2275
2277 size_t N = MangledName[0] - '0';
2280 return nullptr;
2281 }
2282 MangledName.remove_prefix(1);
2283
2286 Current = &(*Current)->Next;
2287 continue;
2288 }
2289
2290 size_t OldSize = MangledName.size();
2291
2294 if (!TN || Error)
2295 return nullptr;
2296
2297 (*Current)->N = TN;
2298
2299 size_t CharsConsumed = OldSize - MangledName.size();
2300 assert(CharsConsumed != 0);
2301
2302
2303
2306
2307 Current = &(*Current)->Next;
2308 }
2309
2311 return nullptr;
2312
2314
2315
2316
2318 return NA;
2319
2321 IsVariadic = true;
2322 return NA;
2323 }
2324
2326}
2327
2329Demangler::demangleTemplateParameterList(std::string_view &MangledName) {
2332 size_t Count = 0;
2333
2334 while (!llvm::itanium_demangle::starts_with(MangledName, '@')) {
2337
2338 continue;
2339 }
2340
2342
2343
2345
2347
2348
2349 const bool IsAutoNTTP = consumeFront(MangledName, "$M");
2350 if (IsAutoNTTP) {
2351
2352
2353
2354
2357 return nullptr;
2358 }
2359
2360 TemplateParameterReferenceNode *TPRN = nullptr;
2362
2363 TP.N = demangleFullyQualifiedTypeName(MangledName);
2364 } else if (consumeFront(MangledName, "$$B")) {
2365
2367 } else if (consumeFront(MangledName, "$$C")) {
2368
2370 } else if (startsWith(MangledName, "$1", "1", !IsAutoNTTP) ||
2371 startsWith(MangledName, "$H", "H", !IsAutoNTTP) ||
2372 startsWith(MangledName, "$I", "I", !IsAutoNTTP) ||
2373 startsWith(MangledName, "$J", "J", !IsAutoNTTP)) {
2374
2375 TP.N = TPRN = Arena.alloc();
2377
2378 if (!IsAutoNTTP)
2379 MangledName.remove_prefix(1);
2380
2381
2382
2383
2384
2385 char InheritanceSpecifier = MangledName.front();
2386 MangledName.remove_prefix(1);
2387 SymbolNode *S = nullptr;
2388 if (llvm::itanium_demangle::starts_with(MangledName, '?')) {
2389 S = parse(MangledName);
2392 return nullptr;
2393 }
2395 }
2396
2397 switch (InheritanceSpecifier) {
2398 case 'J':
2400 demangleSigned(MangledName);
2402 case 'I':
2404 demangleSigned(MangledName);
2406 case 'H':
2408 demangleSigned(MangledName);
2410 case '1':
2411 break;
2412 default:
2414 }
2417 } else if (llvm::itanium_demangle::starts_with(MangledName, "$E?")) {
2419
2420 TP.N = TPRN = Arena.alloc();
2423 } else if (startsWith(MangledName, "$F", "F", !IsAutoNTTP) ||
2424 startsWith(MangledName, "$G", "G", !IsAutoNTTP)) {
2425 TP.N = TPRN = Arena.alloc();
2426
2427
2428 if (!IsAutoNTTP)
2429 MangledName.remove_prefix(1);
2430 char InheritanceSpecifier = MangledName.front();
2431 MangledName.remove_prefix(1);
2432
2433 switch (InheritanceSpecifier) {
2434 case 'G':
2436 demangleSigned(MangledName);
2438 case 'F':
2440 demangleSigned(MangledName);
2442 demangleSigned(MangledName);
2443 break;
2444 default:
2446 }
2448
2449 } else if (consumeFront(MangledName, "$0", "0", !IsAutoNTTP)) {
2450
2451 bool IsNegative = false;
2452 uint64_t Value = 0;
2453 std::tie(Value, IsNegative) = demangleNumber(MangledName);
2454
2455 TP.N = Arena.alloc(Value, IsNegative);
2456 } else {
2458 }
2460 return nullptr;
2461
2462 Current = &TP.Next;
2463 }
2464
2465
2467
2468
2469
2470 assert(llvm::itanium_demangle::starts_with(
2471 MangledName, '@'));
2474}
2475
2476void Demangler::dumpBackReferences() {
2477 std::printf("%d function parameter backreferences\n",
2478 (int)Backrefs.FunctionParamCount);
2479
2480
2482 for (size_t I = 0; I < Backrefs.FunctionParamCount; ++I) {
2483 OB.setCurrentPosition(0);
2484
2485 TypeNode *T = Backrefs.FunctionParams[I];
2487
2488 std::string_view B = OB;
2489 std::printf(" [%d] - %.*s\n", (int)I, (int)B.size(), B.data());
2490 }
2491 std::free(OB.getBuffer());
2492
2493 if (Backrefs.FunctionParamCount > 0)
2494 std::printf("\n");
2495 std::printf("%d name backreferences\n", (int)Backrefs.NamesCount);
2496 for (size_t I = 0; I < Backrefs.NamesCount; ++I) {
2497 std::printf(" [%d] - %.*s\n", (int)I, (int)Backrefs.Names[I]->Name.size(),
2498 Backrefs.Names[I]->Name.data());
2499 }
2500 if (Backrefs.NamesCount > 0)
2501 std::printf("\n");
2502}
2503
2504std::optional<size_t>
2506 std::string_view ProcessedName{MangledName};
2507
2508
2510 return std::nullopt;
2511
2512
2513
2515 D.demangleFullyQualifiedSymbolName(ProcessedName);
2516 if (D.Error)
2517 return std::nullopt;
2518
2519 return MangledName.length() - ProcessedName.length();
2520}
2521
2525
2526 std::string_view Name{MangledName};
2528 if (.Error && NMangled)
2529 *NMangled = MangledName.size() - Name.size();
2530
2532 D.dumpBackReferences();
2533
2545
2547 char *Buf;
2548 if (D.Error)
2550 else {
2552 AST->output(OB, OF);
2553 OB += '\0';
2554 Buf = OB.getBuffer();
2555 }
2556
2558 *Status = InternalStatus;
2560}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
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")
#define DEMANGLE_FALLTHROUGH
#define DEMANGLE_UNREACHABLE
static bool startsWithLocalScopePattern(std::string_view S)
Definition MicrosoftDemangle.cpp:171
static bool isArrayType(std::string_view S)
Definition MicrosoftDemangle.cpp:238
static unsigned countEmbeddedNulls(const uint8_t *StringBytes, unsigned Length)
Definition MicrosoftDemangle.cpp:1280
static bool startsWithDigit(std::string_view S)
Definition MicrosoftDemangle.cpp:33
static QualifiedNameNode * synthesizeQualifiedName(ArenaAllocator &Arena, IdentifierNode *Identifier)
Definition MicrosoftDemangle.cpp:396
static void outputEscapedChar(OutputBuffer &OB, unsigned C)
Definition MicrosoftDemangle.cpp:1221
static bool isCustomType(std::string_view S)
Definition MicrosoftDemangle.cpp:221
static void outputHex(OutputBuffer &OB, unsigned C)
Definition MicrosoftDemangle.cpp:1195
static std::pair< Qualifiers, PointerAffinity > demanglePointerCVQualifiers(std::string_view &MangledName)
Definition MicrosoftDemangle.cpp:255
static VariableSymbolNode * synthesizeVariable(ArenaAllocator &Arena, TypeNode *Type, std::string_view VariableName)
Definition MicrosoftDemangle.cpp:412
static unsigned decodeMultiByteChar(const uint8_t *StringBytes, unsigned CharIndex, unsigned CharBytes)
Definition MicrosoftDemangle.cpp:1327
static void writeHexDigit(char *Buffer, uint8_t Digit)
Definition MicrosoftDemangle.cpp:1190
static FunctionRefQualifier demangleFunctionRefQualifier(std::string_view &MangledName)
Definition MicrosoftDemangle.cpp:246
static bool isRebasedHexDigit(char C)
Definition MicrosoftDemangle.cpp:1108
static NodeArrayNode * nodeListToNodeArray(ArenaAllocator &Arena, NodeList *Head, size_t Count)
Definition MicrosoftDemangle.cpp:279
static uint8_t rebasedHexDigitToNumber(char C)
Definition MicrosoftDemangle.cpp:1110
static unsigned countTrailingNullBytes(const uint8_t *StringBytes, int Length)
Definition MicrosoftDemangle.cpp:1269
static NamedIdentifierNode * synthesizeNamedIdentifier(ArenaAllocator &Arena, std::string_view Name)
Definition MicrosoftDemangle.cpp:389
static bool startsWith(std::string_view S, std::string_view PrefixA, std::string_view PrefixB, bool A)
Definition MicrosoftDemangle.cpp:62
static bool consumeFront(std::string_view &S, char C)
Definition MicrosoftDemangle.cpp:42
static bool isFunctionType(std::string_view S)
Definition MicrosoftDemangle.cpp:240
static bool isPointerType(std::string_view S)
Definition MicrosoftDemangle.cpp:223
static unsigned guessCharByteSize(const uint8_t *StringBytes, unsigned NumChars, uint64_t NumBytes)
Definition MicrosoftDemangle.cpp:1293
static SpecialIntrinsicKind consumeSpecialIntrinsicKind(std::string_view &MangledName)
Definition MicrosoftDemangle.cpp:135
static bool isTagType(std::string_view S)
Definition MicrosoftDemangle.cpp:210
static int Lookup(ArrayRef< TableEntry > Table, unsigned Opcode)
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.
T * alloc(Args &&... ConstructorArgs)
char * allocUnalignedBuffer(size_t Size)
T * allocArray(size_t Count)
DEMANGLE_ABI SymbolNode * parse(std::string_view &MangledName)
Definition MicrosoftDemangle.cpp:880
@ Tail
Attemps to make calls as fast as possible while guaranteeing that tail call optimization can always b...
@ C
The default llvm calling convention, compatible with C.
@ OB
OB - OneByte - Set if this instruction has a one byte opcode.
Scope
Defines the scope in which this symbol should be visible: Default – Visible in the public interface o...
FunctionIdentifierCodeGroup
@ ConversionOperatorIdentifier
@ RttiBaseClassDescriptor
@ DynamicAtexitDestructor
@ RttiClassHierarchyDescriptor
NodeAddr< NodeBase * > Node
SmallVector< Node, 4 > NodeList
This is an optimization pass for GlobalISel generic memory operations.
FunctionAddr VTableAddr Value
@ demangle_invalid_mangled_name
DEMANGLE_ABI std::optional< size_t > getArm64ECInsertionPointInMangledName(std::string_view MangledName)
Definition MicrosoftDemangle.cpp:2505
FunctionAddr VTableAddr Count
DEMANGLE_ABI char * microsoftDemangle(std::string_view mangled_name, size_t *n_read, int *status, MSDemangleFlags Flags=MSDF_None)
Demangles the Microsoft symbol pointed at by mangled_name and returns it.
Definition MicrosoftDemangle.cpp:2522
@ MSDF_NoCallingConvention
FunctionAddr VTableAddr Next
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
Node * N
Definition MicrosoftDemangle.cpp:38
NodeList * Next
Definition MicrosoftDemangle.cpp:39
NodeArrayNode * Dimensions
static constexpr size_t Max
NamedIdentifierNode * Names[Max]
TypeNode * FunctionParams[Max]
size_t FunctionParamCount
IdentifierNode * Identifier
VariableSymbolNode * Variable
FunctionRefQualifier RefQualifier
CallingConv CallConvention
FunctionSignatureNode * Signature
std::array< uint64_t, NumArgs > ArgArray
static constexpr unsigned NumArgs
NodeArrayNode * Components
QualifiedNameNode * ClassParent
IdentifierNode * getUnqualifiedIdentifier()
NodeArrayNode * Components
NodeArrayNode * TargetNames
void output(OutputBuffer &OB, OutputFlags Flags) const override
std::array< int64_t, 3 > ThunkOffsets