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) {

285 N->Nodes[I] = Head->N;

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 (Error)

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 (consumeFront(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 (Error && !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 (D.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