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 && ->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 ((&*Suc, ForwardedRegWorklist, Params, ClobberedRegUnits))
852 return;
853 }
854
855
857
858 if ((&*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 (.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 (.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 (.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 (.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 (->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 (.Expr ||
.Expr)
1126 return !.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 });
1137 }),
1138 GVEs.end());
1139 return GVEs;
1140}
1141
1142
1143
1144
1147
1148 if ()
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 (.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 (->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;
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 (.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 (->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 ()
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 () {
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 ( && !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->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;
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 && .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 (.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 ( && 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
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.