LLVM: lib/CodeGen/AsmPrinter/CodeViewDebug.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

9

10

11

12

33#include "llvm/Config/llvm-config.h"

68#include

69#include

70#include

71#include

72#include

73

74using namespace llvm;

76

77namespace {

79public:

80 CVMCAdapter(MCStreamer &OS, TypeCollection &TypeTable)

81 : OS(&OS), TypeTable(TypeTable) {}

82

83 void emitBytes(StringRef Data) override { OS->emitBytes(Data); }

84

85 void emitIntValue(uint64_t Value, unsigned Size) override {

86 OS->emitIntValueInHex(Value, Size);

87 }

88

89 void emitBinaryData(StringRef Data) override { OS->emitBinaryData(Data); }

90

91 void AddComment(const Twine &T) override { OS->AddComment(T); }

92

93 void AddRawComment(const Twine &T) override { OS->emitRawComment(T); }

94

95 bool isVerboseAsm() override { return OS->isVerboseAsm(); }

96

97 std::string getTypeName(TypeIndex TI) override {

102 else

103 TypeName = std::string(TypeTable.getTypeName(TI));

104 }

106 }

107

108private:

109 MCStreamer *OS = nullptr;

110 TypeCollection &TypeTable;

111};

112}

113

115 switch (Type) {

121

122

130 default:

131 report_fatal_error("target architecture doesn't map to a CodeView CPUType");

132 }

133}

134

137

138StringRef CodeViewDebug::getFullFilepath(const DIFile *File) {

139 std::string &Filepath = FileToFilepathMap[File];

140 if (!Filepath.empty())

141 return Filepath;

142

143 StringRef Dir = File->getDirectory(), Filename = File->getFilename();

144

145

146

147 if (Dir.starts_with("/") || Filename.starts_with("/")) {

149 return Filename;

150 Filepath = std::string(Dir);

151 if (Dir.back() != '/')

152 Filepath += '/';

153 Filepath += Filename;

154 return Filepath;

155 }

156

157

158

159

160

161 if (Filename.find(':') == 1)

162 Filepath = std::string(Filename);

163 else

164 Filepath = (Dir + "\\" + Filename).str();

165

166

167

168

170

171

172 size_t Cursor = 0;

173 while ((Cursor = Filepath.find("\\.\\", Cursor)) != std:🧵:npos)

174 Filepath.erase(Cursor, 2);

175

176

177

178 Cursor = 0;

179 while ((Cursor = Filepath.find("\\..\\", Cursor)) != std:🧵:npos) {

180

181 if (Cursor == 0)

182 break;

183

184 size_t PrevSlash = Filepath.rfind('\\', Cursor - 1);

185 if (PrevSlash == std:🧵:npos)

186

187 break;

188

189 Filepath.erase(PrevSlash, Cursor + 3 - PrevSlash);

190

191 Cursor = PrevSlash;

192 }

193

194

195 Cursor = 0;

196 while ((Cursor = Filepath.find("\\\\", Cursor)) != std:🧵:npos)

197 Filepath.erase(Cursor, 1);

198

199 return Filepath;

200}

201

202unsigned CodeViewDebug::maybeRecordFile(const DIFile *F) {

203 StringRef FullPath = getFullFilepath(F);

204 unsigned NextId = FileIdMap.size() + 1;

205 auto Insertion = FileIdMap.insert(std::make_pair(FullPath, NextId));

206 if (Insertion.second) {

207

208 ArrayRef<uint8_t> ChecksumAsBytes;

210 if (F->getChecksum()) {

211 std::string Checksum = fromHex(F->getChecksum()->Value);

212 void *CKMem = OS.getContext().allocate(Checksum.size(), 1);

213 memcpy(CKMem, Checksum.data(), Checksum.size());

214 ChecksumAsBytes = ArrayRef<uint8_t>(

215 reinterpret_cast<const uint8_t *>(CKMem), Checksum.size());

216 switch (F->getChecksum()->Kind) {

218 CSKind = FileChecksumKind::MD5;

219 break;

221 CSKind = FileChecksumKind::SHA1;

222 break;

224 CSKind = FileChecksumKind::SHA256;

225 break;

226 }

227 }

228 bool Success = OS.emitCVFileDirective(NextId, FullPath, ChecksumAsBytes,

229 static_cast<unsigned>(CSKind));

232 }

233 return Insertion.first->second;

234}

235

236CodeViewDebug::InlineSite &

237CodeViewDebug::getInlineSite(const DILocation *InlinedAt,

239 auto SiteInsertion = CurFn->InlineSites.try_emplace(InlinedAt);

240 InlineSite *Site = &SiteInsertion.first->second;

241 if (SiteInsertion.second) {

242 unsigned ParentFuncId = CurFn->FuncId;

243 if (const DILocation *OuterIA = InlinedAt->getInlinedAt())

244 ParentFuncId =

245 getInlineSite(OuterIA, InlinedAt->getScope()->getSubprogram())

246 .SiteFuncId;

247

248 Site->SiteFuncId = NextFuncId++;

249 OS.emitCVInlineSiteIdDirective(

250 Site->SiteFuncId, ParentFuncId, maybeRecordFile(InlinedAt->getFile()),

251 InlinedAt->getLine(), InlinedAt->getColumn(), SMLoc());

253 InlinedSubprograms.insert(Inlinee);

254 auto InlineeIdx = getFuncIdForSubprogram(Inlinee);

255

256 if (InlinedAt->getInlinedAt() == nullptr)

257 CurFn->Inlinees.insert(InlineeIdx);

258 }

259 return *Site;

260}

261

263 StringRef ScopeName = Scope->getName();

264 if (!ScopeName.empty())

265 return ScopeName;

266

267 switch (Scope->getTag()) {

268 case dwarf::DW_TAG_enumeration_type:

269 case dwarf::DW_TAG_class_type:

270 case dwarf::DW_TAG_structure_type:

271 case dwarf::DW_TAG_union_type:

272 return "";

273 case dwarf::DW_TAG_namespace:

274 return "`anonymous namespace'";

275 default:

277 }

278}

279

280const DISubprogram *CodeViewDebug::collectParentScopeNames(

282 const DISubprogram *ClosestSubprogram = nullptr;

283 while (Scope != nullptr) {

284 if (ClosestSubprogram == nullptr)

286

287

288

289

291 DeferredCompleteTypes.push_back(Ty);

292

294 if (!ScopeName.empty())

295 QualifiedNameComponents.push_back(ScopeName);

297 }

298 return ClosestSubprogram;

299}

300

303 std::string FullyQualifiedName;

304 for (StringRef QualifiedNameComponent :

306 FullyQualifiedName.append(std::string(QualifiedNameComponent));

307 FullyQualifiedName.append("::");

308 }

309 FullyQualifiedName.append(std::string(TypeName));

310 return FullyQualifiedName;

311}

312

316

317

318 if (CVD.TypeEmissionLevel == 1)

319 CVD.emitDeferredCompleteTypes();

320 --CVD.TypeEmissionLevel;

321 }

323};

324

325std::string CodeViewDebug::getFullyQualifiedName(const DIScope *Scope,

327

328

329

332 collectParentScopeNames(Scope, QualifiedNameComponents);

334}

335

336std::string CodeViewDebug::getFullyQualifiedName(const DIScope *Ty) {

339}

340

341TypeIndex CodeViewDebug::getScopeIndex(const DIScope *Scope) {

342

343

344

345

346

347

348

349

350

351

354

355 assert(isa<DIType>(Scope) && "shouldn't make a namespace scope for a type");

356

357

358 auto I = TypeIndices.find({Scope, nullptr});

359 if (I != TypeIndices.end())

360 return I->second;

361

362

363 std::string ScopeName = getFullyQualifiedName(Scope);

364 StringIdRecord SID(TypeIndex(), ScopeName);

365 auto TI = TypeTable.writeLeafType(SID);

366 return recordTypeIndexForDINode(Scope, TI);

367}

368

370

371

372 if (Name.empty() || Name.back() != '>')

373 return Name;

374

375 int OpenBrackets = 0;

376 for (int i = Name.size() - 1; i >= 0; --i) {

377 if (Name[i] == '>')

378 ++OpenBrackets;

379 else if (Name[i] == '<') {

380 --OpenBrackets;

381 if (OpenBrackets == 0)

382 return Name.substr(0, i);

383 }

384 }

385 return Name;

386}

387

388TypeIndex CodeViewDebug::getFuncIdForSubprogram(const DISubprogram *SP) {

390

391

392 auto I = TypeIndices.find({SP, nullptr});

393 if (I != TypeIndices.end())

394 return I->second;

395

396

397

398

400

401 const DIScope *Scope = SP->getScope();

402 TypeIndex TI;

404

405

406

407 TypeIndex ClassType = getTypeIndex(Class);

408 MemberFuncIdRecord MFuncId(ClassType, getMemberFunctionType(SP, Class),

409 DisplayName);

410 TI = TypeTable.writeLeafType(MFuncId);

411 } else {

412

413 TypeIndex ParentScope = getScopeIndex(Scope);

414 FuncIdRecord FuncId(ParentScope, getTypeIndex(SP->getType()), DisplayName);

415 TI = TypeTable.writeLeafType(FuncId);

416 }

417

418 return recordTypeIndexForDINode(SP, TI);

419}

420

422 return ((DCTy->getFlags() & DINode::FlagNonTrivial) == DINode::FlagNonTrivial);

423}

424

430 const DIType *ReturnTy = nullptr;

431 if (auto TypeArray = Ty->getTypeArray()) {

432 if (TypeArray.size())

433 ReturnTy = TypeArray[0];

434 }

435

436

437

441

442

443 if (ClassTy && isNonTrivial(ClassTy) && SPName == ClassTy->getName()) {

445

446

447

448 }

449 return FO;

450}

451

452TypeIndex CodeViewDebug::getMemberFunctionType(const DISubprogram *SP,

454

455

456 if (SP->getDeclaration())

457 SP = SP->getDeclaration();

458 assert(SP->getDeclaration() && "should use declaration as key");

459

460

461

462 auto I = TypeIndices.find({SP, Class});

463 if (I != TypeIndices.end())

464 return I->second;

465

466

467

468

470 const bool IsStaticMethod = (SP->getFlags() & DINode::FlagStaticMember) != 0;

471

473 TypeIndex TI = lowerTypeMemberFunction(

474 SP->getType(), Class, SP->getThisAdjustment(), IsStaticMethod, FO);

475 return recordTypeIndexForDINode(SP, TI, Class);

476}

477

478TypeIndex CodeViewDebug::recordTypeIndexForDINode(const DINode *Node,

479 TypeIndex TI,

480 const DIType *ClassTy) {

481 auto InsertResult = TypeIndices.insert({{Node, ClassTy}, TI});

482 (void)InsertResult;

483 assert(InsertResult.second && "DINode was already assigned a type index");

484 return TI;

485}

486

487unsigned CodeViewDebug::getPointerSizeInBytes() {

488 return MMI->getModule()->getDataLayout().getPointerSizeInBits() / 8;

489}

490

491void CodeViewDebug::recordLocalVariable(LocalVariable &&Var,

493 if (const DILocation *InlinedAt = LS->getInlinedAt()) {

494

495 const DISubprogram *Inlinee = Var.DIVar->getScope()->getSubprogram();

496 InlineSite &Site = getInlineSite(InlinedAt, Inlinee);

497 Site.InlinedLocals.emplace_back(std::move(Var));

498 } else {

499

500 ScopeVariables[LS].emplace_back(std::move(Var));

501 }

502}

503

509

510void CodeViewDebug::maybeRecordLocation(const DebugLoc &DL,

512

514 return;

515

516 const DIScope *Scope = DL->getScope();

517 if (!Scope)

518 return;

519

520

521 LineInfo LI(DL.getLine(), DL.getLine(), true);

522 if (LI.getStartLine() != DL.getLine() || LI.isAlwaysStepInto() ||

523 LI.isNeverStepInto())

524 return;

525

526 ColumnInfo CI(DL.getCol(), 0);

527 if (CI.getStartColumn() != DL.getCol())

528 return;

529

530 if (!CurFn->HaveLineInfo)

531 CurFn->HaveLineInfo = true;

532 unsigned FileId = 0;

534 FileId = CurFn->LastFileId;

535 else

536 FileId = CurFn->LastFileId = maybeRecordFile(DL->getFile());

538

539 unsigned FuncId = CurFn->FuncId;

540 if (const DILocation *SiteLoc = DL->getInlinedAt()) {

541 const DILocation *Loc = DL.get();

542

543

544

545 FuncId =

546 getInlineSite(SiteLoc, Loc->getScope()->getSubprogram()).SiteFuncId;

547

548

549 bool FirstLoc = true;

550 while ((SiteLoc = Loc->getInlinedAt())) {

551 InlineSite &Site =

552 getInlineSite(SiteLoc, Loc->getScope()->getSubprogram());

553 if (!FirstLoc)

555 FirstLoc = false;

556 Loc = SiteLoc;

557 }

559 }

560

561 OS.emitCVLocDirective(FuncId, FileId, DL.getLine(), DL.getCol(),

562 false, false,

563 DL->getFilename(), SMLoc());

564}

565

566void CodeViewDebug::emitCodeViewMagicVersion() {

567 OS.emitValueToAlignment(Align(4));

568 OS.AddComment("Debug section magic");

570}

571

574 switch (DWLName) {

575 case dwarf::DW_LNAME_C:

576 return SourceLanguage::C;

577 case dwarf::DW_LNAME_C_plus_plus:

578 return SourceLanguage::Cpp;

579 case dwarf::DW_LNAME_Fortran:

580 return SourceLanguage::Fortran;

581 case dwarf::DW_LNAME_Pascal:

582 return SourceLanguage::Pascal;

583 case dwarf::DW_LNAME_Cobol:

584 return SourceLanguage::Cobol;

585 case dwarf::DW_LNAME_Java:

586 return SourceLanguage::Java;

587 case dwarf::DW_LNAME_D:

588 return SourceLanguage::D;

589 case dwarf::DW_LNAME_Swift:

590 return SourceLanguage::Swift;

591 case dwarf::DW_LNAME_Rust:

592 return SourceLanguage::Rust;

593 case dwarf::DW_LNAME_ObjC:

594 return SourceLanguage::ObjC;

595 case dwarf::DW_LNAME_ObjC_plus_plus:

596 return SourceLanguage::ObjCpp;

597 default:

598

599

600

601 return SourceLanguage::Masm;

602 }

603}

604

607 if (!MaybeLName)

609

611}

612

614

615 if (Asm->getObjFileLowering().getCOFFDebugSymbolsSection()) {

616 Asm = nullptr;

617 return;

618 }

619

620 CompilerInfoAsm = Asm;

622

623

625 if (Asm->hasDebugInfo()) {

626 Node = *M->debug_compile_units_begin();

627 } else {

628

629

630 NamedMDNode *CUs = MMI->getModule()->getNamedMetadata("llvm.dbg.cu");

632 Asm = nullptr;

633 return;

634 }

636 }

637

640 CurrentSourceLanguage =

646 if (!M->getCodeViewFlag() ||

648 Asm = nullptr;

649 return;

650 }

651

652 collectGlobalVariableInfo();

653

654

657 EmitDebugGlobalHashes = GH && !GH->isZero();

658}

659

661 if (!CompilerInfoAsm)

662 return;

663

664

665

666

667

668

669

670

671 switchToDebugSectionForSymbol(nullptr);

672

674 emitObjName();

675 emitCompilerInformation();

676 endCVSubsection(CompilerInfo);

677 if (Asm)

678 return;

679

680 emitSecureHotPatchInformation();

681

682 emitInlineeLinesSubsection();

683

684

685 for (auto &P : FnDebugInfo)

686 if (P.first->isDeclarationForLinker())

687 emitDebugInfoForFunction(P.first, *P.second);

688

689

690

691

692 collectDebugInfoForGlobals();

693

694

695 emitDebugInfoForRetainedTypes();

696

697

698 setCurrentSubprogram(nullptr);

699 emitDebugInfoForGlobals();

700

701

702

703 switchToDebugSectionForSymbol(nullptr);

704

705

706 if (!GlobalUDTs.empty()) {

708 emitDebugInfoForUDTs(GlobalUDTs);

709 endCVSubsection(SymbolsEnd);

710 }

711

712

713 OS.AddComment("File index to string table offset subsection");

714 OS.emitCVFileChecksumsDirective();

715

716

717 OS.AddComment("String table");

718 OS.emitCVStringTableDirective();

719

720

721

722

723 emitBuildInfo();

724

725

726

727 emitTypeInformation();

728

729 if (EmitDebugGlobalHashes)

730 emitTypeGlobalHashes();

731

732 clear();

733}

734

735static void

737 unsigned MaxFixedRecordLength = 0xF00) {

738

739

740

741

744 NullTerminatedString.push_back('\0');

745 OS.emitBytes(NullTerminatedString);

746}

747

748void CodeViewDebug::emitTypeInformation() {

749 if (TypeTable.empty())

750 return;

751

752

753 OS.switchSection(Asm->getObjFileLowering().getCOFFDebugTypesSection());

754 emitCodeViewMagicVersion();

755

756 TypeTableCollection Table(TypeTable.records());

757 TypeVisitorCallbackPipeline Pipeline;

758

759

760 CVMCAdapter CVMCOS(OS, Table);

761 TypeRecordMapping typeMapping(CVMCOS);

763

764 std::optional B = Table.getFirst();

765 while (B) {

766

767 CVType Record = Table.getType(*B);

768

770

771 if (E) {

774 }

775

776 B = Table.getNext(*B);

777 }

778}

779

780void CodeViewDebug::emitTypeGlobalHashes() {

781 if (TypeTable.empty())

782 return;

783

784

785

786 OS.switchSection(Asm->getObjFileLowering().getCOFFGlobalTypeHashesSection());

787

788 OS.emitValueToAlignment(Align(4));

789 OS.AddComment("Magic");

791 OS.AddComment("Section Version");

792 OS.emitInt16(0);

793 OS.AddComment("Hash Algorithm");

794 OS.emitInt16(uint16_t(GlobalTypeHashAlg::BLAKE3));

795

797 for (const auto &GHR : TypeTable.hashes()) {

798 if (OS.isVerboseAsm()) {

799

800

802 raw_svector_ostream CommentOS(Comment);

803 CommentOS << formatv("{0:X+} [{1}]", TI.getIndex(), GHR);

804 OS.AddComment(Comment);

805 ++TI;

806 }

807 assert(GHR.Hash.size() == 8);

808 StringRef S(reinterpret_cast<const char *>(GHR.Hash.data()),

809 GHR.Hash.size());

810 OS.emitBinaryData(S);

811 }

812}

813

814void CodeViewDebug::emitObjName() {

815 MCSymbol *CompilerEnd = beginSymbolRecord(SymbolKind::S_OBJNAME);

816

817 StringRef PathRef(CompilerInfoAsm->TM.Options.ObjectFilenameForDebug);

818 llvm::SmallString<256> PathStore(PathRef);

819

820 if (PathRef.empty() || PathRef == "-") {

821

822 PathRef = {};

823 } else {

824 PathRef = PathStore;

825 }

826

827 OS.AddComment("Signature");

828 OS.emitIntValue(0, 4);

829

830 OS.AddComment("Object name");

832

833 endSymbolRecord(CompilerEnd);

834}

835

836void CodeViewDebug::emitSecureHotPatchInformation() {

837 MCSymbol *hotPatchInfo = nullptr;

838

839 for (const auto &F : MMI->getModule()->functions()) {

840 if (F.isDeclarationForLinker() &&

841 F.hasFnAttribute("marked_for_windows_hot_patching")) {

842 if (hotPatchInfo == nullptr)

843 hotPatchInfo = beginCVSubsection(DebugSubsectionKind::Symbols);

844 MCSymbol *HotPatchEnd = beginSymbolRecord(SymbolKind::S_HOTPATCHFUNC);

845 auto *SP = F.getSubprogram();

846 OS.AddComment("Function");

847 OS.emitInt32(getFuncIdForSubprogram(SP).getIndex());

848 OS.AddComment("Name");

850 endSymbolRecord(HotPatchEnd);

851 }

852 }

853

854 if (hotPatchInfo != nullptr)

855 endCVSubsection(hotPatchInfo);

856}

857

858namespace {

860 int Part[4];

861};

862}

863

864

865

867 Version V = {{0}};

868 int N = 0;

869 for (const char C : Name) {

870 if (isdigit(C)) {

871 V.Part[N] *= 10;

872 V.Part[N] += C - '0';

873 V.Part[N] =

874 std::min(V.Part[N], std::numeric_limits<uint16_t>::max());

875 } else if (C == '.') {

876 ++N;

877 if (N >= 4)

878 return V;

879 } else if (N > 0)

880 return V;

881 }

882 return V;

883}

884

885void CodeViewDebug::emitCompilerInformation() {

886 MCSymbol *CompilerEnd = beginSymbolRecord(SymbolKind::S_COMPILE3);

887 uint32_t Flags = 0;

888

889

890 Flags = CurrentSourceLanguage;

891

892 if (MMI->getModule()->getProfileSummary( false) != nullptr) {

893 Flags |= static_cast<uint32_t>(CompileSym3Flags::PGO);

894 }

896 ArchType Arch = MMI->getModule()->getTargetTriple().getArch();

897 if (CompilerInfoAsm->TM.Options.Hotpatch || Arch == ArchType::thumb ||

898 Arch == ArchType::aarch64) {

899 Flags |= static_cast<uint32_t>(CompileSym3Flags::HotPatch);

900 }

901

902 OS.AddComment("Flags and language");

903 OS.emitInt32(Flags);

904

905 OS.AddComment("CPUType");

906 OS.emitInt16(static_cast<uint64_t>(TheCPU));

907

908 StringRef CompilerVersion = "0";

909 if (TheCU)

910 CompilerVersion = TheCU->getProducer();

911

913 OS.AddComment("Frontend version");

914 for (int N : FrontVer.Part) {

915 OS.emitInt16(N);

916 }

917

918

919

920

921 int Major = 1000 * LLVM_VERSION_MAJOR +

922 10 * LLVM_VERSION_MINOR +

923 LLVM_VERSION_PATCH;

924

925 Major = std::min(Major, std::numeric_limits<uint16_t>::max());

926 Version BackVer = {{ Major, 0, 0, 0 }};

927 OS.AddComment("Backend version");

928 for (int N : BackVer.Part)

929 OS.emitInt16(N);

930

931 OS.AddComment("Null-terminated compiler version string");

933

934 endSymbolRecord(CompilerEnd);

935}

936

942

943void CodeViewDebug::emitBuildInfo() {

944

945

946

947

948

949

950

951

952

953

955 NamedMDNode *CUs = MMI->getModule()->getNamedMetadata("llvm.dbg.cu");

956 const MDNode *Node = *CUs->operands().begin();

958 const DIFile *MainSourceFile = CU->getFile();

963

969 TypeTable, Asm->TM.Options.MCOptions.CommandlineArgs);

970

971 BuildInfoRecord BIR(BuildInfoArgs);

972 TypeIndex BuildInfoIndex = TypeTable.writeLeafType(BIR);

973

974

975

976 MCSymbol *BISubsecEnd = beginCVSubsection(DebugSubsectionKind::Symbols);

977 MCSymbol *BIEnd = beginSymbolRecord(SymbolKind::S_BUILDINFO);

978 OS.AddComment("LF_BUILDINFO index");

979 OS.emitInt32(BuildInfoIndex.getIndex());

980 endSymbolRecord(BIEnd);

981 endCVSubsection(BISubsecEnd);

982}

983

984void CodeViewDebug::emitInlineeLinesSubsection() {

985 if (InlinedSubprograms.empty())

986 return;

987

988 OS.AddComment("Inlinee lines subsection");

989 MCSymbol *InlineEnd = beginCVSubsection(DebugSubsectionKind::InlineeLines);

990

991

992

993

994

995 OS.AddComment("Inlinee lines signature");

996 OS.emitInt32(unsigned(InlineeLinesSignature::Normal));

997

998 for (const DISubprogram *SP : InlinedSubprograms) {

999 assert(TypeIndices.count({SP, nullptr}));

1000 TypeIndex InlineeIdx = TypeIndices[{SP, nullptr}];

1001

1002 OS.addBlankLine();

1003 unsigned FileId = maybeRecordFile(SP->getFile());

1004 OS.AddComment("Inlined function " + SP->getName() + " starts at " +

1005 SP->getFilename() + Twine(':') + Twine(SP->getLine()));

1006 OS.addBlankLine();

1007 OS.AddComment("Type index of inlined function");

1008 OS.emitInt32(InlineeIdx.getIndex());

1009 OS.AddComment("Offset into filechecksum table");

1010 OS.emitCVFileChecksumOffsetDirective(FileId);

1011 OS.AddComment("Starting line number");

1012 OS.emitInt32(SP->getLine());

1013 }

1014

1015 endCVSubsection(InlineEnd);

1016}

1017

1018void CodeViewDebug::emitInlinedCallSite(const FunctionInfo &FI,

1021 assert(TypeIndices.count({Site.Inlinee, nullptr}));

1022 TypeIndex InlineeIdx = TypeIndices[{Site.Inlinee, nullptr}];

1023

1024

1025 MCSymbol *InlineEnd = beginSymbolRecord(SymbolKind::S_INLINESITE);

1026

1027 OS.AddComment("PtrParent");

1028 OS.emitInt32(0);

1029 OS.AddComment("PtrEnd");

1030 OS.emitInt32(0);

1031 OS.AddComment("Inlinee type index");

1032 OS.emitInt32(InlineeIdx.getIndex());

1033

1034 unsigned FileId = maybeRecordFile(Site.Inlinee->getFile());

1035 unsigned StartLineNum = Site.Inlinee->getLine();

1036

1037 OS.emitCVInlineLinetableDirective(Site.SiteFuncId, FileId, StartLineNum,

1038 FI.Begin, FI.End);

1039

1040 endSymbolRecord(InlineEnd);

1041

1042 emitLocalVariableList(FI, Site.InlinedLocals);

1043

1044

1045 for (const DILocation *ChildSite : Site.ChildSites) {

1046 auto I = FI.InlineSites.find(ChildSite);

1047 assert(I != FI.InlineSites.end() &&

1048 "child site not in function inline site map");

1049 emitInlinedCallSite(FI, ChildSite, I->second);

1050 }

1051

1052

1053 emitEndSymbolRecord(SymbolKind::S_INLINESITE_END);

1054}

1055

1056void CodeViewDebug::switchToDebugSectionForSymbol(const MCSymbol *GVSym) {

1057

1058

1059

1060 MCSectionCOFF *GVSec =

1061 GVSym ? static_cast<MCSectionCOFF *>(&GVSym->getSection()) : nullptr;

1063

1064 auto *DebugSec = static_cast<MCSectionCOFF *>(

1065 CompilerInfoAsm->getObjFileLowering().getCOFFDebugSymbolsSection());

1066 DebugSec = OS.getContext().getAssociativeCOFFSection(DebugSec, KeySym);

1067

1068 OS.switchSection(DebugSec);

1069

1070

1071

1072 if (ComdatDebugSections.insert(DebugSec).second)

1073 emitCodeViewMagicVersion();

1074}

1075

1076

1077

1078void CodeViewDebug::emitDebugInfoForThunk(const Function *GV,

1079 FunctionInfo &FI,

1081 std::string FuncName =

1083 const ThunkOrdinal ordinal = ThunkOrdinal::Standard;

1084

1085 OS.AddComment("Symbol subsection for " + Twine(FuncName));

1086 MCSymbol *SymbolsEnd = beginCVSubsection(DebugSubsectionKind::Symbols);

1087

1088

1089 MCSymbol *ThunkRecordEnd = beginSymbolRecord(SymbolKind::S_THUNK32);

1090 OS.AddComment("PtrParent");

1091 OS.emitInt32(0);

1092 OS.AddComment("PtrEnd");

1093 OS.emitInt32(0);

1094 OS.AddComment("PtrNext");

1095 OS.emitInt32(0);

1096 OS.AddComment("Thunk section relative address");

1097 OS.emitCOFFSecRel32(Fn, 0);

1098 OS.AddComment("Thunk section index");

1099 OS.emitCOFFSectionIndex(Fn);

1100 OS.AddComment("Code size");

1101 OS.emitAbsoluteSymbolDiff(FI.End, Fn, 2);

1102 OS.AddComment("Ordinal");

1103 OS.emitInt8(unsigned(ordinal));

1104 OS.AddComment("Function name");

1106

1107 endSymbolRecord(ThunkRecordEnd);

1108

1109

1110

1111

1112

1113 emitEndSymbolRecord(SymbolKind::S_PROC_ID_END);

1114

1115 endCVSubsection(SymbolsEnd);

1116}

1117

1118void CodeViewDebug::emitDebugInfoForFunction(const Function *GV,

1119 FunctionInfo &FI) {

1120

1121

1122 const MCSymbol *Fn = Asm->getSymbol(GV);

1124

1125

1126 switchToDebugSectionForSymbol(Fn);

1127

1128 std::string FuncName;

1131 setCurrentSubprogram(SP);

1132

1133 if (SP->isThunk()) {

1134 emitDebugInfoForThunk(GV, FI, Fn);

1135 return;

1136 }

1137

1138

1139

1140 if (SP->getName().empty())

1141 FuncName = getFullyQualifiedName(SP->getScope(), SP->getName());

1142

1143

1144 if (FuncName.empty())

1146

1147

1148 if (MMI->getModule()->getTargetTriple().getArch() == Triple::x86)

1149 OS.emitCVFPOData(Fn);

1150

1151

1152 OS.AddComment("Symbol subsection for " + Twine(FuncName));

1153 MCSymbol *SymbolsEnd = beginCVSubsection(DebugSubsectionKind::Symbols);

1154 {

1156 : SymbolKind::S_GPROC32_ID;

1157 MCSymbol *ProcRecordEnd = beginSymbolRecord(ProcKind);

1158

1159

1160 OS.AddComment("PtrParent");

1161 OS.emitInt32(0);

1162 OS.AddComment("PtrEnd");

1163 OS.emitInt32(0);

1164 OS.AddComment("PtrNext");

1165 OS.emitInt32(0);

1166

1167

1168 OS.AddComment("Code size");

1169 OS.emitAbsoluteSymbolDiff(FI.End, Fn, 4);

1170 OS.AddComment("Offset after prologue");

1171 OS.emitInt32(0);

1172 OS.AddComment("Offset before epilogue");

1173 OS.emitInt32(0);

1174 OS.AddComment("Function type index");

1175 OS.emitInt32(getFuncIdForSubprogram(GV->getSubprogram()).getIndex());

1176 OS.AddComment("Function section relative address");

1177 OS.emitCOFFSecRel32(Fn, 0);

1178 OS.AddComment("Function section index");

1179 OS.emitCOFFSectionIndex(Fn);

1180 OS.AddComment("Flags");

1181 ProcSymFlags ProcFlags = ProcSymFlags::HasOptimizedDebugInfo;

1182 if (FI.HasFramePointer)

1183 ProcFlags |= ProcSymFlags::HasFP;

1185 ProcFlags |= ProcSymFlags::IsNoReturn;

1187 ProcFlags |= ProcSymFlags::IsNoInline;

1188 OS.emitInt8(static_cast<uint8_t>(ProcFlags));

1189

1190 OS.AddComment("Function name");

1191

1193 endSymbolRecord(ProcRecordEnd);

1194

1195 MCSymbol *FrameProcEnd = beginSymbolRecord(SymbolKind::S_FRAMEPROC);

1196

1197 OS.AddComment("FrameSize");

1198 OS.emitInt32(FI.FrameSize - FI.CSRSize);

1199 OS.AddComment("Padding");

1200 OS.emitInt32(0);

1201 OS.AddComment("Offset of padding");

1202 OS.emitInt32(0);

1203 OS.AddComment("Bytes of callee saved registers");

1204 OS.emitInt32(FI.CSRSize);

1205 OS.AddComment("Exception handler offset");

1206 OS.emitInt32(0);

1207 OS.AddComment("Exception handler section");

1208 OS.emitInt16(0);

1209 OS.AddComment("Flags (defines frame register)");

1210 OS.emitInt32(uint32_t(FI.FrameProcOpts));

1211 endSymbolRecord(FrameProcEnd);

1212

1213 emitInlinees(FI.Inlinees);

1214 emitLocalVariableList(FI, FI.Locals);

1215 emitGlobalVariableList(FI.Globals);

1216 emitLexicalBlockList(FI.ChildBlocks, FI);

1217

1218

1219

1220

1221 for (const DILocation *InlinedAt : FI.ChildSites) {

1222 auto I = FI.InlineSites.find(InlinedAt);

1223 assert(I != FI.InlineSites.end() &&

1224 "child site not in function inline site map");

1225 emitInlinedCallSite(FI, InlinedAt, I->second);

1226 }

1227

1228 for (auto Annot : FI.Annotations) {

1231 MCSymbol *AnnotEnd = beginSymbolRecord(SymbolKind::S_ANNOTATION);

1232 OS.emitCOFFSecRel32(Label, 0);

1233

1234 OS.emitCOFFSectionIndex(Label);

1237

1238

1240 assert(Str.data()[Str.size()] == '\0' && "non-nullterminated MDString");

1241 OS.emitBytes(StringRef(Str.data(), Str.size() + 1));

1242 }

1243 endSymbolRecord(AnnotEnd);

1244 }

1245

1246 for (auto HeapAllocSite : FI.HeapAllocSites) {

1247 const MCSymbol *BeginLabel = std::get<0>(HeapAllocSite);

1248 const MCSymbol *EndLabel = std::get<1>(HeapAllocSite);

1249 const DIType *DITy = std::get<2>(HeapAllocSite);

1250 MCSymbol *HeapAllocEnd = beginSymbolRecord(SymbolKind::S_HEAPALLOCSITE);

1251 OS.AddComment("Call site offset");

1252 OS.emitCOFFSecRel32(BeginLabel, 0);

1253 OS.AddComment("Call site section index");

1254 OS.emitCOFFSectionIndex(BeginLabel);

1255 OS.AddComment("Call instruction length");

1256 OS.emitAbsoluteSymbolDiff(EndLabel, BeginLabel, 2);

1257 OS.AddComment("Type index");

1258 OS.emitInt32(getCompleteTypeIndex(DITy).getIndex());

1259 endSymbolRecord(HeapAllocEnd);

1260 }

1261

1262 if (SP != nullptr)

1263 emitDebugInfoForUDTs(LocalUDTs);

1264

1265 emitDebugInfoForJumpTables(FI);

1266

1267

1268 emitEndSymbolRecord(SymbolKind::S_PROC_ID_END);

1269 }

1270 endCVSubsection(SymbolsEnd);

1271

1272

1273 OS.emitCVLinetableDirective(FI.FuncId, Fn, FI.End);

1274}

1275

1277CodeViewDebug::createDefRangeMem(uint16_t CVRegister, int Offset) {

1280 DR.DataOffset = Offset;

1281 assert(DR.DataOffset == Offset && "truncation");

1282 DR.IsSubfield = 0;

1283 DR.StructOffset = 0;

1284 DR.CVRegister = CVRegister;

1285 return DR;

1286}

1287

1288void CodeViewDebug::collectVariableInfoFromMFTable(

1290 const MachineFunction &MF = *Asm->MF;

1291 const TargetSubtargetInfo &TSI = MF.getSubtarget();

1294

1295 for (const MachineFunction::VariableDbgInfo &VI :

1297 if (VI.Var)

1298 continue;

1299 assert(VI.Var->isValidLocationForIntrinsic(VI.Loc) &&

1300 "Expected inlined-at fields to agree");

1301

1302 Processed.insert(InlinedEntity(VI.Var, VI.Loc->getInlinedAt()));

1303 LexicalScope *Scope = LScopes.findLexicalScope(VI.Loc);

1304

1305

1306 if (!Scope)

1307 continue;

1308

1309

1310

1311 int64_t ExprOffset = 0;

1312 bool Deref = false;

1313 if (VI.Expr) {

1314

1315 if (VI.Expr->getNumElements() == 1 &&

1316 VI.Expr->getElement(0) == llvm::dwarf::DW_OP_deref)

1317 Deref = true;

1318 else if (VI.Expr->extractIfOffset(ExprOffset))

1319 continue;

1320 }

1321

1322

1324 StackOffset FrameOffset =

1326 uint16_t CVReg = TRI->getCodeViewRegNum(FrameReg);

1327

1329

1330 continue;

1331 }

1332

1333

1335 createDefRangeMem(CVReg, FrameOffset.getFixed() + ExprOffset);

1336

1337 LocalVariable Var;

1338 Var.DIVar = VI.Var;

1339

1343 End = End ? End : Asm->getFunctionEnd();

1344 Var.DefRanges[DefRange].emplace_back(Begin, End);

1345 }

1346

1347 if (Deref)

1348 Var.UseReferenceType = true;

1349

1350 recordLocalVariable(std::move(Var), Scope);

1351 }

1352}

1353

1355 return Loc.LoadChain.empty() && Loc.LoadChain.back() == 0;

1356}

1357

1359 return Loc.LoadChain.size() == 2 && Loc.LoadChain.back() == 0;

1360}

1361

1362void CodeViewDebug::calculateRanges(

1364 const TargetRegisterInfo *TRI = Asm->MF->getSubtarget().getRegisterInfo();

1365

1366

1367 for (auto I = Entries.begin(), E = Entries.end(); I != E; ++I) {

1368 const auto &Entry = *I;

1369 if (Entry.isDbgValue())

1370 continue;

1371 const MachineInstr *DVInst = Entry.getInstr();

1373

1374

1375 std::optional Location =

1377 if (!Location)

1378 {

1379

1380

1381

1382

1383

1385 if (Op.isImm())

1386 Var.ConstantValue = APSInt(APInt(64, Op.getImm()), false);

1387 continue;

1388 }

1389

1390

1391

1392

1393

1394

1395

1396

1397 if (Var.UseReferenceType) {

1398

1400 Location->LoadChain.pop_back();

1401 else

1402 continue;

1404

1405

1406 Var.UseReferenceType = true;

1407 Var.DefRanges.clear();

1408 calculateRanges(Var, Entries);

1409 return;

1410 }

1411

1412

1414 continue;

1415

1416

1417

1419 if (Location->FragmentInfo->OffsetInBits % 8)

1420 continue;

1421

1422 if (TRI->isIgnoredCVReg(Location->Register)) {

1423

1424 continue;

1425 }

1426

1429 DR.InMemory = Location->LoadChain.empty();

1430 DR.DataOffset =

1431 Location->LoadChain.empty() ? Location->LoadChain.back() : 0;

1432 if (Location->FragmentInfo) {

1433 DR.IsSubfield = true;

1434 DR.StructOffset = Location->FragmentInfo->OffsetInBits / 8;

1435 } else {

1436 DR.IsSubfield = false;

1437 DR.StructOffset = 0;

1438 }

1439

1440

1444 auto &EndingEntry = Entries[Entry.getEndIndex()];

1445 End = EndingEntry.isDbgValue()

1448 } else

1449 End = Asm->getFunctionEnd();

1450

1451

1452

1453 SmallVectorImpl<std::pair<const MCSymbol *, const MCSymbol *>> &R =

1454 Var.DefRanges[DR];

1455 if (R.empty() && R.back().second == Begin)

1456 R.back().second = End;

1457 else

1458 R.emplace_back(Begin, End);

1459

1460

1461 }

1462}

1463

1464void CodeViewDebug::collectVariableInfo(const DISubprogram *SP) {

1465 DenseSet Processed;

1466

1467 collectVariableInfoFromMFTable(Processed);

1468

1470 InlinedEntity IV = I.first;

1471 if (Processed.count(IV))

1472 continue;

1474 const DILocation *InlinedAt = IV.second;

1475

1476

1477 const auto &Entries = I.second;

1478

1479 LexicalScope *Scope = nullptr;

1480 if (InlinedAt)

1482 else

1484

1485 if (!Scope)

1486 continue;

1487

1488 LocalVariable Var;

1489 Var.DIVar = DIVar;

1490

1491 calculateRanges(Var, Entries);

1492 recordLocalVariable(std::move(Var), Scope);

1493 }

1494}

1495

1501 auto Insertion = FnDebugInfo.insert({&GV, std::make_unique()});

1502 assert(Insertion.second && "function already has info");

1503 CurFn = Insertion.first->second.get();

1504 CurFn->FuncId = NextFuncId++;

1505 CurFn->Begin = Asm->getFunctionBegin();

1506

1507

1508

1509

1513 CurFn->HasStackRealignment = TRI->hasStackRealignment(*MF);

1514

1515

1516

1519 if (CurFn->FrameSize > 0) {

1523 } else {

1524 CurFn->HasFramePointer = true;

1525

1527 if (CurFn->HasStackRealignment) {

1528

1530 } else {

1531

1532

1534 }

1535 }

1536 }

1537

1538

1544

1551 else

1553 }

1560 if (GV.hasFnAttribute(Attribute::StackProtectStrong) ||

1563 }

1565

1567 }

1576 }

1577

1578 CurFn->FrameProcOpts = FPO;

1579

1580 OS.emitCVFuncIdDirective(CurFn->FuncId);

1581

1582

1583

1584

1585

1587 bool EmptyPrologue = true;

1588 for (const auto &MBB : *MF) {

1589 for (const auto &MI : MBB) {

1591 MI.getDebugLoc()) {

1593 break;

1594 } else if (MI.isMetaInstruction()) {

1595 EmptyPrologue = false;

1596 }

1597 }

1598 }

1599

1600

1603 maybeRecordLocation(FnStartDL, MF);

1604 }

1605

1606

1607 for (const auto &MBB : *MF) {

1608 for (const auto &MI : MBB) {

1609 if (MI.getHeapAllocMarker()) {

1612 }

1613 }

1614 }

1615

1616

1617 bool isThumb = MMI->getModule()->getTargetTriple().getArch() ==

1619 discoverJumpTableBranches(MF, isThumb);

1620}

1621

1623 if (T)

1624 return false;

1625

1626

1627 if (T->getTag() == dwarf::DW_TAG_typedef) {

1628 if (DIScope *Scope = T->getScope()) {

1629 switch (Scope->getTag()) {

1630 case dwarf::DW_TAG_structure_type:

1631 case dwarf::DW_TAG_class_type:

1632 case dwarf::DW_TAG_union_type:

1633 return false;

1634 default:

1635

1636 ;

1637 }

1638 }

1639 }

1640

1641 while (true) {

1642 if (T || T->isForwardDecl())

1643 return false;

1644

1646 if (!DT)

1647 return true;

1648 T = DT->getBaseType();

1649 }

1650 return true;

1651}

1652

1653void CodeViewDebug::addToUDTs(const DIType *Ty) {

1654

1656 return;

1658 return;

1659

1661 const DISubprogram *ClosestSubprogram =

1662 collectParentScopeNames(Ty->getScope(), ParentScopeNames);

1663

1664 std::string FullyQualifiedName =

1666

1667 if (ClosestSubprogram == nullptr) {

1668 GlobalUDTs.emplace_back(std::move(FullyQualifiedName), Ty);

1669 } else if (ClosestSubprogram == CurrentSubprogram) {

1670 LocalUDTs.emplace_back(std::move(FullyQualifiedName), Ty);

1671 }

1672

1673

1674

1675

1676

1677

1678

1679}

1680

1681TypeIndex CodeViewDebug::lowerType(const DIType *Ty, const DIType *ClassTy) {

1682

1683 switch (Ty->getTag()) {

1684 case dwarf::DW_TAG_array_type:

1686 case dwarf::DW_TAG_typedef:

1688 case dwarf::DW_TAG_base_type:

1690 case dwarf::DW_TAG_pointer_type:

1693 [[fallthrough]];

1694 case dwarf::DW_TAG_reference_type:

1695 case dwarf::DW_TAG_rvalue_reference_type:

1697 case dwarf::DW_TAG_ptr_to_member_type:

1699 case dwarf::DW_TAG_restrict_type:

1700 case dwarf::DW_TAG_const_type:

1701 case dwarf::DW_TAG_volatile_type:

1702

1704 case dwarf::DW_TAG_subroutine_type:

1705 if (ClassTy) {

1706

1707

1709 0,

1710 false);

1711 }

1713 case dwarf::DW_TAG_enumeration_type:

1715 case dwarf::DW_TAG_class_type:

1716 case dwarf::DW_TAG_structure_type:

1718 case dwarf::DW_TAG_union_type:

1720 case dwarf::DW_TAG_string_type:

1722 case dwarf::DW_TAG_unspecified_type:

1723 if (Ty->getName() == "decltype(nullptr)")

1726 default:

1727

1728 return TypeIndex();

1729 }

1730}

1731

1732TypeIndex CodeViewDebug::lowerTypeAlias(const DIDerivedType *Ty) {

1733 TypeIndex UnderlyingTypeIndex = getTypeIndex(Ty->getBaseType());

1735

1736 addToUDTs(Ty);

1737

1738 if (UnderlyingTypeIndex == TypeIndex(SimpleTypeKind::Int32Long) &&

1739 TypeName == "HRESULT")

1740 return TypeIndex(SimpleTypeKind::HResult);

1741 if (UnderlyingTypeIndex == TypeIndex(SimpleTypeKind::UInt16Short) &&

1742 TypeName == "wchar_t")

1743 return TypeIndex(SimpleTypeKind::WideCharacter);

1744

1745 return UnderlyingTypeIndex;

1746}

1747

1748TypeIndex CodeViewDebug::lowerTypeArray(const DICompositeType *Ty) {

1750 TypeIndex ElementTypeIndex = getTypeIndex(ElementType);

1751

1752 TypeIndex IndexType = getPointerSizeInBytes() == 8

1753 ? TypeIndex(SimpleTypeKind::UInt64Quad)

1755

1756 uint64_t ElementSize = getBaseTypeSize(ElementType) / 8;

1757

1758

1760 for (int i = Elements.size() - 1; i >= 0; --i) {

1761 const DINode *Element = Elements[i];

1762 assert(Element->getTag() == dwarf::DW_TAG_subrange_type);

1763

1765 int64_t Count = -1;

1766

1767

1768

1769

1770

1772 Count = CI->getSExtValue();

1774 Subrange->getUpperBound())) {

1775

1778 Lowerbound = (LI) ? LI->getSExtValue() : Lowerbound;

1779 Count = UI->getSExtValue() - Lowerbound + 1;

1780 }

1781

1782

1783

1784

1785

1786 if (Count == -1)

1788

1789

1790 ElementSize *= Count;

1791

1792

1793

1794 uint64_t ArraySize =

1795 (i == 0 && ElementSize == 0) ? Ty->getSizeInBits() / 8 : ElementSize;

1796

1797 StringRef Name = (i == 0) ? Ty->getName() : "";

1798 ArrayRecord AR(ElementTypeIndex, IndexType, ArraySize, Name);

1799 ElementTypeIndex = TypeTable.writeLeafType(AR);

1800 }

1801

1802 return ElementTypeIndex;

1803}

1804

1805

1806

1807

1808

1809

1810TypeIndex CodeViewDebug::lowerTypeString(const DIStringType *Ty) {

1811 TypeIndex CharType = TypeIndex(SimpleTypeKind::NarrowCharacter);

1814

1815 TypeIndex IndexType = getPointerSizeInBytes() == 8

1816 ? TypeIndex(SimpleTypeKind::UInt64Quad)

1818

1819

1820 ArrayRecord AR(CharType, IndexType, ArraySize, Name);

1821

1822 return TypeTable.writeLeafType(AR);

1823}

1824

1825TypeIndex CodeViewDebug::lowerTypeBasic(const DIBasicType *Ty) {

1826 TypeIndex Index;

1828 uint32_t ByteSize;

1829

1832

1834 switch (Kind) {

1835 case dwarf::DW_ATE_address:

1836

1837 break;

1838 case dwarf::DW_ATE_boolean:

1839 switch (ByteSize) {

1840 case 1: STK = SimpleTypeKind::Boolean8; break;

1841 case 2: STK = SimpleTypeKind::Boolean16; break;

1842 case 4: STK = SimpleTypeKind::Boolean32; break;

1843 case 8: STK = SimpleTypeKind::Boolean64; break;

1844 case 16: STK = SimpleTypeKind::Boolean128; break;

1845 }

1846 break;

1847 case dwarf::DW_ATE_complex_float:

1848

1849

1850 switch (ByteSize) {

1851 case 4: STK = SimpleTypeKind::Complex16; break;

1852 case 8: STK = SimpleTypeKind::Complex32; break;

1853 case 16: STK = SimpleTypeKind::Complex64; break;

1854 case 20: STK = SimpleTypeKind::Complex80; break;

1855 case 32: STK = SimpleTypeKind::Complex128; break;

1856 }

1857 break;

1858 case dwarf::DW_ATE_float:

1859 switch (ByteSize) {

1860 case 2: STK = SimpleTypeKind::Float16; break;

1861 case 4: STK = SimpleTypeKind::Float32; break;

1862 case 6: STK = SimpleTypeKind::Float48; break;

1863 case 8: STK = SimpleTypeKind::Float64; break;

1864 case 10: STK = SimpleTypeKind::Float80; break;

1865 case 16: STK = SimpleTypeKind::Float128; break;

1866 }

1867 break;

1868 case dwarf::DW_ATE_signed:

1869 switch (ByteSize) {

1870 case 1: STK = SimpleTypeKind::SignedCharacter; break;

1871 case 2: STK = SimpleTypeKind::Int16Short; break;

1872 case 4: STK = SimpleTypeKind::Int32; break;

1873 case 8: STK = SimpleTypeKind::Int64Quad; break;

1874 case 16: STK = SimpleTypeKind::Int128Oct; break;

1875 }

1876 break;

1877 case dwarf::DW_ATE_unsigned:

1878 switch (ByteSize) {

1879 case 1: STK = SimpleTypeKind::UnsignedCharacter; break;

1880 case 2: STK = SimpleTypeKind::UInt16Short; break;

1881 case 4: STK = SimpleTypeKind::UInt32; break;

1882 case 8: STK = SimpleTypeKind::UInt64Quad; break;

1883 case 16: STK = SimpleTypeKind::UInt128Oct; break;

1884 }

1885 break;

1886 case dwarf::DW_ATE_UTF:

1887 switch (ByteSize) {

1888 case 1: STK = SimpleTypeKind::Character8; break;

1889 case 2: STK = SimpleTypeKind::Character16; break;

1890 case 4: STK = SimpleTypeKind::Character32; break;

1891 }

1892 break;

1893 case dwarf::DW_ATE_signed_char:

1894 if (ByteSize == 1)

1895 STK = SimpleTypeKind::SignedCharacter;

1896 break;

1897 case dwarf::DW_ATE_unsigned_char:

1898 if (ByteSize == 1)

1899 STK = SimpleTypeKind::UnsignedCharacter;

1900 break;

1901 default:

1902 break;

1903 }

1904

1905

1906

1907

1908

1909 if (STK == SimpleTypeKind::Int32 &&

1910 (Ty->getName() == "long int" || Ty->getName() == "long"))

1911 STK = SimpleTypeKind::Int32Long;

1912 if (STK == SimpleTypeKind::UInt32 && (Ty->getName() == "long unsigned int" ||

1913 Ty->getName() == "unsigned long"))

1914 STK = SimpleTypeKind::UInt32Long;

1915 if (STK == SimpleTypeKind::UInt16Short &&

1916 (Ty->getName() == "wchar_t" || Ty->getName() == "__wchar_t"))

1917 STK = SimpleTypeKind::WideCharacter;

1918 if ((STK == SimpleTypeKind::SignedCharacter ||

1919 STK == SimpleTypeKind::UnsignedCharacter) &&

1920 Ty->getName() == "char")

1921 STK = SimpleTypeKind::NarrowCharacter;

1922

1923 return TypeIndex(STK);

1924}

1925

1926TypeIndex CodeViewDebug::lowerTypePointer(const DIDerivedType *Ty,

1928 TypeIndex PointeeTI = getTypeIndex(Ty->getBaseType());

1929

1930

1931

1932 if (PointeeTI.isSimple() && PO == PointerOptions::None &&

1933 PointeeTI.getSimpleMode() == SimpleTypeMode::Direct &&

1934 Ty->getTag() == dwarf::DW_TAG_pointer_type) {

1936 ? SimpleTypeMode::NearPointer64

1937 : SimpleTypeMode::NearPointer32;

1939 }

1940

1942 Ty->getSizeInBits() == 64 ? PointerKind::Near64 : PointerKind::Near32;

1944 switch (Ty->getTag()) {

1946 case dwarf::DW_TAG_pointer_type:

1947 PM = PointerMode::Pointer;

1948 break;

1949 case dwarf::DW_TAG_reference_type:

1950 PM = PointerMode::LValueReference;

1951 break;

1952 case dwarf::DW_TAG_rvalue_reference_type:

1953 PM = PointerMode::RValueReference;

1954 break;

1955 }

1956

1958 PO |= PointerOptions::Const;

1959

1960 PointerRecord PR(PointeeTI, PK, PM, PO, Ty->getSizeInBits() / 8);

1961 return TypeTable.writeLeafType(PR);

1962}

1963

1966

1967

1968

1969 if (IsPMF) {

1971 case 0:

1974 case DINode::FlagSingleInheritance:

1976 case DINode::FlagMultipleInheritance:

1978 case DINode::FlagVirtualInheritance:

1980 }

1981 } else {

1983 case 0:

1986 case DINode::FlagSingleInheritance:

1988 case DINode::FlagMultipleInheritance:

1990 case DINode::FlagVirtualInheritance:

1992 }

1993 }

1995}

1996

1997TypeIndex CodeViewDebug::lowerTypeMemberPointer(const DIDerivedType *Ty,

1999 assert(Ty->getTag() == dwarf::DW_TAG_ptr_to_member_type);

2001 TypeIndex ClassTI = getTypeIndex(Ty->getClassType());

2002 TypeIndex PointeeTI =

2003 getTypeIndex(Ty->getBaseType(), IsPMF ? Ty->getClassType() : nullptr);

2004 PointerKind PK = getPointerSizeInBytes() == 8 ? PointerKind::Near64

2005 : PointerKind::Near32;

2006 PointerMode PM = IsPMF ? PointerMode::PointerToMemberFunction

2007 : PointerMode::PointerToDataMember;

2008

2011 MemberPointerInfo MPI(

2013 PointerRecord PR(PointeeTI, PK, PM, PO, SizeInBytes, MPI);

2014 return TypeTable.writeLeafType(PR);

2015}

2016

2017

2018

2020 switch (DwarfCC) {

2027 }

2029}

2030

2031TypeIndex CodeViewDebug::lowerTypeModifier(const DIDerivedType *Ty) {

2035 const DIType *BaseTy = Ty;

2036 while (IsModifier && BaseTy) {

2037

2038 switch (BaseTy->getTag()) {

2039 case dwarf::DW_TAG_const_type:

2040 Mods |= ModifierOptions::Const;

2041 PO |= PointerOptions::Const;

2042 break;

2043 case dwarf::DW_TAG_volatile_type:

2044 Mods |= ModifierOptions::Volatile;

2045 PO |= PointerOptions::Volatile;

2046 break;

2047 case dwarf::DW_TAG_restrict_type:

2048

2049

2050 PO |= PointerOptions::Restrict;

2051 break;

2052 default:

2054 break;

2055 }

2056 if (IsModifier)

2058 }

2059

2060

2061

2062

2063

2064 if (BaseTy) {

2065 switch (BaseTy->getTag()) {

2066 case dwarf::DW_TAG_pointer_type:

2067 case dwarf::DW_TAG_reference_type:

2068 case dwarf::DW_TAG_rvalue_reference_type:

2070 case dwarf::DW_TAG_ptr_to_member_type:

2072 default:

2073 break;

2074 }

2075 }

2076

2077 TypeIndex ModifiedTI = getTypeIndex(BaseTy);

2078

2079

2080

2081 if (Mods == ModifierOptions::None)

2082 return ModifiedTI;

2083

2084 ModifierRecord MR(ModifiedTI, Mods);

2085 return TypeTable.writeLeafType(MR);

2086}

2087

2088TypeIndex CodeViewDebug::lowerTypeFunction(const DISubroutineType *Ty) {

2090 for (const DIType *ArgType : Ty->getTypeArray())

2091 ReturnAndArgTypeIndices.push_back(getTypeIndex(ArgType));

2092

2093

2094 if (ReturnAndArgTypeIndices.size() > 1 &&

2097 }

2100 if (!ReturnAndArgTypeIndices.empty()) {

2101 auto ReturnAndArgTypesRef = ArrayRef(ReturnAndArgTypeIndices);

2102 ReturnTypeIndex = ReturnAndArgTypesRef.consume_front();

2103 ArgTypeIndices = ReturnAndArgTypesRef;

2104 }

2105

2106 ArgListRecord ArgListRec(TypeRecordKind::ArgList, ArgTypeIndices);

2107 TypeIndex ArgListIndex = TypeTable.writeLeafType(ArgListRec);

2108

2110

2112 ProcedureRecord Procedure(ReturnTypeIndex, CC, FO, ArgTypeIndices.size(),

2113 ArgListIndex);

2114 return TypeTable.writeLeafType(Procedure);

2115}

2116

2117TypeIndex CodeViewDebug::lowerTypeMemberFunction(const DISubroutineType *Ty,

2118 const DIType *ClassTy,

2119 int ThisAdjustment,

2120 bool IsStaticMethod,

2122

2123 TypeIndex ClassType = getTypeIndex(ClassTy);

2124

2125 DITypeRefArray ReturnAndArgs = Ty->getTypeArray();

2126

2127 unsigned Index = 0;

2130 if (ReturnAndArgs.size() > Index) {

2131 ReturnTypeIndex = getTypeIndex(ReturnAndArgs[Index++]);

2132 }

2133

2134

2135

2136

2137 TypeIndex ThisTypeIndex;

2138 if (!IsStaticMethod && ReturnAndArgs.size() > Index) {

2139 if (const DIDerivedType *PtrTy =

2141 if (PtrTy->getTag() == dwarf::DW_TAG_pointer_type) {

2142 ThisTypeIndex = getTypeIndexForThisPtr(PtrTy, Ty);

2144 }

2145 }

2146 }

2147

2148 while (Index < ReturnAndArgs.size())

2149 ArgTypeIndices.push_back(getTypeIndex(ReturnAndArgs[Index++]));

2150

2151

2154

2155 ArgListRecord ArgListRec(TypeRecordKind::ArgList, ArgTypeIndices);

2156 TypeIndex ArgListIndex = TypeTable.writeLeafType(ArgListRec);

2157

2159

2160 MemberFunctionRecord MFR(ReturnTypeIndex, ClassType, ThisTypeIndex, CC, FO,

2161 ArgTypeIndices.size(), ArgListIndex, ThisAdjustment);

2162 return TypeTable.writeLeafType(MFR);

2163}

2164

2165TypeIndex CodeViewDebug::lowerTypeVFTableShape(const DIDerivedType *Ty) {

2166 unsigned VSlotCount =

2169

2170 VFTableShapeRecord VFTSR(Slots);

2171 return TypeTable.writeLeafType(VFTSR);

2172}

2173

2179 case 0:

2180

2183 }

2185}

2186

2188 if (SP->isArtificial())

2190

2191

2192

2194}

2195

2197 bool Introduced) {

2198 if (SP->getFlags() & DINode::FlagStaticMember)

2200

2201 switch (SP->getVirtuality()) {

2202 case dwarf::DW_VIRTUALITY_none:

2203 break;

2204 case dwarf::DW_VIRTUALITY_virtual:

2206 case dwarf::DW_VIRTUALITY_pure_virtual:

2209 default:

2211 }

2212

2214}

2215

2217 switch (Ty->getTag()) {

2218 case dwarf::DW_TAG_class_type:

2219 return TypeRecordKind::Class;

2220 case dwarf::DW_TAG_structure_type:

2221 return TypeRecordKind::Struct;

2222 default:

2224 }

2225}

2226

2227

2228

2231

2232

2233

2234

2235 if (!Ty->getIdentifier().empty())

2237

2238

2239

2240

2244

2245

2246

2247

2248

2249 if (Ty->getTag() == dwarf::DW_TAG_enumeration_type) {

2252 } else {

2253 for (const DIScope *Scope = ImmediateScope; Scope != nullptr;

2254 Scope = Scope->getScope()) {

2257 break;

2258 }

2259 }

2260 }

2261

2262 return CO;

2263}

2264

2265void CodeViewDebug::addUDTSrcLine(const DIType *Ty, TypeIndex TI) {

2266 switch (Ty->getTag()) {

2267 case dwarf::DW_TAG_class_type:

2268 case dwarf::DW_TAG_structure_type:

2269 case dwarf::DW_TAG_union_type:

2270 case dwarf::DW_TAG_enumeration_type:

2271 break;

2272 default:

2273 return;

2274 }

2275

2276 if (const auto *File = Ty->getFile()) {

2277 StringIdRecord SIDR(TypeIndex(0x0), getFullFilepath(File));

2278 TypeIndex SIDI = TypeTable.writeLeafType(SIDR);

2279

2280 UdtSourceLineRecord USLR(TI, SIDI, Ty->getLine());

2281 TypeTable.writeLeafType(USLR);

2282 }

2283}

2284

2285TypeIndex CodeViewDebug::lowerTypeEnum(const DICompositeType *Ty) {

2287 TypeIndex FTI;

2288 unsigned EnumeratorCount = 0;

2289

2291 CO |= ClassOptions::ForwardReference;

2292 } else {

2293 ContinuationRecordBuilder ContinuationBuilder;

2294 ContinuationBuilder.begin(ContinuationRecordKind::FieldList);

2295 for (const DINode *Element : Ty->getElements()) {

2296

2297

2299

2300 EnumeratorRecord ER(MemberAccess::Public,

2304 EnumeratorCount++;

2305 }

2306 }

2307 FTI = TypeTable.insertRecord(ContinuationBuilder);

2308 }

2309

2310 std::string FullName = getFullyQualifiedName(Ty);

2311

2312 EnumRecord ER(EnumeratorCount, CO, FTI, FullName, Ty->getIdentifier(),

2314 TypeIndex EnumTI = TypeTable.writeLeafType(ER);

2315

2316 addUDTSrcLine(Ty, EnumTI);

2317

2318 return EnumTI;

2319}

2320

2321

2322

2323

2324

2330

2332

2334

2336

2337

2339

2340

2342

2344

2346

2348};

2349

2350void CodeViewDebug::clear() {

2351 assert(CurFn == nullptr);

2352 FileIdMap.clear();

2353 FnDebugInfo.clear();

2354 FileToFilepathMap.clear();

2355 LocalUDTs.clear();

2356 GlobalUDTs.clear();

2357 TypeIndices.clear();

2358 CompleteTypeIndices.clear();

2359 ScopeGlobals.clear();

2360 CVGlobalVariableOffsets.clear();

2361}

2362

2363void CodeViewDebug::collectMemberInfo(ClassInfo &Info,

2366 Info.Members.push_back({DDTy, 0});

2367

2368

2369 if ((DDTy->getFlags() & DINode::FlagStaticMember) ==

2370 DINode::FlagStaticMember) {

2373 StaticConstMembers.push_back(DDTy);

2374 }

2375

2376 return;

2377 }

2378

2379

2380

2381

2382

2385 const DIType *Ty = DDTy->getBaseType();

2386 bool FullyResolved = false;

2387 while (!FullyResolved) {

2388 switch (Ty->getTag()) {

2389 case dwarf::DW_TAG_const_type:

2390 case dwarf::DW_TAG_volatile_type:

2391

2392

2394 break;

2395 default:

2396 FullyResolved = true;

2397 break;

2398 }

2399 }

2400

2402 if (!DCTy)

2403 return;

2404

2405 ClassInfo NestedInfo = collectClassInfo(DCTy);

2406 for (const ClassInfo::MemberInfo &IndirectField : NestedInfo.Members)

2407 Info.Members.push_back(

2409}

2410

2412 ClassInfo Info;

2413

2415 for (auto *Element : Elements) {

2416

2417

2418 if (!Element)

2419 continue;

2421 Info.Methods[SP->getRawName()].push_back(SP);

2423 if (DDTy->getTag() == dwarf::DW_TAG_member) {

2424 collectMemberInfo(Info, DDTy);

2425 } else if (DDTy->getTag() == dwarf::DW_TAG_inheritance) {

2426 Info.Inheritance.push_back(DDTy);

2427 } else if (DDTy->getTag() == dwarf::DW_TAG_pointer_type &&

2428 DDTy->getName() == "__vtbl_ptr_type") {

2429 Info.VShapeTI = getTypeIndex(DDTy);

2430 } else if (DDTy->getTag() == dwarf::DW_TAG_typedef) {

2431 Info.NestedTypes.push_back(DDTy);

2432 } else if (DDTy->getTag() == dwarf::DW_TAG_friend) {

2433

2434

2435 }

2437 Info.NestedTypes.push_back(Composite);

2438 }

2439

2440 }

2441 return Info;

2442}

2443

2445

2446

2447 return Ty->getName().empty() && Ty->getIdentifier().empty() &&

2448 !Ty->isForwardDecl();

2449}

2450

2451TypeIndex CodeViewDebug::lowerTypeClass(const DICompositeType *Ty) {

2452

2453

2454

2455

2457

2458

2459

2460 auto I = CompleteTypeIndices.find(Ty);

2461 if (I != CompleteTypeIndices.end() && I->second == TypeIndex())

2462 report_fatal_error("cannot debug circular reference to unnamed type");

2463 return getCompleteTypeIndex(Ty);

2464 }

2465

2466

2467

2471 std::string FullName = getFullyQualifiedName(Ty);

2472 ClassRecord CR(Kind, 0, CO, TypeIndex(), TypeIndex(), TypeIndex(), 0,

2474 TypeIndex FwdDeclTI = TypeTable.writeLeafType(CR);

2476 DeferredCompleteTypes.push_back(Ty);

2477 return FwdDeclTI;

2478}

2479

2480TypeIndex CodeViewDebug::lowerCompleteTypeClass(const DICompositeType *Ty) {

2481

2484 TypeIndex FieldTI;

2485 TypeIndex VShapeTI;

2486 unsigned FieldCount;

2489 lowerRecordFieldList(Ty);

2490

2492 CO |= ClassOptions::ContainsNestedClass;

2493

2494

2495

2496

2497

2498

2500 CO |= ClassOptions::HasConstructorOrDestructor;

2501

2502 std::string FullName = getFullyQualifiedName(Ty);

2503

2505

2506 ClassRecord CR(Kind, FieldCount, CO, FieldTI, TypeIndex(), VShapeTI,

2508 TypeIndex ClassTI = TypeTable.writeLeafType(CR);

2509

2510 addUDTSrcLine(Ty, ClassTI);

2511

2512 addToUDTs(Ty);

2513

2514 return ClassTI;

2515}

2516

2517TypeIndex CodeViewDebug::lowerTypeUnion(const DICompositeType *Ty) {

2518

2520 return getCompleteTypeIndex(Ty);

2521

2524 std::string FullName = getFullyQualifiedName(Ty);

2525 UnionRecord UR(0, CO, TypeIndex(), 0, FullName, Ty->getIdentifier());

2526 TypeIndex FwdDeclTI = TypeTable.writeLeafType(UR);

2528 DeferredCompleteTypes.push_back(Ty);

2529 return FwdDeclTI;

2530}

2531

2532TypeIndex CodeViewDebug::lowerCompleteTypeUnion(const DICompositeType *Ty) {

2534 TypeIndex FieldTI;

2535 unsigned FieldCount;

2538 lowerRecordFieldList(Ty);

2539

2541 CO |= ClassOptions::ContainsNestedClass;

2542

2544 std::string FullName = getFullyQualifiedName(Ty);

2545

2546 UnionRecord UR(FieldCount, CO, FieldTI, SizeInBytes, FullName,

2548 TypeIndex UnionTI = TypeTable.writeLeafType(UR);

2549

2550 addUDTSrcLine(Ty, UnionTI);

2551

2552 addToUDTs(Ty);

2553

2554 return UnionTI;

2555}

2556

2557std::tuple<TypeIndex, TypeIndex, unsigned, bool>

2558CodeViewDebug::lowerRecordFieldList(const DICompositeType *Ty) {

2559

2560

2561

2562

2563 unsigned MemberCount = 0;

2564 ClassInfo Info = collectClassInfo(Ty);

2565 ContinuationRecordBuilder ContinuationBuilder;

2566 ContinuationBuilder.begin(ContinuationRecordKind::FieldList);

2567

2568

2569 for (const DIDerivedType *I : Info.Inheritance) {

2570 if (I->getFlags() & DINode::FlagVirtual) {

2571

2572 unsigned VBPtrOffset = I->getVBPtrOffset();

2573

2574 unsigned VBTableIndex = I->getOffsetInBits() / 4;

2575 auto RecordKind = (I->getFlags() & DINode::FlagIndirectVirtualBase) == DINode::FlagIndirectVirtualBase

2576 ? TypeRecordKind::IndirectVirtualBaseClass

2577 : TypeRecordKind::VirtualBaseClass;

2578 VirtualBaseClassRecord VBCR(

2580 getTypeIndex(I->getBaseType()), getVBPTypeIndex(), VBPtrOffset,

2581 VBTableIndex);

2582

2584 MemberCount++;

2585 } else {

2586 assert(I->getOffsetInBits() % 8 == 0 &&

2587 "bases must be on byte boundaries");

2589 getTypeIndex(I->getBaseType()),

2590 I->getOffsetInBits() / 8);

2592 MemberCount++;

2593 }

2594 }

2595

2596

2597 for (ClassInfo::MemberInfo &MemberInfo : Info.Members) {

2599 TypeIndex MemberBaseType = getTypeIndex(Member->getBaseType());

2600 StringRef MemberName = Member->getName();

2603

2604 if (Member->isStaticMember()) {

2605 StaticDataMemberRecord SDMR(Access, MemberBaseType, MemberName);

2607 MemberCount++;

2608 continue;

2609 }

2610

2611

2612 if ((Member->getFlags() & DINode::FlagArtificial) &&

2613 Member->getName().starts_with("_vptr$")) {

2614 VFPtrRecord VFPR(getTypeIndex(Member->getBaseType()));

2616 MemberCount++;

2617 continue;

2618 }

2619

2620

2621 uint64_t MemberOffsetInBits =

2623 if (Member->isBitField()) {

2624 uint64_t StartBitOffset = MemberOffsetInBits;

2625 if (const auto *CI =

2627 MemberOffsetInBits = CI->getZExtValue() + MemberInfo.BaseOffset;

2628 }

2629 StartBitOffset -= MemberOffsetInBits;

2630 BitFieldRecord BFR(MemberBaseType, Member->getSizeInBits(),

2631 StartBitOffset);

2632 MemberBaseType = TypeTable.writeLeafType(BFR);

2633 }

2634 uint64_t MemberOffsetInBytes = MemberOffsetInBits / 8;

2635 DataMemberRecord DMR(Access, MemberBaseType, MemberOffsetInBytes,

2636 MemberName);

2638 MemberCount++;

2639 }

2640

2641

2642 for (auto &MethodItr : Info.Methods) {

2643 StringRef Name = MethodItr.first->getString();

2644

2645 std::vector Methods;

2646 for (const DISubprogram *SP : MethodItr.second) {

2647 TypeIndex MethodType = getMemberFunctionType(SP, Ty);

2648 bool Introduced = SP->getFlags() & DINode::FlagIntroducedVirtual;

2649

2650 unsigned VFTableOffset = -1;

2651 if (Introduced)

2652 VFTableOffset = SP->getVirtualIndex() * getPointerSizeInBytes();

2653

2654 Methods.push_back(OneMethodRecord(

2658 MemberCount++;

2659 }

2660 assert(!Methods.empty() && "Empty methods map entry");

2661 if (Methods.size() == 1)

2663 else {

2664

2665

2666 MethodOverloadListRecord MOLR(Methods);

2667 TypeIndex MethodList = TypeTable.writeLeafType(MOLR);

2668

2669 OverloadedMethodRecord OMR(Methods.size(), MethodList, Name);

2671 }

2672 }

2673

2674

2675 for (const DIType *Nested : Info.NestedTypes) {

2676 NestedTypeRecord R(getTypeIndex(Nested), Nested->getName());

2678 MemberCount++;

2679 }

2680

2681 TypeIndex FieldTI = TypeTable.insertRecord(ContinuationBuilder);

2682 return std::make_tuple(FieldTI, Info.VShapeTI, MemberCount,

2683 Info.NestedTypes.empty());

2684}

2685

2686TypeIndex CodeViewDebug::getVBPTypeIndex() {

2687 if (!VBPType.getIndex()) {

2688

2689 ModifierRecord MR(TypeIndex::Int32(), ModifierOptions::Const);

2690 TypeIndex ModifiedTI = TypeTable.writeLeafType(MR);

2691

2692 PointerKind PK = getPointerSizeInBytes() == 8 ? PointerKind::Near64

2693 : PointerKind::Near32;

2696 PointerRecord PR(ModifiedTI, PK, PM, PO, getPointerSizeInBytes());

2697 VBPType = TypeTable.writeLeafType(PR);

2698 }

2699

2700 return VBPType;

2701}

2702

2703TypeIndex CodeViewDebug::getTypeIndex(const DIType *Ty, const DIType *ClassTy) {

2704

2705 if (!Ty)

2707

2708

2709

2710

2711 auto I = TypeIndices.find({Ty, ClassTy});

2712 if (I != TypeIndices.end())

2713 return I->second;

2714

2716 TypeIndex TI = lowerType(Ty, ClassTy);

2717 return recordTypeIndexForDINode(Ty, TI, ClassTy);

2718}

2719

2721CodeViewDebug::getTypeIndexForThisPtr(const DIDerivedType *PtrTy,

2723 assert(PtrTy->getTag() == dwarf::DW_TAG_pointer_type &&

2724 "this type must be a pointer type");

2725

2727 if (SubroutineTy->getFlags() & DINode::DIFlags::FlagLValueReference)

2728 Options = PointerOptions::LValueRefThisPointer;

2729 else if (SubroutineTy->getFlags() & DINode::DIFlags::FlagRValueReference)

2730 Options = PointerOptions::RValueRefThisPointer;

2731

2732

2733

2734

2735

2736

2737 auto I = TypeIndices.find({PtrTy, SubroutineTy});

2738 if (I != TypeIndices.end())

2739 return I->second;

2740

2742 TypeIndex TI = lowerTypePointer(PtrTy, Options);

2743 return recordTypeIndexForDINode(PtrTy, TI, SubroutineTy);

2744}

2745

2746TypeIndex CodeViewDebug::getTypeIndexForReferenceTo(const DIType *Ty) {

2747 PointerRecord PR(getTypeIndex(Ty),

2748 getPointerSizeInBytes() == 8 ? PointerKind::Near64

2749 : PointerKind::Near32,

2750 PointerMode::LValueReference, PointerOptions::None,

2752 return TypeTable.writeLeafType(PR);

2753}

2754

2755TypeIndex CodeViewDebug::getCompleteTypeIndex(const DIType *Ty) {

2756

2757 if (!Ty)

2759

2760

2761

2762

2763 if (Ty->getTag() == dwarf::DW_TAG_typedef)

2764 (void)getTypeIndex(Ty);

2765 while (Ty->getTag() == dwarf::DW_TAG_typedef)

2767

2768

2769

2770 switch (Ty->getTag()) {

2771 case dwarf::DW_TAG_class_type:

2772 case dwarf::DW_TAG_structure_type:

2773 case dwarf::DW_TAG_union_type:

2774 break;

2775 default:

2776 return getTypeIndex(Ty);

2777 }

2778

2780

2782

2783

2784

2785

2786

2787 if (!CTy->getName().empty() || !CTy->getIdentifier().empty()) {

2788 TypeIndex FwdDeclTI = getTypeIndex(CTy);

2789

2790

2791

2792

2793 if (CTy->isForwardDecl())

2794 return FwdDeclTI;

2795 }

2796

2797

2798

2799

2800 auto InsertResult = CompleteTypeIndices.try_emplace(CTy);

2801 if (!InsertResult.second)

2802 return InsertResult.first->second;

2803

2804 TypeIndex TI;

2805 switch (CTy->getTag()) {

2806 case dwarf::DW_TAG_class_type:

2807 case dwarf::DW_TAG_structure_type:

2808 TI = lowerCompleteTypeClass(CTy);

2809 break;

2810 case dwarf::DW_TAG_union_type:

2811 TI = lowerCompleteTypeUnion(CTy);

2812 break;

2813 default:

2815 }

2816

2817

2818

2819

2820

2821 CompleteTypeIndices[CTy] = TI;

2822 return TI;

2823}

2824

2825

2826

2827

2828

2829void CodeViewDebug::emitDeferredCompleteTypes() {

2831 while (!DeferredCompleteTypes.empty()) {

2832 std::swap(DeferredCompleteTypes, TypesToEmit);

2833 for (const DICompositeType *RecordTy : TypesToEmit)

2834 getCompleteTypeIndex(RecordTy);

2835 TypesToEmit.clear();

2836 }

2837}

2838

2839void CodeViewDebug::emitLocalVariableList(const FunctionInfo &FI,

2841

2843 for (const LocalVariable &L : Locals)

2844 if (L.DIVar->isParameter())

2846 llvm::sort(Params, [](const LocalVariable *L, const LocalVariable *R) {

2847 return L->DIVar->getArg() < R->DIVar->getArg();

2848 });

2849 for (const LocalVariable *L : Params)

2850 emitLocalVariable(FI, *L);

2851

2852

2853 for (const LocalVariable &L : Locals) {

2854 if (L.DIVar->isParameter()) {

2855 if (L.ConstantValue) {

2856

2857

2858 const DIType *Ty = L.DIVar->getType();

2859 APSInt Val(*L.ConstantValue);

2860 emitConstantSymbolRecord(Ty, Val, std::string(L.DIVar->getName()));

2861 } else {

2862 emitLocalVariable(FI, L);

2863 }

2864 }

2865 }

2866}

2867

2868void CodeViewDebug::emitLocalVariable(const FunctionInfo &FI,

2869 const LocalVariable &Var) {

2870

2871 MCSymbol *LocalEnd = beginSymbolRecord(SymbolKind::S_LOCAL);

2872

2874 if (Var.DIVar->isParameter())

2875 Flags |= LocalSymFlags::IsParameter;

2876 if (Var.DefRanges.empty())

2877 Flags |= LocalSymFlags::IsOptimizedOut;

2878

2879 OS.AddComment("TypeIndex");

2880 TypeIndex TI = Var.UseReferenceType

2881 ? getTypeIndexForReferenceTo(Var.DIVar->getType())

2882 : getCompleteTypeIndex(Var.DIVar->getType());

2883 OS.emitInt32(TI.getIndex());

2884 OS.AddComment("Flags");

2885 OS.emitInt16(static_cast<uint16_t>(Flags));

2886

2888 endSymbolRecord(LocalEnd);

2889

2890

2891

2892

2893 SmallString<20> BytePrefix;

2894 for (const auto &Pair : Var.DefRanges) {

2895 LocalVarDef DefRange = Pair.first;

2896 const auto &Ranges = Pair.second;

2897 BytePrefix.clear();

2898 if (DefRange.InMemory) {

2899 int Offset = DefRange.DataOffset;

2900 unsigned Reg = DefRange.CVRegister;

2901

2902

2903

2904

2905 if (RegisterId(Reg) == RegisterId::ESP) {

2906 Reg = unsigned(RegisterId::VFRAME);

2907 Offset += FI.OffsetAdjustment;

2908 }

2909

2910

2911

2912

2913 EncodedFramePtrReg EncFP = encodeFramePtrReg(RegisterId(Reg), TheCPU);

2914 if (!DefRange.IsSubfield && EncFP != EncodedFramePtrReg::None &&

2915 (bool(Flags & LocalSymFlags::IsParameter)

2916 ? (EncFP == FI.EncodedParamFramePtrReg)

2917 : (EncFP == FI.EncodedLocalFramePtrReg))) {

2918 DefRangeFramePointerRelHeader DRHdr;

2919 DRHdr.Offset = Offset;

2920 OS.emitCVDefRangeDirective(Ranges, DRHdr);

2921 } else {

2922 uint16_t RegRelFlags = 0;

2923 if (DefRange.IsSubfield) {

2924 RegRelFlags = DefRangeRegisterRelSym::IsSubfieldFlag |

2925 (DefRange.StructOffset

2926 << DefRangeRegisterRelSym::OffsetInParentShift);

2927 }

2928 DefRangeRegisterRelHeader DRHdr;

2929 DRHdr.Register = Reg;

2930 DRHdr.Flags = RegRelFlags;

2931 DRHdr.BasePointerOffset = Offset;

2932 OS.emitCVDefRangeDirective(Ranges, DRHdr);

2933 }

2934 } else {

2935 assert(DefRange.DataOffset == 0 && "unexpected offset into register");

2936 if (DefRange.IsSubfield) {

2937 DefRangeSubfieldRegisterHeader DRHdr;

2938 DRHdr.Register = DefRange.CVRegister;

2939 DRHdr.MayHaveNoName = 0;

2940 DRHdr.OffsetInParent = DefRange.StructOffset;

2941 OS.emitCVDefRangeDirective(Ranges, DRHdr);

2942 } else {

2943 DefRangeRegisterHeader DRHdr;

2944 DRHdr.Register = DefRange.CVRegister;

2945 DRHdr.MayHaveNoName = 0;

2946 OS.emitCVDefRangeDirective(Ranges, DRHdr);

2947 }

2948 }

2949 }

2950}

2951

2953 const FunctionInfo& FI) {

2954 for (LexicalBlock *Block : Blocks)

2955 emitLexicalBlock(*Block, FI);

2956}

2957

2958

2959

2960void CodeViewDebug::emitLexicalBlock(const LexicalBlock &Block,

2961 const FunctionInfo& FI) {

2962 MCSymbol *RecordEnd = beginSymbolRecord(SymbolKind::S_BLOCK32);

2963 OS.AddComment("PtrParent");

2964 OS.emitInt32(0);

2965 OS.AddComment("PtrEnd");

2966 OS.emitInt32(0);

2967 OS.AddComment("Code size");

2968 OS.emitAbsoluteSymbolDiff(Block.End, Block.Begin, 4);

2969 OS.AddComment("Function section relative address");

2970 OS.emitCOFFSecRel32(Block.Begin, 0);

2971 OS.AddComment("Function section index");

2972 OS.emitCOFFSectionIndex(FI.Begin);

2973 OS.AddComment("Lexical block name");

2975 endSymbolRecord(RecordEnd);

2976

2977

2978 emitLocalVariableList(FI, Block.Locals);

2979 emitGlobalVariableList(Block.Globals);

2980

2981

2982 emitLexicalBlockList(Block.Children, FI);

2983

2984

2985 emitEndSymbolRecord(SymbolKind::S_END);

2986}

2987

2988

2989

2990void CodeViewDebug::collectLexicalBlockInfo(

2995 for (LexicalScope *Scope : Scopes)

2996 collectLexicalBlockInfo(*Scope, Blocks, Locals, Globals);

2997}

2998

2999

3000

3001void CodeViewDebug::collectLexicalBlockInfo(

3006 if (Scope.isAbstractScope())

3007 return;

3008

3009

3010

3011 bool IgnoreScope = false;

3012 auto LI = ScopeVariables.find(&Scope);

3013 SmallVectorImpl *Locals =

3014 LI != ScopeVariables.end() ? &LI->second : nullptr;

3015 auto GI = ScopeGlobals.find(Scope.getScopeNode());

3016 SmallVectorImpl *Globals =

3017 GI != ScopeGlobals.end() ? GI->second.get() : nullptr;

3019 const SmallVectorImpl &Ranges = Scope.getRanges();

3020

3021

3022 if (!Locals && !Globals)

3023 IgnoreScope = true;

3024

3025

3026 if (!DILB)

3027 IgnoreScope = true;

3028

3029

3030

3031

3032

3033

3034

3035

3036

3037

3038

3039

3041 IgnoreScope = true;

3042

3043 if (IgnoreScope) {

3044

3045

3046

3047

3048 if (Locals)

3050 if (Globals)

3051 ParentGlobals.append(Globals->begin(), Globals->end());

3052 collectLexicalBlockInfo(Scope.getChildren(),

3053 ParentBlocks,

3054 ParentLocals,

3055 ParentGlobals);

3056 return;

3057 }

3058

3059

3060

3061

3062 auto BlockInsertion = CurFn->LexicalBlocks.try_emplace(DILB);

3063 if (!BlockInsertion.second)

3064 return;

3065

3066

3067

3070 LexicalBlock &Block = BlockInsertion.first->second;

3073 assert(Block.Begin && "missing label for scope begin");

3074 assert(Block.End && "missing label for scope end");

3076 if (Locals)

3077 Block.Locals = std::move(*Locals);

3078 if (Globals)

3079 Block.Globals = std::move(*Globals);

3081 collectLexicalBlockInfo(Scope.getChildren(),

3085}

3086

3089 assert(FnDebugInfo.count(&GV));

3090 assert(CurFn == FnDebugInfo[&GV].get());

3091

3093

3094

3096 collectLexicalBlockInfo(*CFS,

3097 CurFn->ChildBlocks,

3098 CurFn->Locals,

3099 CurFn->Globals);

3100

3101

3102

3103

3104 ScopeVariables.clear();

3105

3106

3107

3108 if (!CurFn->HaveLineInfo && !GV.getSubprogram()->isThunk()) {

3109 FnDebugInfo.erase(&GV);

3110 CurFn = nullptr;

3111 return;

3112 }

3113

3114

3115 for (const auto &MBB : *MF) {

3116 for (const auto &MI : MBB) {

3117 if (MDNode *MD = MI.getHeapAllocMarker()) {

3121 }

3122 }

3123 }

3124

3125 bool isThumb = MMI->getModule()->getTargetTriple().getArch() ==

3127 collectDebugInfoForJumpTables(MF, isThumb);

3128

3130

3131 CurFn->End = Asm->getFunctionEnd();

3132

3133 CurFn = nullptr;

3134}

3135

3136

3137

3138

3139

3141 return DL && DL.getLine() != 0;

3142}

3143

3146

3147

3148 if (Asm || !CurFn || MI->isDebugInstr() ||

3150 return;

3151

3152

3153

3156 for (const auto &NextMI : *MI->getParent()) {

3157 if (NextMI.isDebugInstr())

3158 continue;

3159 DL = NextMI.getDebugLoc();

3161 break;

3162 }

3163

3164

3165 }

3167

3168

3170 return;

3171

3172 maybeRecordLocation(DL, Asm->MF);

3173}

3174

3182 return EndLabel;

3183}

3184

3185void CodeViewDebug::endCVSubsection(MCSymbol *EndLabel) {

3187

3189}

3190

3193 if (EE.Value == SymKind)

3194 return EE.Name;

3195 return "";

3196}

3197

3199 MCSymbol *BeginLabel = MMI->getContext().createTempSymbol(),

3200 *EndLabel = MMI->getContext().createTempSymbol();

3201 OS.AddComment("Record length");

3202 OS.emitAbsoluteSymbolDiff(EndLabel, BeginLabel, 2);

3203 OS.emitLabel(BeginLabel);

3204 if (OS.isVerboseAsm())

3205 OS.AddComment("Record kind: " + getSymbolName(SymKind));

3206 OS.emitInt16(unsigned(SymKind));

3207 return EndLabel;

3208}

3209

3210void CodeViewDebug::endSymbolRecord(MCSymbol *SymEnd) {

3211

3212

3213

3214

3215 OS.emitValueToAlignment(Align(4));

3216 OS.emitLabel(SymEnd);

3217}

3218

3219void CodeViewDebug::emitEndSymbolRecord(SymbolKind EndKind) {

3220 OS.AddComment("Record length");

3221 OS.emitInt16(2);

3222 if (OS.isVerboseAsm())

3223 OS.AddComment("Record kind: " + getSymbolName(EndKind));

3224 OS.emitInt16(uint16_t(EndKind));

3225}

3226

3227void CodeViewDebug::emitDebugInfoForUDTs(

3228 const std::vector<std::pair<std::string, const DIType *>> &UDTs) {

3229#ifndef NDEBUG

3230 size_t OriginalSize = UDTs.size();

3231#endif

3232 for (const auto &UDT : UDTs) {

3233 const DIType *T = UDT.second;

3235 MCSymbol *UDTRecordEnd = beginSymbolRecord(SymbolKind::S_UDT);

3236 OS.AddComment("Type");

3237 OS.emitInt32(getCompleteTypeIndex(T).getIndex());

3238 assert(OriginalSize == UDTs.size() &&

3239 "getCompleteTypeIndex found new UDTs!");

3241 endSymbolRecord(UDTRecordEnd);

3242 }

3243}

3244

3245void CodeViewDebug::collectGlobalVariableInfo() {

3246 DenseMap<const DIGlobalVariableExpression *, const GlobalVariable *>

3247 GlobalMap;

3248 for (const GlobalVariable &GV : MMI->getModule()->globals()) {

3250 GV.getDebugInfo(GVEs);

3251 for (const auto *GVE : GVEs)

3252 GlobalMap[GVE] = &GV;

3253 }

3254

3255 NamedMDNode *CUs = MMI->getModule()->getNamedMetadata("llvm.dbg.cu");

3256 for (const MDNode *Node : CUs->operands()) {

3258 for (const auto *GVE : CU->getGlobalVariables()) {

3259 const DIGlobalVariable *DIGV = GVE->getVariable();

3260 const DIExpression *DIE = GVE->getExpression();

3261

3262

3263

3264

3266

3268 (DIE->getElement(0) == dwarf::DW_OP_plus_uconst))

3269

3270

3271

3272

3273 CVGlobalVariableOffsets.insert(

3274 std::make_pair(DIGV, DIE->getElement(1)));

3275

3276

3278 CVGlobalVariable CVGV = {DIGV, DIE};

3279 GlobalVariables.emplace_back(std::move(CVGV));

3280 }

3281

3282 const auto *GV = GlobalMap.lookup(GVE);

3284 continue;

3285

3287 SmallVector<CVGlobalVariable, 1> *VariableList;

3289

3290

3291 auto Insertion = ScopeGlobals.insert(

3292 {Scope, std::unique_ptr()});

3293 if (Insertion.second)

3294 Insertion.first->second = std::make_unique();

3295 VariableList = Insertion.first->second.get();

3297

3298 VariableList = &ComdatVariables;

3299 else

3300

3301 VariableList = &GlobalVariables;

3302 CVGlobalVariable CVGV = {DIGV, GV};

3303 VariableList->emplace_back(std::move(CVGV));

3304 }

3305 }

3306}

3307

3308void CodeViewDebug::collectDebugInfoForGlobals() {

3309 for (const CVGlobalVariable &CVGV : GlobalVariables) {

3310 const DIGlobalVariable *DIGV = CVGV.DIGV;

3312 getCompleteTypeIndex(DIGV->getType());

3313 getFullyQualifiedName(Scope, DIGV->getName());

3314 }

3315

3316 for (const CVGlobalVariable &CVGV : ComdatVariables) {

3317 const DIGlobalVariable *DIGV = CVGV.DIGV;

3319 getCompleteTypeIndex(DIGV->getType());

3320 getFullyQualifiedName(Scope, DIGV->getName());

3321 }

3322}

3323

3324void CodeViewDebug::emitDebugInfoForGlobals() {

3325

3326

3327

3328 switchToDebugSectionForSymbol(nullptr);

3329 if (!GlobalVariables.empty() || !StaticConstMembers.empty()) {

3330 OS.AddComment("Symbol subsection for globals");

3331 MCSymbol *EndLabel = beginCVSubsection(DebugSubsectionKind::Symbols);

3332 emitGlobalVariableList(GlobalVariables);

3333 emitStaticConstMemberList();

3334 endCVSubsection(EndLabel);

3335 }

3336

3337

3338

3339 for (const CVGlobalVariable &CVGV : ComdatVariables) {

3342 OS.AddComment("Symbol subsection for " +

3344 switchToDebugSectionForSymbol(GVSym);

3345 MCSymbol *EndLabel = beginCVSubsection(DebugSubsectionKind::Symbols);

3346

3347 emitDebugInfoForGlobal(CVGV);

3348 endCVSubsection(EndLabel);

3349 }

3350}

3351

3352void CodeViewDebug::emitDebugInfoForRetainedTypes() {

3353 NamedMDNode *CUs = MMI->getModule()->getNamedMetadata("llvm.dbg.cu");

3354 for (const MDNode *Node : CUs->operands()) {

3357 getTypeIndex(RT);

3358

3359 }

3360 }

3361 }

3362}

3363

3364

3366 for (const CVGlobalVariable &CVGV : Globals) {

3367

3368 emitDebugInfoForGlobal(CVGV);

3369 }

3370}

3371

3372void CodeViewDebug::emitConstantSymbolRecord(const DIType *DTy, APSInt &Value,

3373 const std::string &QualifiedName) {

3374 MCSymbol *SConstantEnd = beginSymbolRecord(SymbolKind::S_CONSTANT);

3375 OS.AddComment("Type");

3376 OS.emitInt32(getTypeIndex(DTy).getIndex());

3377

3378 OS.AddComment("Value");

3379

3380

3381 uint8_t Data[10];

3383 CodeViewRecordIO IO(Writer);

3385 StringRef SRef((char *)Data, Writer.getOffset());

3386 OS.emitBinaryData(SRef);

3387

3388 OS.AddComment("Name");

3390 endSymbolRecord(SConstantEnd);

3391}

3392

3393void CodeViewDebug::emitStaticConstMemberList() {

3394 for (const DIDerivedType *DTy : StaticConstMembers) {

3396

3398 if (const ConstantInt *CI =

3402 else if (const ConstantFP *CFP =

3404 Value = APSInt(CFP->getValueAPF().bitcastToAPInt(), true);

3405 else

3407

3408 emitConstantSymbolRecord(DTy->getBaseType(), Value,

3409 getFullyQualifiedName(Scope, DTy->getName()));

3410 }

3411}

3412

3415 return false;

3416

3419 if (T == dwarf::DW_TAG_pointer_type ||

3420 T == dwarf::DW_TAG_ptr_to_member_type ||

3421 T == dwarf::DW_TAG_reference_type ||

3422 T == dwarf::DW_TAG_rvalue_reference_type)

3423 return false;

3424 assert(DTy->getBaseType() && "Expected valid base type");

3426 }

3427

3429 return (BTy->getEncoding() == dwarf::DW_ATE_float);

3430}

3431

3432void CodeViewDebug::emitDebugInfoForGlobal(const CVGlobalVariable &CVGV) {

3433 const DIGlobalVariable *DIGV = CVGV.DIGV;

3434

3436

3439 Scope = MemberDecl->getScope();

3440

3441

3442

3445 ? std::string(DIGV->getName())

3446 : getFullyQualifiedName(Scope, DIGV->getName());

3447

3448 if (const GlobalVariable *GV =

3450

3451

3452 MCSymbol *GVSym = Asm->getSymbol(GV);

3453 SymbolKind DataSym = GV->isThreadLocal()

3454 ? (DIGV->isLocalToUnit() ? SymbolKind::S_LTHREAD32

3455 : SymbolKind::S_GTHREAD32)

3456 : (DIGV->isLocalToUnit() ? SymbolKind::S_LDATA32

3457 : SymbolKind::S_GDATA32);

3458 MCSymbol *DataEnd = beginSymbolRecord(DataSym);

3459 OS.AddComment("Type");

3460 OS.emitInt32(getCompleteTypeIndex(DIGV->getType()).getIndex());

3461 OS.AddComment("DataOffset");

3462

3463

3464 uint64_t Offset = CVGlobalVariableOffsets.lookup(DIGV);

3465 OS.emitCOFFSecRel32(GVSym, Offset);

3466

3467 OS.AddComment("Segment");

3468 OS.emitCOFFSectionIndex(GVSym);

3469 OS.AddComment("Name");

3470 const unsigned LengthOfDataRecord = 12;

3471 emitNullTerminatedSymbolName(OS, QualifiedName, LengthOfDataRecord);

3472 endSymbolRecord(DataEnd);

3473 } else {

3474 const DIExpression *DIE = cast<const DIExpression *>(CVGV.GVInfo);

3475 assert(DIE->isConstant() &&

3476 "Global constant variables must contain a constant expression.");

3477

3478

3479 bool isUnsigned = isFloatDIType(DIGV->getType())

3480 ? true

3481 : DebugHandlerBase::isUnsignedDIType(DIGV->getType());

3482 APSInt Value(APInt(64, DIE->getElement(1)), isUnsigned);

3483 emitConstantSymbolRecord(DIGV->getType(), Value, QualifiedName);

3484 }

3485}

3486

3490 int64_t)> &Callback) {

3492 if (JTI && !JTI->isEmpty()) {

3493#ifndef NDEBUG

3495#endif

3496 for (const auto &MBB : *MF) {

3497

3498 const auto LastMI = MBB.getFirstTerminator();

3499 if (LastMI != MBB.end() && LastMI->isIndirectBranch()) {

3501

3502

3503

3504

3505

3506

3507 for (const auto &MO : LastMI->operands()) {

3508 if (MO.isJTI()) {

3509 unsigned Index = MO.getIndex();

3510#ifndef NDEBUG

3511 UsedJTs.set(Index);

3512#endif

3513 Callback(*JTI, *LastMI, Index);

3514 break;

3515 }

3516 }

3517 } else {

3518

3519

3520

3521 for (auto I = MBB.instr_rbegin(), E = MBB.instr_rend(); I != E; ++I) {

3522 if (I->isJumpTableDebugInfo()) {

3523 unsigned Index = I->getOperand(0).getImm();

3524#ifndef NDEBUG

3525 UsedJTs.set(Index);

3526#endif

3527 Callback(*JTI, *LastMI, Index);

3528 break;

3529 }

3530 }

3531 }

3532 }

3533 }

3534#ifndef NDEBUG

3535 assert(UsedJTs.all() &&

3536 "Some of jump tables were not used in a debug info instruction");

3537#endif

3538 }

3539}

3540

3541void CodeViewDebug::discoverJumpTableBranches(const MachineFunction *MF,

3545 [this](const MachineJumpTableInfo &, const MachineInstr &BranchMI,

3547}

3548

3549void CodeViewDebug::collectDebugInfoForJumpTables(const MachineFunction *MF,

3553 [this, MF](const MachineJumpTableInfo &JTI, const MachineInstr &BranchMI,

3554 int64_t JumpTableIndex) {

3555

3556

3557

3559 uint64_t BaseOffset = 0;

3567 "EK_Custom32, EK_GPRel32BlockAddress, and "

3568 "EK_GPRel64BlockAddress should never be emitted for COFF");

3570

3571 EntrySize = JumpTableEntrySize::Pointer;

3572 Base = nullptr;

3573 break;

3577

3578 std::tie(Base, BaseOffset, Branch, EntrySize) =

3579 Asm->getCodeViewJumpTableInfo(JumpTableIndex, &BranchMI, Branch);

3580 break;

3581 }

3582

3583 const MachineJumpTableEntry &JTE = JTI.getJumpTables()[JumpTableIndex];

3584 JumpTableInfo CVJTI{EntrySize,

3586 BaseOffset,

3589 JTE.MBBs.size(),

3590 {}};

3591 for (const auto &MBB : JTE.MBBs)

3593 CurFn->JumpTables.push_back(std::move(CVJTI));

3594 });

3595}

3596

3597void CodeViewDebug::emitDebugInfoForJumpTables(const FunctionInfo &FI) {

3598

3599 for (const auto &JumpTable : FI.JumpTables) {

3600 for (const auto &CaseSym : JumpTable.Cases) {

3601 MCSymbol *LabelEnd = beginSymbolRecord(SymbolKind::S_LABEL32);

3602 OS.AddComment("Offset and segment");

3603 OS.emitCOFFSecRel32(CaseSym, 0);

3604 OS.AddComment("Flags");

3605 OS.emitInt8(0);

3607 endSymbolRecord(LabelEnd);

3608 }

3609 }

3610

3611 for (const auto &JumpTable : FI.JumpTables) {

3612 MCSymbol *JumpTableEnd = beginSymbolRecord(SymbolKind::S_ARMSWITCHTABLE);

3614 OS.AddComment("Base offset");

3616 OS.AddComment("Base section index");

3617 OS.emitCOFFSectionIndex(JumpTable.Base);

3618 } else {

3619 OS.AddComment("Base offset");

3620 OS.emitInt32(0);

3621 OS.AddComment("Base section index");

3622 OS.emitInt16(0);

3623 }

3624 OS.AddComment("Switch type");

3625 OS.emitInt16(static_cast<uint16_t>(JumpTable.EntrySize));

3626 OS.AddComment("Branch offset");

3627 OS.emitCOFFSecRel32(JumpTable.Branch, 0);

3628 OS.AddComment("Table offset");

3629 OS.emitCOFFSecRel32(JumpTable.Table, 0);

3630 OS.AddComment("Branch section index");

3631 OS.emitCOFFSectionIndex(JumpTable.Branch);

3632 OS.AddComment("Table section index");

3633 OS.emitCOFFSectionIndex(JumpTable.Table);

3634 OS.AddComment("Entries count");

3635 OS.emitInt32(JumpTable.TableSize);

3636 endSymbolRecord(JumpTableEnd);

3637 }

3638}

3639

3640void CodeViewDebug::emitInlinees(

3642

3643

3644 constexpr size_t ChunkSize =

3646 sizeof(uint32_t);

3647

3650

3651 size_t CurrentIndex = 0;

3652 while (CurrentIndex < SortedInlinees.size()) {

3653 auto Symbol = beginSymbolRecord(SymbolKind::S_INLINEES);

3654 auto CurrentChunkSize =

3655 std::min(ChunkSize, SortedInlinees.size() - CurrentIndex);

3656 OS.AddComment("Count");

3657 OS.emitInt32(CurrentChunkSize);

3658

3659 const size_t CurrentChunkEnd = CurrentIndex + CurrentChunkSize;

3660 for (; CurrentIndex < CurrentChunkEnd; ++CurrentIndex) {

3661 OS.AddComment("Inlinee");

3662 OS.emitInt32(SortedInlinees[CurrentIndex].getIndex());

3663 }

3664 endSymbolRecord(Symbol);

3665 }

3666}

assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")

This file implements the APSInt class, which is a simple class that represents an arbitrary sized int...

static bool isThumb(const MCSubtargetInfo &STI)

MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL

static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")

static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")

Analysis containing CSE Info

static bool canUseReferenceType(const DbgVariableLocation &Loc)

Definition CodeViewDebug.cpp:1354

static MethodKind translateMethodKindFlags(const DISubprogram *SP, bool Introduced)

Definition CodeViewDebug.cpp:2196

static bool isUsableDebugLoc(DebugLoc DL)

Definition CodeViewDebug.cpp:3140

static TypeIndex getStringIdTypeIdx(GlobalTypeTableBuilder &TypeTable, StringRef S)

Definition CodeViewDebug.cpp:937

static CPUType mapArchToCVCPUType(Triple::ArchType Type)

Definition CodeViewDebug.cpp:114

static void emitNullTerminatedSymbolName(MCStreamer &OS, StringRef S, unsigned MaxFixedRecordLength=0xF00)

Definition CodeViewDebug.cpp:736

static Version parseVersion(StringRef Name)

Definition CodeViewDebug.cpp:866

static MethodOptions translateMethodOptionFlags(const DISubprogram *SP)

Definition CodeViewDebug.cpp:2187

static bool isNonTrivial(const DICompositeType *DCTy)

Definition CodeViewDebug.cpp:421

static std::string formatNestedName(ArrayRef< StringRef > QualifiedNameComponents, StringRef TypeName)

Definition CodeViewDebug.cpp:301

static ClassOptions getCommonClassOptions(const DICompositeType *Ty)

Return ClassOptions that should be present on both the forward declaration and the defintion of a tag...

Definition CodeViewDebug.cpp:2229

static PointerToMemberRepresentation translatePtrToMemberRep(unsigned SizeInBytes, bool IsPMF, unsigned Flags)

Definition CodeViewDebug.cpp:1965

static FunctionOptions getFunctionOptions(const DISubroutineType *Ty, const DICompositeType *ClassTy=nullptr, StringRef SPName=StringRef(""))

Definition CodeViewDebug.cpp:426

static StringRef removeTemplateArgs(StringRef Name)

Definition CodeViewDebug.cpp:369

static TypeRecordKind getRecordKind(const DICompositeType *Ty)

Definition CodeViewDebug.cpp:2216

void forEachJumpTableBranch(const MachineFunction *MF, bool isThumb, const std::function< void(const MachineJumpTableInfo &, const MachineInstr &, int64_t)> &Callback)

Definition CodeViewDebug.cpp:3487

static CallingConvention dwarfCCToCodeView(unsigned DwarfCC)

Given a DWARF calling convention, get the CodeView equivalent.

Definition CodeViewDebug.cpp:2019

static SourceLanguage MapDWARFLanguageToCVLang(dwarf::SourceLanguageName DWLName)

Definition CodeViewDebug.cpp:573

static bool isFloatDIType(const DIType *Ty)

Definition CodeViewDebug.cpp:3413

static void addLocIfNotPresent(SmallVectorImpl< const DILocation * > &Locs, const DILocation *Loc)

Definition CodeViewDebug.cpp:504

static bool shouldEmitUdt(const DIType *T)

Definition CodeViewDebug.cpp:1622

static StringRef getPrettyScopeName(const DIScope *Scope)

Definition CodeViewDebug.cpp:262

static bool shouldAlwaysEmitCompleteClassType(const DICompositeType *Ty)

Definition CodeViewDebug.cpp:2444

static bool needsReferenceType(const DbgVariableLocation &Loc)

Definition CodeViewDebug.cpp:1358

static MemberAccess translateAccessFlags(unsigned RecordTag, unsigned Flags)

Definition CodeViewDebug.cpp:2174

This file contains the declarations for the subclasses of Constant, which represent the different fla...

This file contains constants used for implementing Dwarf debug support.

Module.h This file contains the declarations for the Module class.

Register const TargetRegisterInfo * TRI

Promote Memory to Register

ConstantRange Range(APInt(BitWidth, Low), APInt(BitWidth, High))

static StringRef getName(Value *V)

static cl::opt< RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode > Mode("regalloc-enable-advisor", cl::Hidden, cl::init(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Default), cl::desc("Enable regalloc advisor mode"), cl::values(clEnumValN(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Default, "default", "Default"), clEnumValN(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Release, "release", "precompiled"), clEnumValN(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Development, "development", "for training")))

This file implements the SmallBitVector class.

This file defines the SmallString class.

static SymbolRef::Type getType(const Symbol *Sym)

This file describes how to lower LLVM code to machine code.

static const uint32_t IV[8]

An arbitrary precision integer that knows its signedness.

ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...

size_t size() const

size - Get the array size.

This class is intended to be used as a driving class for all asm writers.

CodeViewDebug(AsmPrinter *AP)

Definition CodeViewDebug.cpp:135

void beginModule(Module *M) override

Definition CodeViewDebug.cpp:613

bool moduleIsInFortran()

Check if the current module is in Fortran.

void endFunctionImpl(const MachineFunction *) override

Gather post-function debug information.

Definition CodeViewDebug.cpp:3087

void endModule() override

Emit the COFF section that holds the line table information.

Definition CodeViewDebug.cpp:660

void beginInstruction(const MachineInstr *MI) override

Process beginning of an instruction.

Definition CodeViewDebug.cpp:3144

void beginFunctionImpl(const MachineFunction *MF) override

Gather pre-function debug information.

Definition CodeViewDebug.cpp:1496

This is the shared class of boolean and integer constants.

bool isZero() const

This is just a convenience method to make client code smaller for a common code.

Basic type, like 'int' or 'float'.

unsigned getEncoding() const

StringRef getIdentifier() const

DINodeArray getElements() const

DIType * getBaseType() const

LLVM_ABI DIType * getClassType() const

Get casted version of extra data.

LLVM_ABI Constant * getConstant() const

unsigned getNumElements() const

uint64_t getElement(unsigned I) const

LLVM_ABI std::optional< SignedOrUnsignedConstant > isConstant() const

Determine whether this represents a constant value, if so.

Metadata * getRawStaticDataMemberDeclaration() const

DILocalScope * getScope() const

Get the local scope for this variable.

Tagged DWARF-like metadata node.

LLVM_ABI dwarf::Tag getTag() const

Base class for scope-like contexts.

StringRef getFilename() const

LLVM_ABI StringRef getName() const

StringRef getDirectory() const

LLVM_ABI DIScope * getScope() const

Wrapper structure that holds a language name and its version.

bool hasVersionedName() const

uint16_t getName() const

Returns a versioned or unversioned language name.

String type, Fortran CHARACTER(n)

Subprogram description. Uses SubclassData1.

Type array for a subprogram.

DITypeRefArray getTypeArray() const

uint64_t getOffsetInBits() const

bool isObjectPointer() const

StringRef getName() const

bool isForwardDecl() const

uint64_t getSizeInBits() const

DIScope * getScope() const

DIScope * getScope() const

StringRef getName() const

SmallVector< Entry, 4 > Entries

static const EntryIndex NoEntry

Special value to indicate that an entry is valid until the end of the function.

static bool isUnsignedDIType(const DIType *Ty)

Return true if type encoding is unsigned.

AsmPrinter * Asm

Target of debug info emission.

MCSymbol * getLabelBeforeInsn(const MachineInstr *MI)

Return Label preceding the instruction.

MachineModuleInfo * MMI

Collected machine module information.

DebugLoc PrevInstLoc

Previous instruction's location information.

MCSymbol * getLabelAfterInsn(const MachineInstr *MI)

Return Label immediately following the instruction.

DebugHandlerBase(AsmPrinter *A)

void beginInstruction(const MachineInstr *MI) override

Process beginning of an instruction.

const MachineBasicBlock * PrevInstBB

void requestLabelAfterInsn(const MachineInstr *MI)

Ensure that a label will be emitted after MI.

DbgValueHistoryMap DbgValues

History of DBG_VALUE and clobber instructions for each user variable.

void requestLabelBeforeInsn(const MachineInstr *MI)

Ensure that a label will be emitted before MI.

const MachineInstr * PrologEndLoc

This location indicates end of function prologue and beginning of function body.

static uint64_t getBaseTypeSize(const DIType *Ty)

If this type is derived from a base type then return base type size.

ValueT lookup(const_arg_type_t< KeyT > Val) const

lookup - Return the entry for the specified key, or a default constructed value if no such entry exis...

size_type count(const_arg_type_t< KeyT > Val) const

Return 1 if the specified key is in the map, 0 otherwise.

Implements a dense probed hash-table based set.

bool hasOptSize() const

Optimize this function for size (-Os) or minimum size (-Oz).

bool hasStackProtectorFnAttr() const

Returns true if the function has ssp, sspstrong, or sspreq fn attrs.

DISubprogram * getSubprogram() const

Get the attached subprogram.

bool hasPersonalityFn() const

Check whether this function has a personality function.

Constant * getPersonalityFn() const

Get the personality function associated with this function.

bool hasProfileData(bool IncludeSynthetic=false) const

Return true if the function is annotated with profile data.

bool hasOptNone() const

Do not optimize this function (-O0).

Function::iterator insert(Function::iterator Position, BasicBlock *BB)

Insert BB in the basic block list at Position.

bool hasFnAttribute(Attribute::AttrKind Kind) const

Return true if the function has the attribute.

bool hasLocalLinkage() const

static StringRef dropLLVMManglingEscape(StringRef Name)

If the given string begins with the GlobalValue name mangling escape character '\1',...

bool isDeclarationForLinker() const

This class is used to track scope information.

LLVM_ABI MCSymbol * createTempSymbol()

Create a temporary symbol with a unique name.

MCSymbol * getCOMDATSymbol() const

Streaming machine code generation interface.

virtual void AddComment(const Twine &T, bool EOL=true)

Add a textual comment.

virtual void emitAbsoluteSymbolDiff(const MCSymbol *Hi, const MCSymbol *Lo, unsigned Size)

Emit the absolute difference between two symbols.

virtual void emitLabel(MCSymbol *Symbol, SMLoc Loc=SMLoc())

Emit a label for Symbol into the current section.

virtual void emitValueToAlignment(Align Alignment, int64_t Fill=0, uint8_t FillLen=1, unsigned MaxBytesToEmit=0)

Emit some number of copies of Value until the byte alignment ByteAlignment is reached.

void emitInt32(uint64_t Value)

virtual void emitBytes(StringRef Data)

Emit the bytes in Data into the output.

MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...

MCSection & getSection() const

Get the section associated with a defined, non-absolute symbol.

ArrayRef< MDOperand > operands() const

unsigned getNumOperands() const

Return number of MDNode operands.

LLVM_ABI MCSymbol * getSymbol() const

Return the MCSymbol for this basic block.

The MachineFrameInfo class represents an abstract stack frame until prolog/epilog code is inserted.

bool hasVarSizedObjects() const

This method may be called any time after instruction selection is complete to determine if the stack ...

uint64_t getStackSize() const

Return the number of bytes that must be allocated to hold all of the fixed size frame objects.

int64_t getOffsetAdjustment() const

Return the correction for frame offsets.

unsigned getCVBytesOfCalleeSavedRegisters() const

Returns how many bytes of callee-saved registers the target pushed in the prologue.

bool hasStackProtectorIndex() const

const TargetSubtargetInfo & getSubtarget() const

getSubtarget - Return the subtarget for which this machine code is being compiled.

bool hasInlineAsm() const

Returns true if the function contains any inline assembly.

bool exposesReturnsTwice() const

exposesReturnsTwice - Returns true if the function calls setjmp or any other similar functions with a...

MachineFrameInfo & getFrameInfo()

getFrameInfo - Return the frame info object for the current function.

MCSymbol * getJTISymbol(unsigned JTI, MCContext &Ctx, bool isLinkerPrivate=false) const

getJTISymbol - Return the MCSymbol for the specified non-empty jump table.

auto getInStackSlotVariableDbgInfo()

Returns the collection of variables for which we have debug info and that have been assigned a stack ...

Function & getFunction()

Return the LLVM function that this machine code represents.

const MachineJumpTableInfo * getJumpTableInfo() const

getJumpTableInfo - Return the jump table info object for the current function.

ArrayRef< std::pair< MCSymbol *, MDNode * > > getCodeViewAnnotations() const

Representation of each machine instruction.

bool isDebugValue() const

MachineOperand & getDebugOperand(unsigned Index)

@ EK_GPRel32BlockAddress

EK_GPRel32BlockAddress - Each entry is an address of block, encoded with a relocation as gp-relative,...

@ EK_Inline

EK_Inline - Jump table entries are emitted inline at their point of use.

@ EK_LabelDifference32

EK_LabelDifference32 - Each entry is the address of the block minus the address of the jump table.

@ EK_Custom32

EK_Custom32 - Each entry is a 32-bit value that is custom lowered by the TargetLowering::LowerCustomJ...

@ EK_LabelDifference64

EK_LabelDifference64 - Each entry is the address of the block minus the address of the jump table.

@ EK_BlockAddress

EK_BlockAddress - Each entry is a plain address of block, e.g.: .word LBB123.

@ EK_GPRel64BlockAddress

EK_GPRel64BlockAddress - Each entry is an address of block, encoded with a relocation as gp-relative,...

JTEntryKind getEntryKind() const

const std::vector< MachineJumpTableEntry > & getJumpTables() const

const MCContext & getContext() const

This class implements a map that also provides access to all stored values in a deterministic order.

A Module instance is used to store all the information related to an LLVM module.

iterator_range< op_iterator > operands()

This is a 'bitvector' (really, a variable-sized bit array), optimized for the case when the array is ...

SmallSet - This maintains a set of unique values, optimizing for the case when the set is small (less...

const_iterator begin() const

const_iterator end() const

SmallString - A SmallString is just a SmallVector with methods and accessors that make it work better...

This class consists of common code factored out of the SmallVector class to reduce code duplication b...

reference emplace_back(ArgTypes &&... Args)

void append(ItTy in_start, ItTy in_end)

Add the specified range to the end of the SmallVector.

void push_back(const T &Elt)

This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.

static StackOffset getScalable(int64_t Scalable)

static StackOffset getFixed(int64_t Fixed)

StringRef - Represent a constant reference to a string, i.e.

bool starts_with(StringRef Prefix) const

Check if this string starts with the given Prefix.

constexpr bool empty() const

empty - Check if the string is empty.

char back() const

back - Get the last character in the string.

StringRef take_front(size_t N=1) const

Return a StringRef equal to 'this' but with only the first N elements remaining.

bool hasFP(const MachineFunction &MF) const

hasFP - Return true if the specified function should have a dedicated frame pointer register.

virtual StackOffset getFrameIndexReference(const MachineFunction &MF, int FI, Register &FrameReg) const

getFrameIndexReference - This method should return the base register and offset used to reference a f...

TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...

TargetSubtargetInfo - Generic base class for all target subtargets.

virtual const TargetFrameLowering * getFrameLowering() const

virtual const TargetRegisterInfo * getRegisterInfo() const =0

Return the target's register information.

TinyPtrVector - This class is specialized for cases where there are normally 0 or 1 element in a vect...

The instances of the Type class are immutable: once they are created, they are never changed.

LLVM Value Representation.

LLVM_ABI StringRef getName() const

Return a constant reference to the value's name.

@ CurrentDirectory

Absolute CWD path.

@ SourceFile

Path to main source file, relative or absolute.

@ BuildTool

Absolute compiler path.

@ CommandLine

Full canonical command line (maybe -cc1)

@ TypeServerPDB

Absolute path of type server PDB (/Fd)

LLVM_ABI void begin(ContinuationRecordKind RecordKind)

void writeMemberType(RecordType &Record)

TypeIndex writeLeafType(T &Record)

SimpleTypeKind getSimpleKind() const

SimpleTypeMode getSimpleMode() const

static const uint32_t FirstNonSimpleIndex

static LLVM_ABI StringRef simpleTypeName(TypeIndex TI)

uint32_t getIndex() const

static TypeIndex NullptrT()

void addCallbackToPipeline(TypeVisitorCallbacks &Callbacks)

std::pair< iterator, bool > insert(const ValueT &V)

size_type count(const_arg_type_t< ValueT > V) const

Return 1 if the specified key is in the set, 0 otherwise.

#define llvm_unreachable(msg)

Marks that the current location is not supposed to be reachable.

constexpr char Align[]

Key for Kernel::Arg::Metadata::mAlign.

constexpr char TypeName[]

Key for Kernel::Arg::Metadata::mTypeName.

@ DEBUG_HASHES_SECTION_MAGIC

@ C

The default llvm calling convention, compatible with C.

PointerMode

Equivalent to CV_ptrmode_e.

ProcSymFlags

Corresponds to the CV_PROCFLAGS bitfield.

PointerOptions

Equivalent to misc lfPointerAttr bitfields.

LocalSymFlags

Corresponds to CV_LVARFLAGS bitfield.

MethodKind

Part of member attribute flags. (CV_methodprop_e)

CVRecord< TypeLeafKind > CVType

PointerKind

Equivalent to CV_ptrtype_e.

CPUType

These values correspond to the CV_CPU_TYPE_e enumeration, and are documented here: https://msdn....

PointerToMemberRepresentation

Equivalent to CV_pmtype_e.

@ MultipleInheritanceData

@ SingleInheritanceFunction

@ VirtualInheritanceFunction

@ MultipleInheritanceFunction

CallingConvention

These values correspond to the CV_call_e enumeration, and are documented at the following locations: ...

MethodOptions

Equivalent to CV_fldattr_t bitfield.

LLVM_ABI ArrayRef< EnumEntry< SymbolKind > > getSymbolTypeNames()

MemberAccess

Source-level access specifier. (CV_access_e)

ThunkOrdinal

These values correspond to the THUNK_ORDINAL enumeration.

TypeRecordKind

Distinguishes individual records in .debug$T or .debug$P section or PDB type stream.

SymbolKind

Duplicate copy of the above enum, but using the official CV names.

ModifierOptions

Equivalent to CV_modifier_t.

@ ProfileGuidedOptimization

@ HasStructuredExceptionHandling

LLVM_ABI StringRef getSymbolName(CVSymbol Sym)

LLVM_ABI Error visitTypeRecord(CVType &Record, TypeIndex Index, TypeVisitorCallbacks &Callbacks, VisitorDataSource Source=VDS_BytesPresent)

SourceLanguage

These values correspond to the CV_CFL_LANG enumeration in the Microsoft Debug Interface Access SDK,...

std::optional< std::pair< SourceLanguageName, uint32_t > > toDW_LNAME(SourceLanguage language)

Convert a DWARF 5 DW_LANG to a DWARF 6 pair of language name and version.

ElementType

The element type of an SRV or UAV resource.

Scope

Defines the scope in which this symbol should be visible: Default – Visible in the public interface o...

std::enable_if_t< detail::IsValidPointer< X, Y >::value, X * > extract_or_null(Y &&MD)

Extract a Value from Metadata, allowing null.

NodeAddr< NodeBase * > Node

LLVM_ABI bool is_absolute(const Twine &path, Style style=Style::native)

Is path absolute?

This is an optimization pass for GlobalISel generic memory operations.

LLVM_ABI void logAllUnhandledErrors(Error E, raw_ostream &OS, Twine ErrorBanner={})

Log all errors (if any) in E to OS.

FunctionAddr VTableAddr Value

std::string fromHex(StringRef Input)

Convert hexadecimal string Input to its binary representation. The return string is half the size of ...

decltype(auto) dyn_cast(const From &Val)

dyn_cast - Return the argument parameter cast to the specified type.

auto dyn_cast_if_present(const Y &Val)

dyn_cast_if_present - Functionally identical to dyn_cast, except that a null (or none in the case ...

std::tuple< uint64_t, uint32_t > InlineSite

LLVM_GET_TYPE_NAME_CONSTEXPR StringRef getTypeName()

We provide a function which tries to compute the (demangled) name of a type statically.

std::pair< const MachineInstr *, const MachineInstr * > InsnRange

This is used to track range of instructions with identical lexical scope.

auto dyn_cast_or_null(const Y &Val)

auto formatv(bool Validate, const char *Fmt, Ts &&...Vals)

FunctionAddr VTableAddr uintptr_t uintptr_t Version

auto reverse(ContainerTy &&C)

decltype(auto) get(const PointerIntPair< PointerTy, IntBits, IntType, PtrTraits, Info > &Pair)

void sort(IteratorTy Start, IteratorTy End)

LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)

FunctionAddr VTableAddr Count

LLVM_ABI EHPersonality classifyEHPersonality(const Value *Pers)

See if the given exception handling personality function is one that we understand.

class LLVM_GSL_OWNER SmallVector

Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...

bool isa(const From &Val)

isa - Return true if the parameter to the template is an instance of one of the template type argu...

@ Success

The lock was released successfully.

LLVM_ABI raw_fd_ostream & errs()

This returns a reference to a raw_ostream for standard error.

void cantFail(Error Err, const char *Msg=nullptr)

Report a fatal error if Err is a failure value.

FunctionAddr VTableAddr uintptr_t uintptr_t Data

void replace(R &&Range, const T &OldValue, const T &NewValue)

Provide wrappers to std::replace which take ranges instead of having to pass begin/end explicitly.

DWARFExpression::Operation Op

ArrayRef(const T &OneElt) -> ArrayRef< T >

bool isAsynchronousEHPersonality(EHPersonality Pers)

Returns true if this personality function catches asynchronous exceptions.

decltype(auto) cast(const From &Val)

cast - Return the argument parameter cast to the specified type.

bool is_contained(R &&Range, const E &Element)

Returns true if Element is found in Range.

void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)

Implement std::swap in terms of BitVector swap.

Definition CodeViewDebug.cpp:313

CodeViewDebug & CVD

Definition CodeViewDebug.cpp:322

~TypeLoweringScope()

Definition CodeViewDebug.cpp:315

TypeLoweringScope(CodeViewDebug &CVD)

Definition CodeViewDebug.cpp:314

This struct is a compact representation of a valid (non-zero power of two) alignment.

Definition CodeViewDebug.cpp:2326

uint64_t BaseOffset

Definition CodeViewDebug.cpp:2328

const DIDerivedType * MemberTypeNode

Definition CodeViewDebug.cpp:2327

Definition CodeViewDebug.cpp:2325

std::vector< MemberInfo > MemberList

Definition CodeViewDebug.cpp:2331

MemberList Members

Direct members.

Definition CodeViewDebug.cpp:2341

std::vector< const DIType * > NestedTypes

Definition CodeViewDebug.cpp:2347

MapVector< MDString *, MethodsList > MethodsMap

Definition CodeViewDebug.cpp:2335

std::vector< const DIDerivedType * > Inheritance

Base classes.

Definition CodeViewDebug.cpp:2338

TypeIndex VShapeTI

Definition CodeViewDebug.cpp:2345

MethodsMap Methods

Definition CodeViewDebug.cpp:2343

TinyPtrVector< const DISubprogram * > MethodsList

Definition CodeViewDebug.cpp:2333

int InMemory

Indicates that variable data is stored in memory relative to the specified register.

uint32_t CVRegister

Register containing the data or the register base of the memory location containing the data.

Represents the location at which a variable is stored.

static std::optional< DbgVariableLocation > extractFromMachineInstruction(const MachineInstr &Instruction)

Extract a VariableLocation from a MachineInstr.

std::vector< MachineBasicBlock * > MBBs

MBBs - The vector of basic blocks from which to create the jump table.