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:

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

82

84

87 }

88

90

92

94

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

96

102 else

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

104 }

106 }

107

108private:

111};

112}

113

115 switch (Type) {

116 case Triple::ArchType::x86:

117 return CPUType::Pentium3;

118 case Triple::ArchType::x86_64:

119 return CPUType::X64;

120 case Triple::ArchType::thumb:

121

122

123 return CPUType::ARMNT;

124 case Triple::ArchType::aarch64:

125 return CPUType::ARM64;

126 case Triple::ArchType::mipsel:

127 return CPUType::MIPS;

128 default:

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

130 }

131}

132

135

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

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

138 if (!Filepath.empty())

139 return Filepath;

140

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

142

143

144

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

147 return Filename;

148 Filepath = std::string(Dir);

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

150 Filepath += '/';

151 Filepath += Filename;

152 return Filepath;

153 }

154

155

156

157

158

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

160 Filepath = std::string(Filename);

161 else

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

163

164

165

166

167 std::replace(Filepath.begin(), Filepath.end(), '/', '\\');

168

169

170 size_t Cursor = 0;

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

172 Filepath.erase(Cursor, 2);

173

174

175

176 Cursor = 0;

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

178

179 if (Cursor == 0)

180 break;

181

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

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

184

185 break;

186

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

188

189 Cursor = PrevSlash;

190 }

191

192

193 Cursor = 0;

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

195 Filepath.erase(Cursor, 1);

196

197 return Filepath;

198}

199

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

201 StringRef FullPath = getFullFilepath(F);

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

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

204 if (Insertion.second) {

205

208 if (F->getChecksum()) {

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

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

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

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

216 CSKind = FileChecksumKind::MD5;

217 break;

219 CSKind = FileChecksumKind::SHA1;

220 break;

222 CSKind = FileChecksumKind::SHA256;

223 break;

224 }

225 }

227 static_cast<unsigned>(CSKind));

230 }

231 return Insertion.first->second;

232}

233

234CodeViewDebug::InlineSite &

235CodeViewDebug::getInlineSite(const DILocation *InlinedAt,

237 auto SiteInsertion = CurFn->InlineSites.insert({InlinedAt, InlineSite()});

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

239 if (SiteInsertion.second) {

240 unsigned ParentFuncId = CurFn->FuncId;

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

242 ParentFuncId =

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

244 .SiteFuncId;

245

246 Site->SiteFuncId = NextFuncId++;

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

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

251 InlinedSubprograms.insert(Inlinee);

252 auto InlineeIdx = getFuncIdForSubprogram(Inlinee);

253

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

255 CurFn->Inlinees.insert(InlineeIdx);

256 }

257 return *Site;

258}

259

261 StringRef ScopeName = Scope->getName();

262 if (!ScopeName.empty())

263 return ScopeName;

264

265 switch (Scope->getTag()) {

266 case dwarf::DW_TAG_enumeration_type:

267 case dwarf::DW_TAG_class_type:

268 case dwarf::DW_TAG_structure_type:

269 case dwarf::DW_TAG_union_type:

270 return "";

271 case dwarf::DW_TAG_namespace:

272 return "`anonymous namespace'";

273 default:

275 }

276}

277

278const DISubprogram *CodeViewDebug::collectParentScopeNames(

280 const DISubprogram *ClosestSubprogram = nullptr;

281 while (Scope != nullptr) {

282 if (ClosestSubprogram == nullptr)

283 ClosestSubprogram = dyn_cast(Scope);

284

285

286

287

288 if (const auto *Ty = dyn_cast(Scope))

289 DeferredCompleteTypes.push_back(Ty);

290

292 if (!ScopeName.empty())

293 QualifiedNameComponents.push_back(ScopeName);

295 }

296 return ClosestSubprogram;

297}

298

301 std::string FullyQualifiedName;

302 for (StringRef QualifiedNameComponent :

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

305 FullyQualifiedName.append("::");

306 }

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

308 return FullyQualifiedName;

309}

310

314

315

316 if (CVD.TypeEmissionLevel == 1)

317 CVD.emitDeferredCompleteTypes();

318 --CVD.TypeEmissionLevel;

319 }

321};

322

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

325

326

327

330 collectParentScopeNames(Scope, QualifiedNameComponents);

332}

333

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

337}

338

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

340

341

342

343

344

345

346

347

348

349

350 if (!Scope || isa(Scope) || isa(Scope))

352

353 assert(!isa(Scope) && "shouldn't make a namespace scope for a type");

354

355

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

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

358 return I->second;

359

360

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

364 return recordTypeIndexForDINode(Scope, TI);

365}

366

368

369

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

372

373 int OpenBrackets = 0;

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

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

376 ++OpenBrackets;

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

378 --OpenBrackets;

379 if (OpenBrackets == 0)

380 return Name.substr(0, i);

381 }

382 }

384}

385

388

389

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

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

392 return I->second;

393

394

395

396

398

401 if (const auto *Class = dyn_cast_or_null(Scope)) {

402

403

404

405 TypeIndex ClassType = getTypeIndex(Class);

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

407 DisplayName);

409 } else {

410

411 TypeIndex ParentScope = getScopeIndex(Scope);

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

414 }

415

416 return recordTypeIndexForDINode(SP, TI);

417}

418

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

421}

422

428 const DIType *ReturnTy = nullptr;

430 if (TypeArray.size())

431 ReturnTy = TypeArray[0];

432 }

433

434

435

436 if (auto *ReturnDCTy = dyn_cast_or_null(ReturnTy))

438 FO |= FunctionOptions::CxxReturnUdt;

439

440

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

442 FO |= FunctionOptions::Constructor;

443

444

445

446 }

447 return FO;

448}

449

452

453

454 if (SP->getDeclaration())

455 SP = SP->getDeclaration();

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

457

458

459

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

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

462 return I->second;

463

464

465

466

467 TypeLoweringScope S(*this);

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

469

471 TypeIndex TI = lowerTypeMemberFunction(

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

473 return recordTypeIndexForDINode(SP, TI, Class);

474}

475

478 const DIType *ClassTy) {

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

480 (void)InsertResult;

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

482 return TI;

483}

484

485unsigned CodeViewDebug::getPointerSizeInBytes() {

487}

488

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

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

492

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

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

496 } else {

497

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

499 }

500}

501

506}

507

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

510

512 return;

513

515 if (!Scope)

516 return;

517

518

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

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

521 LI.isNeverStepInto())

522 return;

523

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

526 return;

527

528 if (!CurFn->HaveLineInfo)

529 CurFn->HaveLineInfo = true;

530 unsigned FileId = 0;

532 FileId = CurFn->LastFileId;

533 else

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

536

537 unsigned FuncId = CurFn->FuncId;

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

540

541

542

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

545

546

547 bool FirstLoc = true;

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

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

551 if (!FirstLoc)

553 FirstLoc = false;

554 Loc = SiteLoc;

555 }

557 }

558

560 false, false,

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

562}

563

564void CodeViewDebug::emitCodeViewMagicVersion() {

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

568}

569

571 switch (DWLang) {

572 case dwarf::DW_LANG_C:

573 case dwarf::DW_LANG_C89:

574 case dwarf::DW_LANG_C99:

575 case dwarf::DW_LANG_C11:

576 return SourceLanguage::C;

577 case dwarf::DW_LANG_C_plus_plus:

578 case dwarf::DW_LANG_C_plus_plus_03:

579 case dwarf::DW_LANG_C_plus_plus_11:

580 case dwarf::DW_LANG_C_plus_plus_14:

581 return SourceLanguage::Cpp;

582 case dwarf::DW_LANG_Fortran77:

583 case dwarf::DW_LANG_Fortran90:

584 case dwarf::DW_LANG_Fortran95:

585 case dwarf::DW_LANG_Fortran03:

586 case dwarf::DW_LANG_Fortran08:

587 return SourceLanguage::Fortran;

588 case dwarf::DW_LANG_Pascal83:

589 return SourceLanguage::Pascal;

590 case dwarf::DW_LANG_Cobol74:

591 case dwarf::DW_LANG_Cobol85:

592 return SourceLanguage::Cobol;

593 case dwarf::DW_LANG_Java:

594 return SourceLanguage::Java;

595 case dwarf::DW_LANG_D:

596 return SourceLanguage::D;

597 case dwarf::DW_LANG_Swift:

598 return SourceLanguage::Swift;

599 case dwarf::DW_LANG_Rust:

600 return SourceLanguage::Rust;

601 case dwarf::DW_LANG_ObjC:

602 return SourceLanguage::ObjC;

603 case dwarf::DW_LANG_ObjC_plus_plus:

604 return SourceLanguage::ObjCpp;

605 default:

606

607

608

609 return SourceLanguage::Masm;

610 }

611}

612

614

615

618 Asm = nullptr;

619 return;

620 }

621

623

624

625 const MDNode *Node = *M->debug_compile_units_begin();

626 const auto *CU = cast(Node);

627

629

630 collectGlobalVariableInfo();

631

632

634 mdconst::extract_or_null(M->getModuleFlag("CodeViewGHash"));

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

636}

637

640 return;

641

642

643

644

645

646

647

648

649 switchToDebugSectionForSymbol(nullptr);

650

651 MCSymbol *CompilerInfo = beginCVSubsection(DebugSubsectionKind::Symbols);

652 emitObjName();

653 emitCompilerInformation();

654 endCVSubsection(CompilerInfo);

655

656 emitInlineeLinesSubsection();

657

658

659 for (auto &P : FnDebugInfo)

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

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

662

663

664

665

666 collectDebugInfoForGlobals();

667

668

669 emitDebugInfoForRetainedTypes();

670

671

672 setCurrentSubprogram(nullptr);

673 emitDebugInfoForGlobals();

674

675

676

677 switchToDebugSectionForSymbol(nullptr);

678

679

680 if (!GlobalUDTs.empty()) {

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

682 emitDebugInfoForUDTs(GlobalUDTs);

683 endCVSubsection(SymbolsEnd);

684 }

685

686

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

689

690

693

694

695

696

697 emitBuildInfo();

698

699

700

701 emitTypeInformation();

702

703 if (EmitDebugGlobalHashes)

704 emitTypeGlobalHashes();

705

706 clear();

707}

708

709static void

711 unsigned MaxFixedRecordLength = 0xF00) {

712

713

714

715

718 NullTerminatedString.push_back('\0');

719 OS.emitBytes(NullTerminatedString);

720}

721

722void CodeViewDebug::emitTypeInformation() {

723 if (TypeTable.empty())

724 return;

725

726

728 emitCodeViewMagicVersion();

729

732

733

734 CVMCAdapter CVMCOS(OS, Table);

737

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

739 while (B) {

740

742

744

745 if (E) {

748 }

749

750 B = Table.getNext(*B);

751 }

752}

753

754void CodeViewDebug::emitTypeGlobalHashes() {

755 if (TypeTable.empty())

756 return;

757

758

759

761

769

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

773

774

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

779 ++TI;

780 }

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

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

783 GHR.Hash.size());

785 }

786}

787

788void CodeViewDebug::emitObjName() {

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

790

793

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

795

796 PathRef = {};

797 } else {

798 PathRef = PathStore;

799 }

800

803

806

807 endSymbolRecord(CompilerEnd);

808}

809

810namespace {

812 int Part[4];

813};

814}

815

816

817

820 int N = 0;

821 for (const char C : Name) {

822 if (isdigit(C)) {

823 V.Part[N] *= 10;

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

825 V.Part[N] =

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

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

828 ++N;

829 if (N >= 4)

830 return V;

831 } else if (N > 0)

832 return V;

833 }

834 return V;

835}

836

837void CodeViewDebug::emitCompilerInformation() {

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

840

841

842 Flags = CurrentSourceLanguage;

843

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

846 }

850 Arch == ArchType::aarch64) {

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

852 }

853

856

859

862 const auto *CU = cast(Node);

863

864 StringRef CompilerVersion = CU->getProducer();

867 for (int N : FrontVer.Part) {

869 }

870

871

872

873

874 int Major = 1000 * LLVM_VERSION_MAJOR +

875 10 * LLVM_VERSION_MINOR +

876 LLVM_VERSION_PATCH;

877

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

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

881 for (int N : BackVer.Part)

883

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

886

887 endSymbolRecord(CompilerEnd);

888}

889

894}

895

896void CodeViewDebug::emitBuildInfo() {

897

898

899

900

901

902

903

904

905

906

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

910 const auto *CU = cast(Node);

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

916

923

926

927

928

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

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

933 endSymbolRecord(BIEnd);

934 endCVSubsection(BISubsecEnd);

935}

936

937void CodeViewDebug::emitInlineeLinesSubsection() {

938 if (InlinedSubprograms.empty())

939 return;

940

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

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

943

944

945

946

947

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

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

950

951 for (const DISubprogram *SP : InlinedSubprograms) {

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

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

954

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

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

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

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

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

966 }

967

968 endCVSubsection(InlineEnd);

969}

970

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

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

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

976

977

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

979

986

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

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

989

991 FI.Begin, FI.End);

992

993 endSymbolRecord(InlineEnd);

994

995 emitLocalVariableList(FI, Site.InlinedLocals);

996

997

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

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

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

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

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

1003 }

1004

1005

1006 emitEndSymbolRecord(SymbolKind::S_INLINESITE_END);

1007}

1008

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

1010

1011

1012

1014 GVSym ? dyn_cast(&GVSym->getSection()) : nullptr;

1016

1020

1022

1023

1024

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

1026 emitCodeViewMagicVersion();

1027}

1028

1029

1030

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

1032 FunctionInfo &FI,

1034 std::string FuncName =

1036 const ThunkOrdinal ordinal = ThunkOrdinal::Standard;

1037

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

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

1040

1041

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

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

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

1056 OS.emitInt8(unsigned(ordinal));

1059

1060 endSymbolRecord(ThunkRecordEnd);

1061

1062

1063

1064

1065

1066 emitEndSymbolRecord(SymbolKind::S_PROC_ID_END);

1067

1068 endCVSubsection(SymbolsEnd);

1069}

1070

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

1072 FunctionInfo &FI) {

1073

1074

1077

1078

1079 switchToDebugSectionForSymbol(Fn);

1080

1081 std::string FuncName;

1084 setCurrentSubprogram(SP);

1085

1086 if (SP->isThunk()) {

1087 emitDebugInfoForThunk(GV, FI, Fn);

1088 return;

1089 }

1090

1091

1092

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

1095

1096

1097 if (FuncName.empty())

1099

1100

1103

1104

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

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

1107 {

1109 : SymbolKind::S_GPROC32_ID;

1110 MCSymbol *ProcRecordEnd = beginSymbolRecord(ProcKind);

1111

1112

1119

1120

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

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

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

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

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

1134 ProcSymFlags ProcFlags = ProcSymFlags::HasOptimizedDebugInfo;

1135 if (FI.HasFramePointer)

1136 ProcFlags |= ProcSymFlags::HasFP;

1138 ProcFlags |= ProcSymFlags::IsNoReturn;

1140 ProcFlags |= ProcSymFlags::IsNoInline;

1142

1144

1146 endSymbolRecord(ProcRecordEnd);

1147

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

1149

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

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

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

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

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

1164 endSymbolRecord(FrameProcEnd);

1165

1166 emitInlinees(FI.Inlinees);

1167 emitLocalVariableList(FI, FI.Locals);

1168 emitGlobalVariableList(FI.Globals);

1169 emitLexicalBlockList(FI.ChildBlocks, FI);

1170

1171

1172

1173

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

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

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

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

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

1179 }

1180

1181 for (auto Annot : FI.Annotations) {

1183 MDTuple *Strs = cast(Annot.second);

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

1186

1190

1191

1192 StringRef Str = cast(MD)->getString();

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

1195 }

1196 endSymbolRecord(AnnotEnd);

1197 }

1198

1199 for (auto HeapAllocSite : FI.HeapAllocSites) {

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

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

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

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

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

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

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

1212 endSymbolRecord(HeapAllocEnd);

1213 }

1214

1215 if (SP != nullptr)

1216 emitDebugInfoForUDTs(LocalUDTs);

1217

1218 emitDebugInfoForJumpTables(FI);

1219

1220

1221 emitEndSymbolRecord(SymbolKind::S_PROC_ID_END);

1222 }

1223 endCVSubsection(SymbolsEnd);

1224

1225

1227}

1228

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

1231 LocalVarDef DR;

1233 DR.DataOffset = Offset;

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

1235 DR.IsSubfield = 0;

1236 DR.StructOffset = 0;

1237 DR.CVRegister = CVRegister;

1238 return DR;

1239}

1240

1241void CodeViewDebug::collectVariableInfoFromMFTable(

1247

1250 if (VI.Var)

1251 continue;

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

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

1254

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

1257

1258

1259 if (!Scope)

1260 continue;

1261

1262

1263

1264 int64_t ExprOffset = 0;

1265 bool Deref = false;

1266 if (VI.Expr) {

1267

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

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

1270 Deref = true;

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

1272 continue;

1273 }

1274

1275

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

1280

1282 "Frame offsets with a scalable component are not supported");

1283

1284

1285 LocalVarDef DefRange =

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

1287

1288 LocalVariable Var;

1289 Var.DIVar = VI.Var;

1290

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

1296 }

1297

1298 if (Deref)

1299 Var.UseReferenceType = true;

1300

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

1302 }

1303}

1304

1307}

1308

1311}

1312

1313void CodeViewDebug::calculateRanges(

1316

1317

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

1319 const auto &Entry = *I;

1320 if (Entry.isDbgValue())

1321 continue;

1324

1325

1326 std::optional Location =

1328 if (!Location)

1329 {

1330

1331

1332

1333

1334

1336 if (Op.isImm())

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

1338 continue;

1339 }

1340

1341

1342

1343

1344

1345

1346

1347

1348 if (Var.UseReferenceType) {

1349

1351 Location->LoadChain.pop_back();

1352 else

1353 continue;

1355

1356

1357 Var.UseReferenceType = true;

1358 Var.DefRanges.clear();

1359 calculateRanges(Var, Entries);

1360 return;

1361 }

1362

1363

1364 if (Location->Register == 0 || Location->LoadChain.size() > 1)

1365 continue;

1366

1367

1368

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

1371 continue;

1372

1373 LocalVarDef DR;

1374 DR.CVRegister = TRI->getCodeViewRegNum(Location->Register);

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

1376 DR.DataOffset =

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

1378 if (Location->FragmentInfo) {

1379 DR.IsSubfield = true;

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

1381 } else {

1382 DR.IsSubfield = false;

1383 DR.StructOffset = 0;

1384 }

1385

1386

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

1391 End = EndingEntry.isDbgValue()

1394 } else

1396

1397

1398

1400 Var.DefRanges[DR];

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

1402 R.back().second = End;

1403 else

1404 R.emplace_back(Begin, End);

1405

1406

1407 }

1408}

1409

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

1412

1413 collectVariableInfoFromMFTable(Processed);

1414

1416 InlinedEntity IV = I.first;

1417 if (Processed.count(IV))

1418 continue;

1421

1422

1423 const auto &Entries = I.second;

1424

1426 if (InlinedAt)

1428 else

1430

1431 if (!Scope)

1432 continue;

1433

1434 LocalVariable Var;

1435 Var.DIVar = DIVar;

1436

1437 calculateRanges(Var, Entries);

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

1439 }

1440}

1441

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

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

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

1450 CurFn->FuncId = NextFuncId++;

1452

1453

1454

1455

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

1460

1461

1462

1463 CurFn->EncodedParamFramePtrReg = EncodedFramePtrReg::None;

1464 CurFn->EncodedLocalFramePtrReg = EncodedFramePtrReg::None;

1465 if (CurFn->FrameSize > 0) {

1467 CurFn->EncodedLocalFramePtrReg = EncodedFramePtrReg::StackPtr;

1468 CurFn->EncodedParamFramePtrReg = EncodedFramePtrReg::StackPtr;

1469 } else {

1470 CurFn->HasFramePointer = true;

1471

1472 CurFn->EncodedParamFramePtrReg = EncodedFramePtrReg::FramePtr;

1473 if (CurFn->HasStackRealignment) {

1474

1475 CurFn->EncodedLocalFramePtrReg = EncodedFramePtrReg::StackPtr;

1476 } else {

1477

1478

1479 CurFn->EncodedLocalFramePtrReg = EncodedFramePtrReg::FramePtr;

1480 }

1481 }

1482 }

1483

1484

1487 FPO |= FrameProcedureOptions::HasAlloca;

1489 FPO |= FrameProcedureOptions::HasSetJmp;

1490

1492 FPO |= FrameProcedureOptions::HasInlineAssembly;

1496 FPO |= FrameProcedureOptions::HasStructuredExceptionHandling;

1497 else

1498 FPO |= FrameProcedureOptions::HasExceptionHandling;

1499 }

1501 FPO |= FrameProcedureOptions::MarkedInline;

1503 FPO |= FrameProcedureOptions::Naked;

1505 FPO |= FrameProcedureOptions::SecurityChecks;

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

1508 FPO |= FrameProcedureOptions::StrictSecurityChecks;

1509 }

1511

1512 FPO |= FrameProcedureOptions::SafeBuffers;

1513 }

1518 FPO |= FrameProcedureOptions::OptimizedForSpeed;

1520 FPO |= FrameProcedureOptions::ValidProfileCounts;

1521 FPO |= FrameProcedureOptions::ProfileGuidedOptimization;

1522 }

1523

1524 CurFn->FrameProcOpts = FPO;

1525

1527

1528

1529

1530

1531

1533 bool EmptyPrologue = true;

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

1535 for (const auto &MI : MBB) {

1537 MI.getDebugLoc()) {

1539 break;

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

1541 EmptyPrologue = false;

1542 }

1543 }

1544 }

1545

1546

1549 maybeRecordLocation(FnStartDL, MF);

1550 }

1551

1552

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

1554 for (const auto &MI : MBB) {

1555 if (MI.getHeapAllocMarker()) {

1558 }

1559 }

1560 }

1561

1562

1565 discoverJumpTableBranches(MF, isThumb);

1566}

1567

1569 if (T)

1570 return false;

1571

1572

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

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

1575 switch (Scope->getTag()) {

1576 case dwarf::DW_TAG_structure_type:

1577 case dwarf::DW_TAG_class_type:

1578 case dwarf::DW_TAG_union_type:

1579 return false;

1580 default:

1581

1582 ;

1583 }

1584 }

1585 }

1586

1587 while (true) {

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

1589 return false;

1590

1591 const DIDerivedType *DT = dyn_cast(T);

1592 if (!DT)

1593 return true;

1594 T = DT->getBaseType();

1595 }

1596 return true;

1597}

1598

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

1600

1602 return;

1604 return;

1605

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

1609

1610 std::string FullyQualifiedName =

1612

1613 if (ClosestSubprogram == nullptr) {

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

1615 } else if (ClosestSubprogram == CurrentSubprogram) {

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

1617 }

1618

1619

1620

1621

1622

1623

1624

1625}

1626

1628

1629 switch (Ty->getTag()) {

1630 case dwarf::DW_TAG_array_type:

1631 return lowerTypeArray(cast(Ty));

1632 case dwarf::DW_TAG_typedef:

1633 return lowerTypeAlias(cast(Ty));

1634 case dwarf::DW_TAG_base_type:

1635 return lowerTypeBasic(cast(Ty));

1636 case dwarf::DW_TAG_pointer_type:

1637 if (cast(Ty)->getName() == "__vtbl_ptr_type")

1638 return lowerTypeVFTableShape(cast(Ty));

1639 [[fallthrough]];

1640 case dwarf::DW_TAG_reference_type:

1641 case dwarf::DW_TAG_rvalue_reference_type:

1642 return lowerTypePointer(cast(Ty));

1643 case dwarf::DW_TAG_ptr_to_member_type:

1644 return lowerTypeMemberPointer(cast(Ty));

1645 case dwarf::DW_TAG_restrict_type:

1646 case dwarf::DW_TAG_const_type:

1647 case dwarf::DW_TAG_volatile_type:

1648

1649 return lowerTypeModifier(cast(Ty));

1650 case dwarf::DW_TAG_subroutine_type:

1651 if (ClassTy) {

1652

1653

1654 return lowerTypeMemberFunction(cast(Ty), ClassTy,

1655 0,

1656 false);

1657 }

1658 return lowerTypeFunction(cast(Ty));

1659 case dwarf::DW_TAG_enumeration_type:

1660 return lowerTypeEnum(cast(Ty));

1661 case dwarf::DW_TAG_class_type:

1662 case dwarf::DW_TAG_structure_type:

1663 return lowerTypeClass(cast(Ty));

1664 case dwarf::DW_TAG_union_type:

1665 return lowerTypeUnion(cast(Ty));

1666 case dwarf::DW_TAG_string_type:

1667 return lowerTypeString(cast(Ty));

1668 case dwarf::DW_TAG_unspecified_type:

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

1672 default:

1673

1675 }

1676}

1677

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

1681

1682 addToUDTs(Ty);

1683

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

1685 TypeName == "HRESULT")

1686 return TypeIndex(SimpleTypeKind::HResult);

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

1688 TypeName == "wchar_t")

1689 return TypeIndex(SimpleTypeKind::WideCharacter);

1690

1691 return UnderlyingTypeIndex;

1692}

1693

1696 TypeIndex ElementTypeIndex = getTypeIndex(ElementType);

1697

1698 TypeIndex IndexType = getPointerSizeInBytes() == 8

1699 ? TypeIndex(SimpleTypeKind::UInt64Quad)

1701

1703

1704

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

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

1709

1711 int64_t Count = -1;

1712

1713

1714

1715

1716

1717 if (auto *CI = dyn_cast_if_present<ConstantInt *>(Subrange->getCount()))

1718 Count = CI->getSExtValue();

1719 else if (auto *UI = dyn_cast_if_present<ConstantInt *>(

1720 Subrange->getUpperBound())) {

1721

1723 auto *LI = dyn_cast_if_present<ConstantInt *>(Subrange->getLowerBound());

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

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

1726 }

1727

1728

1729

1730

1731

1732 if (Count == -1)

1733 Count = 0;

1734

1735

1736 ElementSize *= Count;

1737

1738

1739

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

1742

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

1746 }

1747

1748 return ElementTypeIndex;

1749}

1750

1751

1752

1753

1754

1755

1760

1761 TypeIndex IndexType = getPointerSizeInBytes() == 8

1762 ? TypeIndex(SimpleTypeKind::UInt64Quad)

1764

1765

1767

1769}

1770

1775

1778

1780 switch (Kind) {

1781 case dwarf::DW_ATE_address:

1782

1783 break;

1784 case dwarf::DW_ATE_boolean:

1785 switch (ByteSize) {

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

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

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

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

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

1791 }

1792 break;

1793 case dwarf::DW_ATE_complex_float:

1794

1795

1796 switch (ByteSize) {

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

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

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

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

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

1802 }

1803 break;

1804 case dwarf::DW_ATE_float:

1805 switch (ByteSize) {

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

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

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

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

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

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

1812 }

1813 break;

1814 case dwarf::DW_ATE_signed:

1815 switch (ByteSize) {

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

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

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

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

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

1821 }

1822 break;

1823 case dwarf::DW_ATE_unsigned:

1824 switch (ByteSize) {

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

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

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

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

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

1830 }

1831 break;

1832 case dwarf::DW_ATE_UTF:

1833 switch (ByteSize) {

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

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

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

1837 }

1838 break;

1839 case dwarf::DW_ATE_signed_char:

1840 if (ByteSize == 1)

1841 STK = SimpleTypeKind::SignedCharacter;

1842 break;

1843 case dwarf::DW_ATE_unsigned_char:

1844 if (ByteSize == 1)

1845 STK = SimpleTypeKind::UnsignedCharacter;

1846 break;

1847 default:

1848 break;

1849 }

1850

1851

1852

1853

1854

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

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

1857 STK = SimpleTypeKind::Int32Long;

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

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

1860 STK = SimpleTypeKind::UInt32Long;

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

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

1863 STK = SimpleTypeKind::WideCharacter;

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

1865 STK == SimpleTypeKind::UnsignedCharacter) &&

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

1867 STK = SimpleTypeKind::NarrowCharacter;

1868

1870}

1871

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

1875

1876

1877

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

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

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

1882 ? SimpleTypeMode::NearPointer64

1883 : SimpleTypeMode::NearPointer32;

1885 }

1886

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

1890 switch (Ty->getTag()) {

1892 case dwarf::DW_TAG_pointer_type:

1893 PM = PointerMode::Pointer;

1894 break;

1895 case dwarf::DW_TAG_reference_type:

1896 PM = PointerMode::LValueReference;

1897 break;

1898 case dwarf::DW_TAG_rvalue_reference_type:

1899 PM = PointerMode::RValueReference;

1900 break;

1901 }

1902

1904 PO |= PointerOptions::Const;

1905

1908}

1909

1912

1913

1914

1915 if (IsPMF) {

1917 case 0:

1918 return SizeInBytes == 0 ? PointerToMemberRepresentation::Unknown

1919 : PointerToMemberRepresentation::GeneralFunction;

1920 case DINode::FlagSingleInheritance:

1921 return PointerToMemberRepresentation::SingleInheritanceFunction;

1922 case DINode::FlagMultipleInheritance:

1923 return PointerToMemberRepresentation::MultipleInheritanceFunction;

1924 case DINode::FlagVirtualInheritance:

1925 return PointerToMemberRepresentation::VirtualInheritanceFunction;

1926 }

1927 } else {

1929 case 0:

1930 return SizeInBytes == 0 ? PointerToMemberRepresentation::Unknown

1931 : PointerToMemberRepresentation::GeneralData;

1932 case DINode::FlagSingleInheritance:

1933 return PointerToMemberRepresentation::SingleInheritanceData;

1934 case DINode::FlagMultipleInheritance:

1935 return PointerToMemberRepresentation::MultipleInheritanceData;

1936 case DINode::FlagVirtualInheritance:

1937 return PointerToMemberRepresentation::VirtualInheritanceData;

1938 }

1939 }

1941}

1942

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

1946 bool IsPMF = isa(Ty->getBaseType());

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

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

1951 : PointerKind::Near32;

1952 PointerMode PM = IsPMF ? PointerMode::PointerToMemberFunction

1953 : PointerMode::PointerToDataMember;

1954

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

1961}

1962

1963

1964

1966 switch (DwarfCC) {

1967 case dwarf::DW_CC_normal: return CallingConvention::NearC;

1968 case dwarf::DW_CC_BORLAND_msfastcall: return CallingConvention::NearFast;

1969 case dwarf::DW_CC_BORLAND_thiscall: return CallingConvention::ThisCall;

1970 case dwarf::DW_CC_BORLAND_stdcall: return CallingConvention::NearStdCall;

1971 case dwarf::DW_CC_BORLAND_pascal: return CallingConvention::NearPascal;

1972 case dwarf::DW_CC_LLVM_vectorcall: return CallingConvention::NearVector;

1973 }

1974 return CallingConvention::NearC;

1975}

1976

1982 while (IsModifier && BaseTy) {

1983

1984 switch (BaseTy->getTag()) {

1985 case dwarf::DW_TAG_const_type:

1986 Mods |= ModifierOptions::Const;

1987 PO |= PointerOptions::Const;

1988 break;

1989 case dwarf::DW_TAG_volatile_type:

1990 Mods |= ModifierOptions::Volatile;

1991 PO |= PointerOptions::Volatile;

1992 break;

1993 case dwarf::DW_TAG_restrict_type:

1994

1995

1996 PO |= PointerOptions::Restrict;

1997 break;

1998 default:

2000 break;

2001 }

2002 if (IsModifier)

2003 BaseTy = cast(BaseTy)->getBaseType();

2004 }

2005

2006

2007

2008

2009

2011 switch (BaseTy->getTag()) {

2012 case dwarf::DW_TAG_pointer_type:

2013 case dwarf::DW_TAG_reference_type:

2014 case dwarf::DW_TAG_rvalue_reference_type:

2015 return lowerTypePointer(cast(BaseTy), PO);

2016 case dwarf::DW_TAG_ptr_to_member_type:

2017 return lowerTypeMemberPointer(cast(BaseTy), PO);

2018 default:

2019 break;

2020 }

2021 }

2022

2024

2025

2026

2027 if (Mods == ModifierOptions::None)

2028 return ModifiedTI;

2029

2032}

2033

2037 ReturnAndArgTypeIndices.push_back(getTypeIndex(ArgType));

2038

2039

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

2043 }

2046 if (!ReturnAndArgTypeIndices.empty()) {

2047 auto ReturnAndArgTypesRef = ArrayRef(ReturnAndArgTypeIndices);

2048 ReturnTypeIndex = ReturnAndArgTypesRef.front();

2049 ArgTypeIndices = ReturnAndArgTypesRef.drop_front();

2050 }

2051

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

2054

2056

2059 ArgListIndex);

2061}

2062

2064 const DIType *ClassTy,

2065 int ThisAdjustment,

2066 bool IsStaticMethod,

2068

2069 TypeIndex ClassType = getTypeIndex(ClassTy);

2070

2072

2073 unsigned Index = 0;

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

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

2078 }

2079

2080

2081

2082

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

2086 dyn_cast_or_null(ReturnAndArgs[Index])) {

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

2088 ThisTypeIndex = getTypeIndexForThisPtr(PtrTy, Ty);

2090 }

2091 }

2092 }

2093

2094 while (Index < ReturnAndArgs.size())

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

2096

2097

2100

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

2103

2105

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

2109}

2110

2112 unsigned VSlotCount =

2115

2118}

2119

2122 case DINode::FlagPrivate: return MemberAccess::Private;

2123 case DINode::FlagPublic: return MemberAccess::Public;

2124 case DINode::FlagProtected: return MemberAccess::Protected;

2125 case 0:

2126

2127 return RecordTag == dwarf::DW_TAG_class_type ? MemberAccess::Private

2128 : MemberAccess::Public;

2129 }

2131}

2132

2134 if (SP->isArtificial())

2135 return MethodOptions::CompilerGenerated;

2136

2137

2138

2139 return MethodOptions::None;

2140}

2141

2143 bool Introduced) {

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

2145 return MethodKind::Static;

2146

2147 switch (SP->getVirtuality()) {

2148 case dwarf::DW_VIRTUALITY_none:

2149 break;

2150 case dwarf::DW_VIRTUALITY_virtual:

2151 return Introduced ? MethodKind::IntroducingVirtual : MethodKind::Virtual;

2152 case dwarf::DW_VIRTUALITY_pure_virtual:

2153 return Introduced ? MethodKind::PureIntroducingVirtual

2154 : MethodKind::PureVirtual;

2155 default:

2157 }

2158

2159 return MethodKind::Vanilla;

2160}

2161

2163 switch (Ty->getTag()) {

2164 case dwarf::DW_TAG_class_type:

2165 return TypeRecordKind::Class;

2166 case dwarf::DW_TAG_structure_type:

2167 return TypeRecordKind::Struct;

2168 default:

2170 }

2171}

2172

2173

2174

2177

2178

2179

2180

2182 CO |= ClassOptions::HasUniqueName;

2183

2184

2185

2186

2188 if (ImmediateScope && isa(ImmediateScope))

2189 CO |= ClassOptions::Nested;

2190

2191

2192

2193

2194

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

2196 if (ImmediateScope && isa(ImmediateScope))

2197 CO |= ClassOptions::Scoped;

2198 } else {

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

2200 Scope = Scope->getScope()) {

2201 if (isa(Scope)) {

2202 CO |= ClassOptions::Scoped;

2203 break;

2204 }

2205 }

2206 }

2207

2208 return CO;

2209}

2210

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

2212 switch (Ty->getTag()) {

2213 case dwarf::DW_TAG_class_type:

2214 case dwarf::DW_TAG_structure_type:

2215 case dwarf::DW_TAG_union_type:

2216 case dwarf::DW_TAG_enumeration_type:

2217 break;

2218 default:

2219 return;

2220 }

2221

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

2225

2228 }

2229}

2230

2234 unsigned EnumeratorCount = 0;

2235

2237 CO |= ClassOptions::ForwardReference;

2238 } else {

2240 ContinuationBuilder.begin(ContinuationRecordKind::FieldList);

2242

2243

2244 if (auto *Enumerator = dyn_cast_or_null(Element)) {

2245

2250 EnumeratorCount++;

2251 }

2252 }

2253 FTI = TypeTable.insertRecord(ContinuationBuilder);

2254 }

2255

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

2257

2261

2262 addUDTSrcLine(Ty, EnumTI);

2263

2264 return EnumTI;

2265}

2266

2267

2268

2269

2270

2275 };

2276

2278

2280

2282

2283

2285

2286

2288

2290

2292

2294};

2295

2296void CodeViewDebug::clear() {

2297 assert(CurFn == nullptr);

2298 FileIdMap.clear();

2299 FnDebugInfo.clear();

2300 FileToFilepathMap.clear();

2301 LocalUDTs.clear();

2302 GlobalUDTs.clear();

2303 TypeIndices.clear();

2304 CompleteTypeIndices.clear();

2305 ScopeGlobals.clear();

2306 CVGlobalVariableOffsets.clear();

2307}

2308

2309void CodeViewDebug::collectMemberInfo(ClassInfo &Info,

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

2313

2314

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

2316 DINode::FlagStaticMember) {

2319 StaticConstMembers.push_back(DDTy);

2320 }

2321

2322 return;

2323 }

2324

2325

2326

2327

2328

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

2332 bool FullyResolved = false;

2333 while (!FullyResolved) {

2334 switch (Ty->getTag()) {

2335 case dwarf::DW_TAG_const_type:

2336 case dwarf::DW_TAG_volatile_type:

2337

2338

2339 Ty = cast(Ty)->getBaseType();

2340 break;

2341 default:

2342 FullyResolved = true;

2343 break;

2344 }

2345 }

2346

2347 const DICompositeType *DCTy = dyn_cast(Ty);

2348 if (!DCTy)

2349 return;

2350

2351 ClassInfo NestedInfo = collectClassInfo(DCTy);

2353 Info.Members.push_back(

2355}

2356

2359

2361 for (auto *Element : Elements) {

2362

2363

2364 if (!Element)

2365 continue;

2366 if (auto *SP = dyn_cast(Element)) {

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

2368 } else if (auto *DDTy = dyn_cast(Element)) {

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

2370 collectMemberInfo(Info, DDTy);

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

2372 Info.Inheritance.push_back(DDTy);

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

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

2375 Info.VShapeTI = getTypeIndex(DDTy);

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

2377 Info.NestedTypes.push_back(DDTy);

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

2379

2380

2381 }

2382 } else if (auto *Composite = dyn_cast(Element)) {

2383 Info.NestedTypes.push_back(Composite);

2384 }

2385

2386 }

2387 return Info;

2388}

2389

2391

2392

2395}

2396

2398

2399

2400

2401

2403

2404

2405

2406 auto I = CompleteTypeIndices.find(Ty);

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

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

2409 return getCompleteTypeIndex(Ty);

2410 }

2411

2412

2413

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

2422 DeferredCompleteTypes.push_back(Ty);

2423 return FwdDeclTI;

2424}

2425

2427

2432 unsigned FieldCount;

2435 lowerRecordFieldList(Ty);

2436

2438 CO |= ClassOptions::ContainsNestedClass;

2439

2440

2441

2442

2443

2444

2446 CO |= ClassOptions::HasConstructorOrDestructor;

2447

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

2449

2451

2455

2456 addUDTSrcLine(Ty, ClassTI);

2457

2458 addToUDTs(Ty);

2459

2460 return ClassTI;

2461}

2462

2464

2466 return getCompleteTypeIndex(Ty);

2467

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

2474 DeferredCompleteTypes.push_back(Ty);

2475 return FwdDeclTI;

2476}

2477

2481 unsigned FieldCount;

2484 lowerRecordFieldList(Ty);

2485

2487 CO |= ClassOptions::ContainsNestedClass;

2488

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

2491

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

2495

2496 addUDTSrcLine(Ty, UnionTI);

2497

2498 addToUDTs(Ty);

2499

2500 return UnionTI;

2501}

2502

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

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

2505

2506

2507

2508

2509 unsigned MemberCount = 0;

2512 ContinuationBuilder.begin(ContinuationRecordKind::FieldList);

2513

2514

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

2517

2518 unsigned VBPtrOffset = I->getVBPtrOffset();

2519

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

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

2522 ? TypeRecordKind::IndirectVirtualBaseClass

2523 : TypeRecordKind::VirtualBaseClass;

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

2527 VBTableIndex);

2528

2530 MemberCount++;

2531 } else {

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

2533 "bases must be on byte boundaries");

2535 getTypeIndex(I->getBaseType()),

2536 I->getOffsetInBits() / 8);

2538 MemberCount++;

2539 }

2540 }

2541

2542

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

2549

2550 if (Member->isStaticMember()) {

2553 MemberCount++;

2554 continue;

2555 }

2556

2557

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

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

2562 MemberCount++;

2563 continue;

2564 }

2565

2566

2567 uint64_t MemberOffsetInBits =

2569 if (Member->isBitField()) {

2570 uint64_t StartBitOffset = MemberOffsetInBits;

2571 if (const auto *CI =

2572 dyn_cast_or_null(Member->getStorageOffsetInBits())) {

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

2574 }

2575 StartBitOffset -= MemberOffsetInBits;

2577 StartBitOffset);

2579 }

2580 uint64_t MemberOffsetInBytes = MemberOffsetInBits / 8;

2582 MemberName);

2584 MemberCount++;

2585 }

2586

2587

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

2590

2591 std::vector Methods;

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

2593 TypeIndex MethodType = getMemberFunctionType(SP, Ty);

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

2595

2596 unsigned VFTableOffset = -1;

2597 if (Introduced)

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

2599

2604 MemberCount++;

2605 }

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

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

2609 else {

2610

2611

2614

2617 }

2618 }

2619

2620

2624 MemberCount++;

2625 }

2626

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

2629 Info.NestedTypes.empty());

2630}

2631

2632TypeIndex CodeViewDebug::getVBPTypeIndex() {

2634

2637

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

2639 : PointerKind::Near32;

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

2644 }

2645

2646 return VBPType;

2647}

2648

2650

2651 if (!Ty)

2653

2654

2655

2656

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

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

2659 return I->second;

2660

2661 TypeLoweringScope S(*this);

2662 TypeIndex TI = lowerType(Ty, ClassTy);

2663 return recordTypeIndexForDINode(Ty, TI, ClassTy);

2664}

2665

2667CodeViewDebug::getTypeIndexForThisPtr(const DIDerivedType *PtrTy,

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

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

2671

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

2674 Options = PointerOptions::LValueRefThisPointer;

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

2676 Options = PointerOptions::RValueRefThisPointer;

2677

2678

2679

2680

2681

2682

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

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

2685 return I->second;

2686

2687 TypeLoweringScope S(*this);

2689 return recordTypeIndexForDINode(PtrTy, TI, SubroutineTy);

2690}

2691

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

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

2695 : PointerKind::Near32,

2696 PointerMode::LValueReference, PointerOptions::None,

2699}

2700

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

2702

2703 if (!Ty)

2705

2706

2707

2708

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

2710 (void)getTypeIndex(Ty);

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

2712 Ty = cast(Ty)->getBaseType();

2713

2714

2715

2716 switch (Ty->getTag()) {

2717 case dwarf::DW_TAG_class_type:

2718 case dwarf::DW_TAG_structure_type:

2719 case dwarf::DW_TAG_union_type:

2720 break;

2721 default:

2722 return getTypeIndex(Ty);

2723 }

2724

2725 const auto *CTy = cast(Ty);

2726

2727 TypeLoweringScope S(*this);

2728

2729

2730

2731

2732

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

2734 TypeIndex FwdDeclTI = getTypeIndex(CTy);

2735

2736

2737

2738

2739 if (CTy->isForwardDecl())

2740 return FwdDeclTI;

2741 }

2742

2743

2744

2745

2746 auto InsertResult = CompleteTypeIndices.insert({CTy, TypeIndex()});

2747 if (!InsertResult.second)

2748 return InsertResult.first->second;

2749

2751 switch (CTy->getTag()) {

2752 case dwarf::DW_TAG_class_type:

2753 case dwarf::DW_TAG_structure_type:

2754 TI = lowerCompleteTypeClass(CTy);

2755 break;

2756 case dwarf::DW_TAG_union_type:

2757 TI = lowerCompleteTypeUnion(CTy);

2758 break;

2759 default:

2761 }

2762

2763

2764

2765

2766

2767 CompleteTypeIndices[CTy] = TI;

2768 return TI;

2769}

2770

2771

2772

2773

2774

2775void CodeViewDebug::emitDeferredCompleteTypes() {

2777 while (!DeferredCompleteTypes.empty()) {

2778 std::swap(DeferredCompleteTypes, TypesToEmit);

2780 getCompleteTypeIndex(RecordTy);

2781 TypesToEmit.clear();

2782 }

2783}

2784

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

2787

2789 for (const LocalVariable &L : Locals)

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

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

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

2794 });

2795 for (const LocalVariable *L : Params)

2796 emitLocalVariable(FI, *L);

2797

2798

2799 for (const LocalVariable &L : Locals) {

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

2801 if (L.ConstantValue) {

2802

2803

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

2805 APSInt Val(*L.ConstantValue);

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

2807 } else {

2808 emitLocalVariable(FI, L);

2809 }

2810 }

2811 }

2812}

2813

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

2815 const LocalVariable &Var) {

2816

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

2818

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

2821 Flags |= LocalSymFlags::IsParameter;

2822 if (Var.DefRanges.empty())

2823 Flags |= LocalSymFlags::IsOptimizedOut;

2824

2826 TypeIndex TI = Var.UseReferenceType

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

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

2832

2834 endSymbolRecord(LocalEnd);

2835

2836

2837

2838

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

2841 LocalVarDef DefRange = Pair.first;

2842 const auto &Ranges = Pair.second;

2843 BytePrefix.clear();

2844 if (DefRange.InMemory) {

2845 int Offset = DefRange.DataOffset;

2846 unsigned Reg = DefRange.CVRegister;

2847

2848

2849

2850

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

2853 Offset += FI.OffsetAdjustment;

2854 }

2855

2856

2857

2858

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

2861 (bool(Flags & LocalSymFlags::IsParameter)

2862 ? (EncFP == FI.EncodedParamFramePtrReg)

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

2867 } else {

2869 if (DefRange.IsSubfield) {

2871 (DefRange.StructOffset

2873 }

2876 DRHdr.Flags = RegRelFlags;

2879 }

2880 } else {

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

2882 if (DefRange.IsSubfield) {

2884 DRHdr.Register = DefRange.CVRegister;

2888 } else {

2890 DRHdr.Register = DefRange.CVRegister;

2893 }

2894 }

2895 }

2896}

2897

2899 const FunctionInfo& FI) {

2901 emitLexicalBlock(*Block, FI);

2902}

2903

2904

2905

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

2907 const FunctionInfo& FI) {

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

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

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

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

2921 endSymbolRecord(RecordEnd);

2922

2923

2924 emitLocalVariableList(FI, Block.Locals);

2925 emitGlobalVariableList(Block.Globals);

2926

2927

2928 emitLexicalBlockList(Block.Children, FI);

2929

2930

2931 emitEndSymbolRecord(SymbolKind::S_END);

2932}

2933

2934

2935

2936void CodeViewDebug::collectLexicalBlockInfo(

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

2943}

2944

2945

2946

2947void CodeViewDebug::collectLexicalBlockInfo(

2952 if (Scope.isAbstractScope())

2953 return;

2954

2955

2956

2957 bool IgnoreScope = false;

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

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

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

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

2964 const DILexicalBlock *DILB = dyn_cast(Scope.getScopeNode());

2966

2967

2968 if (!Locals && !Globals)

2969 IgnoreScope = true;

2970

2971

2972 if (!DILB)

2973 IgnoreScope = true;

2974

2975

2976

2977

2978

2979

2980

2981

2982

2983

2984

2985

2987 IgnoreScope = true;

2988

2989 if (IgnoreScope) {

2990

2991

2992

2993

2994 if (Locals)

2996 if (Globals)

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

2998 collectLexicalBlockInfo(Scope.getChildren(),

2999 ParentBlocks,

3000 ParentLocals,

3001 ParentGlobals);

3002 return;

3003 }

3004

3005

3006

3007

3008 auto BlockInsertion = CurFn->LexicalBlocks.insert({DILB, LexicalBlock()});

3009 if (!BlockInsertion.second)

3010 return;

3011

3012

3013

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

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

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

3022 if (Locals)

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

3024 if (Globals)

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

3027 collectLexicalBlockInfo(Scope.getChildren(),

3031}

3032

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

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

3037

3039

3040

3042 collectLexicalBlockInfo(*CFS,

3043 CurFn->ChildBlocks,

3044 CurFn->Locals,

3045 CurFn->Globals);

3046

3047

3048

3049

3050 ScopeVariables.clear();

3051

3052

3053

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

3055 FnDebugInfo.erase(&GV);

3056 CurFn = nullptr;

3057 return;

3058 }

3059

3060

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

3062 for (const auto &MI : MBB) {

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

3066 dyn_cast(MD)));

3067 }

3068 }

3069 }

3070

3073 collectDebugInfoForJumpTables(MF, isThumb);

3074

3076

3078

3079 CurFn = nullptr;

3080}

3081

3082

3083

3084

3085

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

3088}

3089

3092

3093

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

3096 return;

3097

3098

3099

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

3103 if (NextMI.isDebugInstr())

3104 continue;

3105 DL = NextMI.getDebugLoc();

3107 break;

3108 }

3109

3110

3111 }

3113

3114

3116 return;

3117

3118 maybeRecordLocation(DL, Asm->MF);

3119}

3120

3128 return EndLabel;

3129}

3130

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

3133

3135}

3136

3139 if (EE.Value == SymKind)

3140 return EE.Name;

3141 return "";

3142}

3143

3152 OS.emitInt16(unsigned(SymKind));

3153 return EndLabel;

3154}

3155

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

3157

3158

3159

3160

3163}

3164

3165void CodeViewDebug::emitEndSymbolRecord(SymbolKind EndKind) {

3171}

3172

3173void CodeViewDebug::emitDebugInfoForUDTs(

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

3175#ifndef NDEBUG

3176 size_t OriginalSize = UDTs.size();

3177#endif

3178 for (const auto &UDT : UDTs) {

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

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

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

3185 "getCompleteTypeIndex found new UDTs!");

3187 endSymbolRecord(UDTRecordEnd);

3188 }

3189}

3190

3191void CodeViewDebug::collectGlobalVariableInfo() {

3193 GlobalMap;

3196 GV.getDebugInfo(GVEs);

3197 for (const auto *GVE : GVEs)

3198 GlobalMap[GVE] = &GV;

3199 }

3200

3203 const auto *CU = cast(Node);

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

3207

3208

3209

3210

3212

3213 if ((DIE->getNumElements() == 2) &&

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

3215

3216

3217

3218

3219 CVGlobalVariableOffsets.insert(

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

3221

3222

3223 if (GlobalMap.count(GVE) == 0 && DIE->isConstant()) {

3224 CVGlobalVariable CVGV = {DIGV, DIE};

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

3226 }

3227

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

3230 continue;

3231

3234 if (Scope && isa(Scope)) {

3235

3236

3237 auto Insertion = ScopeGlobals.insert(

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

3239 if (Insertion.second)

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

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

3243

3244 VariableList = &ComdatVariables;

3245 else

3246

3247 VariableList = &GlobalVariables;

3248 CVGlobalVariable CVGV = {DIGV, GV};

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

3250 }

3251 }

3252}

3253

3254void CodeViewDebug::collectDebugInfoForGlobals() {

3255 for (const CVGlobalVariable &CVGV : GlobalVariables) {

3258 getCompleteTypeIndex(DIGV->getType());

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

3260 }

3261

3262 for (const CVGlobalVariable &CVGV : ComdatVariables) {

3265 getCompleteTypeIndex(DIGV->getType());

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

3267 }

3268}

3269

3270void CodeViewDebug::emitDebugInfoForGlobals() {

3271

3272

3273

3274 switchToDebugSectionForSymbol(nullptr);

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

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

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

3278 emitGlobalVariableList(GlobalVariables);

3279 emitStaticConstMemberList();

3280 endCVSubsection(EndLabel);

3281 }

3282

3283

3284

3285 for (const CVGlobalVariable &CVGV : ComdatVariables) {

3286 const GlobalVariable *GV = cast<const GlobalVariable *>(CVGV.GVInfo);

3288 OS.AddComment("Symbol subsection for " +

3290 switchToDebugSectionForSymbol(GVSym);

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

3292

3293 emitDebugInfoForGlobal(CVGV);

3294 endCVSubsection(EndLabel);

3295 }

3296}

3297

3298void CodeViewDebug::emitDebugInfoForRetainedTypes() {

3301 for (auto *Ty : cast(Node)->getRetainedTypes()) {

3302 if (DIType *RT = dyn_cast(Ty)) {

3303 getTypeIndex(RT);

3304

3305 }

3306 }

3307 }

3308}

3309

3310

3312 for (const CVGlobalVariable &CVGV : Globals) {

3313

3314 emitDebugInfoForGlobal(CVGV);

3315 }

3316}

3317

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

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

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

3323

3325

3326

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

3333

3336 endSymbolRecord(SConstantEnd);

3337}

3338

3339void CodeViewDebug::emitStaticConstMemberList() {

3340 for (const DIDerivedType *DTy : StaticConstMembers) {

3342

3345 dyn_cast_or_null(DTy->getConstant()))

3349 dyn_cast_or_null(DTy->getConstant()))

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

3351 else

3353

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

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

3356 }

3357}

3358

3360 if (isa(Ty))

3361 return false;

3362

3363 if (auto *DTy = dyn_cast(Ty)) {

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

3366 T == dwarf::DW_TAG_ptr_to_member_type ||

3367 T == dwarf::DW_TAG_reference_type ||

3368 T == dwarf::DW_TAG_rvalue_reference_type)

3369 return false;

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

3372 }

3373

3374 auto *BTy = cast(Ty);

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

3376}

3377

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

3380

3382

3383 if (const auto *MemberDecl = dyn_cast_or_null(

3385 Scope = MemberDecl->getScope();

3386

3387

3388

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

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

3393

3395 dyn_cast_if_present<const GlobalVariable *>(CVGV.GVInfo)) {

3396

3397

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

3401 : SymbolKind::S_GTHREAD32)

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

3403 : SymbolKind::S_GDATA32);

3408

3409

3410 uint64_t Offset = CVGlobalVariableOffsets.lookup(DIGV);

3412

3416 const unsigned LengthOfDataRecord = 12;

3418 endSymbolRecord(DataEnd);

3419 } else {

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

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

3423

3424

3430 }

3431}

3432

3436 int64_t)> &Callback) {

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

3439#ifndef NDEBUG

3441#endif

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

3443

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

3447

3448

3449

3450

3451

3452

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

3454 if (MO.isJTI()) {

3455 unsigned Index = MO.getIndex();

3456#ifndef NDEBUG

3457 UsedJTs.set(Index);

3458#endif

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

3460 break;

3461 }

3462 }

3463 } else {

3464

3465

3466

3468 if (I->isJumpTableDebugInfo()) {

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

3470#ifndef NDEBUG

3471 UsedJTs.set(Index);

3472#endif

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

3474 break;

3475 }

3476 }

3477 }

3478 }

3479 }

3480#ifndef NDEBUG

3481 assert(UsedJTs.all() &&

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

3483#endif

3484 }

3485}

3486

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

3493}

3494

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

3500 int64_t JumpTableIndex) {

3501

3502

3503

3513 "EK_Custom32, EK_GPRel32BlockAddress, and "

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

3516

3517 EntrySize = JumpTableEntrySize::Pointer;

3518 Base = nullptr;

3519 break;

3523

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

3526 break;

3527 }

3528

3529 CurFn->JumpTables.push_back(

3530 {EntrySize, Base, BaseOffset, Branch,

3532 JTI.getJumpTables()[JumpTableIndex].MBBs.size()});

3533 });

3534}

3535

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

3537 for (auto JumpTable : FI.JumpTables) {

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

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

3544 } else {

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

3549 }

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

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

3562 endSymbolRecord(JumpTableEnd);

3563 }

3564}

3565

3566void CodeViewDebug::emitInlinees(

3568

3569

3570 constexpr size_t ChunkSize =

3573

3576

3577 size_t CurrentIndex = 0;

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

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

3580 auto CurrentChunkSize =

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

3584

3585 const size_t CurrentChunkEnd = CurrentIndex + CurrentChunkSize;

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

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

3589 }

3590 endSymbolRecord(Symbol);

3591 }

3592}

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< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")

Analysis containing CSE Info

static bool canUseReferenceType(const DbgVariableLocation &Loc)

static SourceLanguage MapDWLangToCVLang(unsigned DWLang)

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

static bool isUsableDebugLoc(DebugLoc DL)

static TypeIndex getStringIdTypeIdx(GlobalTypeTableBuilder &TypeTable, StringRef S)

static CPUType mapArchToCVCPUType(Triple::ArchType Type)

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

static Version parseVersion(StringRef Name)

static MethodOptions translateMethodOptionFlags(const DISubprogram *SP)

static bool isNonTrivial(const DICompositeType *DCTy)

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

static ClassOptions getCommonClassOptions(const DICompositeType *Ty)

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

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

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

static StringRef removeTemplateArgs(StringRef Name)

static TypeRecordKind getRecordKind(const DICompositeType *Ty)

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

static CallingConvention dwarfCCToCodeView(unsigned DwarfCC)

Given a DWARF calling convention, get the CodeView equivalent.

static bool isFloatDIType(const DIType *Ty)

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

static bool shouldEmitUdt(const DIType *T)

static StringRef getPrettyScopeName(const DIScope *Scope)

static bool shouldAlwaysEmitCompleteClassType(const DICompositeType *Ty)

static bool needsReferenceType(const DbgVariableLocation &Loc)

static MemberAccess translateAccessFlags(unsigned RecordTag, unsigned Flags)

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.

DenseMap< Block *, BlockRelaxAux > Blocks

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

unsigned const TargetRegisterInfo * TRI

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

static StringRef getName(Value *V)

assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())

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]

Class for arbitrary precision integers.

An arbitrary precision integer that knows its signedness.

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

ArrayRef< T > drop_front(size_t N=1) const

Drop the first N elements of the array.

size_t size() const

size - Get the array size.

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

const TargetLoweringObjectFile & getObjFileLowering() const

Return information about object file lowering.

MCSymbol * getSymbol(const GlobalValue *GV) const

TargetMachine & TM

Target machine description.

MCSymbol * getFunctionBegin() const

const MCAsmInfo * MAI

Target Asm Printer information.

MachineFunction * MF

The current machine function.

bool hasDebugInfo() const

Returns true if valid debug info is present.

MCSymbol * getFunctionEnd() const

virtual std::tuple< const MCSymbol *, uint64_t, const MCSymbol *, codeview::JumpTableEntrySize > getCodeViewJumpTableInfo(int JTI, const MachineInstr *BranchInstr, const MCSymbol *BranchLabel) const

Gets information required to create a CodeView debug symbol for a jump table.

Provides write only access to a subclass of WritableBinaryStream.

Collects and handles line tables information in a CodeView format.

CodeViewDebug(AsmPrinter *AP)

void beginModule(Module *M) override

bool moduleIsInFortran()

Check if the current module is in Fortran.

void endFunctionImpl(const MachineFunction *) override

Gather post-function debug information.

void endModule() override

Emit the COFF section that holds the line table information.

void beginInstruction(const MachineInstr *MI) override

Process beginning of an instruction.

void beginFunctionImpl(const MachineFunction *MF) override

Gather pre-function debug information.

ConstantFP - Floating Point Values [float, double].

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

DIType * getClassType() const

Get casted version of extra data.

Constant * getConstant() const

A structured debug information entry.

bool isLocalToUnit() const

Metadata * getRawStaticDataMemberDeclaration() const

DILocalScope * getScope() const

Get the local scope for this variable.

Tagged DWARF-like metadata node.

dwarf::Tag getTag() const

Base class for scope-like contexts.

StringRef getFilename() const

StringRef getName() const

StringRef getDirectory() const

DIScope * getScope() const

String type, Fortran CHARACTER(n)

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

This class represents an Operation in the Expression.

unsigned getPointerSizeInBits(unsigned AS=0) const

Layout pointer size, in bits FIXME: The defaults need to be removed once all of the backends/clients ...

static const EntryIndex NoEntry

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

Base class for debug information backends.

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.

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.

DILocation * get() const

Get the underlying DILocation.

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.

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

Implements a dense probed hash-table based set.

Lightweight error class with error context and mandatory checking.

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

bool hasFnAttribute(Attribute::AttrKind Kind) const

Return true if the function has the attribute.

bool isThreadLocal() const

If the value is "Thread Local", its value isn't shared by the threads.

bool hasLocalLinkage() const

static StringRef dropLLVMManglingEscape(StringRef Name)

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

bool isDeclarationForLinker() const

LexicalScope - This class is used to track scope information.

LexicalScope * findLexicalScope(const DILocation *DL)

findLexicalScope - Find lexical scope, either regular or inlined, for the given DebugLoc.

LexicalScope * findInlinedScope(const DILocalScope *N, const DILocation *IA)

findInlinedScope - Find an inlined scope for the given scope/inlined-at.

LexicalScope * getCurrentFunctionScope() const

getCurrentFunctionScope - Return lexical scope for the current function.

unsigned getCodePointerSize() const

Get the code pointer size in bytes.

void * allocate(unsigned Size, unsigned Align=8)

MCSymbol * createTempSymbol()

Create a temporary symbol with a unique name.

MCSectionCOFF * getAssociativeCOFFSection(MCSectionCOFF *Sec, const MCSymbol *KeySym, unsigned UniqueID=GenericSectionID)

Gets or creates a section equivalent to Sec that is associated with the section containing KeySym.

MCSection * getCOFFDebugSymbolsSection() const

MCSection * getCOFFDebugTypesSection() const

MCSection * getCOFFGlobalTypeHashesSection() const

This represents a section on Windows.

MCSymbol * getCOMDATSymbol() const

Streaming machine code generation interface.

virtual void addBlankLine()

Emit a blank line to a .s file to pretty it up.

virtual bool emitCVFuncIdDirective(unsigned FunctionId)

Introduces a function id for use with .cv_loc.

virtual void emitBinaryData(StringRef Data)

Functionally identical to EmitBytes.

virtual bool emitCVFileDirective(unsigned FileNo, StringRef Filename, ArrayRef< uint8_t > Checksum, unsigned ChecksumKind)

Associate a filename with a specified logical file number, and also specify that file's checksum info...

virtual void emitCVStringTableDirective()

This implements the CodeView '.cv_stringtable' assembler directive.

virtual bool isVerboseAsm() const

Return true if this streamer supports verbose assembly and if it is enabled.

virtual void emitCVFileChecksumOffsetDirective(unsigned FileNo)

This implements the CodeView '.cv_filechecksumoffset' assembler directive.

MCContext & getContext() const

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

Add a textual comment.

virtual void emitCVFPOData(const MCSymbol *ProcSym, SMLoc Loc={})

This implements the CodeView '.cv_fpo_data' assembler directive.

virtual void emitCOFFSecRel32(MCSymbol const *Symbol, uint64_t Offset)

Emits a COFF section relative relocation.

virtual void emitCVFileChecksumsDirective()

This implements the CodeView '.cv_filechecksums' assembler directive.

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 emitCOFFSectionIndex(MCSymbol const *Symbol)

Emits a COFF section index.

virtual void emitCVLinetableDirective(unsigned FunctionId, const MCSymbol *FnStart, const MCSymbol *FnEnd)

This implements the CodeView '.cv_linetable' assembler directive.

virtual void emitValueToAlignment(Align Alignment, int64_t Value=0, unsigned ValueSize=1, unsigned MaxBytesToEmit=0)

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

virtual void emitIntValue(uint64_t Value, unsigned Size)

Special case of EmitValue that avoids the client having to pass in a MCExpr for constant integers.

void emitInt16(uint64_t Value)

virtual void switchSection(MCSection *Section, uint32_t Subsec=0)

Set the current section where code is being emitted to Section.

virtual void emitCVDefRangeDirective(ArrayRef< std::pair< const MCSymbol *, const MCSymbol * > > Ranges, StringRef FixedSizePortion)

This implements the CodeView '.cv_def_range' assembler directive.

void emitInt32(uint64_t Value)

virtual void emitCVLocDirective(unsigned FunctionId, unsigned FileNo, unsigned Line, unsigned Column, bool PrologueEnd, bool IsStmt, StringRef FileName, SMLoc Loc)

This implements the CodeView '.cv_loc' assembler directive.

virtual bool emitCVInlineSiteIdDirective(unsigned FunctionId, unsigned IAFunc, unsigned IAFile, unsigned IALine, unsigned IACol, SMLoc Loc)

Introduces an inline call site id for use with .cv_loc.

void emitInt8(uint64_t Value)

virtual void emitCVInlineLinetableDirective(unsigned PrimaryFunctionId, unsigned SourceFileId, unsigned SourceLineNum, const MCSymbol *FnStartSym, const MCSymbol *FnEndSym)

This implements the CodeView '.cv_inline_linetable' assembler directive.

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.

std::string CommandlineArgs

ArrayRef< MDOperand > operands() const

unsigned getNumOperands() const

Return number of MDNode operands.

reverse_instr_iterator instr_rbegin()

iterator getFirstTerminator()

Returns an iterator to the first terminator instruction of this basic block.

reverse_instr_iterator instr_rend()

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

Description of the location of a variable whose Address is valid and unchanging during function execu...

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

const Module * getModule() const

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

NamedMDNode * getNamedMetadata(StringRef Name) const

Return the first NamedMDNode in the module with the specified name.

const std::string & getTargetTriple() const

Get the target triple which is a string describing the target host.

iterator_range< global_iterator > globals()

const DataLayout & getDataLayout() const

Get the data layout for the module's target platform.

Metadata * getProfileSummary(bool IsCS) const

Returns profile summary metadata.

iterator_range< op_iterator > operands()

const RecordRecTy * getType() const

Wrapper class representing virtual and physical registers.

Represents a location in source code.

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.

StackOffset holds a fixed and a scalable offset in bytes.

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.

Information about stack frame layout on the target.

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...

CodeGenOptLevel getOptLevel() const

Returns the optimization level: None, Less, Default, or Aggressive.

MCTargetOptions MCOptions

Machine level options.

std::string ObjectFilenameForDebug

Stores the filename/path of the final .o/.obj file, to be written in the debug information.

unsigned Hotpatch

Emit the hotpatch flag in CodeView debug.

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

TargetSubtargetInfo - Generic base class for all target subtargets.

virtual const TargetRegisterInfo * getRegisterInfo() const

getRegisterInfo - If register information is available, return it.

virtual const TargetFrameLowering * getFrameLowering() const

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

Triple - Helper class for working with autoconf configuration names.

ArchType getArch() const

Get the parsed architecture type of this triple.

Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...

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

LLVM Value Representation.

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)

virtual void emitBytes(StringRef Data)=0

virtual bool isVerboseAsm()=0

virtual void AddComment(const Twine &T)=0

virtual void emitIntValue(uint64_t Value, unsigned Size)=0

virtual void emitBinaryData(StringRef Data)=0

virtual void AddRawComment(const Twine &T)=0

void begin(ContinuationRecordKind RecordKind)

void writeMemberType(RecordType &Record)

ArrayRef< ArrayRef< uint8_t > > records() const

TypeIndex insertRecord(ContinuationRecordBuilder &Builder)

ArrayRef< GloballyHashedType > hashes() const

TypeIndex writeLeafType(T &Record)

For method overload sets. LF_METHOD.

SimpleTypeKind getSimpleKind() const

SimpleTypeMode getSimpleMode() const

static const uint32_t FirstNonSimpleIndex

static 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.

A raw_ostream that writes to an SmallVector or SmallString.

#define llvm_unreachable(msg)

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

constexpr char TypeName[]

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

@ DEBUG_HASHES_SECTION_MAGIC

@ C

The default llvm calling convention, compatible with C.

Reg

All possible values of the reg field in the ModR/M byte.

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)

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.

CallingConvention

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

MethodOptions

Equivalent to CV_fldattr_t bitfield.

ArrayRef< EnumEntry< SymbolKind > > getSymbolTypeNames()

MemberAccess

Source-level access specifier. (CV_access_e)

ThunkOrdinal

These values correspond to the THUNK_ORDINAL enumeration.

EncodedFramePtrReg

Two-bit value indicating which register is the designated frame pointer register.

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.

StringRef getSymbolName(CVSymbol Sym)

EncodedFramePtrReg encodeFramePtrReg(RegisterId Reg, CPUType CPU)

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,...

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...

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

Is path absolute?

This is an optimization pass for GlobalISel generic memory operations.

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

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

std::tuple< uint64_t, uint32_t > InlineSite

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

auto reverse(ContainerTy &&C)

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

void sort(IteratorTy Start, IteratorTy End)

void report_fatal_error(Error Err, bool gen_crash_diag=true)

Report a serious error, calling any installed error handler.

EHPersonality classifyEHPersonality(const Value *Pers)

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

raw_fd_ostream & errs()

This returns a reference to a raw_ostream for standard error.

StringRef getTypeName()

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

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

Report a fatal error if Err is a failure value.

bool isAsynchronousEHPersonality(EHPersonality Pers)

Returns true if this personality function catches asynchronous exceptions.

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

Returns true if Element is found in Range.

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

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

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

Implement std::swap in terms of BitVector swap.

TypeLoweringScope(CodeViewDebug &CVD)

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

const DIDerivedType * MemberTypeNode

std::vector< MemberInfo > MemberList

MemberList Members

Direct members.

std::vector< const DIType * > NestedTypes

std::vector< const DIDerivedType * > Inheritance

Base classes.

int InMemory

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

Represents the location at which a variable is stored.

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

Extract a VariableLocation from a MachineInstr.

SmallVector< int64_t, 1 > LoadChain

Chain of offsetted loads necessary to load the value if it lives in memory.