65#define DEBUG_TYPE "dwarfdebug"
67STATISTIC(NumCSParams,
"Number of dbg call site params created");
70 "use-dwarf-ranges-base-address-specifier",
cl::Hidden,
80 cl::desc(
"Generate DWARF4 type units."),
91 cl::desc(
"Make an absence of debug location information explicit."),
99 "Default for platform"),
107 cl::desc(
"Use inlined strings rather than string section."),
115 cl::desc(
"Disable emission .debug_ranges section."),
120 cl::desc(
"Use sections+offset as references rather than labels."),
127 cl::desc(
"Emit the GNU .debug_macro format with DWARF <5"),
132 cl::desc(
"Enable use of the DWARFv5 DW_OP_convert operator"),
145 cl::desc(
"Which DWARF linkage-name attributes to emit."),
147 "Default for platform"),
150 "Abstract subprograms")),
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"),
160 "Use rnglists for contiguous ranges if that allows "
161 "using a pre-existing base address"),
164 "Use exprloc addrx+offset expressions for any "
165 "address with a prior base address"),
167 "Use addrx+offset extension form for any address "
168 "with a prior base address"),
176 cl::desc(
"Set to false to ignore Key Instructions metadata"));
180void DebugLocDwarfExpression::emitOp(
uint8_t Op,
const char *Comment) {
186void DebugLocDwarfExpression::emitSigned(int64_t
Value) {
187 getActiveStreamer().emitSLEB128(
Value, Twine(
Value));
191 getActiveStreamer().emitULEB128(
Value, Twine(
Value));
194void DebugLocDwarfExpression::emitData1(uint8_t
Value) {
195 getActiveStreamer().emitInt8(
Value, Twine(
Value));
198void DebugLocDwarfExpression::emitBaseTypeRef(
uint64_t Idx) {
210 assert(!IsBuffering &&
"Already buffering?");
212 TmpBuf = std::make_unique<TempBuffer>(OutBS.GenerateComments);
219 return TmpBuf ? TmpBuf->Bytes.size() : 0;
225 for (
auto Byte :
enumerate(TmpBuf->Bytes)) {
226 const char *
Comment = (
Byte.index() < TmpBuf->Comments.size())
227 ? TmpBuf->Comments[
Byte.index()].c_str()
229 OutBS.emitInt8(
Byte.value(), Comment);
231 TmpBuf->Bytes.clear();
232 TmpBuf->Comments.clear();
243 const bool IsVariadic = !SingleLocExprOpt;
246 if (!IsVariadic && !
MI->isNonListDebugValue()) {
247 assert(
MI->getNumDebugOperands() == 1 &&
248 "Mismatched DIExpression and debug operands for debug instruction.");
249 Expr = *SingleLocExprOpt;
256 MI->isNonListDebugValue() &&
MI->isDebugOffsetImm());
258 }
else if (
Op.isTargetIndex()) {
261 }
else if (
Op.isGlobal()) {
264 }
else if (
Op.isImm())
266 else if (
Op.isFPImm())
268 else if (
Op.isCImm())
273 return DbgValueLoc(Expr, DbgValueLocEntries, IsVariadic);
292 Expr(ValueLoc.getExpression()) {
293 if (!Expr->getNumElements())
309 return FIE.Expr && FIE.Expr->isFragment();
311 "conflicting locations for variable");
315 bool GenerateTypeUnits,
324 if (GenerateTypeUnits && (DwarfVersion < 5 || !TT.isOSBinFormatELF()))
330 if (DwarfVersion >= 5)
340 SkeletonHolder(
A,
"skel_string", DIEValueAllocator),
341 IsDarwin(
A->TM.getTargetTriple().isOSDarwin()),
343 const Triple &TT =
Asm->TM.getTargetTriple();
348 DebuggerTuning =
Asm->TM.Options.DebuggerTuning;
353 else if (TT.isOSAIX())
369 HasSplitDwarf = !
Asm->TM.Options.MCOptions.SplitDwarfFile.empty();
377 unsigned DwarfVersionNumber =
Asm->TM.Options.MCOptions.DwarfVersion;
378 unsigned DwarfVersion = DwarfVersionNumber ? DwarfVersionNumber
379 :
MMI->getModule()->getDwarfVersion();
383 bool Dwarf64 = DwarfVersion >= 3 &&
392 ((
Asm->TM.Options.MCOptions.Dwarf64 ||
MMI->getModule()->isDwarf64()) &&
393 TT.isOSBinFormatELF()) ||
394 TT.isOSBinFormatXCOFF();
396 if (!Dwarf64 && TT.isArch64Bit() && TT.isOSBinFormatXCOFF())
405 GenerateTypeUnits = (
A->TM.getTargetTriple().isOSBinFormatELF() ||
406 A->TM.getTargetTriple().isOSBinFormatWasm()) &&
410 DwarfVersion, GenerateTypeUnits, DebuggerTuning,
A->TM.getTargetTriple());
417 UseGNUTLSOpcode =
tuneForGDB() || DwarfVersion < 3;
419 UseDWARF2Bitfields = DwarfVersion < 4;
425 UseSegmentedStringOffsetsTable = DwarfVersion >= 5;
429 EmitDebugEntryValues =
Asm->TM.shouldEmitDebugEntryValues();
433 UseDebugMacroSection =
442 if (DwarfVersion >= 5)
445 Asm->OutStreamer->getContext().setDwarfVersion(DwarfVersion);
454 return Name.starts_with(
"+") || Name.starts_with(
"-");
461 return Name.contains(
") ");
467 Class = In.slice(In.find(
'[') + 1, In.find(
' '));
472 Class = In.slice(In.find(
'[') + 1, In.find(
'('));
473 Category = In.slice(In.find(
'[') + 1, In.find(
' '));
477 return In.slice(In.find(
' ') + 1, In.find(
']'));
490 if (!SP->isDefinition())
493 if (SP->getName() !=
"")
524 if (Scope->isAbstractScope())
542 if (
auto *SkelCU =
CU.getSkeleton())
543 if (
CU.getCUNode()->getSplitDebugInlining())
554 auto &
CU = getOrCreateDwarfCompileUnit(SP->getUnit());
555 if (
CU.getSkeleton())
561void DwarfDebug::constructAbstractSubprogramScopeDIE(
DwarfCompileUnit &SrcCU,
563 assert(Scope && Scope->getScopeNode());
564 assert(Scope->isAbstractScope());
565 assert(!Scope->getInlinedAt());
571 auto &
CU = getOrCreateDwarfCompileUnit(SP->getUnit());
573 TargetCU.constructAbstractSubprogramScopeDIE(Scope);
574 if (
auto *SkelCU =
CU.getSkeleton())
575 if (
CU.getCUNode()->getSplitDebugInlining())
576 SkelCU->constructAbstractSubprogramScopeDIE(Scope);
610template <
typename ValT>
614 for (
auto Param : DescribedParams) {
615 bool ShouldCombineExpressions = Expr && Param.Expr->
getNumElements() > 0;
625 "Combined debug expression is invalid");
640 auto &ParamsForFwdReg = Worklist[
Reg];
641 for (
auto Param : ParamsToAdd) {
644 return D.ParamReg == Param.ParamReg;
646 "Same parameter described twice by forwarding reg");
653 ParamsForFwdReg.push_back({Param.ParamReg, CombinedExpr});
673 auto IsRegClobberedInMeantime = [&](
Register Reg) ->
bool {
674 for (
auto &RegUnit : ClobberedRegUnits)
675 if (
TRI.hasRegUnit(
Reg, RegUnit))
680 auto DescribeFwdRegsByCalleeSavedCopy = [&](
const DestSourcePair &CopyInst) {
681 Register CopyDestReg = CopyInst.Destination->getReg();
682 Register CopySrcReg = CopyInst.Source->getReg();
683 if (IsRegClobberedInMeantime(CopyDestReg))
687 if (!
TRI.isCalleeSavedPhysReg(CopyDestReg, *MF))
694 for (
auto FwdRegIt = ForwardedRegWorklist.
begin();
695 FwdRegIt != ForwardedRegWorklist.
end();) {
697 if (FwdRegIt->first == CopySrcReg)
699 else if (
unsigned SubRegIdx =
700 TRI.getSubRegIndex(CopySrcReg, FwdRegIt->first))
701 if (
Register CopyDestSubReg =
TRI.getSubReg(CopyDestReg, SubRegIdx))
711 FwdRegIt = ForwardedRegWorklist.
erase(FwdRegIt);
719 if (
auto CopyInst =
TII.isCopyInstr(*CurMI))
720 DescribeFwdRegsByCalleeSavedCopy(*CopyInst);
748 if (
MI.isDebugInstr())
752 if (MO.getReg().isPhysical()) {
753 for (
auto &FwdReg : ForwardedRegWorklist)
754 if (
TRI.regsOverlap(FwdReg.first, MO.getReg()))
755 Defs.insert(FwdReg.first);
764 getForwardingRegsDefinedByMI(*CurMI, FwdRegDefs);
765 if (FwdRegDefs.
empty()) {
771 for (
auto ParamFwdReg : FwdRegDefs) {
772 if (
auto ParamValue =
TII.describeLoadedValue(*CurMI, ParamFwdReg)) {
773 if (ParamValue->first.isImm()) {
774 int64_t Val = ParamValue->first.getImm();
776 ForwardedRegWorklist[ParamFwdReg], Params);
777 }
else if (ParamValue->first.isReg()) {
778 Register RegLoc = ParamValue->first.getReg();
779 Register SP = TLI.getStackPointerRegisterToSaveRestore();
781 bool IsSPorFP = (RegLoc == SP) || (RegLoc ==
FP);
784 if (!IsRegClobberedInMeantime(RegLoc) &&
785 (
TRI.isCalleeSavedPhysReg(RegLoc, *MF) || IsSPorFP)) {
788 ForwardedRegWorklist[ParamFwdReg], Params);
797 ForwardedRegWorklist[ParamFwdReg]);
804 for (
auto ParamFwdReg : FwdRegDefs)
805 ForwardedRegWorklist.
erase(ParamFwdReg);
812 for (
auto &New : TmpWorklistItems)
814 TmpWorklistItems.
clear();
831 if (ForwardedRegWorklist.
empty())
838 interpretValues(CurMI, ForwardedRegWorklist, Params, ClobberedRegUnits);
849 auto CSInfo = CalleesMap.
find(CallMI);
852 if (CSInfo == CalleesMap.end())
866 for (
const auto &ArgReg : CSInfo->second.ArgRegPairs) {
868 ForwardedRegWorklist.
insert({ArgReg.Reg, {{ArgReg.Reg, EmptyExpr}}})
870 assert(InsertedReg &&
"Single register used to forward two arguments?");
875 for (
const auto &MO : CallMI->
uses())
876 if (MO.isReg() && MO.isUndef())
877 ForwardedRegWorklist.
erase(MO.getReg());
887 bool ShouldTryEmitEntryVals =
MBB->getIterator() == MF->
begin();
896 assert(std::next(Suc) == BundleEnd &&
897 "More than one instruction in call delay slot");
904 for (;
I !=
MBB->rend(); ++
I) {
911 if (ShouldTryEmitEntryVals) {
915 for (
auto &RegEntry : ForwardedRegWorklist) {
922void DwarfDebug::constructCallSiteEntryDIEs(
const DISubprogram &SP,
927 if (!
SP.areAllCallsDescribed() || !
SP.isDefinition())
934 CU.addFlag(ScopeDIE,
CU.getDwarf5OrGNUAttr(dwarf::DW_AT_call_all_calls));
937 assert(
TII &&
"TargetInstrInfo not found: cannot label tail calls");
940 auto delaySlotSupported = [&](
const MachineInstr &
MI) {
941 if (!
MI.isBundledWithSucc())
943 auto Suc = std::next(
MI.getIterator());
945 (void)CallInstrBundle;
947 (void)DelaySlotBundle;
954 "Call and its successor instruction don't have same label after.");
959 auto addCallSiteTargetForIndirectCalls = [&](
const MachineInstr *
MI,
963 auto CSInfo = CalleesMap.
find(
MI);
965 if (CSInfo == CalleesMap.end() || !CSInfo->second.CallTarget)
968 MDNode *CallTarget = CSInfo->second.CallTarget;
970 assert(!CallSiteDIE.findAttribute(dwarf::DW_AT_LLVM_virtual_call_origin) &&
971 "DW_AT_LLVM_virtual_call_origin already exists");
973 DIE *CalleeDIE =
CU.getOrCreateSubprogramDIE(CalleeSP,
nullptr);
974 assert(CalleeDIE &&
"Could not create DIE for call site entry origin");
975 CU.addDIEEntry(CallSiteDIE,
976 CU.getDwarf5OrGNUAttr(dwarf::DW_AT_LLVM_virtual_call_origin),
979 CU.addLinkageNamesToDeclarations(*
this, *CalleeSP, *CalleeDIE);
983 for (
const MachineBasicBlock &
MBB : MF) {
993 if (!
MI.isCandidateForAdditionalCallInfo())
1002 if (
MI.hasDelaySlot() && !delaySlotSupported(*&
MI))
1010 const MachineOperand &CalleeOp =
TII->getCalleeOperand(
MI);
1011 bool PhysRegCalleeOperand =
1013 MachineLocation CallTarget{0};
1015 const DISubprogram *CalleeSP =
nullptr;
1016 const Function *CalleeDecl =
nullptr;
1017 if (PhysRegCalleeOperand) {
1018 bool Scalable =
false;
1019 const MachineOperand *BaseOp =
nullptr;
1020 const TargetRegisterInfo &
TRI =
1021 *
Asm->MF->getSubtarget().getRegisterInfo();
1022 if (
TII->getMemOperandWithOffset(
MI, BaseOp,
Offset, Scalable, &
TRI)) {
1023 if (BaseOp && BaseOp->
isReg() && !Scalable)
1024 CallTarget = MachineLocation(BaseOp->
getReg(),
true);
1028 CallTarget = MachineLocation(CalleeOp.
getReg());
1037 if (CalleeSP ==
nullptr && CallTarget.
getReg() == 0 &&
1038 AllocSiteTy ==
nullptr)
1048 const MachineInstr *TopLevelCallMI =
1055 const MCSymbol *PCAddr = (!IsTail ||
CU.useGNUAnalogForDwarf5Feature())
1064 assert((IsTail || PCAddr) &&
"Non-tail call without return PC");
1067 dbgs() <<
"CallSiteEntry: " << MF.getName() <<
" -> "
1071 MF.getSubtarget().getRegisterInfo()->getName(
1073 << (IsTail ?
" [IsTail]" :
"") <<
"\n");
1075 DIE &CallSiteDIE =
CU.constructCallSiteEntryDIE(
1076 ScopeDIE, CalleeSP, CalleeDecl, IsTail, PCAddr, CallAddr, CallTarget,
1080 addCallSiteTargetForIndirectCalls(TopLevelCallMI, CallSiteDIE);
1087 CU.constructCallSiteParmEntryDIEs(CallSiteDIE, Params);
1094 if (!
U.hasDwarfPubSections())
1097 U.addFlag(
D, dwarf::DW_AT_GNU_pubnames);
1103 case dwarf::DW_LNAME_Fortran:
1104 case dwarf::DW_LNAME_Cobol:
1105 case dwarf::DW_LNAME_Pascal:
1112 case dwarf::DW_LANG_Cobol74:
1113 case dwarf::DW_LANG_Cobol85:
1114 case dwarf::DW_LANG_Fortran77:
1115 case dwarf::DW_LANG_Fortran90:
1116 case dwarf::DW_LANG_Fortran95:
1117 case dwarf::DW_LANG_Fortran03:
1118 case dwarf::DW_LANG_Fortran08:
1119 case dwarf::DW_LANG_Fortran18:
1120 case dwarf::DW_LANG_Fortran23:
1121 case dwarf::DW_LANG_Pascal83:
1128void DwarfDebug::finishUnitAttributes(
const DICompileUnit *DIUnit,
1136 std::string ProducerWithFlags =
Producer.str() +
" " +
Flags.str();
1137 NewCU.
addString(Die, dwarf::DW_AT_producer, ProducerWithFlags);
1139 NewCU.
addString(Die, dwarf::DW_AT_producer, Producer);
1142 NewCU.
addUInt(Die, dwarf::DW_AT_language_name, dwarf::DW_FORM_data2,
1145 if (uint32_t LangVersion = Lang.getVersion(); LangVersion != 0)
1146 NewCU.
addUInt(Die, dwarf::DW_AT_language_version, std::nullopt,
1149 NewCU.
addUInt(Die, dwarf::DW_AT_language, dwarf::DW_FORM_data2,
1154 NewCU.
addUInt(Die, dwarf::DW_AT_identifier_case, dwarf::DW_FORM_data1,
1156 NewCU.
addString(Die, dwarf::DW_AT_name, FN);
1161 if (!SysRoot.
empty())
1162 NewCU.
addString(Die, dwarf::DW_AT_LLVM_sysroot, SysRoot);
1163 StringRef SDK = DIUnit->
getSDK();
1165 NewCU.
addString(Die, dwarf::DW_AT_APPLE_sdk, SDK);
1176 if (!CompilationDir.empty())
1177 NewCU.
addString(Die, dwarf::DW_AT_comp_dir, CompilationDir);
1178 addGnuPubAttributes(NewCU, Die);
1182 NewCU.
addFlag(Die, dwarf::DW_AT_APPLE_optimized);
1187 NewCU.
addString(Die, dwarf::DW_AT_APPLE_flags, Flags);
1190 NewCU.
addUInt(Die, dwarf::DW_AT_APPLE_major_runtime_vers,
1191 dwarf::DW_FORM_data1, RVer);
1196 NewCU.
addUInt(Die, dwarf::DW_AT_GNU_dwo_id, dwarf::DW_FORM_data8,
1201 ? dwarf::DW_AT_dwo_name
1202 : dwarf::DW_AT_GNU_dwo_name;
1209 if (
auto *
CU = CUMap.lookup(DIUnit))
1216 return CUMap.begin()->second;
1224DwarfDebug::getOrCreateDwarfCompileUnit(
const DICompileUnit *DIUnit) {
1225 if (
auto *
CU = getDwarfCompileUnit(DIUnit))
1230 auto OwnedUnit = std::make_unique<DwarfCompileUnit>(
1232 DwarfCompileUnit &NewCU = *OwnedUnit;
1239 if (!
Asm->OutStreamer->hasRawTextSupport() || SingleCU)
1240 Asm->OutStreamer->emitDwarfFile0Directive(
1246 NewCU.
setSection(
Asm->getObjFileLowering().getDwarfInfoDWOSection());
1248 finishUnitAttributes(DIUnit, NewCU);
1249 NewCU.
setSection(
Asm->getObjFileLowering().getDwarfInfoSection());
1252 CUMap.insert({DIUnit, &NewCU});
1253 CUDieMap.insert({&NewCU.
getUnitDie(), &NewCU});
1267 if (!
A.Expr || !
B.Expr)
1269 auto FragmentA =
A.Expr->getFragmentInfo();
1270 auto FragmentB =
B.Expr->getFragmentInfo();
1271 if (!FragmentA || !FragmentB)
1273 return FragmentA->OffsetInBits < FragmentB->OffsetInBits;
1278 return A.Expr ==
B.Expr;
1293 unsigned NumDebugCUs = std::distance(M->debug_compile_units_begin(),
1294 M->debug_compile_units_end());
1295 if (NumDebugCUs == 0)
1298 assert(NumDebugCUs > 0 &&
"Asm unexpectedly initialized");
1299 SingleCU = NumDebugCUs == 1;
1306 .setStringOffsetsStartSym(
Asm->createTempSymbol(
"str_offsets_base"));
1314 Asm->createTempSymbol(
"rnglists_table_base"));
1318 Asm->createTempSymbol(
"rnglists_dwo_table_base"));
1323 AddrPool.setLabel(
Asm->createTempSymbol(
"addr_table_base"));
1324 DebugLocs.setSym(
Asm->createTempSymbol(
"loclists_table_base"));
1327 if (CUNode->getImportedEntities().empty() &&
1328 CUNode->getEnumTypes().empty() && CUNode->getRetainedTypes().empty() &&
1329 CUNode->getGlobalVariables().empty() && CUNode->getMacros().empty())
1332 getOrCreateDwarfCompileUnit(CUNode);
1336void DwarfDebug::finishEntityDefinitions() {
1337 for (
const auto &Entity : ConcreteEntities) {
1338 DIE *Die = Entity->getDIE();
1345 Unit->finishEntityDefinition(Entity.get());
1349void DwarfDebug::finishSubprogramDefinitions() {
1350 for (
const DISubprogram *SP : ProcessedSPNodes) {
1353 getOrCreateDwarfCompileUnit(
SP->getUnit()),
1354 [&](DwarfCompileUnit &
CU) { CU.finishSubprogramDefinition(SP); });
1358void DwarfDebug::finalizeModuleInfo() {
1359 const TargetLoweringObjectFile &TLOF =
Asm->getObjFileLowering();
1361 finishSubprogramDefinitions();
1363 finishEntityDefinitions();
1365 bool HasEmittedSplitCU =
false;
1369 for (
const auto &
P : CUMap) {
1370 auto &TheCU = *
P.second;
1371 if (TheCU.getCUNode()->isDebugDirectivesOnly())
1373 TheCU.attachLexicalScopesAbstractOrigins();
1376 TheCU.constructContainingTypeDIEs();
1377 TheCU.constructPropertyForwardDIEs();
1382 auto *SkCU = TheCU.getSkeleton();
1384 bool HasSplitUnit = SkCU && !TheCU.getUnitDie().children().empty();
1387 (void)HasEmittedSplitCU;
1389 "Multiple CUs emitted into a single dwo file");
1390 HasEmittedSplitCU =
true;
1392 ? dwarf::DW_AT_dwo_name
1393 : dwarf::DW_AT_GNU_dwo_name;
1394 finishUnitAttributes(TheCU.getCUNode(), TheCU);
1395 StringRef DWOName =
Asm->TM.Options.MCOptions.SplitDwarfFile;
1396 TheCU.addString(TheCU.getUnitDie(), attrDWOName, DWOName);
1397 SkCU->addString(SkCU->getUnitDie(), attrDWOName, DWOName);
1403 DIEHash(
Asm, &TheCU).computeCUSignature(DWOName, TheCU.getUnitDie());
1408 TheCU.addUInt(TheCU.getUnitDie(), dwarf::DW_AT_GNU_dwo_id,
1409 dwarf::DW_FORM_data8, ID);
1410 SkCU->addUInt(SkCU->getUnitDie(), dwarf::DW_AT_GNU_dwo_id,
1411 dwarf::DW_FORM_data8, ID);
1414 if (
getDwarfVersion() < 5 && !SkeletonHolder.getRangeLists().empty()) {
1416 SkCU->addSectionLabel(SkCU->getUnitDie(), dwarf::DW_AT_GNU_ranges_base,
1420 finishUnitAttributes(SkCU->getCUNode(), *SkCU);
1429 DwarfCompileUnit &
U = SkCU ? *SkCU : TheCU;
1431 if (
unsigned NumRanges = TheCU.getRanges().size()) {
1438 U.addUInt(
U.getUnitDie(), dwarf::DW_AT_low_pc, dwarf::DW_FORM_addr,
1441 U.setBaseAddress(TheCU.getRanges().front().Begin);
1442 U.attachRangesOrLowHighPC(
U.getUnitDie(), TheCU.takeRanges());
1449 U.addAddrTableBase();
1452 if (
U.hasRangeLists())
1453 U.addRnglistsBase();
1456 U.addSectionLabel(
U.getUnitDie(), dwarf::DW_AT_loclists_base,
1465 if (CUNode->getMacros()) {
1467 if (UseDebugMacroSection) {
1472 ? dwarf::DW_AT_macros
1473 : dwarf::DW_AT_GNU_macros;
1475 U.getMacroLabelBegin(), Section);
1481 dwarf::DW_AT_macro_info,
1482 U.getMacroLabelBegin(), Section);
1488 for (
auto *CUNode :
MMI->getModule()->debug_compile_units())
1489 if (CUNode->getDWOId())
1490 getOrCreateDwarfCompileUnit(CUNode);
1495 SkeletonHolder.computeSizeAndOffsets();
1499 AccelDebugNames.convertDieToOffset();
1508 assert(CurFn ==
nullptr);
1518 Global.getDebugInfo(GVs);
1519 for (
auto *GVE : GVs)
1520 GVMap[GVE->getVariable()].push_back({&
Global, GVE->getExpression()});
1531 for (
auto *GVE : CUNode->getGlobalVariables()) {
1535 auto &GVMapEntry = GVMap[GVE->getVariable()];
1536 auto *Expr = GVE->getExpression();
1537 if (!GVMapEntry.size() || (Expr && Expr->isConstant()))
1538 GVMapEntry.push_back({
nullptr, Expr});
1541 for (
auto *GVE : CUNode->getGlobalVariables()) {
1544 "Unexpected function-local entity in 'globals' CU field.");
1545 if (Processed.
insert(GV).second)
1550 for (
auto *Ty : CUNode->getEnumTypes()) {
1552 "Unexpected function-local entity in 'enums' CU field.");
1556 for (
auto *Ty : CUNode->getRetainedTypes()) {
1559 CU->getOrCreateTypeDIE(RT);
1564 for (
auto *IE : CUNode->getImportedEntities()) {
1566 "Unexpected function-local entity in 'imports' CU field.");
1567 CU->getOrCreateImportedEntityDIE(IE);
1571 const auto Unexpected = [](
const Metadata *
N) {
1574 for (
const auto *
D :
CU->getDeferredLocalDecls())
1575 DISubprogram::visitRetainedNode<void>(
1576 D, Unexpected, Unexpected,
1577 [
CU](
const auto *IE) {
CU->getOrCreateImportedEntityDIE(IE); },
1578 [
CU](
const auto *Ty) {
CU->getOrCreateTypeDIE(Ty); },
1579 [&](
const auto *GVE) {
1581 if (Processed.
insert(GV).second)
1587 CU->createBaseTypeDIEs();
1592 if (!
Asm || !
Asm->hasDebugInfo())
1596 finalizeModuleInfo();
1606 emitAbbreviations();
1612 if (UseARangesSection)
1620 emitDebugMacinfoDWO();
1630 emitDebugAbbrevDWO();
1632 emitDebugRangesDWO();
1642 emitAccelNamespaces();
1646 emitAccelDebugNames();
1655 emitDebugPubSections();
1663 if (
CU.getExistingAbstractEntity(
Node))
1668 CU.createAbstractEntity(
Node, Scope);
1677void DwarfDebug::collectVariableInfoFromMFTable(
1679 SmallDenseMap<InlinedEntity, DbgVariable *> MFVars;
1680 LLVM_DEBUG(
dbgs() <<
"DwarfDebug: collecting variables from MF side table\n");
1681 for (
const auto &VI :
Asm->MF->getVariableDbgInfo()) {
1684 assert(
VI.Var->isValidLocationForIntrinsic(
VI.Loc) &&
1685 "Expected inlined-at fields to agree");
1687 InlinedEntity Var(
VI.Var,
VI.Loc->getInlinedAt());
1694 <<
", no variable scope found\n");
1698 ensureAbstractEntityIsCreatedIfScoped(TheCU, Var.first,
Scope->getScopeNode());
1702 if (DbgVariable *PreviousLoc = MFVars.
lookup(Var)) {
1703 auto *PreviousMMI = std::get_if<Loc::MMI>(PreviousLoc);
1704 auto *PreviousEntryValue = std::get_if<Loc::EntryValue>(PreviousLoc);
1706 if (PreviousMMI &&
VI.inStackSlot())
1707 PreviousMMI->addFrameIndexExpr(
VI.Expr,
VI.getStackSlot());
1709 else if (PreviousEntryValue &&
VI.inEntryValueRegister())
1710 PreviousEntryValue->addExpr(
VI.getEntryValueRegister(), *
VI.Expr);
1715 if (PreviousLoc->holds<Loc::MMI>())
1716 PreviousLoc->emplace<Loc::EntryValue>(
VI.getEntryValueRegister(),
1719 <<
", conflicting fragment location types\n");
1724 auto RegVar = std::make_unique<DbgVariable>(
1726 if (
VI.inStackSlot())
1727 RegVar->emplace<Loc::MMI>(
VI.Expr,
VI.getStackSlot());
1729 RegVar->emplace<Loc::EntryValue>(
VI.getEntryValueRegister(), *
VI.Expr);
1732 InfoHolder.addScopeVariable(Scope, RegVar.get());
1733 MFVars.
insert({Var, RegVar.get()});
1734 ConcreteEntities.push_back(std::move(RegVar));
1746 assert(
DbgValue->getDebugLoc() &&
"DBG_VALUE without a debug location");
1754 if (LSRange.size() == 0)
1757 const MachineInstr *LScopeBegin = LSRange.front().first;
1761 if (!Ordering.isBefore(
DbgValue, LScopeBegin)) {
1767 for (++Pred; Pred !=
MBB->rend(); ++Pred) {
1770 auto PredDL = Pred->getDebugLoc();
1771 if (!PredDL || Pred->isMetaInstruction())
1775 if (
DL->getScope() == PredDL->getScope())
1778 if (!PredScope || LScope->dominates(PredScope))
1793 if (
MBB->pred_empty() &&
1795 return Op.isImm() || Op.isGlobal();
1801 if (Ordering.isBefore(RangeEnd, LScopeEnd))
1845 std::pair<DbgValueHistoryMap::EntryIndex, DbgValueLoc>;
1847 bool isSafeForSingleLocation =
true;
1848 const MachineInstr *StartDebugMI =
nullptr;
1849 const MachineInstr *EndMI =
nullptr;
1851 for (
auto EB = Entries.
begin(), EI = EB, EE = Entries.
end(); EI != EE; ++EI) {
1852 const MachineInstr *
Instr = EI->getInstr();
1855 size_t Index = std::distance(EB, EI);
1856 erase_if(OpenRanges, [&](OpenRange &R) {
return R.first <=
Index; });
1863 "Forgot label before/after instruction starting a range!");
1866 if (std::next(EI) == Entries.
end()) {
1867 const MachineBasicBlock &EndMBB =
Asm->MF->back();
1869 if (EI->isClobber())
1870 EndMI = EI->getInstr();
1872 else if (std::next(EI)->isClobber())
1876 assert(EndLabel &&
"Forgot label after instruction ending a range!");
1878 if (EI->isDbgValue())
1884 if (EI->isDbgValue()) {
1891 if (!
Instr->isUndefDebugValue()) {
1896 if (
Instr->getDebugExpression()->isFragment())
1897 isSafeForSingleLocation =
false;
1900 StartDebugMI =
Instr;
1902 isSafeForSingleLocation =
false;
1908 if (OpenRanges.
empty())
1912 if (StartLabel == EndLabel) {
1913 LLVM_DEBUG(
dbgs() <<
"Omitting location list entry with empty range.\n");
1918 for (
auto &R : OpenRanges)
1926 if (
Asm->MF->hasBBSections() && StartLabel ==
Asm->getFunctionBegin() &&
1927 !
Instr->getParent()->sameSection(&
Asm->MF->front())) {
1928 for (
const auto &[MBBSectionId, MBBSectionRange] :
1929 Asm->MBBSectionRanges) {
1930 if (
Instr->getParent()->getSectionID() == MBBSectionId) {
1931 DebugLoc.emplace_back(MBBSectionRange.BeginLabel, EndLabel,
Values);
1934 DebugLoc.emplace_back(MBBSectionRange.BeginLabel,
1935 MBBSectionRange.EndLabel,
Values);
1945 dbgs() << CurEntry->getValues().size() <<
" Values:\n";
1946 for (
auto &
Value : CurEntry->getValues())
1948 dbgs() <<
"-----\n";
1951 auto PrevEntry = std::next(CurEntry);
1952 if (PrevEntry !=
DebugLoc.rend() && PrevEntry->MergeRanges(*CurEntry))
1956 if (!isSafeForSingleLocation ||
1963 if (!
Asm->MF->hasBBSections())
1971 const MachineBasicBlock *RangeMBB =
nullptr;
1972 if (
DebugLoc[0].getBeginSym() ==
Asm->getFunctionBegin())
1973 RangeMBB = &
Asm->MF->front();
1975 RangeMBB = Entries.
begin()->getInstr()->getParent();
1977 assert(RangeIt !=
Asm->MBBSectionRanges.end() &&
1978 "Range MBB not found in MBBSectionRanges!");
1980 auto *NextEntry = std::next(CurEntry);
1981 auto NextRangeIt = std::next(RangeIt);
1982 while (NextEntry !=
DebugLoc.end()) {
1983 if (NextRangeIt ==
Asm->MBBSectionRanges.end())
1990 if ((RangeIt->second.EndLabel !=
Asm->getFunctionEnd() &&
1991 CurEntry->getEndSym() != RangeIt->second.EndLabel) ||
1992 NextEntry->getBeginSym() != NextRangeIt->second.BeginLabel ||
1993 CurEntry->getValues() != NextEntry->getValues())
1995 RangeIt = NextRangeIt;
1996 NextRangeIt = std::next(RangeIt);
1997 CurEntry = NextEntry;
1998 NextEntry = std::next(CurEntry);
2008 ensureAbstractEntityIsCreatedIfScoped(TheCU, Node,
Scope.getScopeNode());
2010 ConcreteEntities.push_back(
2016 ConcreteEntities.push_back(
2022 return ConcreteEntities.back().get();
2030 collectVariableInfoFromMFTable(TheCU, Processed);
2033 InlinedEntity
IV =
I.first;
2038 const auto &HistoryMapEntries =
I.second;
2042 if (!
DbgValues.hasNonEmptyLocation(HistoryMapEntries))
2045 LexicalScope *
Scope =
nullptr;
2047 if (
const DILocation *IA =
IV.second)
2057 *Scope, LocalVar,
IV.second));
2059 const MachineInstr *MInsn = HistoryMapEntries.front().getInstr();
2065 size_t HistSize = HistoryMapEntries.size();
2066 bool SingleValueWithClobber =
2067 HistSize == 2 && HistoryMapEntries[1].isClobber();
2068 if (HistSize == 1 || SingleValueWithClobber) {
2070 SingleValueWithClobber ? HistoryMapEntries[1].getInstr() :
nullptr;
2072 RegVar->emplace<Loc::Single>(MInsn);
2078 DebugLocStream::ListBuilder
List(DebugLocs, TheCU, *
Asm, *RegVar);
2082 bool isValidSingleLocation = buildLocationList(Entries, HistoryMapEntries);
2087 if (isValidSingleLocation) {
2088 RegVar->emplace<Loc::Single>(Entries[0].getValues()[0]);
2099 for (
auto &Entry : Entries)
2106 InlinedEntity IL =
I.first;
2107 const MachineInstr *
MI =
I.second;
2111 LexicalScope *
Scope =
nullptr;
2114 const DILocalScope *LocalScope =
2115 Label->getScope()->getNonLexicalBlockFileScope();
2117 if (
const DILocation *IA = IL.second)
2130 createConcreteEntity(TheCU, *Scope, Label, IL.second, Sym);
2134 for (
const MDNode *
N :
SP->getRetainedNodes()) {
2138 if (!Processed.
insert(InlinedEntity(DN,
nullptr)).second)
2140 LexicalScope *LexS =
LScopes.findLexicalScope(LS);
2142 createConcreteEntity(TheCU, *LexS, DN,
nullptr);
2144 LocalDeclsPerLS[
LS].insert(
N);
2158 if (!
MI.isBundledWithSucc())
2160 auto Suc = std::next(
MI.getIterator());
2165 assert(Suc->isBundledWithPred() &&
2166 "Call bundle instructions are out of order");
2171 if (!NoDebug && SP->areAllCallsDescribed() &&
2173 (!
MI->hasDelaySlot() || delaySlotSupported(*
MI))) {
2175 bool IsTail =
TII->isTailCall(*
MI);
2193 auto RecordLineZero = [&]() {
2197 const MDNode *Scope =
nullptr;
2198 unsigned Column = 0;
2203 recordSourceLine(0, Column, Scope, 0);
2208 unsigned LastAsmLine =
2209 Asm->OutStreamer->getContext().getCurrentDwarfLoc().getLine();
2214 if (
MI->isMetaInstruction())
2235 auto RecordSourceLine = [
this](
auto &
DL,
auto Flags) {
2237 if (
Asm->OutStreamer->isVerboseAsm()) {
2241 recordSourceLine(
DL.getLine(),
DL.getCol(),
DL.getScope(), Flags,
2250 bool ScopeUsesKeyInstructions =
2252 DL->getScope()->getSubprogram()->getKeyInstructionsEnabled();
2255 if (ScopeUsesKeyInstructions &&
DL &&
DL.getLine())
2256 IsKey = KeyInstructions.contains(
MI);
2262 assert(
MI->getParent() == &*
MI->getMF()->begin());
2263 recordSourceLine(SP->getScopeLine(), 0, SP,
2268 bool PrevInstInSameSection =
2270 PrevInstBB->getSectionID() ==
MI->getParent()->getSectionID());
2271 bool ForceIsStmt = ForceIsStmtInstrs.contains(
MI);
2272 if (PrevInstInSameSection && !ForceIsStmt &&
DL.isSameSourceLocation(
PrevInstLoc)) {
2282 if ((LastAsmLine == 0 &&
DL.getLine() != 0) || Flags) {
2284 RecordSourceLine(
DL, Flags);
2297 if (LastAsmLine == 0)
2318 if (
DL.getLine() == 0 && LastAsmLine == 0)
2325 if (ScopeUsesKeyInstructions) {
2332 if (
DL.getLine() && (
DL.getLine() != OldLine || ForceIsStmt))
2347 if (
Asm->OutStreamer->isVerboseAsm()) {
2351 recordSourceLine(
DL.getLine(),
DL.getCol(),
DL.getScope(), Flags,
2360static std::pair<const MachineInstr *, bool>
2371 bool IsEmptyPrologue =
2372 !(
F.hasPrologueData() ||
F.getMetadata(LLVMContext::MD_func_sanitize));
2377 -> std::optional<std::pair<const MachineInstr *, bool>> {
2379 bool isCopy = (
TII.isCopyInstr(
MI) ?
true :
false);
2380 bool isTrivRemat =
TII.isTriviallyReMaterializable(
MI);
2383 if (!isFrameSetup &&
MI.getDebugLoc()) {
2389 if (
MI.getDebugLoc().getLine())
2390 return std::make_pair(&
MI, IsEmptyPrologue);
2395 if (!
isCopy && !isTrivRemat && !isFrameSetup && !NonTrivialInst)
2396 NonTrivialInst = &
MI;
2398 IsEmptyPrologue =
false;
2399 return std::nullopt;
2407 auto CurBlock = MF->
begin();
2408 auto CurInst = CurBlock->begin();
2412 while (CurBlock->empty())
2413 CurInst = (++CurBlock)->begin();
2414 assert(CurInst != CurBlock->end());
2418 auto getNextInst = [&CurBlock, &CurInst, MF]() ->
bool {
2420 if (CurInst->isTerminator()) {
2429 if (CurBlock->pred_size() > 1)
2440 if (CurBlock == MF->
end())
2442 }
while (CurBlock->empty());
2443 CurInst = CurBlock->begin();
2449 if (!CurInst->isMetaInstruction()) {
2450 auto FoundInst = ExamineInst(*CurInst);
2461 if (CurInst->isCall()) {
2463 Loc &&
Loc->getLine() == 0) {
2465 unsigned ScopeLine = SP->getScopeLine();
2468 const_cast<MachineInstr *
>(&*CurInst)->setDebugLoc(ScopeLineDILoc);
2471 return std::make_pair(&*CurInst,
false);
2477 auto NextInst = std::next(CurInst);
2478 if (NextInst != CurInst->getParent()->end()) {
2495 if (NonTrivialInst && NonTrivialInst->
getParent() == &*MF->
begin()) {
2496 IsEmptyPrologue = NonTrivialInst == &*MF->
begin()->begin();
2497 return std::make_pair(NonTrivialInst, IsEmptyPrologue);
2501 return std::make_pair(
nullptr, IsEmptyPrologue);
2507 const MDNode *S,
unsigned Flags,
unsigned CUID,
2509 ArrayRef<std::unique_ptr<DwarfCompileUnit>> DCUs,
2512 unsigned FileNo = 1;
2515 Fn =
Scope->getFilename();
2516 if (Line != 0 && DwarfVersion >= 4)
2521 .getOrCreateSourceID(
Scope->getFile());
2523 Asm.OutStreamer->emitDwarfLocDirective(FileNo, Line, Col, Flags, 0,
2524 Discriminator, Fn, Comment);
2535 bool IsEmptyPrologue = PrologEnd.second;
2538 if (IsEmptyPrologue) {
2546 if (!
DL ||
DL->getLine() != 0)
2557 (void)getOrCreateDwarfCompileUnit(SP->getUnit());
2567 KeyInstructions.clear();
2574 std::pair<uint8_t, SmallVector<const MachineInstr *, 2>>>
2591 for (
auto &
MBB : *MF) {
2601 uint64_t BuoyAtom = 0;
2603 for (
auto &
MI :
MBB) {
2604 if (
MI.isMetaInstruction())
2608 if (!
Loc || !
Loc->getLine())
2619 bool IsCallLike =
MI.isCall() ||
TII.isTailCall(
MI);
2624 KeyInstructions.insert(Buoy);
2630 if (!
Loc->getAtomGroup() || !
Loc->getAtomRank())
2634 auto *InlinedAt = Loc->getInlinedAt();
2637 if (!Group || !Rank)
2641 if (BuoyAtom && BuoyAtom != Group) {
2646 auto &[CandidateRank, CandidateInsts] =
2647 GroupCandidates[{InlinedAt, Group}];
2653 assert((CandidateRank == 0 && CandidateInsts.empty()) ||
2654 (CandidateRank != 0 && !CandidateInsts.empty()));
2656 assert(Rank &&
"expected nonzero rank");
2659 if (CandidateRank && CandidateRank < Rank)
2666 if (CandidateRank == Rank)
2670 else if (CandidateRank > Rank)
2671 CandidateInsts.clear();
2675 CandidateInsts.push_back(Buoy);
2676 CandidateRank = Rank;
2684 if (CandidateInsts.empty())
2690 for (
const auto &[
_, Insts] : GroupCandidates.
values())
2691 for (
auto *
I : Insts)
2692 KeyInstructions.insert(
I);
2700 ForceIsStmtInstrs.clear();
2732 SmallDenseSet<MachineBasicBlock *, 4> PredMBBsToExamine;
2733 SmallDenseMap<const MachineBasicBlock *, const MachineInstr *>
2734 PotentialIsStmtMBBInstrs;
2735 for (
const auto &
MBB : *MF) {
2738 for (
auto &
MI :
MBB) {
2739 if (
MI.getDebugLoc() &&
MI.getDebugLoc()->getLine()) {
2752 for (
auto *
MBB : PredMBBsToExamine) {
2753 auto CheckMBBEdge = [&](
const MachineBasicBlock *Succ,
2754 unsigned OutgoingLine) {
2755 auto MBBInstrIt = PotentialIsStmtMBBInstrs.
find(Succ);
2756 if (MBBInstrIt == PotentialIsStmtMBBInstrs.
end())
2758 const MachineInstr *
MI = MBBInstrIt->second;
2759 if (
MI->getDebugLoc()->getLine() == OutgoingLine)
2761 PotentialIsStmtMBBInstrs.
erase(MBBInstrIt);
2762 ForceIsStmtInstrs.insert(
MI);
2769 CheckMBBEdge(Succ, 0);
2775 return PotentialIsStmtMBBInstrs.contains(SuccMBB);
2783 const MachineBasicBlock *
TBB =
nullptr, *FBB =
nullptr;
2784 SmallVector<MachineOperand, 4>
Cond;
2790 if (!AnalyzeFailed && !
Cond.
empty() && FBB !=
nullptr &&
2793 assert(MIIt->isBranch() &&
"Bad result from analyzeBranch?");
2794 CheckMBBEdge(FBB, FBBLine);
2818 unsigned LastLine = 0;
2820 if (
auto DL = MIIt->getDebugLoc();
DL &&
DL->getLine()) {
2821 LastLine =
DL->getLine();
2826 for (
auto *Succ : SuccessorBBs)
2827 CheckMBBEdge(Succ, LastLine);
2842 FunctionLineTableLabel =
CU.emitFuncLineTableOffsets()
2843 ?
Asm->OutStreamer->emitLineTableLabel()
2846 Asm->OutStreamer->getContext().setDwarfCompileUnitID(
2854 *MF,
Asm->OutStreamer->getContext().getDwarfCompileUnitID());
2860 computeKeyInstructions(MF);
2861 findForceIsStmtInstrs(MF);
2869 if (
Asm->OutStreamer->hasRawTextSupport())
2873 return CU.getUniqueID();
2877 const auto &CURanges =
CU->getRanges();
2878 auto &LineTable =
Asm->OutStreamer->getContext().getMCDwarfLineTable(
2881 LineTable.getMCLineSections().addEndEntry(
2882 const_cast<MCSymbol *
>(CURanges.back().End));
2902 "endFunction should be called with the same function as beginFunction");
2905 Asm->OutStreamer->getContext().setDwarfCompileUnitID(0);
2917 collectEntityInfo(TheCU, SP, Processed);
2921 for (
const auto &R :
Asm->MBBSectionRanges)
2922 TheCU.
addRange({R.second.BeginLabel, R.second.EndLabel});
2929 LScopes.getAbstractScopesList().empty() && !IsDarwin) {
2930 for (
const auto &R :
Asm->MBBSectionRanges)
2940 size_t NumAbstractSubprograms =
LScopes.getAbstractScopesList().size();
2944 for (
const MDNode *
N : SP->getRetainedNodes()) {
2947 auto *LexS =
LScopes.getOrCreateAbstractScope(LS);
2948 assert(LexS &&
"Expected the LexicalScope to be created.");
2952 if (!Processed.
insert(InlinedEntity(DN,
nullptr)).second ||
2958 LocalDeclsPerLS[LS].insert(
N);
2961 LScopes.getAbstractScopesList().size() == NumAbstractSubprograms &&
2962 "getOrCreateAbstractScope() inserted an abstract subprogram scope");
2964 constructAbstractSubprogramScopeDIE(TheCU, AScope);
2967 ProcessedSPNodes.insert(SP);
2971 if (!
LScopes.getAbstractScopesList().empty() &&
2973 SkelCU->constructSubprogramScopeDIE(SP,
F, FnScope,
2974 FunctionLineTableLabel);
2976 FunctionLineTableLabel =
nullptr;
2979 constructCallSiteEntryDIEs(*SP, TheCU, ScopeDIE, *MF);
2987 LocalDeclsPerLS.clear();
2994void DwarfDebug::recordSourceLine(
unsigned Line,
unsigned Col,
const MDNode *S,
3006void DwarfDebug::emitDebugInfo() {
3012void DwarfDebug::emitAbbreviations() {
3015 Holder.
emitAbbrevs(
Asm->getObjFileLowering().getDwarfAbbrevSection());
3018void DwarfDebug::emitStringOffsetsTableHeader() {
3021 *
Asm,
Asm->getObjFileLowering().getDwarfStrOffSection(),
3025template <
typename AccelTableT>
3026void DwarfDebug::emitAccel(AccelTableT &Accel,
MCSection *Section,
3028 Asm->OutStreamer->switchSection(Section);
3034void DwarfDebug::emitAccelDebugNames() {
3043void DwarfDebug::emitAccelNames() {
3044 emitAccel(AccelNames,
Asm->getObjFileLowering().getDwarfAccelNamesSection(),
3050void DwarfDebug::emitAccelObjC() {
3051 emitAccel(AccelObjC,
Asm->getObjFileLowering().getDwarfAccelObjCSection(),
3056void DwarfDebug::emitAccelNamespaces() {
3057 emitAccel(AccelNamespace,
3058 Asm->getObjFileLowering().getDwarfAccelNamespaceSection(),
3063void DwarfDebug::emitAccelTypes() {
3064 emitAccel(AccelTypes,
Asm->getObjFileLowering().getDwarfAccelTypesSection(),
3094 if (Die->
getTag() == dwarf::DW_TAG_compile_unit)
3102 DIE &SpecDIE = SpecVal.getDIEEntry().getEntry();
3109 case dwarf::DW_TAG_class_type:
3110 case dwarf::DW_TAG_structure_type:
3111 case dwarf::DW_TAG_union_type:
3112 case dwarf::DW_TAG_enumeration_type:
3117 case dwarf::DW_TAG_typedef:
3118 case dwarf::DW_TAG_base_type:
3119 case dwarf::DW_TAG_subrange_type:
3120 case dwarf::DW_TAG_template_alias:
3122 case dwarf::DW_TAG_namespace:
3124 case dwarf::DW_TAG_subprogram:
3126 case dwarf::DW_TAG_variable:
3128 case dwarf::DW_TAG_enumerator:
3138void DwarfDebug::emitDebugPubSections() {
3139 for (
const auto &NU : CUMap) {
3140 DwarfCompileUnit *TheU = NU.second;
3147 Asm->OutStreamer->switchSection(
3148 GnuStyle ?
Asm->getObjFileLowering().getDwarfGnuPubNamesSection()
3149 :
Asm->getObjFileLowering().getDwarfPubNamesSection());
3150 emitDebugPubSection(GnuStyle,
"Names", TheU, TheU->
getGlobalNames());
3152 Asm->OutStreamer->switchSection(
3153 GnuStyle ?
Asm->getObjFileLowering().getDwarfGnuPubTypesSection()
3154 :
Asm->getObjFileLowering().getDwarfPubTypesSection());
3155 emitDebugPubSection(GnuStyle,
"Types", TheU, TheU->
getGlobalTypes());
3161 Asm->emitDwarfOffset(
CU.getSection()->getBeginSymbol(),
3162 CU.getDebugSectionOffset());
3164 Asm->emitDwarfSymbolReference(
CU.getLabelBegin());
3167void DwarfDebug::emitDebugPubSection(
bool GnuStyle,
StringRef Name,
3175 "pub" + Name,
"Length of Public " + Name +
" Info");
3177 Asm->OutStreamer->AddComment(
"DWARF Version");
3180 Asm->OutStreamer->AddComment(
"Offset of Compilation Unit Info");
3181 emitSectionReference(*TheU);
3183 Asm->OutStreamer->AddComment(
"Compilation Unit Length");
3188 for (
const auto &GI : Globals)
3191 return A.second->getOffset() <
B.second->getOffset();
3193 for (
const auto &[Name, Entity] : Vec) {
3194 Asm->OutStreamer->AddComment(
"DIE offset");
3195 Asm->emitDwarfLengthOrOffset(Entity->getOffset());
3199 Asm->OutStreamer->AddComment(
3205 Asm->OutStreamer->AddComment(
"External Name");
3206 Asm->OutStreamer->emitBytes(StringRef(
Name.data(),
Name.size() + 1));
3209 Asm->OutStreamer->AddComment(
"End Mark");
3210 Asm->emitDwarfLengthOrOffset(0);
3211 Asm->OutStreamer->emitLabel(EndLabel);
3215void DwarfDebug::emitDebugStr() {
3216 MCSection *StringOffsetsSection =
nullptr;
3218 emitStringOffsetsTableHeader();
3219 StringOffsetsSection =
Asm->getObjFileLowering().getDwarfStrOffSection();
3222 Holder.
emitStrings(
Asm->getObjFileLowering().getDwarfStrSection(),
3223 StringOffsetsSection,
true);
3229 auto &&Comments = DebugLocs.getComments(Entry);
3230 auto Comment = Comments.begin();
3231 auto End = Comments.end();
3238 unsigned PtrSize =
Asm->MAI.getCodePointerSize();
3240 DebugLocs.getBytes(Entry).size()),
3241 Asm->getDataLayout().isLittleEndian(), PtrSize);
3246 for (
const auto &
Op : Expr) {
3247 assert(
Op.getCode() != dwarf::DW_OP_const_type &&
3248 "3 operand ops not yet supported");
3249 assert(!
Op.getSubCode() &&
"SubOps not yet supported");
3250 Streamer.emitInt8(
Op.getCode(), Comment != End ? *(Comment++) :
"");
3252 for (
unsigned I = 0;
I <
Op.getDescription().
Op.size(); ++
I) {
3253 if (
Op.getDescription().Op[
I] == Encoding::BaseTypeRef) {
3255 Streamer.emitDIERef(*
CU->ExprRefedBaseTypes[
Op.getRawOperand(
I)].Die);
3257 for (
unsigned J = 0; J <
Length; ++J)
3261 for (uint64_t J =
Offset; J <
Op.getOperandEndOffset(
I); ++J)
3262 Streamer.emitInt8(
Data.getData()[J], Comment != End ? *(Comment++) :
"");
3273 auto *DIExpr =
Value.getExpression();
3280 return Entry.isGlobalAddress();
3288 if (DIExpr && DIExpr->isEntryValue()) {
3306 auto EmitValueLocEntry = [&DwarfExpr, &
BT,
3309 if (Entry.isInt()) {
3310 if (
BT && (
BT->getEncoding() == dwarf::DW_ATE_boolean)) {
3315 bool IsSigned =
BT && (
BT->getEncoding() == dwarf::DW_ATE_signed ||
3316 BT->getEncoding() == dwarf::DW_ATE_signed_char);
3327 uint64_t TypeBitSize =
BT->getSizeInBits();
3328 bool IsByteSized = TypeBitSize % 8 == 0;
3330 IsSigned ? !
isIntN(GenericBitSize, Entry.getInt())
3332 static_cast<uint64_t
>(Entry.getInt()));
3333 if (TypeBitSize > GenericBitSize && IsByteSized && IsOutOfRange) {
3335 APInt(
static_cast<unsigned>(TypeBitSize),
3336 static_cast<uint64_t
>(Entry.getInt()), IsSigned,
3347 }
else if (Entry.isLocation()) {
3349 if (Location.isIndirect())
3355 }
else if (Entry.isTargetIndexLocation()) {
3361 }
else if (Entry.isGlobalAddress()) {
3363 Entry.getGlobalOffset()))
3365 }
else if (Entry.isConstantFP()) {
3368 DwarfExpr.
addConstantFP(Entry.getConstantFP()->getValueAPF(), AP);
3369 }
else if (Entry.getConstantFP()
3372 .getBitWidth() <= 64 ) {
3374 Entry.getConstantFP()->getValueAPF().bitcastToAPInt());
3377 dbgs() <<
"Skipped DwarfExpression creation for ConstantFP of size"
3378 << Entry.getConstantFP()
3389 if (!
Value.isVariadic()) {
3390 if (!EmitValueLocEntry(
Value.getLocEntries()[0], ExprCursor))
3399 return Entry.isLocation() && !Entry.getLoc().getReg();
3404 std::move(ExprCursor),
3405 [EmitValueLocEntry, &
Value](
unsigned Idx,
3407 return EmitValueLocEntry(
Value.getLocEntries()[Idx], Cursor);
3415 assert(!Values.empty() &&
3416 "location list entries without values are redundant");
3417 assert(Begin != End &&
"unexpected location list entry with empty range");
3422 if (
Value.isFragment()) {
3425 return P.isFragment();
3426 }) &&
"all values are expected to be fragments");
3429 for (
const auto &
Fragment : Values)
3433 assert(Values.size() == 1 &&
"only fragments may have >1 value");
3444 Asm->OutStreamer->AddComment(
"Loc expr size");
3446 Asm->emitULEB128(DebugLocs.getBytes(Entry).size());
3447 else if (DebugLocs.getBytes(Entry).size() <= std::numeric_limits<uint16_t>::max())
3448 Asm->emitInt16(DebugLocs.getBytes(Entry).size());
3467 Asm->OutStreamer->AddComment(
"Offset entry count");
3473 Asm->getDwarfOffsetByteSize());
3487 Asm->OutStreamer->AddComment(
"Offset entry count");
3488 Asm->emitInt32(DebugLocs.getLists().size());
3489 Asm->OutStreamer->emitLabel(DebugLocs.getSym());
3491 for (
const auto &List : DebugLocs.getLists())
3492 Asm->emitLabelDifference(List.Label, DebugLocs.getSym(),
3493 Asm->getDwarfOffsetByteSize());
3498template <
typename Ranges,
typename PayloadEmitter>
3502 unsigned OffsetPair,
unsigned StartxLength,
unsigned StartxEndx,
3504 bool ShouldUseBaseAddress, PayloadEmitter EmitPayload) {
3505 auto Size = Asm->MAI.getCodePointerSize();
3509 Asm->OutStreamer->emitLabel(Sym);
3516 for (
const auto &
Range : R)
3517 SectionRanges[&
Range.Begin->getSection()].push_back(&
Range);
3519 const MCSymbol *CUBase =
CU.getBaseAddress();
3520 bool BaseIsSet =
false;
3521 for (
const auto &
P : SectionRanges) {
3522 auto *
Base = CUBase;
3524 (DD.
useSplitDwarf() && UseDwarf5 &&
P.first->isLinkerRelaxable())) {
3527 }
else if (!
Base && ShouldUseBaseAddress) {
3528 const MCSymbol *Begin =
P.second.front()->Begin;
3533 Asm->OutStreamer->emitIntValue(-1,
Size);
3534 Asm->OutStreamer->AddComment(
" base address");
3535 Asm->OutStreamer->emitSymbolValue(
Base,
Size);
3536 }
else if (NewBase != Begin ||
P.second.size() > 1) {
3542 Asm->OutStreamer->AddComment(StringifyEnum(BaseAddressx));
3543 Asm->emitInt8(BaseAddressx);
3544 Asm->OutStreamer->AddComment(
" base address index");
3547 }
else if (BaseIsSet && !UseDwarf5) {
3550 Asm->OutStreamer->emitIntValue(-1,
Size);
3551 Asm->OutStreamer->emitIntValue(0,
Size);
3554 for (
const auto *RS :
P.second) {
3557 assert(Begin &&
"Range without a begin symbol?");
3558 assert(End &&
"Range without an end symbol?");
3562 Asm->OutStreamer->AddComment(StringifyEnum(OffsetPair));
3563 Asm->emitInt8(OffsetPair);
3564 Asm->OutStreamer->AddComment(
" starting offset");
3565 Asm->emitLabelDifferenceAsULEB128(Begin,
Base);
3566 Asm->OutStreamer->AddComment(
" ending offset");
3567 Asm->emitLabelDifferenceAsULEB128(End,
Base);
3569 Asm->emitLabelDifference(Begin,
Base,
Size);
3570 Asm->emitLabelDifference(End,
Base,
Size);
3572 }
else if (UseDwarf5) {
3580 Asm->OutStreamer->AddComment(StringifyEnum(StartxEndx));
3581 Asm->emitInt8(StartxEndx);
3582 Asm->OutStreamer->AddComment(
" start index");
3584 Asm->OutStreamer->AddComment(
" end index");
3587 Asm->OutStreamer->AddComment(StringifyEnum(StartxLength));
3588 Asm->emitInt8(StartxLength);
3589 Asm->OutStreamer->AddComment(
" start index");
3591 Asm->OutStreamer->AddComment(
" length");
3592 Asm->emitLabelDifferenceAsULEB128(End, Begin);
3595 Asm->OutStreamer->emitSymbolValue(Begin,
Size);
3596 Asm->OutStreamer->emitSymbolValue(End,
Size);
3603 Asm->OutStreamer->AddComment(StringifyEnum(
EndOfList));
3607 Asm->OutStreamer->emitIntValue(0,
Size);
3608 Asm->OutStreamer->emitIntValue(0,
Size);
3616 dwarf::DW_LLE_base_addressx, dwarf::DW_LLE_offset_pair,
3617 dwarf::DW_LLE_startx_length, dwarf::DW_LLE_startx_endx,
3620 DD.emitDebugLocEntryLocation(E, List.CU);
3624void DwarfDebug::emitDebugLocImpl(
MCSection *Sec) {
3625 if (DebugLocs.getLists().empty())
3628 Asm->OutStreamer->switchSection(Sec);
3634 for (
const auto &
List : DebugLocs.getLists())
3638 Asm->OutStreamer->emitLabel(TableEnd);
3642void DwarfDebug::emitDebugLoc() {
3645 ?
Asm->getObjFileLowering().getDwarfLoclistsSection()
3646 :
Asm->getObjFileLowering().getDwarfLocSection());
3650void DwarfDebug::emitDebugLocDWO() {
3653 Asm->getObjFileLowering().getDwarfLoclistsDWOSection());
3658 for (
const auto &
List : DebugLocs.getLists()) {
3659 Asm->OutStreamer->switchSection(
3660 Asm->getObjFileLowering().getDwarfLocDWOSection());
3661 Asm->OutStreamer->emitLabel(
List.Label);
3663 for (
const auto &Entry : DebugLocs.getEntries(
List)) {
3672 Asm->emitInt8(dwarf::DW_LLE_startx_length);
3673 unsigned idx = AddrPool.getIndex(
Entry.Begin);
3674 Asm->emitULEB128(idx);
3680 Asm->emitInt8(dwarf::DW_LLE_end_of_list);
3690void DwarfDebug::emitDebugARanges() {
3691 if (ArangeLabels.empty())
3698 for (
const SymbolCU &SCU : ArangeLabels) {
3699 if (SCU.Sym->isInSection()) {
3701 MCSection *Section = &SCU.Sym->getSection();
3702 SectionMap[Section].push_back(SCU);
3707 SectionMap[
nullptr].push_back(SCU);
3711 DenseMap<DwarfCompileUnit *, std::vector<ArangeSpan>> Spans;
3713 for (
auto &
I : SectionMap) {
3721 for (
const SymbolCU &Cur :
List) {
3723 Span.
Start = Cur.Sym;
3726 Spans[Cur.CU].push_back(Span);
3732 List.push_back(SymbolCU(
nullptr,
Asm->OutStreamer->endSection(Section)));
3736 for (
size_t n = 1, e =
List.size(); n < e; n++) {
3737 const SymbolCU &Prev =
List[n - 1];
3738 const SymbolCU &Cur =
List[n];
3741 if (Cur.
CU != Prev.
CU) {
3743 Span.
Start = StartSym;
3746 Spans[Prev.
CU].push_back(Span);
3753 Asm->OutStreamer->switchSection(
3754 Asm->getObjFileLowering().getDwarfARangesSection());
3756 unsigned PtrSize =
Asm->MAI.getCodePointerSize();
3759 std::vector<DwarfCompileUnit *> CUs;
3760 for (
const auto &it : Spans) {
3761 DwarfCompileUnit *
CU = it.first;
3766 llvm::sort(CUs, [](
const DwarfCompileUnit *
A,
const DwarfCompileUnit *
B) {
3767 return A->getUniqueID() <
B->getUniqueID();
3771 for (DwarfCompileUnit *
CU : CUs) {
3772 std::vector<ArangeSpan> &
List = Spans[
CU];
3775 if (
auto *Skel =
CU->getSkeleton())
3779 unsigned ContentSize =
3781 Asm->getDwarfOffsetByteSize() +
3786 unsigned TupleSize = PtrSize * 2;
3790 Asm->getUnitLengthFieldByteSize() + ContentSize,
Align(TupleSize));
3793 ContentSize += (
List.size() + 1) * TupleSize;
3796 Asm->emitDwarfUnitLength(ContentSize,
"Length of ARange Set");
3797 Asm->OutStreamer->AddComment(
"DWARF Arange version number");
3799 Asm->OutStreamer->AddComment(
"Offset Into Debug Info Section");
3800 emitSectionReference(*
CU);
3801 Asm->OutStreamer->AddComment(
"Address Size (in bytes)");
3802 Asm->emitInt8(PtrSize);
3803 Asm->OutStreamer->AddComment(
"Segment Size (in bytes)");
3806 Asm->OutStreamer->emitFill(Padding, 0xff);
3808 for (
const ArangeSpan &Span :
List) {
3809 Asm->emitLabelReference(Span.Start, PtrSize);
3816 auto SizeRef = SymSize.find(Span.Start);
3817 if ((SizeRef == SymSize.end() || SizeRef->second != 0) && Span.End) {
3818 Asm->emitLabelDifference(Span.End, Span.Start, PtrSize);
3823 if (SizeRef == SymSize.end() || SizeRef->second == 0)
3826 Size = SizeRef->second;
3828 Asm->OutStreamer->emitIntValue(
Size, PtrSize);
3832 Asm->OutStreamer->AddComment(
"ARange terminator");
3833 Asm->OutStreamer->emitIntValue(0, PtrSize);
3834 Asm->OutStreamer->emitIntValue(0, PtrSize);
3842 dwarf::DW_RLE_base_addressx, dwarf::DW_RLE_offset_pair,
3843 dwarf::DW_RLE_startx_length, dwarf::DW_RLE_startx_endx,
3845 List.CU->getCUNode()->getRangesBaseAddress() ||
3857 return !Pair.second->getCUNode()->isDebugDirectivesOnly();
3860 Asm->OutStreamer->switchSection(Section);
3870 Asm->OutStreamer->emitLabel(TableEnd);
3875void DwarfDebug::emitDebugRanges() {
3878 emitDebugRangesImpl(Holder,
3880 ?
Asm->getObjFileLowering().getDwarfRnglistsSection()
3881 :
Asm->getObjFileLowering().getDwarfRangesSection());
3884void DwarfDebug::emitDebugRangesDWO() {
3886 Asm->getObjFileLowering().getDwarfRnglistsDWOSection());
3893 enum HeaderFlagMask {
3894#define HANDLE_MACRO_FLAG(ID, NAME) MACRO_FLAG_##NAME = ID,
3895#include "llvm/BinaryFormat/Dwarf.def"
3897 Asm->OutStreamer->AddComment(
"Macro information version");
3898 Asm->emitInt16(DwarfVersion >= 5 ? DwarfVersion : 4);
3901 if (Asm->isDwarf64()) {
3902 Asm->OutStreamer->AddComment(
"Flags: 64 bit, debug_line_offset present");
3903 Asm->emitInt8(MACRO_FLAG_OFFSET_SIZE | MACRO_FLAG_DEBUG_LINE_OFFSET);
3905 Asm->OutStreamer->AddComment(
"Flags: 32 bit, debug_line_offset present");
3906 Asm->emitInt8(MACRO_FLAG_DEBUG_LINE_OFFSET);
3908 Asm->OutStreamer->AddComment(
"debug_line_offset");
3910 Asm->emitDwarfLengthOrOffset(0);
3912 Asm->emitDwarfSymbolReference(
CU.getLineTableStartSym());
3915void DwarfDebug::handleMacroNodes(DIMacroNodeArray Nodes,
DwarfCompileUnit &U) {
3916 for (
auto *MN : Nodes) {
3920 emitMacroFile(*
F, U);
3926void DwarfDebug::emitMacro(
DIMacro &M) {
3927 StringRef
Name =
M.getName();
3928 StringRef
Value =
M.getValue();
3934 if (UseDebugMacroSection) {
3937 ? dwarf::DW_MACRO_define_strx
3938 : dwarf::DW_MACRO_undef_strx;
3941 Asm->OutStreamer->AddComment(
"Line Number");
3942 Asm->emitULEB128(
M.getLine());
3943 Asm->OutStreamer->AddComment(
"Macro String");
3945 InfoHolder.getStringPool().getIndexedEntry(*
Asm, Str).getIndex());
3948 ? dwarf::DW_MACRO_GNU_define_indirect
3949 : dwarf::DW_MACRO_GNU_undef_indirect;
3952 Asm->OutStreamer->AddComment(
"Line Number");
3953 Asm->emitULEB128(
M.getLine());
3954 Asm->OutStreamer->AddComment(
"Macro String");
3955 Asm->emitDwarfSymbolReference(
3956 InfoHolder.getStringPool().getEntry(*
Asm, Str).getSymbol());
3960 Asm->emitULEB128(
M.getMacinfoType());
3961 Asm->OutStreamer->AddComment(
"Line Number");
3962 Asm->emitULEB128(
M.getLine());
3963 Asm->OutStreamer->AddComment(
"Macro String");
3964 Asm->OutStreamer->emitBytes(Str);
3965 Asm->emitInt8(
'\0');
3969void DwarfDebug::emitMacroFileImpl(
3971 StringRef (*MacroFormToString)(
unsigned Form)) {
3973 Asm->OutStreamer->AddComment(MacroFormToString(StartFile));
3974 Asm->emitULEB128(StartFile);
3975 Asm->OutStreamer->AddComment(
"Line Number");
3977 Asm->OutStreamer->AddComment(
"File Number");
3980 Asm->emitULEB128(getDwoLineTable(U)->getFile(
3982 Asm->OutContext.getDwarfVersion(),
F.getSource()));
3984 Asm->emitULEB128(
U.getOrCreateSourceID(&
F));
3986 Asm->OutStreamer->AddComment(MacroFormToString(EndFile));
3987 Asm->emitULEB128(EndFile);
3994 if (UseDebugMacroSection)
3996 F, U, dwarf::DW_MACRO_start_file, dwarf::DW_MACRO_end_file,
4003void DwarfDebug::emitDebugMacinfoImpl(
MCSection *Section) {
4004 for (
const auto &
P : CUMap) {
4005 auto &TheCU = *
P.second;
4007 DwarfCompileUnit &
U = SkCU ? *SkCU : TheCU;
4009 DIMacroNodeArray Macros = CUNode->getMacros();
4012 Asm->OutStreamer->switchSection(Section);
4013 Asm->OutStreamer->emitLabel(
U.getMacroLabelBegin());
4014 if (UseDebugMacroSection)
4016 handleMacroNodes(Macros, U);
4017 Asm->OutStreamer->AddComment(
"End Of Macro List Mark");
4023void DwarfDebug::emitDebugMacinfo() {
4024 auto &ObjLower =
Asm->getObjFileLowering();
4025 emitDebugMacinfoImpl(UseDebugMacroSection
4026 ? ObjLower.getDwarfMacroSection()
4027 : ObjLower.getDwarfMacinfoSection());
4030void DwarfDebug::emitDebugMacinfoDWO() {
4031 auto &ObjLower =
Asm->getObjFileLowering();
4032 emitDebugMacinfoImpl(UseDebugMacroSection
4033 ? ObjLower.getDwarfMacroDWOSection()
4034 : ObjLower.getDwarfMacinfoDWOSection());
4039void DwarfDebug::initSkeletonUnit(
const DwarfUnit &U,
DIE &Die,
4040 std::unique_ptr<DwarfCompileUnit> NewU) {
4042 if (!CompilationDir.empty())
4043 NewU->addString(Die, dwarf::DW_AT_comp_dir, CompilationDir);
4044 addGnuPubAttributes(*NewU, Die);
4046 SkeletonHolder.addUnit(std::move(NewU));
4051 auto OwnedUnit = std::make_unique<DwarfCompileUnit>(
4052 CU.getUniqueID(),
CU.getCUNode(),
Asm,
this, &SkeletonHolder,
4054 DwarfCompileUnit &NewCU = *OwnedUnit;
4055 NewCU.
setSection(
Asm->getObjFileLowering().getDwarfInfoSection());
4062 initSkeletonUnit(
CU, NewCU.
getUnitDie(), std::move(OwnedUnit));
4069void DwarfDebug::emitDebugInfoDWO() {
4077void DwarfDebug::emitDebugAbbrevDWO() {
4079 InfoHolder.emitAbbrevs(
Asm->getObjFileLowering().getDwarfAbbrevDWOSection());
4082void DwarfDebug::emitDebugLineDWO() {
4084 SplitTypeUnitFileTable.Emit(
4085 *
Asm->OutStreamer, MCDwarfLineTableParams(),
4086 Asm->getObjFileLowering().getDwarfLineDWOSection());
4089void DwarfDebug::emitStringOffsetsTableHeaderDWO() {
4091 InfoHolder.getStringPool().emitStringOffsetsTableHeader(
4092 *
Asm,
Asm->getObjFileLowering().getDwarfStrOffDWOSection(),
4099void DwarfDebug::emitDebugStrDWO() {
4101 emitStringOffsetsTableHeaderDWO();
4103 MCSection *OffSec =
Asm->getObjFileLowering().getDwarfStrOffDWOSection();
4104 InfoHolder.emitStrings(
Asm->getObjFileLowering().getDwarfStrDWOSection(),
4109void DwarfDebug::emitDebugAddr() {
4110 AddrPool.emit(*
Asm,
Asm->getObjFileLowering().getDwarfAddrSection());
4116 const DICompileUnit *DIUnit =
CU.getCUNode();
4117 SplitTypeUnitFileTable.maybeSetRootFile(
4120 return &SplitTypeUnitFileTable;
4131 return Result.high();
4140 if (!TypeUnitsUnderConstruction.empty() && AddrPool.hasBeenUsed())
4143 auto Ins = TypeSignatures.try_emplace(CTy);
4145 CU.addDIETypeSignature(RefDie, Ins.first->second);
4150 bool TopLevelType = TypeUnitsUnderConstruction.empty();
4151 AddrPool.resetUsedFlag();
4153 auto OwnedUnit = std::make_unique<DwarfTypeUnit>(
4157 TypeUnitsUnderConstruction.emplace_back(std::move(OwnedUnit), CTy);
4159 NewTU.
addUInt(UnitDie, dwarf::DW_AT_language, dwarf::DW_FORM_data2,
4160 CU.getSourceLanguage());
4164 Ins.first->second = Signature;
4172 if (!CompilationDir.empty())
4173 NewTU.
addString(UnitDie, dwarf::DW_AT_comp_dir, CompilationDir);
4174 NewTU.
addString(UnitDie, dwarf::DW_AT_dwo_name,
4175 Asm->TM.Options.MCOptions.SplitDwarfFile);
4179 ?
Asm->getObjFileLowering().getDwarfTypesDWOSection()
4180 :
Asm->getObjFileLowering().getDwarfInfoDWOSection();
4185 ?
Asm->getObjFileLowering().getDwarfTypesSection(Signature)
4186 :
Asm->getObjFileLowering().getDwarfInfoSection(Signature);
4189 CU.applyStmtList(UnitDie);
4200 auto TypeUnitsToAdd = std::move(TypeUnitsUnderConstruction);
4201 TypeUnitsUnderConstruction.clear();
4205 if (AddrPool.hasBeenUsed()) {
4206 AccelTypeUnitsDebugNames.clear();
4210 for (
const auto &
TU : TypeUnitsToAdd)
4211 TypeSignatures.erase(
TU.second);
4219 CU.updateAcceleratorTables(CTy->
getScope(), CTy, RefDie);
4225 for (
auto &
TU : TypeUnitsToAdd) {
4226 InfoHolder.computeSizeAndOffsetsForUnit(
TU.first.get());
4231 AccelDebugNames.addTypeUnitSignature(*
TU.first);
4233 AccelDebugNames.addTypeUnitSymbol(*
TU.first);
4236 AccelTypeUnitsDebugNames.convertDieToOffset();
4237 AccelDebugNames.addTypeEntries(AccelTypeUnitsDebugNames);
4238 AccelTypeUnitsDebugNames.clear();
4241 CU.addDIETypeSignature(RefDie, Signature);
4248template <
typename DataT>
4249void DwarfDebug::addAccelNameImpl(
4254 Unit.getUnitDie().getTag() == dwarf::DW_TAG_skeleton_unit || Name.empty())
4271 assert(((&Current == &AccelTypeUnitsDebugNames) ||
4272 ((&Current == &AccelDebugNames) &&
4273 (Unit.getUnitDie().getTag() != dwarf::DW_TAG_type_unit))) &&
4274 "Kind is CU but TU is being processed.");
4275 assert(((&Current == &AccelDebugNames) ||
4276 ((&Current == &AccelTypeUnitsDebugNames) &&
4277 (Unit.getUnitDie().getTag() == dwarf::DW_TAG_type_unit))) &&
4278 "Kind is TU but CU is being processed.");
4281 Current.
addName(
Ref, Die, Unit.getUniqueID(),
4282 Unit.getUnitDie().getTag() == dwarf::DW_TAG_type_unit);
4296 addAccelNameImpl(Unit, NameTableKind, AccelNames, Name, Die);
4305 addAccelNameImpl(Unit, NameTableKind, AccelObjC, Name, Die);
4312 addAccelNameImpl(Unit, NameTableKind, AccelNamespace, Name, Die);
4318 const DIE &Die,
char Flags) {
4319 addAccelNameImpl(Unit, NameTableKind, AccelTypes, Name, Die);
4323 return Asm->OutStreamer->getContext().getDwarfVersion();
4327 if (
Asm->getDwarfVersion() >= 4)
4328 return dwarf::Form::DW_FORM_sec_offset;
4329 assert((!
Asm->isDwarf64() || (
Asm->getDwarfVersion() == 3)) &&
4330 "DWARF64 is not defined prior DWARFv3");
4331 return Asm->isDwarf64() ? dwarf::Form::DW_FORM_data8
4332 : dwarf::Form::DW_FORM_data4;
4336 return SectionLabels.lookup(S);
4340 if (SectionLabels.insert(std::make_pair(&S->
getSection(), S)).second)
4345std::optional<MD5::MD5Result>
4349 return std::nullopt;
4350 std::optional<DIFile::ChecksumInfo<StringRef>> Checksum = File->getChecksum();
4352 return std::nullopt;
4357 std::string ChecksumString =
fromHex(Checksum->Value);
4374 if (
MBB.getAlignment() ==
Align(1))
4377 auto *SP =
MBB.getParent()->getFunction().getSubprogram();
4384 auto PrevLoc =
Asm->OutStreamer->getContext().getCurrentDwarfLoc();
4385 if (PrevLoc.getLine()) {
4386 Asm->OutStreamer->emitDwarfLocDirective(
4387 PrevLoc.getFileNum(), 0, PrevLoc.getColumn(), 0, 0, 0,
StringRef());
4389 Asm->OutStreamer->getCurrentSectionOnly());
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
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< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static unsigned getDwarfVersion(const MachineFunction &MF)
Resolve the DWARF version the way DwarfDebug does.
#define clEnumValN(ENUMVAL, FLAGNAME, DESC)
#define clEnumVal(ENUMVAL, DESC)
This file contains the declarations for the subclasses of Constant, which represent the different fla...
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))
SmallSet< MCRegUnit, 16 > ClobberedRegUnitSet
Container for the set of register units known to be clobbered on the path to a call site.
static cl::opt< bool > KeyInstructionsAreStmts("dwarf-use-key-instructions", cl::Hidden, cl::init(true), cl::desc("Set to false to ignore Key Instructions metadata"))
Set to false to ignore Key Instructions metadata.
static bool interpretNextInstr(const MachineInstr *CurMI, FwdRegWorklist &ForwardedRegWorklist, ParamSet &Params, ClobberedRegUnitSet &ClobberedRegUnits)
static SmallVectorImpl< DwarfCompileUnit::GlobalExpr > & sortGlobalExprs(SmallVectorImpl< DwarfCompileUnit::GlobalExpr > &GVEs)
Sort and unique GVEs by comparing their fragment offset.
static bool isLangCaseSensitive(const DISourceLanguageName &Lang)
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 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))
MapVector< Register, SmallVector< FwdRegParamInfo, 2 > > FwdRegWorklist
Register worklist for finding call site values.
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 emitRangeList(DwarfDebug &DD, AsmPrinter *Asm, MCSymbol *Sym, const Ranges &R, const DwarfCompileUnit &CU, unsigned BaseAddressx, unsigned OffsetPair, unsigned StartxLength, unsigned StartxEndx, unsigned EndOfList, StringRef(*StringifyEnum)(unsigned), bool ShouldUseBaseAddress, PayloadEmitter EmitPayload)
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 void interpretValues(const MachineInstr *CurMI, FwdRegWorklist &ForwardedRegWorklist, ParamSet &Params, ClobberedRegUnitSet &ClobberedRegUnits)
Interpret values loaded into registers by CurMI.
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 recordSourceLine(AsmPrinter &Asm, unsigned Line, unsigned Col, const MDNode *S, unsigned Flags, unsigned CUID, uint16_t DwarfVersion, ArrayRef< std::unique_ptr< DwarfCompileUnit > > DCUs, StringRef Comment={})
Register a source line with debug info.
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 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
Register const TargetRegisterInfo * TRI
ConstantRange Range(APInt(BitWidth, Low), APInt(BitWidth, High))
static const MCPhysReg CalleeSavedReg
const SmallVectorImpl< MachineOperand > MachineBasicBlock * TBB
const SmallVectorImpl< MachineOperand > & Cond
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
std::unique_ptr< MCStreamer > && Streamer
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.
Class for arbitrary precision integers.
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.
Represent a constant reference to an array (0 or more elements consecutively in memory),...
std::vector< T > vec() const
This class is intended to be used as a driving class for all asm writers.
DwarfDebug * getDwarfDebug()
TargetMachine & TM
Target machine description.
MachineFunction * MF
The current machine function.
std::unique_ptr< MCStreamer > OutStreamer
This is the MCStreamer object for the file we are generating.
const MCAsmInfo & MAI
Target Asm Printer information.
uint16_t getDwarfVersion() const
virtual void emitInt8(uint8_t Byte, const Twine &Comment="")=0
Basic type, like 'int' or 'float'.
bool getDebugInfoForProfiling() const
bool isDebugDirectivesOnly() const
StringRef getFlags() const
static LLVM_ABI std::optional< DebugNameTableKind > getNameTableKind(StringRef Str)
unsigned getRuntimeVersion() const
bool getSplitDebugInlining() const
StringRef getSysRoot() const
StringRef getProducer() const
DISourceLanguageName getSourceLanguage() const
uint64_t getDWOId() const
StringRef getSplitDebugFilename() const
static LLVM_ABI std::optional< DebugEmissionKind > getEmissionKind(StringRef Str)
void setSection(MCSection *Section)
Set the section that this DIEUnit will be emitted into.
A structured debug information entry.
LLVM_ABI DIEValue findAttribute(dwarf::Attribute Attribute) const
Find a value in the DIE with the attribute given.
LLVM_ABI const DIE * getUnitDie() const
Climb up the parent chain to get the 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.
static LLVM_ABI DIExpression * append(const DIExpression *Expr, ArrayRef< uint64_t > Ops)
Append the opcodes Ops to DIExpr.
unsigned getNumElements() const
LLVM_ABI bool isImplicit() const
Return whether this is an implicit location description.
static LLVM_ABI std::optional< FragmentInfo > getFragmentInfo(expr_op_iterator Start, expr_op_iterator End)
Retrieve the details of this fragment expression.
static LLVM_ABI std::optional< const DIExpression * > convertToNonVariadicExpression(const DIExpression *Expr)
If Expr is a valid single-location expression, i.e.
ArrayRef< uint64_t > getElements() const
LLVM_ABI bool isValid() const
LLVM_ABI DILocalScope * getNonLexicalBlockFileScope() const
Get the first non DILexicalBlockFile scope of this scope.
uint64_t getAtomGroup() const
uint8_t getAtomRank() const
DIMacroNodeArray getElements() const
Tagged DWARF-like metadata node.
StringRef getFilename() const
StringRef getDirectory() const
std::optional< StringRef > getSource() const
Wrapper structure that holds source language identity metadata that includes language name,...
bool hasVersionedName() const
uint16_t getName() const
Returns a versioned or unversioned language name.
Subprogram description. Uses SubclassData1.
static LLVM_ABI DILocalScope * getRetainedNodeScope(MDNode *N)
DIScope * getScope() const
DIScope * getScope() const
Encoding
Size and signedness of expression operations' operands.
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...
SmallVector< Entry, 4 > Entries
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.
const DILocalVariable * getVariable() const
const DIType * getType() const
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.
DebugHandlerBase(AsmPrinter *A)
void beginInstruction(const MachineInstr *MI) override
Process beginning of an instruction.
const MachineBasicBlock * PrevInstBB
void requestLabelAfterInsn(const MachineInstr *MI)
Ensure that a label will be emitted after MI.
DbgValueHistoryMap DbgValues
History of DBG_VALUE and clobber instructions for each user variable.
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< Entry > getEntries(const List &L) const
LLVM_ABI unsigned getLine() const
iterator find(const_arg_type_t< KeyT > Val)
bool erase(const KeyT &Val)
ValueT lookup(const_arg_type_t< KeyT > Val) const
Return the entry for the specified key, or a default constructed value if no such entry exists.
std::pair< iterator, bool > insert(const std::pair< KeyT, ValueT > &KV)
Implements a dense probed hash-table based set.
void addRange(RangeSpan Range)
addRange - Add an address range to the list of ranges for this unit.
DIE & constructSubprogramScopeDIE(const DISubprogram *Sub, const Function &F, LexicalScope *Scope, MCSymbol *LineTableSym)
Construct a DIE for this subprogram scope.
void createAbstractEntity(const DINode *Node, LexicalScope *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 ...
virtual bool shouldResetBaseAddress(const MCSection &Section) const
Whether the target requires resetting the base address in range/loc lists.
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.
virtual bool shouldAttachCompileUnitRanges() const
Whether to attach ranges/low_pc to the compile unit DIE in endModule.
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.
virtual void finishTargetUnitAttributes(const DICompileUnit &DIUnit, DwarfCompileUnit &NewCU)
Target-specific compile unit attribute finalization.
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.
DwarfCompileUnit & getOrCreateAbstractSubprogramCU(const DISubprogram *SP, DwarfCompileUnit &SrcCU)
Find the matching DwarfCompileUnit for the given SP referenced from SrcCU.
void emitDebugLocEntryLocation(const DebugLocStream::Entry &Entry, const DwarfCompileUnit *CU)
Emit the location for a debug loc entry, including the size header.
const SmallVectorImpl< std::unique_ptr< DwarfCompileUnit > > & getUnits()
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 split DWARF.
virtual void initializeTargetDebugInfo(const MachineFunction &MF)
Target-specific debug info initialization at function start.
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)
virtual void recordTargetSourceLine(const DebugLoc &DL, unsigned Flags)
Target-specific source line recording.
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.
DwarfFile InfoHolder
Holder for the file specific debug information.
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.
bool canAddGlobalAddress() const
Whether addGlobalAddress() can spell a global's address at all.
virtual void disableTemporaryBuffer()=0
Disable emission to the temporary buffer.
virtual unsigned getTemporaryBufferSize()=0
Return the emitted size, in number of bytes, for the data stored in the temporary buffer.
bool addGlobalAddress(const GlobalValue *GV, int64_t Offset)
Emit the address of GV displaced by Offset as an implicit location description, i....
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.
bool addExpression(DIExpressionCursor &&Expr)
Emit all remaining operations in the DIExpressionCursor.
std::optional< uint8_t > TagOffset
void addBooleanConstant(int64_t Value)
Emit a boolean constant.
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 addImplicitValue(const APInt &Value, const AsmPrinter &AP)
Emit an implicit value.
void addSignedConstant(int64_t Value)
Emit a signed constant.
virtual void commitTemporaryBuffer()=0
Commit the data stored in the temporary buffer to the main output.
void addWasmLocation(unsigned Index, uint64_t Offset)
Emit location information expressed via WebAssembly location + offset The Index is an identifier for ...
virtual void enableTemporaryBuffer()=0
Start emitting data to the temporary buffer.
void beginEntryValueExpression(DIExpressionCursor &ExprCursor)
Begin emission of an entry value dwarf operation.
void setRnglistsTableBaseSym(MCSymbol *Sym)
void emitUnits(bool UseOffsets)
Emit all of the units to the section listed with the given abbreviation 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.
DwarfStringPoolEntryRef: Dwarf string pool entry reference.
LLVM_ABI_FOR_TEST EntryRef getEntry(AsmPrinter &Asm, StringRef Str)
Get a reference to an entry in the string pool.
LLVM_ABI_FOR_TEST 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 addSectionLabel(DIE &Die, dwarf::Attribute Attribute, const MCSymbol *Label, const MCSymbol *Sec)
Add a Dwarf section label attribute data and value.
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.
static StringRef dropLLVMManglingEscape(StringRef Name)
If the given string begins with the GlobalValue name mangling escape character '\1',...
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.
This class is used to track scope information.
SmallVectorImpl< InsnRange > & getRanges()
const DILocalScope * getScopeNode() const
This class provides interface to collect and use lexical scoping information from machine instruction...
LLVM_ABI LexicalScope * findLexicalScope(const DILocation *DL)
Find lexical scope, either regular or inlined, for the given DebugLoc.
LexicalScope * findAbstractScope(const DILocalScope *N)
Find an abstract scope or return null.
Single(DbgValueLoc ValueLoc)
unsigned getCodePointerSize() const
Get the code pointer size in bytes.
static LLVM_ABI void make(MCStreamer *MCOS, MCSection *Section)
MCSection * getDwarfLoclistsSection() const
MCSection * getDwarfRangesSection() const
MCSection * getDwarfMacroSection() const
MCSection * getDwarfMacinfoDWOSection() const
MCSection * getDwarfMacinfoSection() const
MCSection * getDwarfMacroDWOSection() const
static constexpr unsigned NoRegister
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 ...
uint32_t getIndex() const
Get the (implementation defined) index.
MCSection & getSection() const
Get the section associated with a defined, non-absolute symbol.
LLVM_ABI void update(ArrayRef< uint8_t > Data)
Updates the hash for the byte stream provided.
LLVM_ABI 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.
iterator_range< succ_iterator > successors()
reverse_iterator rbegin()
iterator_range< pred_iterator > predecessors()
MachineInstrBundleIterator< const MachineInstr, true > const_reverse_iterator
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
const CallSiteInfoMap & getCallSitesInfo() const
Function & getFunction()
Return the LLVM function that this machine code represents.
Representation of each machine instruction.
const MachineBasicBlock * getParent() const
bool isCall(QueryType Type=AnyInBundle) const
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...
mop_range uses()
Returns all operands which may be register uses.
LLVM_ABI 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
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.
std::pair< iterator, bool > insert(const std::pair< KeyT, ValueT > &KV)
VectorType::iterator erase(typename VectorType::iterator Iterator)
Remove the element given by Iterator.
A Module instance is used to store all the information related to an LLVM module.
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.
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...
void insert_range(Range &&R)
SmallString - A SmallString is just a SmallVector with methods and accessors that make it work better...
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
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",...
Represent a constant reference to a string, i.e.
constexpr bool empty() const
Check if the string is empty.
TargetInstrInfo - Interface to description of machine instruction set.
const Triple & getTargetTriple() const
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
virtual const TargetInstrInfo * getInstrInfo() const
virtual const TargetRegisterInfo * getRegisterInfo() const =0
Return the target's register information.
virtual const TargetLowering * getTargetLowering() const
Triple - Helper class for working with autoconf configuration names.
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...
LLVM Value Representation.
LLVM_ABI StringRef getName() const
Return a constant reference to the value's name.
std::pair< iterator, bool > insert(const ValueT &V)
void insert_range(Range &&R)
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()
A raw_ostream that writes to an SmallVector or SmallString.
LLVM_ABI StringRef RangeListEncodingString(unsigned Encoding)
LLVM_ABI StringRef GDBIndexEntryLinkageString(GDBIndexEntryLinkage Linkage)
LLVM_ABI StringRef MacroString(unsigned Encoding)
LLVM_ABI StringRef LocListEncodingString(unsigned Encoding)
LLVM_ABI StringRef GnuMacroString(unsigned Encoding)
LLVM_ABI StringRef MacinfoString(unsigned Encoding)
LLVM_ABI StringRef OperationEncodingString(unsigned Encoding)
LLVM_ABI StringRef GDBIndexEntryKindString(GDBIndexEntryKind Kind)
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
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...
LLVM_ABI 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.
std::string fromHex(StringRef Input)
Convert hexadecimal string Input to its binary representation. The return string is half the size of ...
RelativeUniformCounterPtr Values
auto enumerate(FirstRange &&First, RestRanges &&...Rest)
Given two or more input ranges, returns a new range whose values are tuples (A, B,...
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
LLVM_ABI bool isRangeRelaxable(const MCSymbol *Begin, const MCSymbol *End)
constexpr bool isUIntN(unsigned N, uint64_t x)
Checks if an unsigned integer fits into the given (dynamic) bit width.
auto cast_or_null(const Y &Val)
auto unique(Range &&R, Predicate P)
bool isa_and_nonnull(const Y &Val)
SmallVector< DbgCallSiteParam, 4 > ParamSet
Collection used for storing debug call site parameters.
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Value
auto dyn_cast_or_null(const Y &Val)
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.
LLVM_ABI 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.
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
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...
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
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...
@ Ref
The access may reference the value stored in memory.
auto remove_if(R &&Range, UnaryPredicate P)
Provide wrappers to std::remove_if which take ranges instead of having to pass begin/end explicitly.
void emitAppleAccelTable(AsmPrinter *Asm, AccelTable< DataT > &Contents, StringRef Prefix, const MCSymbol *SecBegin)
Emit an Apple Accelerator Table consisting of entries in the specified AccelTable.
DWARFExpression::Operation Op
OutputIt copy(R &&Range, OutputIt Out)
LLVM_ABI void emitDWARF5AccelTable(AsmPrinter *Asm, DWARF5AccelTable &Contents, const DwarfDebug &DD, ArrayRef< std::unique_ptr< DwarfCompileUnit > > CUs)
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
void erase_if(Container &C, UnaryPredicate P)
Provide a container algorithm similar to C++ Library Fundamentals v2's erase_if which is equivalent t...
constexpr bool isIntN(unsigned N, int64_t x)
Checks if an signed integer fits into the given (dynamic) bit width.
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.
A pair of GlobalVariable and DIExpression.
Represents an entry-value location, or a fragment of one.
This struct describes the address of a global, displaced by a constant.
void addFrameIndexExpr(const DIExpression *Expr, int FI)
std::set< FrameIndexExpr > FrameIndexExprs
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.