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

1

2

3

4

5

6

7

8

9

10

11

12

57#include

58#include

59#include

60#include

61#include

62

63using namespace llvm;

64

65#define DEBUG_TYPE "dwarfdebug"

66

67STATISTIC(NumCSParams, "Number of dbg call site params created");

68

70 "use-dwarf-ranges-base-address-specifier", cl::Hidden,

71 cl::desc("Use base address specifiers in debug_ranges"), cl::init(false));

72

75 cl::desc("Generate dwarf aranges"),

77

80 cl::desc("Generate DWARF4 type units."),

82

84 "split-dwarf-cross-cu-references", cl::Hidden,

85 cl::desc("Enable cross-cu references in DWO files"), cl::init(false));

86

88

91 cl::desc("Make an absence of debug location information explicit."),

95

97 "accel-tables", cl::Hidden, cl::desc("Output dwarf accelerator tables."),

99 "Default for platform"),

100 clEnumValN(AccelTableKind::None, "Disable", "Disabled."),

101 clEnumValN(AccelTableKind::Apple, "Apple", "Apple"),

102 clEnumValN(AccelTableKind::Dwarf, "Dwarf", "DWARF")),

103 cl::init(AccelTableKind::Default));

104

107 cl::desc("Use inlined strings rather than string section."),

112

115 cl::desc("Disable emission .debug_ranges section."),

117

119 "dwarf-sections-as-references", cl::Hidden,

120 cl::desc("Use sections+offset as references rather than labels."),

124

127 cl::desc("Emit the GNU .debug_macro format with DWARF <5"),

129

132 cl::desc("Enable use of the DWARFv5 DW_OP_convert operator"),

136

142

145 cl::desc("Which DWARF linkage-name attributes to emit."),

147 "Default for platform"),

150 "Abstract subprograms")),

152

155 cl::desc("Always use DW_AT_ranges in DWARFv5 whenever it could allow more "

156 "address pool entry sharing to reduce relocations/object size"),

158 "Default address minimization strategy"),

159 clEnumValN(DwarfDebug::MinimizeAddrInV5::Ranges, "Ranges",

160 "Use rnglists for contiguous ranges if that allows "

161 "using a pre-existing base address"),

162 clEnumValN(DwarfDebug::MinimizeAddrInV5::Expressions,

163 "Expressions",

164 "Use exprloc addrx+offset expressions for any "

165 "address with a prior base address"),

166 clEnumValN(DwarfDebug::MinimizeAddrInV5::Form, "Form",

167 "Use addrx+offset extension form for any address "

168 "with a prior base address"),

169 clEnumValN(DwarfDebug::MinimizeAddrInV5::Disabled, "Disabled",

170 "Stuff")),

171 cl::init(DwarfDebug::MinimizeAddrInV5::Default));

172

174

175void DebugLocDwarfExpression::emitOp(uint8_t Op, const char *Comment) {

176 getActiveStreamer().emitInt8(

179}

180

181void DebugLocDwarfExpression::emitSigned(int64_t Value) {

183}

184

185void DebugLocDwarfExpression::emitUnsigned(uint64_t Value) {

187}

188

189void DebugLocDwarfExpression::emitData1(uint8_t Value) {

191}

192

193void DebugLocDwarfExpression::emitBaseTypeRef(uint64_t Idx) {

196}

197

200

201 return false;

202}

203

204void DebugLocDwarfExpression::enableTemporaryBuffer() {

205 assert(!IsBuffering && "Already buffering?");

206 if (!TmpBuf)

207 TmpBuf = std::make_unique(OutBS.GenerateComments);

208 IsBuffering = true;

209}

210

211void DebugLocDwarfExpression::disableTemporaryBuffer() { IsBuffering = false; }

212

213unsigned DebugLocDwarfExpression::getTemporaryBufferSize() {

214 return TmpBuf ? TmpBuf->Bytes.size() : 0;

215}

216

217void DebugLocDwarfExpression::commitTemporaryBuffer() {

218 if (!TmpBuf)

219 return;

220 for (auto Byte : enumerate(TmpBuf->Bytes)) {

221 const char *Comment = (Byte.index() < TmpBuf->Comments.size())

222 ? TmpBuf->Comments[Byte.index()].c_str()

223 : "";

225 }

226 TmpBuf->Bytes.clear();

227 TmpBuf->Comments.clear();

228}

229

232}

233

234

238 const bool IsVariadic = !SingleLocExprOpt;

239

240

241 if (!IsVariadic && MI->isNonListDebugValue()) {

242 assert(MI->getNumDebugOperands() == 1 &&

243 "Mismatched DIExpression and debug operands for debug instruction.");

244 Expr = *SingleLocExprOpt;

245 }

246 assert(MI->getNumOperands() >= 3);

249 if (Op.isReg()) {

251 MI->isNonListDebugValue() && MI->isDebugOffsetImm());

253 } else if (Op.isTargetIndex()) {

256 } else if (Op.isImm())

258 else if (Op.isFPImm())

260 else if (Op.isCImm())

262 else

263 llvm_unreachable("Unexpected debug operand in DBG_VALUE* instruction!");

264 }

265 return DbgValueLoc(Expr, DbgValueLocEntries, IsVariadic);

266}

267

269 std::optionalDIExpression::FragmentInfo Fragment = Expr.getFragmentInfo();

270 return Fragment ? Fragment->OffsetInBits : 0;

271}

272

276}

277

280}

281

284 Expr(ValueLoc.getExpression()) {

286 Expr = nullptr;

287}

288

291

293 return FrameIndexExprs;

294}

295

297 FrameIndexExprs.insert({FI, Expr});

298 assert((FrameIndexExprs.size() == 1 ||

301 return FIE.Expr && FIE.Expr->isFragment();

302 })) &&

303 "conflicting locations for variable");

304}

305

307 bool GenerateTypeUnits,

310

313

314

315

316 if (GenerateTypeUnits && (DwarfVersion < 5 || !TT.isOSBinFormatELF()))

318

319

320

321

322 if (DwarfVersion >= 5)

328}

329

332 InfoHolder(A, "info_string", DIEValueAllocator),

333 SkeletonHolder(A, "skel_string", DIEValueAllocator),

334 IsDarwin(A->TM.getTargetTriple().isOSDarwin()) {

336

337

338

341 else if (IsDarwin)

343 else if (TT.isPS())

345 else if (TT.isOSAIX())

347 else

349

351 UseInlineStrings = TT.isNVPTX() || tuneForDBX();

352 else

354

355

357

358 HasAppleExtensionAttributes = tuneForLLDB();

359

360

362

363

366 else

368

370 unsigned DwarfVersion = DwarfVersionNumber ? DwarfVersionNumber

372

373 DwarfVersion =

375

376 bool Dwarf64 = DwarfVersion >= 3 &&

377 TT.isArch64Bit();

378

379

380

381

382

383

384 Dwarf64 &=

386 TT.isOSBinFormatELF()) ||

387 TT.isOSBinFormatXCOFF();

388

389 if (!Dwarf64 && TT.isArch64Bit() && TT.isOSBinFormatXCOFF())

391

393

394

396 UseSectionsAsReferences = TT.isNVPTX();

397 else

399

400

401 GenerateTypeUnits = (A->TM.getTargetTriple().isOSBinFormatELF() ||

402 A->TM.getTargetTriple().isOSBinFormatWasm()) &&

404

406 DwarfVersion, GenerateTypeUnits, DebuggerTuning, A->TM.getTargetTriple());

407

408

409

410

411

412

413 UseGNUTLSOpcode = tuneForGDB() || DwarfVersion < 3;

414

415 UseDWARF2Bitfields = DwarfVersion < 4;

416

417

418

419

420

421 UseSegmentedStringOffsetsTable = DwarfVersion >= 5;

422

423

424

426

427

428

429 UseDebugMacroSection =

433 else

435

436

437

438 if (DwarfVersion >= 5)

440

441 Asm->OutStreamer->getContext().setDwarfVersion(DwarfVersion);

444}

445

446

448

450 return Name.starts_with("+") || Name.starts_with("-");

451}

452

455 return false;

456

457 return Name.contains(") ");

458}

459

463 Class = In.slice(In.find('[') + 1, In.find(' '));

464 Category = "";

465 return;

466 }

467

468 Class = In.slice(In.find('[') + 1, In.find('('));

469 Category = In.slice(In.find('[') + 1, In.find(' '));

470}

471

473 return In.slice(In.find(' ') + 1, In.find(']'));

474}

475

476

484 return;

485

486 if (!SP->isDefinition())

487 return;

488

491

492

493

494

495 if (SP->getLinkageName() != "" && SP->getName() != SP->getLinkageName() &&

497 addAccelName(Unit, NameTableKind, SP->getLinkageName(), Die);

498

499

500

504 addAccelObjC(Unit, NameTableKind, Class, Die);

505 if (Category != "")

506 addAccelObjC(Unit, NameTableKind, Category, Die);

507

509 }

510}

511

512

513

515 if (Scope->isAbstractScope())

516 return false;

517

518

521 return true;

522

523 if (Ranges.size() > 1)

524 return false;

525

526

527

529}

530

533 if (auto *SkelCU = CU.getSkeleton())

534 if (CU.getCUNode()->getSplitDebugInlining())

535 F(*SkelCU);

536}

537

540}

541

542void DwarfDebug::constructAbstractSubprogramScopeDIE(DwarfCompileUnit &SrcCU,

544 assert(Scope && Scope->getScopeNode());

545 assert(Scope->isAbstractScope());

546 assert(!Scope->getInlinedAt());

547

548 auto *SP = cast(Scope->getScopeNode());

549

550

551

553

555 else {

556 auto &CU = getOrCreateDwarfCompileUnit(SP->getUnit());

557 if (auto *SkelCU = CU.getSkeleton()) {

559 .constructAbstractSubprogramScopeDIE(Scope);

560 if (CU.getCUNode()->getSplitDebugInlining())

561 SkelCU->constructAbstractSubprogramScopeDIE(Scope);

562 } else

563 CU.constructAbstractSubprogramScopeDIE(Scope);

564 }

565}

566

567

568

570

572

573

574

576};

577

578

580

581

583

584

587 std::vector<uint64_t> Elts = Addition->getElements().vec();

588

590 llvm::erase(Elts, dwarf::DW_OP_stack_value);

593 return CombinedExpr;

594}

595

596

597

598template

602 for (auto Param : DescribedParams) {

603 bool ShouldCombineExpressions = Expr && Param.Expr->getNumElements() > 0;

604

605

606

607 if (ShouldCombineExpressions && Expr->isEntryValue())

608 continue;

609

610

611

612

613

616 : Expr;

617 assert((!CombinedExpr || CombinedExpr->isValid()) &&

618 "Combined debug expression is invalid");

619

623 ++NumCSParams;

624 }

625}

626

627

628

629

633 auto &ParamsForFwdReg = Worklist[Reg];

634 for (auto Param : ParamsToAdd) {

637 return D.ParamReg == Param.ParamReg;

638 }) &&

639 "Same parameter described twice by forwarding reg");

640

641

642

643

644

646 ParamsForFwdReg.push_back({Param.ParamReg, CombinedExpr});

647 }

648}

649

650

655

662

663

664

665

666

667

668

669

670

671

672

673

674

675

676

677

678

679

680

681

683

684

685

687 auto getForwardingRegsDefinedByMI = [&](const MachineInstr &MI,

689 if (MI.isDebugInstr())

690 return;

691

693 if (MO.getReg().isPhysical()) {

694 for (auto &FwdReg : ForwardedRegWorklist)

695 if (TRI.regsOverlap(FwdReg.first, MO.getReg()))

696 Defs.insert(FwdReg.first);

697 for (MCRegUnit Unit : TRI.regunits(MO.getReg()))

698 NewClobberedRegUnits.insert(Unit);

699 }

700 }

701 };

702

703

705

706 getForwardingRegsDefinedByMI(*CurMI, FwdRegDefs);

707 if (FwdRegDefs.empty()) {

708

709 ClobberedRegUnits.insert(NewClobberedRegUnits.begin(),

710 NewClobberedRegUnits.end());

711 return;

712 }

713

714

715

716

717 auto IsRegClobberedInMeantime = [&](Register Reg) -> bool {

718 for (auto &RegUnit : ClobberedRegUnits)

719 if (TRI.hasRegUnit(Reg, RegUnit))

720 return true;

721 return false;

722 };

723

724 for (auto ParamFwdReg : FwdRegDefs) {

725 if (auto ParamValue = TII.describeLoadedValue(*CurMI, ParamFwdReg)) {

726 if (ParamValue->first.isImm()) {

727 int64_t Val = ParamValue->first.getImm();

729 ForwardedRegWorklist[ParamFwdReg], Params);

730 } else if (ParamValue->first.isReg()) {

731 Register RegLoc = ParamValue->first.getReg();

732 Register SP = TLI.getStackPointerRegisterToSaveRestore();

734 bool IsSPorFP = (RegLoc == SP) || (RegLoc == FP);

735 if (!IsRegClobberedInMeantime(RegLoc) &&

736 (TRI.isCalleeSavedPhysReg(RegLoc, *MF) || IsSPorFP)) {

739 ForwardedRegWorklist[ParamFwdReg], Params);

740 } else {

741

742

743

744

745

746

748 ForwardedRegWorklist[ParamFwdReg]);

749 }

750 }

751 }

752 }

753

754

755 for (auto ParamFwdReg : FwdRegDefs)

756 ForwardedRegWorklist.erase(ParamFwdReg);

757

758

759 ClobberedRegUnits.insert(NewClobberedRegUnits.begin(),

760 NewClobberedRegUnits.end());

761

762

763

764 for (auto &New : TmpWorklistItems)

765 addToFwdRegWorklist(ForwardedRegWorklist, New.first, EmptyExpr, New.second);

766 TmpWorklistItems.clear();

767}

768

773

775 return true;

776

777

778

779

781 return false;

782

783 if (ForwardedRegWorklist.empty())

784 return false;

785

786

788 return true;

789

790 interpretValues(CurMI, ForwardedRegWorklist, Params, ClobberedRegUnits);

791

792 return true;

793}

794

795

796

801 auto CSInfo = CalleesMap.find(CallMI);

802

803

804 if (CSInfo == CalleesMap.end())

805 return;

806

808

809

811

813

816

817

818 for (const auto &ArgReg : CSInfo->second.ArgRegPairs) {

819 bool InsertedReg =

820 ForwardedRegWorklist.insert({ArgReg.Reg, {{ArgReg.Reg, EmptyExpr}}})

821 .second;

822 assert(InsertedReg && "Single register used to forward two arguments?");

823 (void)InsertedReg;

824 }

825

826

827 for (const auto &MO : CallMI->uses())

828 if (MO.isReg() && MO.isUndef())

829 ForwardedRegWorklist.erase(MO.getReg());

830

831

832

833

834

835

836

837

838

840

841

844 auto Suc = std::next(CallMI->getIterator());

845

847 (void)BundleEnd;

848 assert(std::next(Suc) == BundleEnd &&

849 "More than one instruction in call delay slot");

850

851 if (interpretNextInstr(&*Suc, ForwardedRegWorklist, Params, ClobberedRegUnits))

852 return;

853 }

854

855

857

858 if (interpretNextInstr(&*I, ForwardedRegWorklist, Params, ClobberedRegUnits))

859 return;

860 }

861

862

863 if (ShouldTryEmitEntryVals) {

864

867 for (auto &RegEntry : ForwardedRegWorklist) {

870 }

871 }

872}

873

874void DwarfDebug::constructCallSiteEntryDIEs(const DISubprogram &SP,

877

878

879 if (!SP.areAllCallsDescribed() || !SP.isDefinition())

880 return;

881

882

883

884

885

886 CU.addFlag(ScopeDIE, CU.getDwarf5OrGNUAttr(dwarf::DW_AT_call_all_calls));

887

889 assert(TII && "TargetInstrInfo not found: cannot label tail calls");

890

891

892 auto delaySlotSupported = [&](const MachineInstr &MI) {

893 if (MI.isBundledWithSucc())

894 return false;

895 auto Suc = std::next(MI.getIterator());

897 (void)CallInstrBundle;

899 (void)DelaySlotBundle;

900

901

902

903

906 "Call and its successor instruction don't have same label after.");

907 return true;

908 };

909

910

913

914

915

916 if (MI.isBundle())

917 continue;

918

919

920

921 if (MI.isCandidateForAdditionalCallInfo())

922 continue;

923

924

925

927 continue;

928

929

930 if (MI.hasDelaySlot() && !delaySlotSupported(*&MI))

931 return;

932

933

934

935

939 continue;

940

941 unsigned CallReg = 0;

943 const Function *CalleeDecl = nullptr;

944 if (CalleeOp.isReg()) {

945 CallReg = CalleeOp.getReg();

946 if (!CallReg)

947 continue;

948 } else {

949 CalleeDecl = dyn_cast(CalleeOp.getGlobal());

951 continue;

953 }

954

955

956

958

959

960

961

964

965

966

967

968

970 (!IsTail || CU.useGNUAnalogForDwarf5Feature())

972 : nullptr;

973

974

975

978

979 assert((IsTail || PCAddr) && "Non-tail call without return PC");

980

981 LLVM_DEBUG(dbgs() << "CallSiteEntry: " << MF.getName() << " -> "

982 << (CalleeDecl ? CalleeDecl->getName()

984 .getRegisterInfo()

985 ->getName(CallReg)))

986 << (IsTail ? " [IsTail]" : "") << "\n");

987

988 DIE &CallSiteDIE = CU.constructCallSiteEntryDIE(

989 ScopeDIE, CalleeSP, IsTail, PCAddr, CallAddr, CallReg);

990

991

994

996 CU.constructCallSiteParmEntryDIEs(CallSiteDIE, Params);

997 }

998 }

999 }

1000}

1001

1003 if (U.hasDwarfPubSections())

1004 return;

1005

1006 U.addFlag(D, dwarf::DW_AT_GNU_pubnames);

1007}

1008

1009void DwarfDebug::finishUnitAttributes(const DICompileUnit *DIUnit,

1013

1017 std::string ProducerWithFlags = Producer.str() + " " + Flags.str();

1018 NewCU.addString(Die, dwarf::DW_AT_producer, ProducerWithFlags);

1019 } else

1020 NewCU.addString(Die, dwarf::DW_AT_producer, Producer);

1021

1022 NewCU.addUInt(Die, dwarf::DW_AT_language, dwarf::DW_FORM_data2,

1024 NewCU.addString(Die, dwarf::DW_AT_name, FN);

1026 if (!SysRoot.empty())

1027 NewCU.addString(Die, dwarf::DW_AT_LLVM_sysroot, SysRoot);

1029 if (!SDK.empty())

1030 NewCU.addString(Die, dwarf::DW_AT_APPLE_sdk, SDK);

1031

1033

1036

1038

1039

1040

1041 if (!CompilationDir.empty())

1042 NewCU.addString(Die, dwarf::DW_AT_comp_dir, CompilationDir);

1043 addGnuPubAttributes(NewCU, Die);

1044 }

1045

1048 NewCU.addFlag(Die, dwarf::DW_AT_APPLE_optimized);

1049

1051 if (Flags.empty())

1052 NewCU.addString(Die, dwarf::DW_AT_APPLE_flags, Flags);

1053

1055 NewCU.addUInt(Die, dwarf::DW_AT_APPLE_major_runtime_vers,

1056 dwarf::DW_FORM_data1, RVer);

1057 }

1058

1060

1061 NewCU.addUInt(Die, dwarf::DW_AT_GNU_dwo_id, dwarf::DW_FORM_data8,

1064

1066 ? dwarf::DW_AT_dwo_name

1067 : dwarf::DW_AT_GNU_dwo_name;

1069 }

1070 }

1071}

1072

1073

1075DwarfDebug::getOrCreateDwarfCompileUnit(const DICompileUnit *DIUnit) {

1076 if (auto *CU = CUMap.lookup(DIUnit))

1077 return *CU;

1078

1083 !CUMap.empty()) {

1084 return *CUMap.begin()->second;

1085 }

1087

1088 auto OwnedUnit = std::make_unique(

1089 InfoHolder.getUnits().size(), DIUnit, Asm, this, &InfoHolder);

1091 InfoHolder.addUnit(std::move(OwnedUnit));

1092

1093

1094

1095

1096

1097 if (Asm->OutStreamer->hasRawTextSupport() || SingleCU)

1101

1103 NewCU.setSkeleton(constructSkeletonCU(NewCU));

1105 } else {

1106 finishUnitAttributes(DIUnit, NewCU);

1108 }

1109

1110 CUMap.insert({DIUnit, &NewCU});

1111 CUDieMap.insert({&NewCU.getUnitDie(), &NewCU});

1112 return NewCU;

1113}

1114

1115

1120

1121

1122

1123

1124

1125 if (A.Expr || B.Expr)

1126 return !B.Expr;

1127 auto FragmentA = A.Expr->getFragmentInfo();

1128 auto FragmentB = B.Expr->getFragmentInfo();

1129 if (!FragmentA || !FragmentB)

1130 return !!FragmentB;

1131 return FragmentA->OffsetInBits < FragmentB->OffsetInBits;

1132 });

1136 return A.Expr == B.Expr;

1137 }),

1138 GVEs.end());

1139 return GVEs;

1140}

1141

1142

1143

1144

1147

1148 if (Asm)

1149 return;

1150

1151 unsigned NumDebugCUs = std::distance(M->debug_compile_units_begin(),

1152 M->debug_compile_units_end());

1153 if (NumDebugCUs == 0)

1154 return;

1155

1156 assert(NumDebugCUs > 0 && "Asm unexpectedly initialized");

1157 SingleCU = NumDebugCUs == 1;

1159 GVMap;

1162 Global.getDebugInfo(GVs);

1163 for (auto *GVE : GVs)

1164 GVMap[GVE->getVariable()].push_back({&Global, GVE->getExpression()});

1165 }

1166

1167

1168

1169

1173

1174

1175

1176

1181

1185 }

1186

1187

1188

1191

1192 for (DICompileUnit *CUNode : M->debug_compile_units()) {

1193 if (CUNode->getImportedEntities().empty() &&

1194 CUNode->getEnumTypes().empty() && CUNode->getRetainedTypes().empty() &&

1195 CUNode->getGlobalVariables().empty() && CUNode->getMacros().empty())

1196 continue;

1197

1199

1200

1201 for (auto *GVE : CUNode->getGlobalVariables()) {

1202

1203

1204

1205 auto &GVMapEntry = GVMap[GVE->getVariable()];

1206 auto *Expr = GVE->getExpression();

1207 if (!GVMapEntry.size() || (Expr && Expr->isConstant()))

1208 GVMapEntry.push_back({nullptr, Expr});

1209 }

1210

1212 for (auto *GVE : CUNode->getGlobalVariables()) {

1214 if (Processed.insert(GV).second)

1215 CU.getOrCreateGlobalVariableDIE(GV, sortGlobalExprs(GVMap[GV]));

1216 }

1217

1218 for (auto *Ty : CUNode->getEnumTypes())

1219 CU.getOrCreateTypeDIE(cast(Ty));

1220

1221 for (auto *Ty : CUNode->getRetainedTypes()) {

1222

1223

1224 if (DIType *RT = dyn_cast(Ty))

1225

1226 CU.getOrCreateTypeDIE(RT);

1227 }

1228 }

1229}

1230

1231void DwarfDebug::finishEntityDefinitions() {

1232 for (const auto &Entity : ConcreteEntities) {

1233 DIE *Die = Entity->getDIE();

1235

1236

1237

1240 Unit->finishEntityDefinition(Entity.get());

1241 }

1242}

1243

1244void DwarfDebug::finishSubprogramDefinitions() {

1245 for (const DISubprogram *SP : ProcessedSPNodes) {

1248 getOrCreateDwarfCompileUnit(SP->getUnit()),

1250 }

1251}

1252

1253void DwarfDebug::finalizeModuleInfo() {

1255

1256 finishSubprogramDefinitions();

1257

1258 finishEntityDefinitions();

1259

1260 bool HasEmittedSplitCU = false;

1261

1262

1263

1264 for (const auto &P : CUMap) {

1265 auto &TheCU = *P.second;

1266 if (TheCU.getCUNode()->isDebugDirectivesOnly())

1267 continue;

1268

1269

1270 TheCU.constructContainingTypeDIEs();

1271

1272

1273

1274

1275 auto *SkCU = TheCU.getSkeleton();

1276

1277 bool HasSplitUnit = SkCU && !TheCU.getUnitDie().children().empty();

1278

1279 if (HasSplitUnit) {

1280 (void)HasEmittedSplitCU;

1282 "Multiple CUs emitted into a single dwo file");

1283 HasEmittedSplitCU = true;

1285 ? dwarf::DW_AT_dwo_name

1286 : dwarf::DW_AT_GNU_dwo_name;

1287 finishUnitAttributes(TheCU.getCUNode(), TheCU);

1289 TheCU.addString(TheCU.getUnitDie(), attrDWOName, DWOName);

1290 SkCU->addString(SkCU->getUnitDie(), attrDWOName, DWOName);

1291

1292

1293

1294

1298 TheCU.setDWOId(ID);

1299 SkCU->setDWOId(ID);

1300 } else {

1301 TheCU.addUInt(TheCU.getUnitDie(), dwarf::DW_AT_GNU_dwo_id,

1302 dwarf::DW_FORM_data8, ID);

1303 SkCU->addUInt(SkCU->getUnitDie(), dwarf::DW_AT_GNU_dwo_id,

1304 dwarf::DW_FORM_data8, ID);

1305 }

1306

1309 SkCU->addSectionLabel(SkCU->getUnitDie(), dwarf::DW_AT_GNU_ranges_base,

1311 }

1312 } else if (SkCU) {

1313 finishUnitAttributes(SkCU->getCUNode(), *SkCU);

1314 }

1315

1316

1317

1318

1319

1320

1321

1323

1324 if (unsigned NumRanges = TheCU.getRanges().size()) {

1325

1326

1327

1328

1331

1332

1333

1334

1335 U.addUInt(U.getUnitDie(), dwarf::DW_AT_low_pc, dwarf::DW_FORM_addr,

1336 0);

1337 else

1338 U.setBaseAddress(TheCU.getRanges().front().Begin);

1339 U.attachRangesOrLowHighPC(U.getUnitDie(), TheCU.takeRanges());

1340 }

1341 }

1342

1343

1344

1346 U.addAddrTableBase();

1347

1349 if (U.hasRangeLists())

1350 U.addRnglistsBase();

1351

1353 U.addSectionLabel(U.getUnitDie(), dwarf::DW_AT_loclists_base,

1356 }

1357 }

1358

1359 auto *CUNode = cast(P.first);

1360

1361

1362 if (CUNode->getMacros()) {

1363 if (UseDebugMacroSection) {

1365 TheCU.addSectionDelta(

1366 TheCU.getUnitDie(), dwarf::DW_AT_macros, U.getMacroLabelBegin(),

1368 else {

1370 ? dwarf::DW_AT_macros

1371 : dwarf::DW_AT_GNU_macros;

1372 U.addSectionLabel(U.getUnitDie(), MacrosAttr, U.getMacroLabelBegin(),

1374 }

1375 } else {

1377 TheCU.addSectionDelta(

1378 TheCU.getUnitDie(), dwarf::DW_AT_macro_info,

1379 U.getMacroLabelBegin(),

1381 else

1382 U.addSectionLabel(U.getUnitDie(), dwarf::DW_AT_macro_info,

1383 U.getMacroLabelBegin(),

1385 }

1386 }

1387 }

1388

1389

1391 if (CUNode->getDWOId())

1392 getOrCreateDwarfCompileUnit(CUNode);

1393

1394

1398

1399

1400

1402}

1403

1404

1406

1407 if (PrevCU)

1409 PrevCU = nullptr;

1410 assert(CurFn == nullptr);

1412

1413 for (const auto &P : CUMap) {

1414 const auto *CUNode = cast(P.first);

1416

1417

1418 for (auto *IE : CUNode->getImportedEntities()) {

1419 assert(!isa_and_nonnull(IE->getScope()) &&

1420 "Unexpected function-local entity in 'imports' CU field.");

1421 CU->getOrCreateImportedEntityDIE(IE);

1422 }

1423 for (const auto *D : CU->getDeferredLocalDecls()) {

1424 if (auto *IE = dyn_cast(D))

1425 CU->getOrCreateImportedEntityDIE(IE);

1426 else

1428 }

1429

1430

1431 CU->createBaseTypeDIEs();

1432 }

1433

1434

1435

1437 return;

1438

1439

1440 finalizeModuleInfo();

1441

1443

1444 emitDebugLocDWO();

1445 else

1446

1447 emitDebugLoc();

1448

1449

1450 emitAbbreviations();

1451

1452

1453 emitDebugInfo();

1454

1455

1456 if (UseARangesSection)

1457 emitDebugARanges();

1458

1459

1460 emitDebugRanges();

1461

1463

1464 emitDebugMacinfoDWO();

1465 else

1466

1467 emitDebugMacinfo();

1468

1469 emitDebugStr();

1470

1472 emitDebugStrDWO();

1473 emitDebugInfoDWO();

1474 emitDebugAbbrevDWO();

1475 emitDebugLineDWO();

1476 emitDebugRangesDWO();

1477 }

1478

1479 emitDebugAddr();

1480

1481

1484 emitAccelNames();

1485 emitAccelObjC();

1486 emitAccelNamespaces();

1487 emitAccelTypes();

1488 break;

1490 emitAccelDebugNames();

1491 break;

1493 break;

1495 llvm_unreachable("Default should have already been resolved.");

1496 }

1497

1498

1499 emitDebugPubSections();

1500

1501

1502

1503}

1504

1505void DwarfDebug::ensureAbstractEntityIsCreatedIfScoped(DwarfCompileUnit &CU,

1506 const DINode *Node, const MDNode *ScopeNode) {

1507 if (CU.getExistingAbstractEntity(Node))

1508 return;

1509

1512 CU.createAbstractEntity(Node, Scope);

1513}

1514

1517 if (const auto *LV = dyn_cast(N))

1519 else if (const auto *L = dyn_cast(N))

1520 S = L->getScope();

1521 else if (const auto *IE = dyn_cast(N))

1522 S = IE->getScope();

1523 else

1525

1526

1527 return cast(S)->getNonLexicalBlockFileScope();

1528}

1529

1530

1531void DwarfDebug::collectVariableInfoFromMFTable(

1534 LLVM_DEBUG(dbgs() << "DwarfDebug: collecting variables from MF side table\n");

1536 if (VI.Var)

1537 continue;

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

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

1540

1541 InlinedEntity Var(VI.Var, VI.Loc->getInlinedAt());

1542 Processed.insert(Var);

1544

1545

1546 if (!Scope) {

1547 LLVM_DEBUG(dbgs() << "Dropping debug info for " << VI.Var->getName()

1548 << ", no variable scope found\n");

1549 continue;

1550 }

1551

1552 ensureAbstractEntityIsCreatedIfScoped(TheCU, Var.first, Scope->getScopeNode());

1553

1554

1555

1557 auto *PreviousMMI = std::get_ifLoc::MMI(PreviousLoc);

1558 auto *PreviousEntryValue = std::get_ifLoc::EntryValue(PreviousLoc);

1559

1560 if (PreviousMMI && VI.inStackSlot())

1561 PreviousMMI->addFrameIndexExpr(VI.Expr, VI.getStackSlot());

1562

1563 else if (PreviousEntryValue && VI.inEntryValueRegister())

1564 PreviousEntryValue->addExpr(VI.getEntryValueRegister(), *VI.Expr);

1565 else {

1566

1567

1568

1569 if (PreviousLoc->holds<Loc::MMI>())

1570 PreviousLoc->emplace<Loc::EntryValue>(VI.getEntryValueRegister(),

1571 *VI.Expr);

1572 LLVM_DEBUG(dbgs() << "Dropping debug info for " << VI.Var->getName()

1573 << ", conflicting fragment location types\n");

1574 }

1575 continue;

1576 }

1577

1578 auto RegVar = std::make_unique(

1579 cast(Var.first), Var.second);

1580 if (VI.inStackSlot())

1581 RegVar->emplace<Loc::MMI>(VI.Expr, VI.getStackSlot());

1582 else

1584 LLVM_DEBUG(dbgs() << "Created DbgVariable for " << VI.Var->getName()

1585 << "\n");

1587 MFVars.insert({Var, RegVar.get()});

1588 ConcreteEntities.push_back(std::move(RegVar));

1589 }

1590}

1591

1592

1593

1594

1595

1600 assert(DbgValue->getDebugLoc() && "DBG_VALUE without a debug location");

1604

1605 if (!LScope)

1606 return false;

1607 auto &LSRange = LScope->getRanges();

1608 if (LSRange.size() == 0)

1609 return false;

1610

1611 const MachineInstr *LScopeBegin = LSRange.front().first;

1612

1613

1614

1615 if (!Ordering.isBefore(DbgValue, LScopeBegin)) {

1616

1618 return false;

1619

1621 for (++Pred; Pred != MBB->rend(); ++Pred) {

1623 break;

1624 auto PredDL = Pred->getDebugLoc();

1625 if (!PredDL || Pred->isMetaInstruction())

1626 continue;

1627

1628

1629 if (DL->getScope() == PredDL->getScope())

1630 return false;

1632 if (!PredScope || LScope->dominates(PredScope))

1633 return false;

1634 }

1635 }

1636

1637

1638 if (!RangeEnd)

1639 return true;

1640

1641

1642

1643

1644

1648 return true;

1649

1650

1651 const MachineInstr *LScopeEnd = LSRange.back().second;

1652 if (Ordering.isBefore(RangeEnd, LScopeEnd))

1653 return false;

1654

1655

1656

1657 return true;

1658}

1659

1660

1661

1662

1663

1664

1665

1666

1667

1668

1669

1670

1671

1672

1673

1674

1675

1676

1677

1678

1679

1680

1681

1682

1683

1684

1685

1686

1687

1688

1689

1690

1691

1692

1695 using OpenRange =

1696 std::pair<DbgValueHistoryMap::EntryIndex, DbgValueLoc>;

1698 bool isSafeForSingleLocation = true;

1701

1702 for (auto EB = Entries.begin(), EI = EB, EE = Entries.end(); EI != EE; ++EI) {

1704

1705

1706 size_t Index = std::distance(EB, EI);

1707 erase_if(OpenRanges, [&](OpenRange &R) { return R.first <= Index; });

1708

1709

1710

1711 const MCSymbol *StartLabel =

1713 assert(StartLabel &&

1714 "Forgot label before/after instruction starting a range!");

1715

1717 if (std::next(EI) == Entries.end()) {

1720 if (EI->isClobber())

1721 EndMI = EI->getInstr();

1722 }

1723 else if (std::next(EI)->isClobber())

1725 else

1727 assert(EndLabel && "Forgot label after instruction ending a range!");

1728

1729 if (EI->isDbgValue())

1730 LLVM_DEBUG(dbgs() << "DotDebugLoc: " << *Instr << "\n");

1731

1732

1733

1734

1735 if (EI->isDbgValue()) {

1736

1737

1738

1739

1740

1741

1742 if (Instr->isUndefDebugValue()) {

1745

1746

1747 if (Instr->getDebugExpression()->isFragment())

1748 isSafeForSingleLocation = false;

1749

1750 if (!StartDebugMI)

1751 StartDebugMI = Instr;

1752 } else {

1753 isSafeForSingleLocation = false;

1754 }

1755 }

1756

1757

1758

1759 if (OpenRanges.empty())

1760 continue;

1761

1762

1763 if (StartLabel == EndLabel) {

1764 LLVM_DEBUG(dbgs() << "Omitting location list entry with empty range.\n");

1765 continue;

1766 }

1767

1769 for (auto &R : OpenRanges)

1771

1772

1773

1774

1775

1776

1779 for (const auto &[MBBSectionId, MBBSectionRange] :

1781 if (Instr->getParent()->getSectionID() == MBBSectionId) {

1782 DebugLoc.emplace_back(MBBSectionRange.BeginLabel, EndLabel, Values);

1783 break;

1784 }

1785 DebugLoc.emplace_back(MBBSectionRange.BeginLabel,

1786 MBBSectionRange.EndLabel, Values);

1787 }

1788 } else {

1789 DebugLoc.emplace_back(StartLabel, EndLabel, Values);

1790 }

1791

1792

1793

1794 auto CurEntry = DebugLoc.rbegin();

1796 dbgs() << CurEntry->getValues().size() << " Values:\n";

1797 for (auto &Value : CurEntry->getValues())

1799 dbgs() << "-----\n";

1800 });

1801

1802 auto PrevEntry = std::next(CurEntry);

1803 if (PrevEntry != DebugLoc.rend() && PrevEntry->MergeRanges(*CurEntry))

1805 }

1806

1807 if (!isSafeForSingleLocation ||

1809 return false;

1810

1812 return true;

1813

1815 return false;

1816

1817

1818

1819

1820

1821

1825 else

1826 RangeMBB = Entries.begin()->getInstr()->getParent();

1829 "Range MBB not found in MBBSectionRanges!");

1830 auto *CurEntry = DebugLoc.begin();

1831 auto *NextEntry = std::next(CurEntry);

1832 auto NextRangeIt = std::next(RangeIt);

1833 while (NextEntry != DebugLoc.end()) {

1835 return false;

1836

1837

1838

1839

1840

1842 CurEntry->getEndSym() != RangeIt->second.EndLabel) ||

1843 NextEntry->getBeginSym() != NextRangeIt->second.BeginLabel ||

1844 CurEntry->getValues() != NextEntry->getValues())

1845 return false;

1846 RangeIt = NextRangeIt;

1847 NextRangeIt = std::next(RangeIt);

1848 CurEntry = NextEntry;

1849 NextEntry = std::next(CurEntry);

1850 }

1851 return true;

1852}

1853

1859 ensureAbstractEntityIsCreatedIfScoped(TheCU, Node, Scope.getScopeNode());

1860 if (isa(Node)) {

1861 ConcreteEntities.push_back(

1862 std::make_unique(cast(Node),

1863 Location));

1865 cast(ConcreteEntities.back().get()));

1866 } else if (isa(Node)) {

1867 ConcreteEntities.push_back(

1868 std::make_unique(cast(Node),

1869 Location, Sym));

1871 cast(ConcreteEntities.back().get()));

1872 }

1873 return ConcreteEntities.back().get();

1874}

1875

1876

1880

1881 collectVariableInfoFromMFTable(TheCU, Processed);

1882

1884 InlinedEntity IV = I.first;

1885 if (Processed.count(IV))

1886 continue;

1887

1888

1889 const auto &HistoryMapEntries = I.second;

1890

1891

1892

1894 continue;

1895

1900 else

1902

1903 if (!Scope)

1904 continue;

1905

1907 DbgVariable *RegVar = cast(createConcreteEntity(TheCU,

1908 *Scope, LocalVar, IV.second));

1909

1910 const MachineInstr *MInsn = HistoryMapEntries.front().getInstr();

1911 assert(MInsn->isDebugValue() && "History must begin with debug value");

1912

1913

1914

1915

1916 size_t HistSize = HistoryMapEntries.size();

1917 bool SingleValueWithClobber =

1918 HistSize == 2 && HistoryMapEntries[1].isClobber();

1919 if (HistSize == 1 || SingleValueWithClobber) {

1920 const auto *End =

1921 SingleValueWithClobber ? HistoryMapEntries[1].getInstr() : nullptr;

1924 continue;

1925 }

1926 }

1927

1928

1930

1931

1933 bool isValidSingleLocation = buildLocationList(Entries, HistoryMapEntries);

1934

1935

1936

1937

1938 if (isValidSingleLocation) {

1939 RegVar->emplace<Loc::Single>(Entries[0].getValues()[0]);

1940 continue;

1941 }

1942

1943

1944

1945

1948

1949

1950 for (auto &Entry : Entries)

1952 }

1953

1954

1955

1957 InlinedEntity IL = I.first;

1959 if (MI == nullptr)

1960 continue;

1961

1963 const DILabel *Label = cast(IL.first);

1964

1966 Label->getScope()->getNonLexicalBlockFileScope();

1967

1968 if (const DILocation *IA = IL.second)

1970 else

1972

1973 if (!Scope)

1974 continue;

1975

1976 Processed.insert(IL);

1977

1978

1979

1981 createConcreteEntity(TheCU, *Scope, Label, IL.second, Sym);

1982 }

1983

1984

1985 for (const DINode *DN : SP->getRetainedNodes()) {

1987 if (isa(DN) || isa(DN)) {

1988 if (!Processed.insert(InlinedEntity(DN, nullptr)).second)

1989 continue;

1991 if (LexS)

1992 createConcreteEntity(TheCU, *LexS, DN, nullptr);

1993 } else {

1994 LocalDeclsPerLS[LS].insert(DN);

1995 }

1996 }

1997}

1998

1999

2003 bool NoDebug =

2005

2006

2007 auto delaySlotSupported = [](const MachineInstr &MI) {

2008 if (MI.isBundledWithSucc())

2009 return false;

2010 auto Suc = std::next(MI.getIterator());

2011 (void)Suc;

2012

2013

2014

2015 assert(Suc->isBundledWithPred() &&

2016 "Call bundle instructions are out of order");

2017 return true;

2018 };

2019

2020

2021 if (!NoDebug && SP->areAllCallsDescribed() &&

2023 (MI->hasDelaySlot() || delaySlotSupported(*MI))) {

2026

2027

2028 if (IsTail)

2030

2031

2032

2034 }

2035

2038 return;

2039

2040 if (NoDebug)

2041 return;

2042

2043

2044

2045

2047 return;

2049 unsigned Flags = 0;

2050

2054

2057 }

2058 }

2059

2060

2061

2062 unsigned LastAsmLine =

2063 Asm->OutStreamer->getContext().getCurrentDwarfLoc().getLine();

2064

2066

2067

2068

2069 assert(MI->getParent() == &*MI->getMF()->begin());

2070 recordSourceLine(SP->getScopeLine(), 0, SP,

2072 return;

2073 }

2074

2075 bool PrevInstInSameSection =

2078 bool ForceIsStmt = ForceIsStmtInstrs.contains(MI);

2079 if (DL == PrevInstLoc && PrevInstInSameSection && !ForceIsStmt) {

2080

2081 if (DL)

2082 return;

2083

2084

2085 if ((LastAsmLine == 0 && DL.getLine() != 0) || Flags) {

2086

2087 const MDNode *Scope = DL.getScope();

2088 recordSourceLine(DL.getLine(), DL.getCol(), Scope, Flags);

2089 }

2090 return;

2091 }

2092

2093 if (DL) {

2094

2095

2096 if (LastAsmLine == 0)

2097 return;

2098

2100 return;

2101

2102

2103

2104

2105

2106

2107

2110

2111

2112

2113 const MDNode *Scope = nullptr;

2114 unsigned Column = 0;

2118 }

2119 recordSourceLine(0, Column, Scope, 0);

2120 }

2121 return;

2122 }

2123

2124

2125

2126

2127 if (DL.getLine() == 0 && LastAsmLine == 0)

2128 return;

2132 }

2133

2134

2136 if (DL.getLine() && (DL.getLine() != OldLine || ForceIsStmt))

2138

2139 const MDNode *Scope = DL.getScope();

2140 recordSourceLine(DL.getLine(), DL.getCol(), Scope, Flags);

2141

2142

2143 if (DL.getLine())

2145}

2146

2147static std::pair<const MachineInstr *, bool>

2149

2150

2152 const MachineInstr *NonTrivialInst = nullptr;

2154

2155

2156

2157 bool IsEmptyPrologue =

2158 !(F.hasPrologueData() || F.getMetadata(LLVMContext::MD_func_sanitize));

2159

2160

2161

2163 -> std::optional<std::pair<const MachineInstr *, bool>> {

2164

2166 bool isTrivRemat = TII.isTriviallyReMaterializable(MI);

2168

2169 if (!isFrameSetup && MI.getDebugLoc()) {

2170

2171

2172

2173

2174

2175 if (MI.getDebugLoc().getLine())

2176 return std::make_pair(&MI, IsEmptyPrologue);

2177 }

2178

2179

2180

2181 if (isCopy && !isTrivRemat && !isFrameSetup && !NonTrivialInst)

2182 NonTrivialInst = &MI;

2183

2184 IsEmptyPrologue = false;

2185 return std::nullopt;

2186 };

2187

2188

2189

2190

2191

2192

2193 auto CurBlock = MF->begin();

2194 auto CurInst = CurBlock->begin();

2195

2196

2197

2198 while (CurBlock->empty())

2199 CurInst = (++CurBlock)->begin();

2200 assert(CurInst != CurBlock->end());

2201

2202

2203

2204 auto getNextInst = [&CurBlock, &CurInst, MF]() -> bool {

2205

2206 if (CurInst->isTerminator()) {

2207

2208

2209

2210 return false;

2211 }

2212

2213

2214

2215 if (CurBlock->pred_size() > 1)

2216 return false;

2217

2218

2219

2220

2221

2222

2223

2224 do {

2225 ++CurBlock;

2226 if (CurBlock == MF->end())

2227 return false;

2228 } while (CurBlock->empty());

2229 CurInst = CurBlock->begin();

2230 return true;

2231 };

2232

2233 while (true) {

2234

2235 if (!CurInst->isMetaInstruction()) {

2236 auto FoundInst = ExamineInst(*CurInst);

2237 if (FoundInst)

2238 return *FoundInst;

2239 }

2240

2241

2242

2243 auto NextInst = std::next(CurInst);

2244 if (NextInst != CurInst->getParent()->end()) {

2245

2246 CurInst = NextInst;

2247 continue;

2248 }

2249

2250 if (!getNextInst())

2251 break;

2252 }

2253

2254

2255

2256

2257

2258

2259

2260

2261 if (NonTrivialInst && NonTrivialInst->getParent() == &*MF->begin()) {

2262 IsEmptyPrologue = NonTrivialInst == &*MF->begin()->begin();

2263 return std::make_pair(NonTrivialInst, IsEmptyPrologue);

2264 }

2265

2266

2267 return std::make_pair(nullptr, IsEmptyPrologue);

2268}

2269

2270

2271

2273 const MDNode *S, unsigned Flags, unsigned CUID,

2275 ArrayRef<std::unique_ptr> DCUs) {

2277 unsigned FileNo = 1;

2278 unsigned Discriminator = 0;

2279 if (auto *Scope = cast_or_null(S)) {

2280 Fn = Scope->getFilename();

2281 if (Line != 0 && DwarfVersion >= 4)

2282 if (auto *LBF = dyn_cast(Scope))

2283 Discriminator = LBF->getDiscriminator();

2284

2286 .getOrCreateSourceID(Scope->getFile());

2287 }

2288 Asm.OutStreamer->emitDwarfLocDirective(FileNo, Line, Col, Flags, 0,

2289 Discriminator, Fn);

2290}

2291

2294

2296 return nullptr;

2297

2298 std::pair<const MachineInstr *, bool> PrologEnd = findPrologueEndLoc(&MF);

2300 bool IsEmptyPrologue = PrologEnd.second;

2301

2302

2303 if (IsEmptyPrologue) {

2304

2305

2307

2308

2309

2311 if (DL || DL->getLine() != 0)

2313

2314

2316 }

2317 }

2318

2319

2320

2322 (void)getOrCreateDwarfCompileUnit(SP->getUnit());

2323

2324

2328}

2329

2330

2331

2332

2333

2334void DwarfDebug::findForceIsStmtInstrs(const MachineFunction *MF) {

2335 ForceIsStmtInstrs.clear();

2336

2337

2338

2339

2340

2341

2342

2343

2344

2345

2346

2347

2348

2349

2350

2351

2352

2353

2354

2355

2356

2357

2358

2359

2360

2361

2362

2364

2365

2366

2369

2370

2373 continue;

2374 for (auto &MI : MBB) {

2375 if (MI.getDebugLoc() && MI.getDebugLoc()->getLine()) {

2377 PredMBBsToExamine.insert(Pred);

2378 PotentialIsStmtMBBInstrs.insert({&MBB, &MI});

2379 break;

2380 }

2381 }

2382 }

2383

2384

2385

2386

2387

2388

2389 for (auto *MBB : PredMBBsToExamine) {

2390 auto CheckMBBEdge = [&](MachineBasicBlock *Succ, unsigned OutgoingLine) {

2391 auto MBBInstrIt = PotentialIsStmtMBBInstrs.find(Succ);

2392 if (MBBInstrIt == PotentialIsStmtMBBInstrs.end())

2393 return;

2395 if (MI->getDebugLoc()->getLine() == OutgoingLine)

2396 return;

2397 PotentialIsStmtMBBInstrs.erase(MBBInstrIt);

2398 ForceIsStmtInstrs.insert(MI);

2399 };

2400

2401

2402

2405 CheckMBBEdge(Succ, 0);

2406 continue;

2407 }

2408

2409

2411 return PotentialIsStmtMBBInstrs.contains(SuccMBB);

2412 }))

2413 continue;

2414

2415

2418 {

2422

2423

2424

2425

2426 if (!AnalyzeFailed && Cond.empty() && FBB != nullptr &&

2429 assert(MIIt->isBranch() && "Bad result from analyzeBranch?");

2430 CheckMBBEdge(FBB, FBBLine);

2431 ++MIIt;

2433 } else {

2434

2436 }

2437 }

2438

2439

2440

2441

2442

2443

2444

2445

2446

2447

2448

2449

2450

2451

2452

2453

2454 unsigned LastLine = 0;

2455 while (MIIt != MBB->rend()) {

2456 if (auto DL = MIIt->getDebugLoc(); DL && DL->getLine()) {

2457 LastLine = DL->getLine();

2458 break;

2459 }

2460 ++MIIt;

2461 }

2462 for (auto *Succ : SuccessorBBs)

2463 CheckMBBEdge(Succ, LastLine);

2464 }

2465}

2466

2467

2468

2470 CurFn = MF;

2471

2475 return;

2476

2478 FunctionLineTableLabel = CU.emitFuncLineTableOffsets()

2480 : nullptr;

2481

2482 Asm->OutStreamer->getContext().setDwarfCompileUnitID(

2484

2485

2487 *MF, Asm->OutStreamer->getContext().getDwarfCompileUnitID());

2488

2489 findForceIsStmtInstrs(MF);

2490}

2491

2492unsigned

2494

2495

2496

2498

2499 return 0;

2500 else

2501 return CU.getUniqueID();

2502}

2503

2505 const auto &CURanges = CU->getRanges();

2506 auto &LineTable = Asm->OutStreamer->getContext().getMCDwarfLineTable(

2508

2509 LineTable.getMCLineSections().addEndEntry(

2510 const_cast<MCSymbol *>(CURanges.back().End));

2511}

2512

2514

2515

2516

2517

2518 if (PrevCU)

2520 PrevCU = nullptr;

2521 CurFn = nullptr;

2522}

2523

2524

2527

2528 assert(CurFn == MF &&

2529 "endFunction should be called with the same function as beginFunction");

2530

2531

2532 Asm->OutStreamer->getContext().setDwarfCompileUnitID(0);

2533

2536 DwarfCompileUnit &TheCU = getOrCreateDwarfCompileUnit(SP->getUnit());

2539 CurFn = nullptr;

2540 return;

2541 }

2542

2544 collectEntityInfo(TheCU, SP, Processed);

2545

2546

2547

2549 TheCU.addRange({R.second.BeginLabel, R.second.EndLabel});

2550

2551

2552

2553

2559

2562 CurFn = nullptr;

2563 return;

2564 }

2565

2566#ifndef NDEBUG

2568#endif

2570 const auto *SP = cast(AScope->getScopeNode());

2571 for (const DINode *DN : SP->getRetainedNodes()) {

2573

2575 assert(LexS && "Expected the LexicalScope to be created.");

2576 if (isa(DN) || isa(DN)) {

2577

2578 if (!Processed.insert(InlinedEntity(DN, nullptr)).second ||

2580 continue;

2582 } else {

2583

2584 LocalDeclsPerLS[LS].insert(DN);

2585 }

2588 "getOrCreateAbstractScope() inserted an abstract subprogram scope");

2589 }

2590 constructAbstractSubprogramScopeDIE(TheCU, AScope);

2591 }

2592

2593 ProcessedSPNodes.insert(SP);

2594 DIE &ScopeDIE =

2599 SkelCU->constructSubprogramScopeDIE(SP, FnScope, FunctionLineTableLabel);

2600

2601 FunctionLineTableLabel = nullptr;

2602

2603

2604 constructCallSiteEntryDIEs(*SP, TheCU, ScopeDIE, *MF);

2605

2606

2607

2608

2609

2612 LocalDeclsPerLS.clear();

2614 CurFn = nullptr;

2615}

2616

2617

2618

2619void DwarfDebug::recordSourceLine(unsigned Line, unsigned Col, const MDNode *S,

2620 unsigned Flags) {

2621 ::recordSourceLine(*Asm, Line, Col, S, Flags,

2622 Asm->OutStreamer->getContext().getDwarfCompileUnitID(),

2624}

2625

2626

2627

2628

2629

2630

2631void DwarfDebug::emitDebugInfo() {

2633 Holder.emitUnits( false);

2634}

2635

2636

2637void DwarfDebug::emitAbbreviations() {

2639

2641}

2642

2643void DwarfDebug::emitStringOffsetsTableHeader() {

2648}

2649

2650template

2651void DwarfDebug::emitAccel(AccelTableT &Accel, MCSection *Section,

2654

2655

2657}

2658

2659void DwarfDebug::emitAccelDebugNames() {

2660

2661 if (getUnits().empty())

2662 return;

2663

2665}

2666

2667

2668void DwarfDebug::emitAccelNames() {

2670 "Names");

2671}

2672

2673

2674

2675void DwarfDebug::emitAccelObjC() {

2677 "ObjC");

2678}

2679

2680

2681void DwarfDebug::emitAccelNamespaces() {

2682 emitAccel(AccelNamespace,

2684 "namespac");

2685}

2686

2687

2688void DwarfDebug::emitAccelTypes() {

2690 "types");

2691}

2692

2693

2694

2695

2696

2697

2698

2699

2700

2701

2702

2703

2704

2705

2706

2707

2709 const DIE *Die) {

2710

2711

2712

2713

2714

2715

2716

2717

2718

2719 if (Die->getTag() == dwarf::DW_TAG_compile_unit)

2723

2724

2725

2727 DIE &SpecDIE = SpecVal.getDIEEntry().getEntry();

2728 if (SpecDIE.findAttribute(dwarf::DW_AT_external))

2730 } else if (Die->findAttribute(dwarf::DW_AT_external))

2732

2733 switch (Die->getTag()) {

2734 case dwarf::DW_TAG_class_type:

2735 case dwarf::DW_TAG_structure_type:

2736 case dwarf::DW_TAG_union_type:

2737 case dwarf::DW_TAG_enumeration_type:

2743 case dwarf::DW_TAG_typedef:

2744 case dwarf::DW_TAG_base_type:

2745 case dwarf::DW_TAG_subrange_type:

2746 case dwarf::DW_TAG_template_alias:

2748 case dwarf::DW_TAG_namespace:

2750 case dwarf::DW_TAG_subprogram:

2752 case dwarf::DW_TAG_variable:

2754 case dwarf::DW_TAG_enumerator:

2757 default:

2759 }

2760}

2761

2762

2763

2764void DwarfDebug::emitDebugPubSections() {

2765 for (const auto &NU : CUMap) {

2768 continue;

2769

2772

2776 emitDebugPubSection(GnuStyle, "Names", TheU, TheU->getGlobalNames());

2777

2781 emitDebugPubSection(GnuStyle, "Types", TheU, TheU->getGlobalTypes());

2782 }

2783}

2784

2788 CU.getDebugSectionOffset());

2789 else

2791}

2792

2793void DwarfDebug::emitDebugPubSection(bool GnuStyle, StringRef Name,

2798

2799

2801 "pub" + Name, "Length of Public " + Name + " Info");

2802

2805

2806 Asm->OutStreamer->AddComment("Offset of Compilation Unit Info");

2807 emitSectionReference(*TheU);

2808

2809 Asm->OutStreamer->AddComment("Compilation Unit Length");

2811

2812

2814 for (const auto &GI : Globals)

2817 return A.second->getOffset() < B.second->getOffset();

2818 });

2819 for (const auto &[Name, Entity] : Vec) {

2822

2823 if (GnuStyle) {

2829 }

2830

2833 }

2834

2838}

2839

2840

2841void DwarfDebug::emitDebugStr() {

2842 MCSection *StringOffsetsSection = nullptr;

2844 emitStringOffsetsTableHeader();

2846 }

2849 StringOffsetsSection, true);

2850}

2851

2855 auto &&Comments = DebugLocs.getComments(Entry);

2856 auto Comment = Comments.begin();

2857 auto End = Comments.end();

2858

2859

2860

2861

2862

2863

2869

2872 for (const auto &Op : Expr) {

2874 "3 operand ops not yet supported");

2882

2883 for (unsigned J = 0; J < Length; ++J)

2884 if (Comment != End)

2885 Comment++;

2886 } else {

2888 Streamer.emitInt8(Data.getData()[J], Comment != End ? *(Comment++) : "");

2889 }

2891 }

2893 }

2894}

2895

2899 auto *DIExpr = Value.getExpression();

2902

2903

2904

2905 if (DIExpr && DIExpr->isEntryValue()) {

2906

2907

2908 assert(Value.getLocEntries().size() == 1);

2909 assert(Value.getLocEntries()[0].isLocation());

2911 DwarfExpr.setLocation(Location, DIExpr);

2912

2914

2917 return;

2918 return DwarfExpr.addExpression(std::move(ExprCursor));

2919 }

2920

2921

2922 auto EmitValueLocEntry = [&DwarfExpr, &BT,

2925 if (Entry.isInt()) {

2926 if (BT && (BT->getEncoding() == dwarf::DW_ATE_signed ||

2927 BT->getEncoding() == dwarf::DW_ATE_signed_char))

2929 else

2931 } else if (Entry.isLocation()) {

2933 if (Location.isIndirect())

2935

2938 return false;

2939 } else if (Entry.isTargetIndexLocation()) {

2941

2942

2945 } else if (Entry.isConstantFP()) {

2947 !Cursor) {

2948 DwarfExpr.addConstantFP(Entry.getConstantFP()->getValueAPF(), AP);

2949 } else if (Entry.getConstantFP()

2950 ->getValueAPF()

2951 .bitcastToAPInt()

2952 .getBitWidth() <= 64 ) {

2954 Entry.getConstantFP()->getValueAPF().bitcastToAPInt());

2955 } else {

2957 dbgs() << "Skipped DwarfExpression creation for ConstantFP of size"

2958 << Entry.getConstantFP()

2959 ->getValueAPF()

2960 .bitcastToAPInt()

2961 .getBitWidth()

2962 << " bits\n");

2963 return false;

2964 }

2965 }

2966 return true;

2967 };

2968

2969 if (Value.isVariadic()) {

2970 if (!EmitValueLocEntry(Value.getLocEntries()[0], ExprCursor))

2971 return;

2973 return;

2974 }

2975

2976

2977

2979 return Entry.isLocation() && !Entry.getLoc().getReg();

2980 }))

2981 return;

2982

2984 std::move(ExprCursor),

2985 [EmitValueLocEntry, &Value](unsigned Idx,

2987 return EmitValueLocEntry(Value.getLocEntries()[Idx], Cursor);

2988 });

2989}

2990

2996 "location list entries without values are redundant");

2997 assert(Begin != End && "unexpected location list entry with empty range");

3002 if (Value.isFragment()) {

3003

3005 return P.isFragment();

3006 }) && "all values are expected to be fragments");

3008

3009 for (const auto &Fragment : Values)

3011

3012 } else {

3013 assert(Values.size() == 1 && "only fragments may have >1 value");

3015 }

3019}

3020

3023

3027 else if (DebugLocs.getBytes(Entry).size() <= std::numeric_limits<uint16_t>::max())

3029 else {

3030

3031

3033 return;

3034 }

3035

3038}

3039

3040

3041

3042

3046

3047 Asm->OutStreamer->AddComment("Offset entry count");

3050

3053 Asm->getDwarfOffsetByteSize());

3054

3055 return TableEnd;

3056}

3057

3058

3059

3060

3064

3066

3067 Asm->OutStreamer->AddComment("Offset entry count");

3068 Asm->emitInt32(DebugLocs.getLists().size());

3069 Asm->OutStreamer->emitLabel(DebugLocs.getSym());

3070

3071 for (const auto &List : DebugLocs.getLists())

3072 Asm->emitLabelDifference(List.Label, DebugLocs.getSym(),

3073 Asm->getDwarfOffsetByteSize());

3074

3075 return TableEnd;

3076}

3077

3078template <typename Ranges, typename PayloadEmitter>

3081 const DwarfCompileUnit &CU, unsigned BaseAddressx, unsigned OffsetPair,

3082 unsigned StartxLength, unsigned EndOfList,

3083 StringRef (*StringifyEnum)(unsigned),

3084 bool ShouldUseBaseAddress,

3085 PayloadEmitter EmitPayload) {

3086

3087 auto Size = Asm->MAI->getCodePointerSize();

3089

3090

3091 Asm->OutStreamer->emitLabel(Sym);

3092

3093

3094

3096 SectionRanges;

3097

3098 for (const auto &Range : R)

3099 SectionRanges[&Range.Begin->getSection()].push_back(&Range);

3100

3101 const MCSymbol *CUBase = CU.getBaseAddress();

3102 bool BaseIsSet = false;

3103 for (const auto &P : SectionRanges) {

3104 auto *Base = CUBase;

3105 if ((Asm->TM.getTargetTriple().isNVPTX() && DD.tuneForGDB())) {

3106

3107

3108

3109

3110

3111

3112

3113 BaseIsSet = false;

3114 Base = nullptr;

3115 } else if (Base && ShouldUseBaseAddress) {

3116 const MCSymbol *Begin = P.second.front()->Begin;

3118 if (!UseDwarf5) {

3119 Base = NewBase;

3120 BaseIsSet = true;

3121 Asm->OutStreamer->emitIntValue(-1, Size);

3122 Asm->OutStreamer->AddComment(" base address");

3123 Asm->OutStreamer->emitSymbolValue(Base, Size);

3124 } else if (NewBase != Begin || P.second.size() > 1) {

3125

3126

3127

3128 Base = NewBase;

3129 BaseIsSet = true;

3130 Asm->OutStreamer->AddComment(StringifyEnum(BaseAddressx));

3131 Asm->emitInt8(BaseAddressx);

3132 Asm->OutStreamer->AddComment(" base address index");

3134 }

3135 } else if (BaseIsSet && !UseDwarf5) {

3136 BaseIsSet = false;

3138 Asm->OutStreamer->emitIntValue(-1, Size);

3139 Asm->OutStreamer->emitIntValue(0, Size);

3140 }

3141

3142 for (const auto *RS : P.second) {

3143 const MCSymbol *Begin = RS->Begin;

3145 assert(Begin && "Range without a begin symbol?");

3146 assert(End && "Range without an end symbol?");

3148 if (UseDwarf5) {

3149

3150 Asm->OutStreamer->AddComment(StringifyEnum(OffsetPair));

3151 Asm->emitInt8(OffsetPair);

3152 Asm->OutStreamer->AddComment(" starting offset");

3153 Asm->emitLabelDifferenceAsULEB128(Begin, Base);

3154 Asm->OutStreamer->AddComment(" ending offset");

3155 Asm->emitLabelDifferenceAsULEB128(End, Base);

3156 } else {

3157 Asm->emitLabelDifference(Begin, Base, Size);

3158 Asm->emitLabelDifference(End, Base, Size);

3159 }

3160 } else if (UseDwarf5) {

3161 Asm->OutStreamer->AddComment(StringifyEnum(StartxLength));

3162 Asm->emitInt8(StartxLength);

3163 Asm->OutStreamer->AddComment(" start index");

3165 Asm->OutStreamer->AddComment(" length");

3166 Asm->emitLabelDifferenceAsULEB128(End, Begin);

3167 } else {

3168 Asm->OutStreamer->emitSymbolValue(Begin, Size);

3169 Asm->OutStreamer->emitSymbolValue(End, Size);

3170 }

3171 EmitPayload(*RS);

3172 }

3173 }

3174

3175 if (UseDwarf5) {

3176 Asm->OutStreamer->AddComment(StringifyEnum(EndOfList));

3178 } else {

3179

3180 Asm->OutStreamer->emitIntValue(0, Size);

3181 Asm->OutStreamer->emitIntValue(0, Size);

3182 }

3183}

3184

3185

3188 *List.CU, dwarf::DW_LLE_base_addressx,

3189 dwarf::DW_LLE_offset_pair, dwarf::DW_LLE_startx_length,

3191 true,

3193 DD.emitDebugLocEntryLocation(E, List.CU);

3194 });

3195}

3196

3197void DwarfDebug::emitDebugLocImpl(MCSection *Sec) {

3198 if (DebugLocs.getLists().empty())

3199 return;

3200

3202

3203 MCSymbol *TableEnd = nullptr;

3206

3207 for (const auto &List : DebugLocs.getLists())

3209

3210 if (TableEnd)

3212}

3213

3214

3215void DwarfDebug::emitDebugLoc() {

3216 emitDebugLocImpl(

3220}

3221

3222

3223void DwarfDebug::emitDebugLocDWO() {

3225 emitDebugLocImpl(

3227

3228 return;

3229 }

3230

3231 for (const auto &List : DebugLocs.getLists()) {

3235

3236 for (const auto &Entry : DebugLocs.getEntries(List)) {

3237

3238

3239

3240

3241

3242

3243

3244

3245 Asm->emitInt8(dwarf::DW_LLE_startx_length);

3248

3249

3252 }

3253 Asm->emitInt8(dwarf::DW_LLE_end_of_list);

3254 }

3255}

3256

3259};

3260

3261

3262

3263void DwarfDebug::emitDebugARanges() {

3264 if (ArangeLabels.empty())

3265 return;

3266

3267

3269

3270

3271 for (const SymbolCU &SCU : ArangeLabels) {

3272 if (SCU.Sym->isInSection()) {

3273

3274 MCSection *Section = &SCU.Sym->getSection();

3275 SectionMap[Section].push_back(SCU);

3276 } else {

3277

3278

3279

3280 SectionMap[nullptr].push_back(SCU);

3281 }

3282 }

3283

3285

3286 for (auto &I : SectionMap) {

3290

3291

3292

3293 if (!Section) {

3296 Span.Start = Cur.Sym;

3297 Span.End = nullptr;

3299 Spans[Cur.CU].push_back(Span);

3300 }

3301 continue;

3302 }

3303

3304

3306

3307

3309 for (size_t n = 1, e = List.size(); n < e; n++) {

3312

3313

3314 if (Cur.CU != Prev.CU) {

3316 Span.Start = StartSym;

3319 Spans[Prev.CU].push_back(Span);

3320 StartSym = Cur.Sym;

3321 }

3322 }

3323 }

3324

3325

3328

3330

3331

3332 std::vector<DwarfCompileUnit *> CUs;

3333 for (const auto &it : Spans) {

3335 CUs.push_back(CU);

3336 }

3337

3338

3340 return A->getUniqueID() < B->getUniqueID();

3341 });

3342

3343

3345 std::vector &List = Spans[CU];

3346

3347

3348 if (auto *Skel = CU->getSkeleton())

3349 CU = Skel;

3350

3351

3352 unsigned ContentSize =

3353 sizeof(int16_t) +

3355

3356 sizeof(int8_t) +

3357 sizeof(int8_t);

3358

3359 unsigned TupleSize = PtrSize * 2;

3360

3361

3364

3366 ContentSize += (List.size() + 1) * TupleSize;

3367

3368

3370 Asm->OutStreamer->AddComment("DWARF Arange version number");

3372 Asm->OutStreamer->AddComment("Offset Into Debug Info Section");

3373 emitSectionReference(*CU);

3374 Asm->OutStreamer->AddComment("Address Size (in bytes)");

3376 Asm->OutStreamer->AddComment("Segment Size (in bytes)");

3378

3380

3383

3384

3385

3386

3387

3388

3389 auto SizeRef = SymSize.find(Span.Start);

3390 if ((SizeRef == SymSize.end() || SizeRef->second != 0) && Span.End) {

3392 } else {

3393

3394

3396 if (SizeRef == SymSize.end() || SizeRef->second == 0)

3398 else

3399 Size = SizeRef->second;

3400

3402 }

3403 }

3404

3408 }

3409}

3410

3411

3415 dwarf::DW_RLE_base_addressx, dwarf::DW_RLE_offset_pair,

3416 dwarf::DW_RLE_startx_length, dwarf::DW_RLE_end_of_list,

3418 List.CU->getCUNode()->getRangesBaseAddress() ||

3420 [](auto) {});

3421}

3422

3423void DwarfDebug::emitDebugRangesImpl(const DwarfFile &Holder, MCSection *Section) {

3425 return;

3426

3428 assert(!CUMap.empty());

3429 assert(llvm::any_of(CUMap, [](const decltype(CUMap)::value_type &Pair) {

3430 return !Pair.second->getCUNode()->isDebugDirectivesOnly();

3431 }));

3432

3434

3435 MCSymbol *TableEnd = nullptr;

3438

3441

3442 if (TableEnd)

3444}

3445

3446

3447

3448void DwarfDebug::emitDebugRanges() {

3449 const auto &Holder = useSplitDwarf() ? SkeletonHolder : InfoHolder;

3450

3451 emitDebugRangesImpl(Holder,

3455}

3456

3457void DwarfDebug::emitDebugRangesDWO() {

3458 emitDebugRangesImpl(InfoHolder,

3460}

3461

3462

3463

3466 enum HeaderFlagMask {

3467#define HANDLE_MACRO_FLAG(ID, NAME) MACRO_FLAG_##NAME = ID,

3468#include "llvm/BinaryFormat/Dwarf.def"

3469 };

3470 Asm->OutStreamer->AddComment("Macro information version");

3471 Asm->emitInt16(DwarfVersion >= 5 ? DwarfVersion : 4);

3472

3473

3474 if (Asm->isDwarf64()) {

3475 Asm->OutStreamer->AddComment("Flags: 64 bit, debug_line_offset present");

3476 Asm->emitInt8(MACRO_FLAG_OFFSET_SIZE | MACRO_FLAG_DEBUG_LINE_OFFSET);

3477 } else {

3478 Asm->OutStreamer->AddComment("Flags: 32 bit, debug_line_offset present");

3479 Asm->emitInt8(MACRO_FLAG_DEBUG_LINE_OFFSET);

3480 }

3481 Asm->OutStreamer->AddComment("debug_line_offset");

3483 Asm->emitDwarfLengthOrOffset(0);

3484 else

3485 Asm->emitDwarfSymbolReference(CU.getLineTableStartSym());

3486}

3487

3488void DwarfDebug::handleMacroNodes(DIMacroNodeArray Nodes, DwarfCompileUnit &U) {

3489 for (auto *MN : Nodes) {

3490 if (auto *M = dyn_cast(MN))

3491 emitMacro(*M);

3492 else if (auto *F = dyn_cast(MN))

3493 emitMacroFile(*F, U);

3494 else

3496 }

3497}

3498

3499void DwarfDebug::emitMacro(DIMacro &M) {

3502

3503

3504

3505 std::string Str = Value.empty() ? Name.str() : (Name + " " + Value).str();

3506

3507 if (UseDebugMacroSection) {

3510 ? dwarf::DW_MACRO_define_strx

3511 : dwarf::DW_MACRO_undef_strx;

3519 } else {

3521 ? dwarf::DW_MACRO_GNU_define_indirect

3522 : dwarf::DW_MACRO_GNU_undef_indirect;

3530 }

3531 } else {

3539 }

3540}

3541

3542void DwarfDebug::emitMacroFileImpl(

3544 StringRef (*MacroFormToString)(unsigned Form)) {

3545

3546 Asm->OutStreamer->AddComment(MacroFormToString(StartFile));

3556 else

3559 Asm->OutStreamer->AddComment(MacroFormToString(EndFile));

3561}

3562

3564

3565

3567 if (UseDebugMacroSection)

3568 emitMacroFileImpl(

3569 F, U, dwarf::DW_MACRO_start_file, dwarf::DW_MACRO_end_file,

3571 else

3574}

3575

3576void DwarfDebug::emitDebugMacinfoImpl(MCSection *Section) {

3577 for (const auto &P : CUMap) {

3578 auto &TheCU = *P.second;

3581 auto *CUNode = cast(P.first);

3582 DIMacroNodeArray Macros = CUNode->getMacros();

3583 if (Macros.empty())

3584 continue;

3587 if (UseDebugMacroSection)

3589 handleMacroNodes(Macros, U);

3590 Asm->OutStreamer->AddComment("End Of Macro List Mark");

3592 }

3593}

3594

3595

3596void DwarfDebug::emitDebugMacinfo() {

3598 emitDebugMacinfoImpl(UseDebugMacroSection

3599 ? ObjLower.getDwarfMacroSection()

3600 : ObjLower.getDwarfMacinfoSection());

3601}

3602

3603void DwarfDebug::emitDebugMacinfoDWO() {

3605 emitDebugMacinfoImpl(UseDebugMacroSection

3606 ? ObjLower.getDwarfMacroDWOSection()

3607 : ObjLower.getDwarfMacinfoDWOSection());

3608}

3609

3610

3611

3612void DwarfDebug::initSkeletonUnit(const DwarfUnit &U, DIE &Die,

3613 std::unique_ptr NewU) {

3614

3615 if (!CompilationDir.empty())

3616 NewU->addString(Die, dwarf::DW_AT_comp_dir, CompilationDir);

3617 addGnuPubAttributes(*NewU, Die);

3618

3619 SkeletonHolder.addUnit(std::move(NewU));

3620}

3621

3623

3624 auto OwnedUnit = std::make_unique(

3625 CU.getUniqueID(), CU.getCUNode(), Asm, this, &SkeletonHolder,

3629

3631

3634

3635 initSkeletonUnit(CU, NewCU.getUnitDie(), std::move(OwnedUnit));

3636

3637 return NewCU;

3638}

3639

3640

3641

3642void DwarfDebug::emitDebugInfoDWO() {

3644

3645 InfoHolder.emitUnits( true);

3646}

3647

3648

3649

3650void DwarfDebug::emitDebugAbbrevDWO() {

3653}

3654

3655void DwarfDebug::emitDebugLineDWO() {

3657 SplitTypeUnitFileTable.Emit(

3660}

3661

3662void DwarfDebug::emitStringOffsetsTableHeaderDWO() {

3667}

3668

3669

3670

3671

3672void DwarfDebug::emitDebugStrDWO() {

3674 emitStringOffsetsTableHeaderDWO();

3678 OffSec, false);

3679}

3680

3681

3682void DwarfDebug::emitDebugAddr() {

3684}

3685

3688 return nullptr;

3693 return &SplitTypeUnitFileTable;

3694}

3695

3697 MD5 Hash;

3698 Hash.update(Identifier);

3699

3700

3701

3703 Hash.final(Result);

3704 return Result.high();

3705}

3706

3710

3711

3712

3713 if (!TypeUnitsUnderConstruction.empty() && AddrPool.hasBeenUsed())

3714 return;

3715

3716 auto Ins = TypeSignatures.insert(std::make_pair(CTy, 0));

3717 if (!Ins.second) {

3718 CU.addDIETypeSignature(RefDie, Ins.first->second);

3719 return;

3720 }

3721

3723 bool TopLevelType = TypeUnitsUnderConstruction.empty();

3725

3726 auto OwnedUnit = std::make_unique(

3727 CU, Asm, this, &InfoHolder, NumTypeUnitsCreated++, getDwoLineTable(CU));

3730 TypeUnitsUnderConstruction.emplace_back(std::move(OwnedUnit), CTy);

3731

3732 NewTU.addUInt(UnitDie, dwarf::DW_AT_language, dwarf::DW_FORM_data2,

3733 CU.getLanguage());

3734

3737 Ins.first->second = Signature;

3738

3740

3741

3742

3743

3745 if (!CompilationDir.empty())

3746 NewTU.addString(UnitDie, dwarf::DW_AT_comp_dir, CompilationDir);

3747 NewTU.addString(UnitDie, dwarf::DW_AT_dwo_name,

3749 }

3755 } else {

3761

3762 CU.applyStmtList(UnitDie);

3763 }

3764

3765

3766

3769

3771

3772 if (TopLevelType) {

3773 auto TypeUnitsToAdd = std::move(TypeUnitsUnderConstruction);

3774 TypeUnitsUnderConstruction.clear();

3775

3776

3777

3779 AccelTypeUnitsDebugNames.clear();

3780

3781

3782

3783 for (const auto &TU : TypeUnitsToAdd)

3784 TypeSignatures.erase(TU.second);

3785

3786

3787

3788

3789

3791 CU.constructTypeDIE(RefDie, cast(CTy));

3792 CU.updateAcceleratorTables(CTy->getScope(), CTy, RefDie);

3793 return;

3794 }

3795

3796

3797

3798 for (auto &TU : TypeUnitsToAdd) {

3805 else

3807 }

3808 }

3810 AccelDebugNames.addTypeEntries(AccelTypeUnitsDebugNames);

3811 AccelTypeUnitsDebugNames.clear();

3813 }

3814 CU.addDIETypeSignature(RefDie, Signature);

3815}

3816

3817

3818

3819

3820

3821template

3822void DwarfDebug::addAccelNameImpl(

3827 Unit.getUnitDie().getTag() == dwarf::DW_TAG_skeleton_unit || Name.empty())

3828 return;

3829

3833 return;

3834

3837

3841 break;

3844 assert(((&Current == &AccelTypeUnitsDebugNames) ||

3845 ((&Current == &AccelDebugNames) &&

3846 (Unit.getUnitDie().getTag() != dwarf::DW_TAG_type_unit))) &&

3847 "Kind is CU but TU is being processed.");

3848 assert(((&Current == &AccelDebugNames) ||

3849 ((&Current == &AccelTypeUnitsDebugNames) &&

3850 (Unit.getUnitDie().getTag() == dwarf::DW_TAG_type_unit))) &&

3851 "Kind is TU but CU is being processed.");

3852

3853

3854 Current.addName(Ref, Die, Unit.getUniqueID(),

3855 Unit.getUnitDie().getTag() == dwarf::DW_TAG_type_unit);

3856 break;

3857 }

3859 llvm_unreachable("Default should have already been resolved.");

3862 }

3863}

3864

3868 const DIE &Die) {

3869 addAccelNameImpl(Unit, NameTableKind, AccelNames, Name, Die);

3870}

3871

3875 const DIE &Die) {

3876

3878 addAccelNameImpl(Unit, NameTableKind, AccelObjC, Name, Die);

3879}

3880

3884 const DIE &Die) {

3885 addAccelNameImpl(Unit, NameTableKind, AccelNamespace, Name, Die);

3886}

3887

3891 const DIE &Die, char Flags) {

3892 addAccelNameImpl(Unit, NameTableKind, AccelTypes, Name, Die);

3893}

3894

3896 return Asm->OutStreamer->getContext().getDwarfVersion();

3897}

3898

3901 return dwarf::Form::DW_FORM_sec_offset;

3903 "DWARF64 is not defined prior DWARFv3");

3904 return Asm->isDwarf64() ? dwarf::Form::DW_FORM_data8

3905 : dwarf::Form::DW_FORM_data4;

3906}

3907

3909 return SectionLabels.lookup(S);

3910}

3911

3913 if (SectionLabels.insert(std::make_pair(&S->getSection(), S)).second)

3916}

3917

3918std::optionalMD5::MD5Result

3922 return std::nullopt;

3923 std::optional<DIFile::ChecksumInfo> Checksum = File->getChecksum();

3925 return std::nullopt;

3926

3927

3928

3929

3930 std::string ChecksumString = fromHex(Checksum->Value);

3932 std::copy(ChecksumString.begin(), ChecksumString.end(), CKMem.data());

3933 return CKMem;

3934}

3935

3938 return true;

3940 return false;

3942 return true;

3943 return false;

3944}

3945

3948 return;

3949

3951 bool NoDebug =

3953

3954 if (NoDebug)

3955 return;

3956

3957 auto PrevLoc = Asm->OutStreamer->getContext().getCurrentDwarfLoc();

3958 if (PrevLoc.getLine()) {

3960 PrevLoc.getFileNum(), 0, PrevLoc.getColumn(), 0, 0, 0, StringRef());

3963 }

3964}

This file implements a class to represent arbitrary precision integral constant values and operations...

MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL

static Expected< bool > hasObjCCategory(BitstreamCursor &Stream)

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

static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")

static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")

#define clEnumValN(ENUMVAL, FLAGNAME, DESC)

#define clEnumVal(ENUMVAL, DESC)

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

Returns the sub type a function will return at a given Idx Should correspond to the result type of an ExtractValue instruction executed with just that one unsigned Idx

static bool isObjCClass(StringRef Name)

static cl::opt< bool > NoDwarfRangesSection("no-dwarf-ranges-section", cl::Hidden, cl::desc("Disable emission .debug_ranges section."), cl::init(false))

static void finishCallSiteParams(ValT Val, const DIExpression *Expr, ArrayRef< FwdRegParamInfo > DescribedParams, ParamSet &Params)

Emit call site parameter entries that are described by the given value and debug expression.

static cl::opt< bool > UseGNUDebugMacro("use-gnu-debug-macro", cl::Hidden, cl::desc("Emit the GNU .debug_macro format with DWARF <5"), cl::init(false))

static cl::opt< DefaultOnOff > DwarfInlinedStrings("dwarf-inlined-strings", cl::Hidden, cl::desc("Use inlined strings rather than string section."), cl::values(clEnumVal(Default, "Default for platform"), clEnumVal(Enable, "Enabled"), clEnumVal(Disable, "Disabled")), cl::init(Default))

static bool validThroughout(LexicalScopes &LScopes, const MachineInstr *DbgValue, const MachineInstr *RangeEnd, const InstructionOrdering &Ordering)

Determine whether a singular DBG_VALUE is valid for the entirety of its enclosing lexical scope.

static cl::opt< bool > GenerateARangeSection("generate-arange-section", cl::Hidden, cl::desc("Generate dwarf aranges"), cl::init(false))

static cl::opt< LinkageNameOption > DwarfLinkageNames("dwarf-linkage-names", cl::Hidden, cl::desc("Which DWARF linkage-name attributes to emit."), cl::values(clEnumValN(DefaultLinkageNames, "Default", "Default for platform"), clEnumValN(AllLinkageNames, "All", "All"), clEnumValN(AbstractLinkageNames, "Abstract", "Abstract subprograms")), cl::init(DefaultLinkageNames))

static void addToFwdRegWorklist(FwdRegWorklist &Worklist, unsigned Reg, const DIExpression *Expr, ArrayRef< FwdRegParamInfo > ParamsToAdd)

Add Reg to the worklist, if it's not already present, and mark that the given parameter registers' va...

static cl::opt< bool > GenerateDwarfTypeUnits("generate-type-units", cl::Hidden, cl::desc("Generate DWARF4 type units."), cl::init(false))

static SmallVectorImpl< DwarfCompileUnit::GlobalExpr > & sortGlobalExprs(SmallVectorImpl< DwarfCompileUnit::GlobalExpr > &GVEs)

Sort and unique GVEs by comparing their fragment offset.

static dwarf::PubIndexEntryDescriptor computeIndexValue(DwarfUnit *CU, const DIE *Die)

computeIndexValue - Compute the gdb index value for the DIE and CU.

static uint64_t getFragmentOffsetInBits(const DIExpression &Expr)

static cl::opt< DefaultOnOff > DwarfOpConvert("dwarf-op-convert", cl::Hidden, cl::desc("Enable use of the DWARFv5 DW_OP_convert operator"), cl::values(clEnumVal(Default, "Default for platform"), clEnumVal(Enable, "Enabled"), clEnumVal(Disable, "Disabled")), cl::init(Default))

static std::pair< const MachineInstr *, bool > findPrologueEndLoc(const MachineFunction *MF)

static void collectCallSiteParameters(const MachineInstr *CallMI, ParamSet &Params)

Try to interpret values loaded into registers that forward parameters for CallMI.

static MCSymbol * emitRnglistsTableHeader(AsmPrinter *Asm, const DwarfFile &Holder)

static void recordSourceLine(AsmPrinter &Asm, unsigned Line, unsigned Col, const MDNode *S, unsigned Flags, unsigned CUID, uint16_t DwarfVersion, ArrayRef< std::unique_ptr< DwarfCompileUnit > > DCUs)

Register a source line with debug info.

static cl::opt< bool > SplitDwarfCrossCuReferences("split-dwarf-cross-cu-references", cl::Hidden, cl::desc("Enable cross-cu references in DWO files"), cl::init(false))

static cl::opt< bool > UseDwarfRangesBaseAddressSpecifier("use-dwarf-ranges-base-address-specifier", cl::Hidden, cl::desc("Use base address specifiers in debug_ranges"), cl::init(false))

static void interpretValues(const MachineInstr *CurMI, FwdRegWorklist &ForwardedRegWorklist, ParamSet &Params, ClobberedRegSet &ClobberedRegUnits)

Interpret values loaded into registers by CurMI.

static bool interpretNextInstr(const MachineInstr *CurMI, FwdRegWorklist &ForwardedRegWorklist, ParamSet &Params, ClobberedRegSet &ClobberedRegUnits)

static void emitLocList(DwarfDebug &DD, AsmPrinter *Asm, const DebugLocStream::List &List)

static constexpr unsigned ULEB128PadSize

static cl::opt< DefaultOnOff > DwarfSectionsAsReferences("dwarf-sections-as-references", cl::Hidden, cl::desc("Use sections+offset as references rather than labels."), cl::values(clEnumVal(Default, "Default for platform"), clEnumVal(Enable, "Enabled"), clEnumVal(Disable, "Disabled")), cl::init(Default))

static AccelTableKind computeAccelTableKind(unsigned DwarfVersion, bool GenerateTypeUnits, DebuggerKind Tuning, const Triple &TT)

static void forBothCUs(DwarfCompileUnit &CU, Func F)

static MCSymbol * emitLoclistsTableHeader(AsmPrinter *Asm, const DwarfDebug &DD)

static const DILocalScope * getRetainedNodeScope(const MDNode *N)

static const DIExpression * combineDIExpressions(const DIExpression *Original, const DIExpression *Addition)

Append the expression Addition to Original and return the result.

static cl::opt< DefaultOnOff > UnknownLocations("use-unknown-locations", cl::Hidden, cl::desc("Make an absence of debug location information explicit."), cl::values(clEnumVal(Default, "At top of block or after label"), clEnumVal(Enable, "In all cases"), clEnumVal(Disable, "Never")), cl::init(Default))

static void emitMacroHeader(AsmPrinter *Asm, const DwarfDebug &DD, const DwarfCompileUnit &CU, uint16_t DwarfVersion)

Emit the header of a DWARF 5 macro section, or the GNU extension for DWARF 4.

static cl::opt< AccelTableKind > AccelTables("accel-tables", cl::Hidden, cl::desc("Output dwarf accelerator tables."), cl::values(clEnumValN(AccelTableKind::Default, "Default", "Default for platform"), clEnumValN(AccelTableKind::None, "Disable", "Disabled."), clEnumValN(AccelTableKind::Apple, "Apple", "Apple"), clEnumValN(AccelTableKind::Dwarf, "Dwarf", "DWARF")), cl::init(AccelTableKind::Default))

static cl::opt< DwarfDebug::MinimizeAddrInV5 > MinimizeAddrInV5Option("minimize-addr-in-v5", cl::Hidden, cl::desc("Always use DW_AT_ranges in DWARFv5 whenever it could allow more " "address pool entry sharing to reduce relocations/object size"), cl::values(clEnumValN(DwarfDebug::MinimizeAddrInV5::Default, "Default", "Default address minimization strategy"), clEnumValN(DwarfDebug::MinimizeAddrInV5::Ranges, "Ranges", "Use rnglists for contiguous ranges if that allows " "using a pre-existing base address"), clEnumValN(DwarfDebug::MinimizeAddrInV5::Expressions, "Expressions", "Use exprloc addrx+offset expressions for any " "address with a prior base address"), clEnumValN(DwarfDebug::MinimizeAddrInV5::Form, "Form", "Use addrx+offset extension form for any address " "with a prior base address"), clEnumValN(DwarfDebug::MinimizeAddrInV5::Disabled, "Disabled", "Stuff")), cl::init(DwarfDebug::MinimizeAddrInV5::Default))

static StringRef getObjCMethodName(StringRef In)

static void emitRangeList(DwarfDebug &DD, AsmPrinter *Asm, MCSymbol *Sym, const Ranges &R, const DwarfCompileUnit &CU, unsigned BaseAddressx, unsigned OffsetPair, unsigned StartxLength, unsigned EndOfList, StringRef(*StringifyEnum)(unsigned), bool ShouldUseBaseAddress, PayloadEmitter EmitPayload)

static DbgValueLoc getDebugLocValue(const MachineInstr *MI)

Get .debug_loc entry for the instruction range starting at MI.

static void getObjCClassCategory(StringRef In, StringRef &Class, StringRef &Category)

const HexagonInstrInfo * TII

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

#define DWARF2_FLAG_IS_STMT

#define DWARF2_FLAG_PROLOGUE_END

#define DWARF2_FLAG_EPILOGUE_BEGIN

unsigned const TargetRegisterInfo * TRI

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

const SmallVectorImpl< MachineOperand > MachineBasicBlock * TBB

const SmallVectorImpl< MachineOperand > & Cond

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

This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...

#define STATISTIC(VARNAME, DESC)

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

static bool isCopy(MachineInstr *MI)

static const uint32_t IV[8]

Class recording the (high level) value of a variable.

This class holds an abstract representation of an Accelerator Table, consisting of a sequence of buck...

void addName(DwarfStringPoolEntryRef Name, Types &&... Args)

unsigned getIndex(const MCSymbol *Sym, bool TLS=false)

Returns the index into the address pool with the given label/symbol.

void emit(AsmPrinter &Asm, MCSection *AddrSection)

void setLabel(MCSymbol *Sym)

void resetUsedFlag(bool HasBeenUsed=false)

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

std::vector< T > vec() const

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.

void emitULEB128(uint64_t Value, const char *Desc=nullptr, unsigned PadTo=0) const

Emit the specified unsigned leb128 value.

void emitDwarfSymbolReference(const MCSymbol *Label, bool ForceOffset=false) const

Emit a reference to a symbol for use in dwarf.

MapVector< MBBSectionID, MBBSectionRange > MBBSectionRanges

DwarfDebug * getDwarfDebug()

void emitDwarfLengthOrOffset(uint64_t Value) const

Emit 32- or 64-bit value depending on the DWARF format.

unsigned int getUnitLengthFieldByteSize() const

Returns 4 for DWARF32 and 12 for DWARF64.

TargetMachine & TM

Target machine description.

MCSymbol * getFunctionBegin() const

void emitLabelDifference(const MCSymbol *Hi, const MCSymbol *Lo, unsigned Size) const

Emit something like ".long Hi-Lo" where the size in bytes of the directive is specified by Size and H...

const MCAsmInfo * MAI

Target Asm Printer information.

MachineFunction * MF

The current machine function.

void emitDwarfOffset(const MCSymbol *Label, uint64_t Offset) const

Emit something like ".long Label + Offset" or ".quad Label + Offset" depending on the DWARF format.

void emitInt8(int Value) const

Emit a byte directive and value.

bool hasDebugInfo() const

Returns true if valid debug info is present.

void emitDwarfUnitLength(uint64_t Length, const Twine &Comment) const

Emit a unit length field.

MCContext & OutContext

This is the context for the output file that we are streaming.

MCSymbol * createTempSymbol(const Twine &Name) const

std::unique_ptr< MCStreamer > OutStreamer

This is the MCStreamer object for the file we are generating.

void emitLabelReference(const MCSymbol *Label, unsigned Size, bool IsSectionRelative=false) const

Emit something like ".long Label" where the size in bytes of the directive is specified by Size and L...

unsigned int getDwarfOffsetByteSize() const

Returns 4 for DWARF32 and 8 for DWARF64.

MCSymbol * getFunctionEnd() const

void emitInt16(int Value) const

Emit a short directive and value.

const DataLayout & getDataLayout() const

Return information about data layout.

uint16_t getDwarfVersion() const

void emitInt8(uint8_t Byte, const Twine &Comment) override

const bool GenerateComments

Only verbose textual output needs comments.

virtual void emitULEB128(uint64_t DWord, const Twine &Comment="", unsigned PadTo=0)=0

virtual void emitSLEB128(uint64_t DWord, const Twine &Comment="")=0

virtual void emitInt8(uint8_t Byte, const Twine &Comment="")=0

virtual unsigned emitDIERef(const DIE &D)=0

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

bool getDebugInfoForProfiling() const

bool isDebugDirectivesOnly() const

StringRef getFlags() const

static std::optional< DebugNameTableKind > getNameTableKind(StringRef Str)

unsigned getRuntimeVersion() const

bool getSplitDebugInlining() const

StringRef getSysRoot() const

StringRef getProducer() const

unsigned getSourceLanguage() const

uint64_t getDWOId() const

StringRef getSplitDebugFilename() const

static std::optional< DebugEmissionKind > getEmissionKind(StringRef Str)

An object containing the capability of hashing and adding hash attributes onto a DIE.

uint64_t computeCUSignature(StringRef DWOName, const DIE &Die)

Computes the CU signature.

void setSection(MCSection *Section)

Set the section that this DIEUnit will be emitted into.

A structured debug information entry.

DIEValue findAttribute(dwarf::Attribute Attribute) const

Find a value in the DIE with the attribute given.

const DIE * getUnitDie() const

Climb up the parent chain to get the compile unit or type unit DIE that this DIE belongs to.

dwarf::Tag getTag() const

Holds a DIExpression and keeps track of how many operands have been consumed so far.

bool isEntryValue() const

Check if the expression consists of exactly one entry value operand.

static DIExpression * append(const DIExpression *Expr, ArrayRef< uint64_t > Ops)

Append the opcodes Ops to DIExpr.

unsigned getNumElements() const

bool isImplicit() const

Return whether this is an implicit location description.

static std::optional< FragmentInfo > getFragmentInfo(expr_op_iterator Start, expr_op_iterator End)

Retrieve the details of this fragment expression.

static std::optional< const DIExpression * > convertToNonVariadicExpression(const DIExpression *Expr)

If Expr is a valid single-location expression, i.e.

ArrayRef< uint64_t > getElements() const

DIMacroNodeArray getElements() const

Tagged DWARF-like metadata node.

Base class for scope-like contexts.

StringRef getFilename() const

StringRef getName() const

StringRef getDirectory() const

std::optional< StringRef > getSource() const

DIScope * getScope() const

DIScope * getScope() const

void addTypeUnitSignature(DwarfTypeUnit &U)

Add a type unit Signature.

void convertDieToOffset()

Convert DIE entries to explicit offset.

void addTypeUnitSymbol(DwarfTypeUnit &U)

Add a type unit start symbol.

void addTypeEntries(DWARF5AccelTable &Table)

This class represents an Operation in the Expression.

std::optional< unsigned > getSubCode() const

uint64_t getEndOffset() const

Encoding

Size and signedness of expression operations' operands.

const Description & getDescription() const

uint64_t getOperandEndOffset(unsigned Idx) const

uint64_t getRawOperand(unsigned Idx) const

bool isLittleEndian() const

Layout endianness...

Used for tracking debug info about call site parameters.

This class is defined as the common parent of DbgVariable and DbgLabel such that it could levarage po...

bool hasNonEmptyLocation(const Entries &Entries) const

Test whether a vector of entries features any non-empty locations.

A single location or constant within a variable location description, with either a single entry (wit...

The location of a single variable, composed of an expression and 0 or more DbgValueLocEntries.

This class is used to track local variable information.

const DILocalVariable * getVariable() const

const DIType * getType() const

Base class for debug information backends.

const MachineInstr * CurMI

If nonnull, stores the current machine instruction we're processing.

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.

DbgLabelInstrMap DbgLabels

Mapping of inlined labels and DBG_LABEL machine instruction.

void beginModule(Module *M) override

const InstructionOrdering & getInstOrdering() const

void requestLabelBeforeInsn(const MachineInstr *MI)

Ensure that a label will be emitted before MI.

const MachineBasicBlock * EpilogBeginBlock

This block includes epilogue instructions.

const MachineInstr * PrologEndLoc

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

DwarfExpression implementation for .debug_loc entries.

void finalize(const AsmPrinter &AP, DebugLocStream::ListBuilder &List, const DIBasicType *BT, DwarfCompileUnit &TheCU)

Lower this entry into a DWARF expression.

Builder for DebugLocStream entries.

Builder for DebugLocStream lists.

ArrayRef< std::string > getComments(const Entry &E) const

ArrayRef< Entry > getEntries(const List &L) const

ArrayRef< char > getBytes(const Entry &E) const

MCSymbol * getSym() const

void setSym(MCSymbol *Sym)

ArrayRef< List > getLists() const

MDNode * getScope() const

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

iterator find(const_arg_type_t< KeyT > Val)

bool erase(const KeyT &Val)

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

Implements a dense probed hash-table based set.

void constructAbstractSubprogramScopeDIE(LexicalScope *Scope)

void addRange(RangeSpan Range)

addRange - Add an address range to the list of ranges for this unit.

void createAbstractEntity(const DINode *Node, LexicalScope *Scope)

DIE & constructSubprogramScopeDIE(const DISubprogram *Sub, LexicalScope *Scope, MCSymbol *LineTableSym)

Construct a DIE for this subprogram scope.

DwarfCompileUnit * getSkeleton() const

void setSkeleton(DwarfCompileUnit &Skel)

Set the skeleton unit associated with this unit.

const StringMap< const DIE * > & getGlobalNames() const

DbgEntity * getExistingAbstractEntity(const DINode *Node)

const StringMap< const DIE * > & getGlobalTypes() const

bool hasDwarfPubSections() const

Collects and handles dwarf debug information.

bool useSegmentedStringOffsetsTable() const

Returns whether to generate a string offsets table with (possibly shared) contributions from each CU ...

std::optional< MD5::MD5Result > getMD5AsBytes(const DIFile *File) const

If the File has an MD5 checksum, return it as an MD5Result allocated in the MCContext.

bool emitDebugEntryValues() const

uint16_t getDwarfVersion() const

Returns the Dwarf Version.

void emitDebugLocEntry(ByteStreamer &Streamer, const DebugLocStream::Entry &Entry, const DwarfCompileUnit *CU)

Emit an entry for the debug loc section.

void addAccelNamespace(const DwarfUnit &Unit, const DICompileUnit::DebugNameTableKind NameTableKind, StringRef Name, const DIE &Die)

void setCurrentDWARF5AccelTable(const DWARF5AccelTableKind Kind)

Sets the current DWARF5AccelTable to use.

bool alwaysUseRanges(const DwarfCompileUnit &) const

Returns whether range encodings should be used for single entry range lists.

void beginModule(Module *M) override

Emit all Dwarf sections that should come prior to the content.

void addSubprogramNames(const DwarfUnit &Unit, const DICompileUnit::DebugNameTableKind NameTableKind, const DISubprogram *SP, DIE &Die)

bool useAllLinkageNames() const

Returns whether we should emit all DW_AT_[MIPS_]linkage_name.

void insertSectionLabel(const MCSymbol *S)

void addAccelObjC(const DwarfUnit &Unit, const DICompileUnit::DebugNameTableKind NameTableKind, StringRef Name, const DIE &Die)

dwarf::Form getDwarfSectionOffsetForm() const

Returns a suitable DWARF form to represent a section offset, i.e.

bool useAppleExtensionAttributes() const

void skippedNonDebugFunction() override

void addArangeLabel(SymbolCU SCU)

Add a label so that arange data can be generated for it.

void beginInstruction(const MachineInstr *MI) override

Process beginning of an instruction.

AddressPool & getAddressPool()

DWARF5AccelTable & getCurrentDWARF5AccelTable()

Returns either CU or TU DWARF5AccelTable.

bool useSectionsAsReferences() const

Returns whether to use sections as labels rather than temp symbols.

const DebugLocStream & getDebugLocs() const

Returns the entries for the .debug_loc section.

bool shareAcrossDWOCUs() const

void terminateLineTable(const DwarfCompileUnit *CU)

Terminate the line table by adding the last range label.

void endFunctionImpl(const MachineFunction *MF) override

Gather and emit post-function debug information.

void emitDebugLocEntryLocation(const DebugLocStream::Entry &Entry, const DwarfCompileUnit *CU)

Emit the location for a debug loc entry, including the size header.

const MCSymbol * getSectionLabel(const MCSection *S)

static void emitDebugLocValue(const AsmPrinter &AP, const DIBasicType *BT, const DbgValueLoc &Value, DwarfExpression &DwarfExpr)

bool useSplitDwarf() const

Returns whether or not to change the current debug info for the split dwarf proposal support.

unsigned getDwarfCompileUnitIDForLineTable(const DwarfCompileUnit &CU)

Get Dwarf compile unit ID for line table.

const MachineInstr * emitInitialLocDirective(const MachineFunction &MF, unsigned CUID)

Emits inital debug location directive.

bool useRangesSection() const

Returns whether ranges section should be emitted.

void addAccelName(const DwarfUnit &Unit, const DICompileUnit::DebugNameTableKind NameTableKind, StringRef Name, const DIE &Die)

bool isLexicalScopeDIENull(LexicalScope *Scope)

A helper function to check whether the DIE for a given Scope is going to be null.

void addDwarfTypeUnitType(DwarfCompileUnit &CU, StringRef Identifier, DIE &Die, const DICompositeType *CTy)

Add a DIE to the set of types that we're going to pull into type units.

void endModule() override

Emit all Dwarf sections that should come after the content.

void addAccelType(const DwarfUnit &Unit, const DICompileUnit::DebugNameTableKind NameTableKind, StringRef Name, const DIE &Die, char Flags)

void beginCodeAlignment(const MachineBasicBlock &MBB) override

Process beginning of code alignment.

DwarfDebug(AsmPrinter *A)

void beginFunctionImpl(const MachineFunction *MF) override

Gather pre-function debug information.

AccelTableKind getAccelTableKind() const

Returns what kind (if any) of accelerator tables to emit.

static uint64_t makeTypeSignature(StringRef Identifier)

Perform an MD5 checksum of Identifier and return the lower 64 bits.

Base class containing the logic for constructing DWARF expressions independently of whether they are ...

void setLocation(const MachineLocation &Loc, const DIExpression *DIExpr)

Set the location (Loc) and DIExpression (DIExpr) to describe.

void finalize()

This needs to be called last to commit any pending changes.

void addFragmentOffset(const DIExpression *Expr)

If applicable, emit an empty DW_OP_piece / DW_OP_bit_piece to advance to the fragment described by Ex...

void setMemoryLocationKind()

Lock this down to become a memory location description.

std::optional< uint8_t > TagOffset

void addConstantFP(const APFloat &Value, const AsmPrinter &AP)

Emit an floating point constant.

bool addMachineRegExpression(const TargetRegisterInfo &TRI, DIExpressionCursor &Expr, llvm::Register MachineReg, unsigned FragmentOffsetInBits=0)

Emit a machine register location.

void addUnsignedConstant(uint64_t Value)

Emit an unsigned constant.

void addExpression(DIExpressionCursor &&Expr)

Emit all remaining operations in the DIExpressionCursor.

void addSignedConstant(int64_t Value)

Emit a signed constant.

void addWasmLocation(unsigned Index, uint64_t Offset)

Emit location information expressed via WebAssembly location + offset The Index is an identifier for ...

void beginEntryValueExpression(DIExpressionCursor &ExprCursor)

Begin emission of an entry value dwarf operation.

void addScopeLabel(LexicalScope *LS, DbgLabel *Label)

void addUnit(std::unique_ptr< DwarfCompileUnit > U)

Add a unit to the list of CUs.

void computeSizeAndOffsets()

Compute the size and offset of all the DIEs.

void setRnglistsTableBaseSym(MCSymbol *Sym)

DenseMap< LexicalScope *, ScopeVars > & getScopeVariables()

unsigned computeSizeAndOffsetsForUnit(DwarfUnit *TheU)

Compute the size and offset of all the DIEs in the given unit.

void emitUnits(bool UseOffsets)

Emit all of the units to the section listed with the given abbreviation section.

void emitUnit(DwarfUnit *TheU, bool UseOffsets)

Emit the given unit to its section.

const SmallVectorImpl< RangeSpanList > & getRangeLists() const

getRangeLists - Get the vector of range lists.

MCSymbol * getStringOffsetsStartSym() const

MCSymbol * getRnglistsTableBaseSym() const

DwarfStringPool & getStringPool()

Returns the string pool.

void emitAbbrevs(MCSection *)

Emit a set of abbreviations to the specific section.

void emitStrings(MCSection *StrSection, MCSection *OffsetSection=nullptr, bool UseRelativeOffsets=false)

Emit all of the strings to the section given.

DenseMap< LexicalScope *, LabelList > & getScopeLabels()

void addScopeVariable(LexicalScope *LS, DbgVariable *Var)

DenseMap< const DILocalScope *, DIE * > & getAbstractScopeDIEs()

const SmallVectorImpl< std::unique_ptr< DwarfCompileUnit > > & getUnits()

DwarfStringPoolEntryRef: Dwarf string pool entry reference.

unsigned getIndex() const

MCSymbol * getSymbol() const

EntryRef getEntry(AsmPrinter &Asm, StringRef Str)

Get a reference to an entry in the string pool.

EntryRef getIndexedEntry(AsmPrinter &Asm, StringRef Str)

Same as getEntry, except that you can use EntryRef::getIndex to obtain a unique ID of this entry (e....

void emitStringOffsetsTableHeader(AsmPrinter &Asm, MCSection *OffsetSection, MCSymbol *StartSym)

void setTypeSignature(uint64_t Signature)

void setType(const DIE *Ty)

This dwarf writer support class manages information associated with a source file.

void addStringOffsetsStart()

Add the DW_AT_str_offsets_base attribute to the unit DIE.

void addUInt(DIEValueList &Die, dwarf::Attribute Attribute, std::optional< dwarf::Form > Form, uint64_t Integer)

Add an unsigned integer attribute data and value.

void addString(DIE &Die, dwarf::Attribute Attribute, StringRef Str)

Add a string attribute data and value.

DIE * createTypeDIE(const DIScope *Context, DIE &ContextDIE, const DIType *Ty)

Creates type DIE with specific context.

const DICompileUnit * getCUNode() const

void addFlag(DIE &Die, dwarf::Attribute Attribute)

Add a flag that is true to the DIE.

unsigned getUniqueID() const

Gets Unique ID for this unit.

DISubprogram * getSubprogram() const

Get the attached subprogram.

LLVMContext & getContext() const

getContext - Return a reference to the LLVMContext associated with this function.

bool analyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB, MachineBasicBlock *&FBB, SmallVectorImpl< MachineOperand > &Cond, bool AllowModify) const override

Analyze the branching code at the end of MBB, returning true if it cannot be understood (e....

bool isTailCall(const MachineInstr &MI) const override

Record instruction ordering so we can query their relative positions within a function.

LexicalScope - This class is used to track scope information.

SmallVectorImpl< InsnRange > & getRanges()

const DILocalScope * getScopeNode() const

LexicalScopes - This class provides interface to collect and use lexical scoping information from mac...

LexicalScope * getOrCreateAbstractScope(const DILocalScope *Scope)

getOrCreateAbstractScope - Find or create an abstract lexical scope.

LexicalScope * findLexicalScope(const DILocation *DL)

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

ArrayRef< LexicalScope * > getAbstractScopesList() const

getAbstractScopesList - Return a reference to list of abstract scopes.

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

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

LexicalScope * findAbstractScope(const DILocalScope *N)

findAbstractScope - Find an abstract scope or return null.

bool empty()

empty - Return true if there is any lexical scope information available.

LexicalScope * getCurrentFunctionScope() const

getCurrentFunctionScope - Return lexical scope for the current function.

Single value location description.

Single(DbgValueLoc ValueLoc)

unsigned getCodePointerSize() const

Get the code pointer size in bytes.

uint16_t getDwarfVersion() const

dwarf::DwarfFormat getDwarfFormat() const

void maybeSetRootFile(StringRef Directory, StringRef FileName, std::optional< MD5::MD5Result > Checksum, std::optional< StringRef > Source)

void Emit(MCStreamer &MCOS, MCDwarfLineTableParams Params, MCSection *Section) const

static void make(MCStreamer *MCOS, MCSection *Section)

MCSection * getDwarfLoclistsSection() const

MCSection * getDwarfAccelTypesSection() const

MCSection * getDwarfGnuPubNamesSection() const

MCSection * getDwarfStrOffDWOSection() const

MCSection * getDwarfRangesSection() const

MCSection * getDwarfAccelNamespaceSection() const

MCSection * getDwarfLineDWOSection() const

MCSection * getDwarfStrOffSection() const

MCSection * getDwarfInfoDWOSection() const

MCSection * getDwarfTypesDWOSection() const

MCSection * getDwarfPubNamesSection() const

MCSection * getDwarfMacroSection() const

MCSection * getDwarfStrSection() const

MCSection * getDwarfLoclistsDWOSection() const

MCSection * getDwarfMacinfoDWOSection() const

MCSection * getDwarfRnglistsSection() const

MCSection * getDwarfAddrSection() const

MCSection * getDwarfInfoSection() const

MCSection * getDwarfPubTypesSection() const

MCSection * getDwarfTypesSection(uint64_t Hash) const

MCSection * getDwarfGnuPubTypesSection() const

MCSection * getDwarfStrDWOSection() const

MCSection * getDwarfAccelNamesSection() const

MCSection * getDwarfAbbrevDWOSection() const

MCSection * getDwarfRnglistsDWOSection() const

MCSection * getDwarfAbbrevSection() const

MCSection * getDwarfMacinfoSection() const

MCSection * getDwarfLocDWOSection() const

MCSection * getDwarfARangesSection() const

MCSection * getDwarfAccelObjCSection() const

MCSection * getDwarfLocSection() const

MCSection * getDwarfMacroDWOSection() const

Instances of this class represent a uniqued identifier for a section in the current translation unit.

MCSymbol * getBeginSymbol()

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 SplitDwarfFile

void update(ArrayRef< uint8_t > Data)

Updates the hash for the byte stream provided.

void final(MD5Result &Result)

Finishes off the hash and puts the result in result.

static MDTuple * get(LLVMContext &Context, ArrayRef< Metadata * > MDs)

succ_iterator succ_begin()

MBBSectionID getSectionID() const

Returns the section ID of this basic block.

const MachineFunction * getParent() const

Return the MachineFunction containing this basic block.

iterator_range< succ_iterator > successors()

reverse_iterator rbegin()

iterator_range< pred_iterator > predecessors()

Align getAlignment() const

Return alignment of the basic block.

const TargetSubtargetInfo & getSubtarget() const

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

const CallSiteInfoMap & getCallSitesInfo() const

bool hasBBSections() const

Returns true if this function has basic block sections enabled.

Function & getFunction()

Return the LLVM function that this machine code represents.

const MachineBasicBlock & back() const

VariableDbgInfoMapTy & getVariableDbgInfo()

const MachineBasicBlock & front() const

MachineBasicBlock iterator that automatically skips over MIs that are inside bundles (i....

Representation of each machine instruction.

const MachineBasicBlock * getParent() const

bool isCall(QueryType Type=AnyInBundle) const

iterator_range< mop_iterator > uses()

Returns a range that includes all operands which may be register uses.

unsigned getNumOperands() const

Retuns the total number of operands.

bool hasDelaySlot(QueryType Type=AnyInBundle) const

Returns true if the specified instruction has a delay slot which must be filled by the code generator...

const MachineFunction * getMF() const

Return the function that contains the basic block that this instruction belongs to.

const DebugLoc & getDebugLoc() const

Returns the debug location id of this MachineInstr.

bool isDebugValue() const

const Module * getModule() const

MachineOperand class - Representation of each machine instruction operand.

const GlobalValue * getGlobal() const

bool isReg() const

isReg - Tests if this is a MO_Register operand.

bool isGlobal() const

isGlobal - Tests if this is a MO_GlobalAddress operand.

Register getReg() const

getReg - Returns the register number.

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

VectorType::iterator erase(typename VectorType::iterator Iterator)

Remove the element given by Iterator.

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

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

iterator_range< debug_compile_units_iterator > debug_compile_units() const

Return an iterator for all DICompileUnits listed in this Module's llvm.dbg.cu named metadata node and...

unsigned getDwarfVersion() const

Returns the Dwarf Version by checking module flags.

bool isDwarf64() const

Returns the DWARF format by checking module flags.

Wrapper class representing virtual and physical registers.

constexpr bool isPhysical() const

Return true if the specified register number is in the physical register namespace.

bool empty() const

Determine if the SetVector is empty or not.

Implements a dense probed hash-table based set with some number of buckets stored inline.

A SetVector that performs no allocations if smaller than a certain size.

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

std::pair< const_iterator, bool > insert(const T &V)

insert - Insert an element into the set if it isn't already there.

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

void assign(size_type NumElts, ValueParamT Elt)

reference emplace_back(ArgTypes &&... Args)

iterator erase(const_iterator CI)

void push_back(const T &Elt)

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

StringMap - This is an unconventional map that is specialized for handling keys that are "strings",...

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

constexpr bool empty() const

empty - Check if the string is empty.

TargetInstrInfo - Interface to description of machine instruction set.

const Triple & getTargetTriple() const

MCTargetOptions MCOptions

Machine level options.

DebuggerKind DebuggerTuning

Which debugger to tune for.

bool ShouldEmitDebugEntryValues() const

NOTE: There are targets that still do not support the debug entry values production.

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

virtual const TargetRegisterInfo * getRegisterInfo() const

getRegisterInfo - If register information is available, return it.

virtual const TargetInstrInfo * getInstrInfo() const

virtual const TargetLowering * getTargetLowering() const

Triple - Helper class for working with autoconf configuration names.

bool isNVPTX() const

Tests whether the target is NVPTX (32- or 64-bit).

bool isWasm() const

Tests whether the target is wasm (32- and 64-bit).

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.

void dump() const

Support for debugging, callable in GDB: V->dump()

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.

reverse_self_iterator getReverseIterator()

self_iterator getIterator()

StringRef RangeListEncodingString(unsigned Encoding)

StringRef GDBIndexEntryLinkageString(GDBIndexEntryLinkage Linkage)

StringRef MacroString(unsigned Encoding)

StringRef LocListEncodingString(unsigned Encoding)

StringRef GnuMacroString(unsigned Encoding)

StringRef MacinfoString(unsigned Encoding)

StringRef OperationEncodingString(unsigned Encoding)

StringRef GDBIndexEntryKindString(GDBIndexEntryKind Kind)

#define llvm_unreachable(msg)

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

ValuesClass values(OptsTy... Options)

Helper to build a ValuesClass by forwarding a variable number of arguments as an initializer list to ...

initializer< Ty > init(const Ty &Val)

bool isCPlusPlus(SourceLanguage S)

@ DW_ARANGES_VERSION

Section version number for .debug_aranges.

@ DW_PUBNAMES_VERSION

Section version number for .debug_pubnames.

@ DWARF_VERSION

Other constants.

Scope

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

MCSymbol * emitListsTableHeaderStart(MCStreamer &S)

NodeAddr< InstrNode * > Instr

This is an optimization pass for GlobalISel generic memory operations.

bool operator<(int64_t V1, const APSInt &V2)

MachineBasicBlock::instr_iterator getBundleStart(MachineBasicBlock::instr_iterator I)

Returns an iterator to the first instruction in the bundle containing I.

bool all_of(R &&range, UnaryPredicate P)

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

auto enumerate(FirstRange &&First, RestRanges &&...Rest)

Given two or more input ranges, returns a new range whose values are tuples (A, B,...

auto unique(Range &&R, Predicate P)

void erase(Container &C, ValueType V)

Wrapper function to remove a value from a container:

bool any_of(R &&range, UnaryPredicate P)

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

void sort(IteratorTy Start, IteratorTy End)

AccelTableKind

The kind of accelerator tables we should emit.

@ Default

Platform default.

@ Apple

.apple_names, .apple_namespaces, .apple_types, .apple_objc.

@ Dwarf

DWARF v5 .debug_names.

raw_ostream & dbgs()

dbgs() - This returns a reference to a raw_ostream for debugging messages.

bool none_of(R &&Range, UnaryPredicate P)

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

void report_fatal_error(Error Err, bool gen_crash_diag=true)

Report a serious error, calling any installed error handler.

MachineBasicBlock::instr_iterator getBundleEnd(MachineBasicBlock::instr_iterator I)

Returns an iterator pointing beyond the bundle containing I.

bool is_sorted(R &&Range, Compare C)

Wrapper function around std::is_sorted to check if elements in a range R are sorted with respect to a...

uint64_t offsetToAlignment(uint64_t Value, Align Alignment)

Returns the offset to the next integer (mod 2**64) that is greater than or equal to Value and is a mu...

@ Global

Append to llvm.global_dtors.

@ Ref

The access may reference the value stored in memory.

void emitAppleAccelTable(AsmPrinter *Asm, AccelTable< DataT > &Contents, StringRef Prefix, const MCSymbol *SecBegin)

Emit an Apple Accelerator Table consisting of entries in the specified AccelTable.

void emitDWARF5AccelTable(AsmPrinter *Asm, DWARF5AccelTable &Contents, const DwarfDebug &DD, ArrayRef< std::unique_ptr< DwarfCompileUnit > > CUs)

void erase_if(Container &C, UnaryPredicate P)

Provide a container algorithm similar to C++ Library Fundamentals v2's erase_if which is equivalent t...

DebuggerKind

Identify a debugger for "tuning" the debug info.

@ SCE

Tune debug info for SCE targets (e.g. PS4).

@ DBX

Tune debug info for dbx.

@ Default

No specific tuning requested.

@ GDB

Tune debug info for gdb.

@ LLDB

Tune debug info for lldb.

Implement std::hash so that hash_code can be used in STL containers.

Represents a parameter whose call site value can be described by applying a debug expression to a reg...

uint64_t ParamReg

The described parameter register.

const DIExpression * Expr

Debug expression that has been built up when walking through the instruction chain that produces the ...

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

Description of the encoding of one expression Op.

SmallVector< Encoding > Op

Encoding for Op operands.

A pair of GlobalVariable and DIExpression.

Represents an entry-value location, or a fragment of one.

Single location defined by (potentially multiple) EntryValueInfo.

Single location defined by (potentially multiple) MMI entries.

void addFrameIndexExpr(const DIExpression *Expr, int FI)

const std::set< FrameIndexExpr > & getFrameIndexExprs() const

Get the FI entries, sorted by fragment offset.

A MapVector that performs no allocations if smaller than a certain size.

Helper used to pair up a symbol and its DWARF compile unit.

This struct describes target specific location.

Describes an entry of the various gnu_pub* debug sections.