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));
190void DebugLocDwarfExpression::emitUnsigned(uint64_t
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.isImm())
263 else if (
Op.isFPImm())
265 else if (
Op.isCImm())
270 return DbgValueLoc(Expr, DbgValueLocEntries, IsVariadic);
274 std::optional<DIExpression::FragmentInfo> Fragment = Expr.
getFragmentInfo();
275 return Fragment ? Fragment->OffsetInBits : 0;
289 Expr(ValueLoc.getExpression()) {
290 if (!Expr->getNumElements())
306 return FIE.Expr && FIE.Expr->isFragment();
308 "conflicting locations for variable");
312 bool GenerateTypeUnits,
321 if (GenerateTypeUnits && (DwarfVersion < 5 || !TT.isOSBinFormatELF()))
327 if (DwarfVersion >= 5)
337 SkeletonHolder(
A,
"skel_string", DIEValueAllocator),
338 IsDarwin(
A->TM.getTargetTriple().isOSDarwin()),
340 const Triple &TT =
Asm->TM.getTargetTriple();
345 DebuggerTuning =
Asm->TM.Options.DebuggerTuning;
350 else if (TT.isOSAIX())
366 HasSplitDwarf = !
Asm->TM.Options.MCOptions.SplitDwarfFile.empty();
374 unsigned DwarfVersionNumber =
Asm->TM.Options.MCOptions.DwarfVersion;
375 unsigned DwarfVersion = DwarfVersionNumber ? DwarfVersionNumber
376 :
MMI->getModule()->getDwarfVersion();
380 bool Dwarf64 = DwarfVersion >= 3 &&
389 ((
Asm->TM.Options.MCOptions.Dwarf64 ||
MMI->getModule()->isDwarf64()) &&
390 TT.isOSBinFormatELF()) ||
391 TT.isOSBinFormatXCOFF();
393 if (!Dwarf64 && TT.isArch64Bit() && TT.isOSBinFormatXCOFF())
402 GenerateTypeUnits = (
A->TM.getTargetTriple().isOSBinFormatELF() ||
403 A->TM.getTargetTriple().isOSBinFormatWasm()) &&
407 DwarfVersion, GenerateTypeUnits, DebuggerTuning,
A->TM.getTargetTriple());
414 UseGNUTLSOpcode =
tuneForGDB() || DwarfVersion < 3;
416 UseDWARF2Bitfields = DwarfVersion < 4;
422 UseSegmentedStringOffsetsTable = DwarfVersion >= 5;
426 EmitDebugEntryValues =
Asm->TM.Options.ShouldEmitDebugEntryValues();
430 UseDebugMacroSection =
439 if (DwarfVersion >= 5)
442 Asm->OutStreamer->getContext().setDwarfVersion(DwarfVersion);
451 return Name.starts_with(
"+") || Name.starts_with(
"-");
458 return Name.contains(
") ");
464 Class = In.slice(In.find(
'[') + 1, In.find(
' '));
469 Class = In.slice(In.find(
'[') + 1, In.find(
'('));
470 Category = In.slice(In.find(
'[') + 1, In.find(
' '));
474 return In.slice(In.find(
' ') + 1, In.find(
']'));
487 if (!SP->isDefinition())
490 if (SP->getName() !=
"")
521 if (Scope->isAbstractScope())
539 if (
auto *SkelCU =
CU.getSkeleton())
540 if (
CU.getCUNode()->getSplitDebugInlining())
551 auto &
CU = getOrCreateDwarfCompileUnit(SP->getUnit());
552 if (
CU.getSkeleton())
558void DwarfDebug::constructAbstractSubprogramScopeDIE(
DwarfCompileUnit &SrcCU,
560 assert(Scope && Scope->getScopeNode());
561 assert(Scope->isAbstractScope());
562 assert(!Scope->getInlinedAt());
568 auto &
CU = getOrCreateDwarfCompileUnit(SP->getUnit());
570 TargetCU.constructAbstractSubprogramScopeDIE(Scope);
571 if (
auto *SkelCU =
CU.getSkeleton())
572 if (
CU.getCUNode()->getSplitDebugInlining())
573 SkelCU->constructAbstractSubprogramScopeDIE(Scope);
607template <
typename ValT>
611 for (
auto Param : DescribedParams) {
612 bool ShouldCombineExpressions = Expr && Param.Expr->
getNumElements() > 0;
622 "Combined debug expression is invalid");
637 auto &ParamsForFwdReg = Worklist[
Reg];
638 for (
auto Param : ParamsToAdd) {
641 return D.ParamReg == Param.ParamReg;
643 "Same parameter described twice by forwarding reg");
650 ParamsForFwdReg.push_back({Param.ParamReg, CombinedExpr});
670 auto IsRegClobberedInMeantime = [&](
Register Reg) ->
bool {
671 for (
auto &RegUnit : ClobberedRegUnits)
672 if (
TRI.hasRegUnit(
Reg, RegUnit))
677 auto DescribeFwdRegsByCalleeSavedCopy = [&](
const DestSourcePair &CopyInst) {
678 Register CopyDestReg = CopyInst.Destination->getReg();
679 Register CopySrcReg = CopyInst.Source->getReg();
680 if (IsRegClobberedInMeantime(CopyDestReg))
684 if (!
TRI.isCalleeSavedPhysReg(CopyDestReg, *MF))
691 for (
auto FwdRegIt = ForwardedRegWorklist.
begin();
692 FwdRegIt != ForwardedRegWorklist.
end();) {
694 if (FwdRegIt->first == CopySrcReg)
696 else if (
unsigned SubRegIdx =
697 TRI.getSubRegIndex(CopySrcReg, FwdRegIt->first))
698 if (
Register CopyDestSubReg =
TRI.getSubReg(CopyDestReg, SubRegIdx))
708 FwdRegIt = ForwardedRegWorklist.
erase(FwdRegIt);
716 if (
auto CopyInst =
TII.isCopyInstr(*CurMI))
717 DescribeFwdRegsByCalleeSavedCopy(*CopyInst);
745 if (
MI.isDebugInstr())
749 if (MO.getReg().isPhysical()) {
750 for (
auto &FwdReg : ForwardedRegWorklist)
751 if (
TRI.regsOverlap(FwdReg.first, MO.getReg()))
752 Defs.insert(FwdReg.first);
761 getForwardingRegsDefinedByMI(*CurMI, FwdRegDefs);
762 if (FwdRegDefs.
empty()) {
768 for (
auto ParamFwdReg : FwdRegDefs) {
769 if (
auto ParamValue =
TII.describeLoadedValue(*CurMI, ParamFwdReg)) {
770 if (ParamValue->first.isImm()) {
771 int64_t Val = ParamValue->first.getImm();
773 ForwardedRegWorklist[ParamFwdReg], Params);
774 }
else if (ParamValue->first.isReg()) {
775 Register RegLoc = ParamValue->first.getReg();
776 Register SP = TLI.getStackPointerRegisterToSaveRestore();
778 bool IsSPorFP = (RegLoc == SP) || (RegLoc ==
FP);
781 if (!IsRegClobberedInMeantime(RegLoc) &&
782 (
TRI.isCalleeSavedPhysReg(RegLoc, *MF) || IsSPorFP)) {
785 ForwardedRegWorklist[ParamFwdReg], Params);
794 ForwardedRegWorklist[ParamFwdReg]);
801 for (
auto ParamFwdReg : FwdRegDefs)
802 ForwardedRegWorklist.
erase(ParamFwdReg);
809 for (
auto &New : TmpWorklistItems)
811 TmpWorklistItems.
clear();
828 if (ForwardedRegWorklist.
empty())
835 interpretValues(CurMI, ForwardedRegWorklist, Params, ClobberedRegUnits);
846 auto CSInfo = CalleesMap.
find(CallMI);
849 if (CSInfo == CalleesMap.end())
863 for (
const auto &ArgReg : CSInfo->second.ArgRegPairs) {
865 ForwardedRegWorklist.
insert({ArgReg.Reg, {{ArgReg.Reg, EmptyExpr}}})
867 assert(InsertedReg &&
"Single register used to forward two arguments?");
872 for (
const auto &MO : CallMI->
uses())
873 if (MO.isReg() && MO.isUndef())
874 ForwardedRegWorklist.
erase(MO.getReg());
884 bool ShouldTryEmitEntryVals =
MBB->getIterator() == MF->
begin();
893 assert(std::next(Suc) == BundleEnd &&
894 "More than one instruction in call delay slot");
901 for (;
I !=
MBB->rend(); ++
I) {
908 if (ShouldTryEmitEntryVals) {
912 for (
auto &RegEntry : ForwardedRegWorklist) {
919void DwarfDebug::constructCallSiteEntryDIEs(
const DISubprogram &SP,
924 if (!
SP.areAllCallsDescribed() || !
SP.isDefinition())
931 CU.addFlag(ScopeDIE,
CU.getDwarf5OrGNUAttr(dwarf::DW_AT_call_all_calls));
934 assert(
TII &&
"TargetInstrInfo not found: cannot label tail calls");
937 auto delaySlotSupported = [&](
const MachineInstr &
MI) {
938 if (!
MI.isBundledWithSucc())
940 auto Suc = std::next(
MI.getIterator());
942 (void)CallInstrBundle;
944 (void)DelaySlotBundle;
951 "Call and its successor instruction don't have same label after.");
956 auto addCallSiteTargetForIndirectCalls = [&](
const MachineInstr *
MI,
958 const MachineFunction *MF =
MI->getMF();
960 auto CSInfo = CalleesMap.
find(
MI);
962 if (CSInfo == CalleesMap.end() || !CSInfo->second.CallTarget)
965 MDNode *CallTarget = CSInfo->second.CallTarget;
967 assert(!CallSiteDIE.findAttribute(dwarf::DW_AT_LLVM_virtual_call_origin) &&
968 "DW_AT_LLVM_virtual_call_origin already exists");
970 DIE *CalleeDIE =
CU.getOrCreateSubprogramDIE(CalleeSP,
nullptr);
971 assert(CalleeDIE &&
"Could not create DIE for call site entry origin");
972 CU.addDIEEntry(CallSiteDIE,
973 CU.getDwarf5OrGNUAttr(dwarf::DW_AT_LLVM_virtual_call_origin),
976 CU.addLinkageNamesToDeclarations(*
this, *CalleeSP, *CalleeDIE);
980 for (
const MachineBasicBlock &
MBB : MF) {
990 if (!
MI.isCandidateForAdditionalCallInfo())
999 if (
MI.hasDelaySlot() && !delaySlotSupported(*&
MI))
1007 const MachineOperand &CalleeOp =
TII->getCalleeOperand(
MI);
1008 bool PhysRegCalleeOperand =
1010 MachineLocation CallTarget{0};
1012 const DISubprogram *CalleeSP =
nullptr;
1013 const Function *CalleeDecl =
nullptr;
1014 if (PhysRegCalleeOperand) {
1015 bool Scalable =
false;
1016 const MachineOperand *BaseOp =
nullptr;
1017 const TargetRegisterInfo &
TRI =
1018 *
Asm->MF->getSubtarget().getRegisterInfo();
1019 if (
TII->getMemOperandWithOffset(
MI, BaseOp,
Offset, Scalable, &
TRI)) {
1020 if (BaseOp && BaseOp->
isReg() && !Scalable)
1021 CallTarget = MachineLocation(BaseOp->
getReg(),
true);
1025 CallTarget = MachineLocation(CalleeOp.
getReg());
1034 if (CalleeSP ==
nullptr && CallTarget.
getReg() == 0 &&
1035 AllocSiteTy ==
nullptr)
1045 const MachineInstr *TopLevelCallMI =
1052 const MCSymbol *PCAddr = (!IsTail ||
CU.useGNUAnalogForDwarf5Feature())
1061 assert((IsTail || PCAddr) &&
"Non-tail call without return PC");
1064 dbgs() <<
"CallSiteEntry: " << MF.getName() <<
" -> "
1068 MF.getSubtarget().getRegisterInfo()->getName(
1070 << (IsTail ?
" [IsTail]" :
"") <<
"\n");
1072 DIE &CallSiteDIE =
CU.constructCallSiteEntryDIE(
1073 ScopeDIE, CalleeSP, CalleeDecl, IsTail, PCAddr, CallAddr, CallTarget,
1077 addCallSiteTargetForIndirectCalls(TopLevelCallMI, CallSiteDIE);
1084 CU.constructCallSiteParmEntryDIEs(CallSiteDIE, Params);
1091 if (!
U.hasDwarfPubSections())
1094 U.addFlag(
D, dwarf::DW_AT_GNU_pubnames);
1097void DwarfDebug::finishUnitAttributes(
const DICompileUnit *DIUnit,
1105 std::string ProducerWithFlags =
Producer.str() +
" " +
Flags.str();
1106 NewCU.
addString(Die, dwarf::DW_AT_producer, ProducerWithFlags);
1108 NewCU.
addString(Die, dwarf::DW_AT_producer, Producer);
1111 NewCU.
addUInt(Die, dwarf::DW_AT_language_name, dwarf::DW_FORM_data2,
1114 if (uint32_t LangVersion = Lang.getVersion(); LangVersion != 0)
1115 NewCU.
addUInt(Die, dwarf::DW_AT_language_version, std::nullopt,
1118 NewCU.
addUInt(Die, dwarf::DW_AT_language, dwarf::DW_FORM_data2,
1122 NewCU.
addString(Die, dwarf::DW_AT_name, FN);
1127 if (!SysRoot.
empty())
1128 NewCU.
addString(Die, dwarf::DW_AT_LLVM_sysroot, SysRoot);
1129 StringRef SDK = DIUnit->
getSDK();
1131 NewCU.
addString(Die, dwarf::DW_AT_APPLE_sdk, SDK);
1142 if (!CompilationDir.empty())
1143 NewCU.
addString(Die, dwarf::DW_AT_comp_dir, CompilationDir);
1144 addGnuPubAttributes(NewCU, Die);
1149 NewCU.
addFlag(Die, dwarf::DW_AT_APPLE_optimized);
1153 NewCU.
addString(Die, dwarf::DW_AT_APPLE_flags, Flags);
1156 NewCU.
addUInt(Die, dwarf::DW_AT_APPLE_major_runtime_vers,
1157 dwarf::DW_FORM_data1, RVer);
1162 NewCU.
addUInt(Die, dwarf::DW_AT_GNU_dwo_id, dwarf::DW_FORM_data8,
1167 ? dwarf::DW_AT_dwo_name
1168 : dwarf::DW_AT_GNU_dwo_name;
1175 if (
auto *
CU = CUMap.lookup(DIUnit))
1182 return CUMap.begin()->second;
1190DwarfDebug::getOrCreateDwarfCompileUnit(
const DICompileUnit *DIUnit) {
1191 if (
auto *
CU = getDwarfCompileUnit(DIUnit))
1196 auto OwnedUnit = std::make_unique<DwarfCompileUnit>(
1198 DwarfCompileUnit &NewCU = *OwnedUnit;
1205 if (!
Asm->OutStreamer->hasRawTextSupport() || SingleCU)
1206 Asm->OutStreamer->emitDwarfFile0Directive(
1212 NewCU.
setSection(
Asm->getObjFileLowering().getDwarfInfoDWOSection());
1214 finishUnitAttributes(DIUnit, NewCU);
1215 NewCU.
setSection(
Asm->getObjFileLowering().getDwarfInfoSection());
1218 CUMap.insert({DIUnit, &NewCU});
1219 CUDieMap.insert({&NewCU.
getUnitDie(), &NewCU});
1233 if (!
A.Expr || !
B.Expr)
1235 auto FragmentA =
A.Expr->getFragmentInfo();
1236 auto FragmentB =
B.Expr->getFragmentInfo();
1237 if (!FragmentA || !FragmentB)
1239 return FragmentA->OffsetInBits < FragmentB->OffsetInBits;
1244 return A.Expr ==
B.Expr;
1259 unsigned NumDebugCUs = std::distance(M->debug_compile_units_begin(),
1260 M->debug_compile_units_end());
1261 if (NumDebugCUs == 0)
1264 assert(NumDebugCUs > 0 &&
"Asm unexpectedly initialized");
1265 SingleCU = NumDebugCUs == 1;
1272 .setStringOffsetsStartSym(
Asm->createTempSymbol(
"str_offsets_base"));
1280 Asm->createTempSymbol(
"rnglists_table_base"));
1284 Asm->createTempSymbol(
"rnglists_dwo_table_base"));
1289 AddrPool.setLabel(
Asm->createTempSymbol(
"addr_table_base"));
1290 DebugLocs.setSym(
Asm->createTempSymbol(
"loclists_table_base"));
1293 if (CUNode->getImportedEntities().empty() &&
1294 CUNode->getEnumTypes().empty() && CUNode->getRetainedTypes().empty() &&
1295 CUNode->getGlobalVariables().empty() && CUNode->getMacros().empty())
1298 getOrCreateDwarfCompileUnit(CUNode);
1302void DwarfDebug::finishEntityDefinitions() {
1303 for (
const auto &Entity : ConcreteEntities) {
1304 DIE *Die = Entity->getDIE();
1311 Unit->finishEntityDefinition(Entity.get());
1315void DwarfDebug::finishSubprogramDefinitions() {
1316 for (
const DISubprogram *SP : ProcessedSPNodes) {
1319 getOrCreateDwarfCompileUnit(
SP->getUnit()),
1320 [&](DwarfCompileUnit &
CU) { CU.finishSubprogramDefinition(SP); });
1324void DwarfDebug::finalizeModuleInfo() {
1325 const TargetLoweringObjectFile &TLOF =
Asm->getObjFileLowering();
1327 finishSubprogramDefinitions();
1329 finishEntityDefinitions();
1331 bool HasEmittedSplitCU =
false;
1335 for (
const auto &
P : CUMap) {
1336 auto &TheCU = *
P.second;
1337 if (TheCU.getCUNode()->isDebugDirectivesOnly())
1339 TheCU.attachLexicalScopesAbstractOrigins();
1342 TheCU.constructContainingTypeDIEs();
1347 auto *SkCU = TheCU.getSkeleton();
1349 bool HasSplitUnit = SkCU && !TheCU.getUnitDie().children().empty();
1352 (void)HasEmittedSplitCU;
1354 "Multiple CUs emitted into a single dwo file");
1355 HasEmittedSplitCU =
true;
1357 ? dwarf::DW_AT_dwo_name
1358 : dwarf::DW_AT_GNU_dwo_name;
1359 finishUnitAttributes(TheCU.getCUNode(), TheCU);
1360 StringRef DWOName =
Asm->TM.Options.MCOptions.SplitDwarfFile;
1361 TheCU.addString(TheCU.getUnitDie(), attrDWOName, DWOName);
1362 SkCU->addString(SkCU->getUnitDie(), attrDWOName, DWOName);
1368 DIEHash(
Asm, &TheCU).computeCUSignature(DWOName, TheCU.getUnitDie());
1373 TheCU.addUInt(TheCU.getUnitDie(), dwarf::DW_AT_GNU_dwo_id,
1374 dwarf::DW_FORM_data8, ID);
1375 SkCU->addUInt(SkCU->getUnitDie(), dwarf::DW_AT_GNU_dwo_id,
1376 dwarf::DW_FORM_data8, ID);
1379 if (
getDwarfVersion() < 5 && !SkeletonHolder.getRangeLists().empty()) {
1381 SkCU->addSectionLabel(SkCU->getUnitDie(), dwarf::DW_AT_GNU_ranges_base,
1385 finishUnitAttributes(SkCU->getCUNode(), *SkCU);
1394 DwarfCompileUnit &
U = SkCU ? *SkCU : TheCU;
1396 if (
unsigned NumRanges = TheCU.getRanges().size()) {
1403 U.addUInt(
U.getUnitDie(), dwarf::DW_AT_low_pc, dwarf::DW_FORM_addr,
1406 U.setBaseAddress(TheCU.getRanges().front().Begin);
1407 U.attachRangesOrLowHighPC(
U.getUnitDie(), TheCU.takeRanges());
1414 U.addAddrTableBase();
1417 if (
U.hasRangeLists())
1418 U.addRnglistsBase();
1421 U.addSectionLabel(
U.getUnitDie(), dwarf::DW_AT_loclists_base,
1430 if (CUNode->getMacros()) {
1431 if (UseDebugMacroSection) {
1433 TheCU.addSectionDelta(
1434 TheCU.getUnitDie(), dwarf::DW_AT_macros,
U.getMacroLabelBegin(),
1438 ? dwarf::DW_AT_macros
1439 : dwarf::DW_AT_GNU_macros;
1440 U.addSectionLabel(
U.getUnitDie(), MacrosAttr,
U.getMacroLabelBegin(),
1445 TheCU.addSectionDelta(
1446 TheCU.getUnitDie(), dwarf::DW_AT_macro_info,
1447 U.getMacroLabelBegin(),
1450 U.addSectionLabel(
U.getUnitDie(), dwarf::DW_AT_macro_info,
1451 U.getMacroLabelBegin(),
1458 for (
auto *CUNode :
MMI->getModule()->debug_compile_units())
1459 if (CUNode->getDWOId())
1460 getOrCreateDwarfCompileUnit(CUNode);
1465 SkeletonHolder.computeSizeAndOffsets();
1469 AccelDebugNames.convertDieToOffset();
1478 assert(CurFn ==
nullptr);
1488 Global.getDebugInfo(GVs);
1489 for (
auto *GVE : GVs)
1490 GVMap[GVE->getVariable()].push_back({&
Global, GVE->getExpression()});
1501 for (
auto *GVE : CUNode->getGlobalVariables()) {
1505 auto &GVMapEntry = GVMap[GVE->getVariable()];
1506 auto *Expr = GVE->getExpression();
1507 if (!GVMapEntry.size() || (Expr && Expr->isConstant()))
1508 GVMapEntry.push_back({
nullptr, Expr});
1511 for (
auto *GVE : CUNode->getGlobalVariables()) {
1514 "Unexpected function-local entity in 'globals' CU field.");
1515 if (Processed.
insert(GV).second)
1520 for (
auto *Ty : CUNode->getEnumTypes()) {
1522 "Unexpected function-local entity in 'enums' CU field.");
1526 for (
auto *Ty : CUNode->getRetainedTypes()) {
1529 CU->getOrCreateTypeDIE(RT);
1534 for (
auto *IE : CUNode->getImportedEntities()) {
1536 "Unexpected function-local entity in 'imports' CU field.");
1537 CU->getOrCreateImportedEntityDIE(IE);
1541 const auto Unexpected = [](
const Metadata *
N) {
1544 for (
const auto *
D :
CU->getDeferredLocalDecls())
1545 DISubprogram::visitRetainedNode<void>(
1546 D, Unexpected, Unexpected,
1547 [
CU](
const auto *IE) {
CU->getOrCreateImportedEntityDIE(IE); },
1548 [
CU](
const auto *Ty) {
CU->getOrCreateTypeDIE(Ty); },
1549 [&](
const auto *GVE) {
1551 if (Processed.
insert(GV).second)
1557 CU->createBaseTypeDIEs();
1562 if (!
Asm || !
Asm->hasDebugInfo())
1566 finalizeModuleInfo();
1576 emitAbbreviations();
1582 if (UseARangesSection)
1590 emitDebugMacinfoDWO();
1600 emitDebugAbbrevDWO();
1602 emitDebugRangesDWO();
1612 emitAccelNamespaces();
1616 emitAccelDebugNames();
1625 emitDebugPubSections();
1633 if (
CU.getExistingAbstractEntity(
Node))
1638 CU.createAbstractEntity(
Node, Scope);
1647void DwarfDebug::collectVariableInfoFromMFTable(
1649 SmallDenseMap<InlinedEntity, DbgVariable *> MFVars;
1650 LLVM_DEBUG(
dbgs() <<
"DwarfDebug: collecting variables from MF side table\n");
1651 for (
const auto &VI :
Asm->MF->getVariableDbgInfo()) {
1654 assert(
VI.Var->isValidLocationForIntrinsic(
VI.Loc) &&
1655 "Expected inlined-at fields to agree");
1657 InlinedEntity Var(
VI.Var,
VI.Loc->getInlinedAt());
1664 <<
", no variable scope found\n");
1668 ensureAbstractEntityIsCreatedIfScoped(TheCU, Var.first,
Scope->getScopeNode());
1672 if (DbgVariable *PreviousLoc = MFVars.
lookup(Var)) {
1673 auto *PreviousMMI = std::get_if<Loc::MMI>(PreviousLoc);
1674 auto *PreviousEntryValue = std::get_if<Loc::EntryValue>(PreviousLoc);
1676 if (PreviousMMI &&
VI.inStackSlot())
1677 PreviousMMI->addFrameIndexExpr(
VI.Expr,
VI.getStackSlot());
1679 else if (PreviousEntryValue &&
VI.inEntryValueRegister())
1680 PreviousEntryValue->addExpr(
VI.getEntryValueRegister(), *
VI.Expr);
1685 if (PreviousLoc->holds<Loc::MMI>())
1686 PreviousLoc->emplace<Loc::EntryValue>(
VI.getEntryValueRegister(),
1689 <<
", conflicting fragment location types\n");
1694 auto RegVar = std::make_unique<DbgVariable>(
1696 if (
VI.inStackSlot())
1697 RegVar->emplace<Loc::MMI>(
VI.Expr,
VI.getStackSlot());
1699 RegVar->emplace<Loc::EntryValue>(
VI.getEntryValueRegister(), *
VI.Expr);
1702 InfoHolder.addScopeVariable(Scope, RegVar.get());
1703 MFVars.
insert({Var, RegVar.get()});
1704 ConcreteEntities.push_back(std::move(RegVar));
1716 assert(
DbgValue->getDebugLoc() &&
"DBG_VALUE without a debug location");
1724 if (LSRange.size() == 0)
1727 const MachineInstr *LScopeBegin = LSRange.front().first;
1731 if (!Ordering.isBefore(
DbgValue, LScopeBegin)) {
1737 for (++Pred; Pred !=
MBB->rend(); ++Pred) {
1740 auto PredDL = Pred->getDebugLoc();
1741 if (!PredDL || Pred->isMetaInstruction())
1745 if (
DL->getScope() == PredDL->getScope())
1748 if (!PredScope || LScope->dominates(PredScope))
1761 if (
MBB->pred_empty() &&
1768 if (Ordering.isBefore(RangeEnd, LScopeEnd))
1812 std::pair<DbgValueHistoryMap::EntryIndex, DbgValueLoc>;
1814 bool isSafeForSingleLocation =
true;
1815 const MachineInstr *StartDebugMI =
nullptr;
1816 const MachineInstr *EndMI =
nullptr;
1818 for (
auto EB = Entries.
begin(), EI = EB, EE = Entries.
end(); EI != EE; ++EI) {
1819 const MachineInstr *
Instr = EI->getInstr();
1822 size_t Index = std::distance(EB, EI);
1823 erase_if(OpenRanges, [&](OpenRange &R) {
return R.first <=
Index; });
1830 "Forgot label before/after instruction starting a range!");
1833 if (std::next(EI) == Entries.
end()) {
1834 const MachineBasicBlock &EndMBB =
Asm->MF->back();
1836 if (EI->isClobber())
1837 EndMI = EI->getInstr();
1839 else if (std::next(EI)->isClobber())
1843 assert(EndLabel &&
"Forgot label after instruction ending a range!");
1845 if (EI->isDbgValue())
1851 if (EI->isDbgValue()) {
1858 if (!
Instr->isUndefDebugValue()) {
1863 if (
Instr->getDebugExpression()->isFragment())
1864 isSafeForSingleLocation =
false;
1867 StartDebugMI =
Instr;
1869 isSafeForSingleLocation =
false;
1875 if (OpenRanges.
empty())
1879 if (StartLabel == EndLabel) {
1880 LLVM_DEBUG(
dbgs() <<
"Omitting location list entry with empty range.\n");
1885 for (
auto &R : OpenRanges)
1893 if (
Asm->MF->hasBBSections() && StartLabel ==
Asm->getFunctionBegin() &&
1894 !
Instr->getParent()->sameSection(&
Asm->MF->front())) {
1895 for (
const auto &[MBBSectionId, MBBSectionRange] :
1896 Asm->MBBSectionRanges) {
1897 if (
Instr->getParent()->getSectionID() == MBBSectionId) {
1898 DebugLoc.emplace_back(MBBSectionRange.BeginLabel, EndLabel,
Values);
1901 DebugLoc.emplace_back(MBBSectionRange.BeginLabel,
1902 MBBSectionRange.EndLabel,
Values);
1912 dbgs() << CurEntry->getValues().size() <<
" Values:\n";
1913 for (
auto &
Value : CurEntry->getValues())
1915 dbgs() <<
"-----\n";
1918 auto PrevEntry = std::next(CurEntry);
1919 if (PrevEntry !=
DebugLoc.rend() && PrevEntry->MergeRanges(*CurEntry))
1923 if (!isSafeForSingleLocation ||
1930 if (!
Asm->MF->hasBBSections())
1938 const MachineBasicBlock *RangeMBB =
nullptr;
1939 if (
DebugLoc[0].getBeginSym() ==
Asm->getFunctionBegin())
1940 RangeMBB = &
Asm->MF->front();
1942 RangeMBB = Entries.
begin()->getInstr()->getParent();
1944 assert(RangeIt !=
Asm->MBBSectionRanges.end() &&
1945 "Range MBB not found in MBBSectionRanges!");
1947 auto *NextEntry = std::next(CurEntry);
1948 auto NextRangeIt = std::next(RangeIt);
1949 while (NextEntry !=
DebugLoc.end()) {
1950 if (NextRangeIt ==
Asm->MBBSectionRanges.end())
1957 if ((RangeIt->second.EndLabel !=
Asm->getFunctionEnd() &&
1958 CurEntry->getEndSym() != RangeIt->second.EndLabel) ||
1959 NextEntry->getBeginSym() != NextRangeIt->second.BeginLabel ||
1960 CurEntry->getValues() != NextEntry->getValues())
1962 RangeIt = NextRangeIt;
1963 NextRangeIt = std::next(RangeIt);
1964 CurEntry = NextEntry;
1965 NextEntry = std::next(CurEntry);
1975 ensureAbstractEntityIsCreatedIfScoped(TheCU, Node,
Scope.getScopeNode());
1977 ConcreteEntities.push_back(
1983 ConcreteEntities.push_back(
1989 return ConcreteEntities.back().get();
1997 collectVariableInfoFromMFTable(TheCU, Processed);
2000 InlinedEntity
IV =
I.first;
2005 const auto &HistoryMapEntries =
I.second;
2009 if (!
DbgValues.hasNonEmptyLocation(HistoryMapEntries))
2012 LexicalScope *
Scope =
nullptr;
2014 if (
const DILocation *IA =
IV.second)
2024 *Scope, LocalVar,
IV.second));
2026 const MachineInstr *MInsn = HistoryMapEntries.front().getInstr();
2032 size_t HistSize = HistoryMapEntries.size();
2033 bool SingleValueWithClobber =
2034 HistSize == 2 && HistoryMapEntries[1].isClobber();
2035 if (HistSize == 1 || SingleValueWithClobber) {
2037 SingleValueWithClobber ? HistoryMapEntries[1].getInstr() :
nullptr;
2039 RegVar->emplace<Loc::Single>(MInsn);
2045 DebugLocStream::ListBuilder
List(DebugLocs, TheCU, *
Asm, *RegVar);
2049 bool isValidSingleLocation = buildLocationList(Entries, HistoryMapEntries);
2054 if (isValidSingleLocation) {
2055 RegVar->emplace<Loc::Single>(Entries[0].getValues()[0]);
2066 for (
auto &Entry : Entries)
2073 InlinedEntity IL =
I.first;
2074 const MachineInstr *
MI =
I.second;
2078 LexicalScope *
Scope =
nullptr;
2081 const DILocalScope *LocalScope =
2082 Label->getScope()->getNonLexicalBlockFileScope();
2084 if (
const DILocation *IA = IL.second)
2097 createConcreteEntity(TheCU, *Scope, Label, IL.second, Sym);
2101 for (
const MDNode *
N :
SP->getRetainedNodes()) {
2105 if (!Processed.
insert(InlinedEntity(DN,
nullptr)).second)
2107 LexicalScope *LexS =
LScopes.findLexicalScope(LS);
2109 createConcreteEntity(TheCU, *LexS, DN,
nullptr);
2111 LocalDeclsPerLS[
LS].insert(
N);
2125 if (!
MI.isBundledWithSucc())
2127 auto Suc = std::next(
MI.getIterator());
2132 assert(Suc->isBundledWithPred() &&
2133 "Call bundle instructions are out of order");
2138 if (!NoDebug && SP->areAllCallsDescribed() &&
2140 (!
MI->hasDelaySlot() || delaySlotSupported(*
MI))) {
2142 bool IsTail =
TII->isTailCall(*
MI);
2160 auto RecordLineZero = [&]() {
2164 const MDNode *Scope =
nullptr;
2165 unsigned Column = 0;
2170 recordSourceLine(0, Column, Scope, 0);
2175 unsigned LastAsmLine =
2176 Asm->OutStreamer->getContext().getCurrentDwarfLoc().getLine();
2181 if (
MI->isMetaInstruction())
2202 auto RecordSourceLine = [
this](
auto &
DL,
auto Flags) {
2204 if (
Asm->OutStreamer->isVerboseAsm()) {
2208 recordSourceLine(
DL.getLine(),
DL.getCol(),
DL.getScope(), Flags,
2217 bool ScopeUsesKeyInstructions =
2219 DL->getScope()->getSubprogram()->getKeyInstructionsEnabled();
2222 if (ScopeUsesKeyInstructions &&
DL &&
DL.getLine())
2223 IsKey = KeyInstructions.contains(
MI);
2229 assert(
MI->getParent() == &*
MI->getMF()->begin());
2230 recordSourceLine(SP->getScopeLine(), 0, SP,
2235 bool PrevInstInSameSection =
2237 PrevInstBB->getSectionID() ==
MI->getParent()->getSectionID());
2238 bool ForceIsStmt = ForceIsStmtInstrs.contains(
MI);
2239 if (PrevInstInSameSection && !ForceIsStmt &&
DL.isSameSourceLocation(
PrevInstLoc)) {
2249 if ((LastAsmLine == 0 &&
DL.getLine() != 0) || Flags) {
2251 RecordSourceLine(
DL, Flags);
2264 if (LastAsmLine == 0)
2285 if (
DL.getLine() == 0 && LastAsmLine == 0)
2292 if (ScopeUsesKeyInstructions) {
2299 if (
DL.getLine() && (
DL.getLine() != OldLine || ForceIsStmt))
2314 if (
Asm->OutStreamer->isVerboseAsm()) {
2318 recordSourceLine(
DL.getLine(),
DL.getCol(),
DL.getScope(), Flags,
2327static std::pair<const MachineInstr *, bool>
2338 bool IsEmptyPrologue =
2339 !(
F.hasPrologueData() ||
F.getMetadata(LLVMContext::MD_func_sanitize));
2344 -> std::optional<std::pair<const MachineInstr *, bool>> {
2346 bool isCopy = (
TII.isCopyInstr(
MI) ?
true :
false);
2347 bool isTrivRemat =
TII.isTriviallyReMaterializable(
MI);
2350 if (!isFrameSetup &&
MI.getDebugLoc()) {
2356 if (
MI.getDebugLoc().getLine())
2357 return std::make_pair(&
MI, IsEmptyPrologue);
2362 if (!
isCopy && !isTrivRemat && !isFrameSetup && !NonTrivialInst)
2363 NonTrivialInst = &
MI;
2365 IsEmptyPrologue =
false;
2366 return std::nullopt;
2374 auto CurBlock = MF->
begin();
2375 auto CurInst = CurBlock->begin();
2379 while (CurBlock->empty())
2380 CurInst = (++CurBlock)->begin();
2381 assert(CurInst != CurBlock->end());
2385 auto getNextInst = [&CurBlock, &CurInst, MF]() ->
bool {
2387 if (CurInst->isTerminator()) {
2396 if (CurBlock->pred_size() > 1)
2407 if (CurBlock == MF->
end())
2409 }
while (CurBlock->empty());
2410 CurInst = CurBlock->begin();
2416 if (!CurInst->isMetaInstruction()) {
2417 auto FoundInst = ExamineInst(*CurInst);
2428 if (CurInst->isCall()) {
2430 Loc &&
Loc->getLine() == 0) {
2432 unsigned ScopeLine = SP->getScopeLine();
2435 const_cast<MachineInstr *
>(&*CurInst)->setDebugLoc(ScopeLineDILoc);
2438 return std::make_pair(&*CurInst,
false);
2444 auto NextInst = std::next(CurInst);
2445 if (NextInst != CurInst->getParent()->end()) {
2462 if (NonTrivialInst && NonTrivialInst->
getParent() == &*MF->
begin()) {
2463 IsEmptyPrologue = NonTrivialInst == &*MF->
begin()->begin();
2464 return std::make_pair(NonTrivialInst, IsEmptyPrologue);
2468 return std::make_pair(
nullptr, IsEmptyPrologue);
2474 const MDNode *S,
unsigned Flags,
unsigned CUID,
2476 ArrayRef<std::unique_ptr<DwarfCompileUnit>> DCUs,
2479 unsigned FileNo = 1;
2482 Fn =
Scope->getFilename();
2483 if (Line != 0 && DwarfVersion >= 4)
2488 .getOrCreateSourceID(
Scope->getFile());
2490 Asm.OutStreamer->emitDwarfLocDirective(FileNo, Line, Col, Flags, 0,
2491 Discriminator, Fn, Comment);
2502 bool IsEmptyPrologue = PrologEnd.second;
2505 if (IsEmptyPrologue) {
2513 if (!
DL ||
DL->getLine() != 0)
2524 (void)getOrCreateDwarfCompileUnit(SP->getUnit());
2534 KeyInstructions.clear();
2541 std::pair<uint8_t, SmallVector<const MachineInstr *, 2>>>
2558 for (
auto &
MBB : *MF) {
2570 for (
auto &
MI :
MBB) {
2571 if (
MI.isMetaInstruction())
2575 if (!
Loc || !
Loc->getLine())
2586 bool IsCallLike =
MI.isCall() ||
TII.isTailCall(
MI);
2591 KeyInstructions.insert(Buoy);
2597 if (!
Loc->getAtomGroup() || !
Loc->getAtomRank())
2601 auto *InlinedAt = Loc->getInlinedAt();
2604 if (!Group || !Rank)
2608 if (BuoyAtom && BuoyAtom != Group) {
2613 auto &[CandidateRank, CandidateInsts] =
2614 GroupCandidates[{InlinedAt, Group}];
2620 assert((CandidateRank == 0 && CandidateInsts.empty()) ||
2621 (CandidateRank != 0 && !CandidateInsts.empty()));
2623 assert(Rank &&
"expected nonzero rank");
2626 if (CandidateRank && CandidateRank < Rank)
2633 if (CandidateRank == Rank)
2637 else if (CandidateRank > Rank)
2638 CandidateInsts.clear();
2642 CandidateInsts.push_back(Buoy);
2643 CandidateRank = Rank;
2651 if (CandidateInsts.empty())
2657 for (
const auto &[
_, Insts] : GroupCandidates.
values())
2658 for (
auto *
I : Insts)
2659 KeyInstructions.insert(
I);
2667 ForceIsStmtInstrs.clear();
2699 SmallDenseSet<MachineBasicBlock *, 4> PredMBBsToExamine;
2700 SmallDenseMap<MachineBasicBlock *, MachineInstr *> PotentialIsStmtMBBInstrs;
2703 for (
auto &
MBB : *
const_cast<MachineFunction *
>(MF)) {
2706 for (
auto &
MI :
MBB) {
2707 if (
MI.getDebugLoc() &&
MI.getDebugLoc()->getLine()) {
2720 for (
auto *
MBB : PredMBBsToExamine) {
2721 auto CheckMBBEdge = [&](MachineBasicBlock *Succ,
unsigned OutgoingLine) {
2722 auto MBBInstrIt = PotentialIsStmtMBBInstrs.
find(Succ);
2723 if (MBBInstrIt == PotentialIsStmtMBBInstrs.
end())
2725 MachineInstr *
MI = MBBInstrIt->second;
2726 if (
MI->getDebugLoc()->getLine() == OutgoingLine)
2728 PotentialIsStmtMBBInstrs.
erase(MBBInstrIt);
2729 ForceIsStmtInstrs.insert(
MI);
2736 CheckMBBEdge(Succ, 0);
2742 return PotentialIsStmtMBBInstrs.contains(SuccMBB);
2750 MachineBasicBlock *
TBB =
nullptr, *FBB =
nullptr;
2757 if (!AnalyzeFailed && !
Cond.empty() && FBB !=
nullptr &&
2760 assert(MIIt->isBranch() &&
"Bad result from analyzeBranch?");
2761 CheckMBBEdge(FBB, FBBLine);
2785 unsigned LastLine = 0;
2787 if (
auto DL = MIIt->getDebugLoc();
DL &&
DL->getLine()) {
2788 LastLine =
DL->getLine();
2793 for (
auto *Succ : SuccessorBBs)
2794 CheckMBBEdge(Succ, LastLine);
2809 FunctionLineTableLabel =
CU.emitFuncLineTableOffsets()
2810 ?
Asm->OutStreamer->emitLineTableLabel()
2813 Asm->OutStreamer->getContext().setDwarfCompileUnitID(
2821 *MF,
Asm->OutStreamer->getContext().getDwarfCompileUnitID());
2827 computeKeyInstructions(MF);
2828 findForceIsStmtInstrs(MF);
2836 if (
Asm->OutStreamer->hasRawTextSupport())
2840 return CU.getUniqueID();
2844 const auto &CURanges =
CU->getRanges();
2845 auto &LineTable =
Asm->OutStreamer->getContext().getMCDwarfLineTable(
2848 LineTable.getMCLineSections().addEndEntry(
2849 const_cast<MCSymbol *
>(CURanges.back().End));
2869 "endFunction should be called with the same function as beginFunction");
2872 Asm->OutStreamer->getContext().setDwarfCompileUnitID(0);
2884 collectEntityInfo(TheCU, SP, Processed);
2888 for (
const auto &R :
Asm->MBBSectionRanges)
2889 TheCU.
addRange({R.second.BeginLabel, R.second.EndLabel});
2896 LScopes.getAbstractScopesList().empty() && !IsDarwin) {
2897 for (
const auto &R :
Asm->MBBSectionRanges)
2907 size_t NumAbstractSubprograms =
LScopes.getAbstractScopesList().size();
2911 for (
const MDNode *
N : SP->getRetainedNodes()) {
2914 auto *LexS =
LScopes.getOrCreateAbstractScope(LS);
2915 assert(LexS &&
"Expected the LexicalScope to be created.");
2919 if (!Processed.
insert(InlinedEntity(DN,
nullptr)).second ||
2925 LocalDeclsPerLS[LS].insert(
N);
2928 LScopes.getAbstractScopesList().size() == NumAbstractSubprograms &&
2929 "getOrCreateAbstractScope() inserted an abstract subprogram scope");
2931 constructAbstractSubprogramScopeDIE(TheCU, AScope);
2934 ProcessedSPNodes.insert(SP);
2938 if (!
LScopes.getAbstractScopesList().empty() &&
2940 SkelCU->constructSubprogramScopeDIE(SP,
F, FnScope,
2941 FunctionLineTableLabel);
2943 FunctionLineTableLabel =
nullptr;
2946 constructCallSiteEntryDIEs(*SP, TheCU, ScopeDIE, *MF);
2954 LocalDeclsPerLS.clear();
2961void DwarfDebug::recordSourceLine(
unsigned Line,
unsigned Col,
const MDNode *S,
2973void DwarfDebug::emitDebugInfo() {
2979void DwarfDebug::emitAbbreviations() {
2982 Holder.
emitAbbrevs(
Asm->getObjFileLowering().getDwarfAbbrevSection());
2985void DwarfDebug::emitStringOffsetsTableHeader() {
2988 *
Asm,
Asm->getObjFileLowering().getDwarfStrOffSection(),
2992template <
typename AccelTableT>
2993void DwarfDebug::emitAccel(AccelTableT &Accel,
MCSection *Section,
2995 Asm->OutStreamer->switchSection(Section);
3001void DwarfDebug::emitAccelDebugNames() {
3010void DwarfDebug::emitAccelNames() {
3011 emitAccel(AccelNames,
Asm->getObjFileLowering().getDwarfAccelNamesSection(),
3017void DwarfDebug::emitAccelObjC() {
3018 emitAccel(AccelObjC,
Asm->getObjFileLowering().getDwarfAccelObjCSection(),
3023void DwarfDebug::emitAccelNamespaces() {
3024 emitAccel(AccelNamespace,
3025 Asm->getObjFileLowering().getDwarfAccelNamespaceSection(),
3030void DwarfDebug::emitAccelTypes() {
3031 emitAccel(AccelTypes,
Asm->getObjFileLowering().getDwarfAccelTypesSection(),
3061 if (Die->
getTag() == dwarf::DW_TAG_compile_unit)
3069 DIE &SpecDIE = SpecVal.getDIEEntry().getEntry();
3076 case dwarf::DW_TAG_class_type:
3077 case dwarf::DW_TAG_structure_type:
3078 case dwarf::DW_TAG_union_type:
3079 case dwarf::DW_TAG_enumeration_type:
3084 case dwarf::DW_TAG_typedef:
3085 case dwarf::DW_TAG_base_type:
3086 case dwarf::DW_TAG_subrange_type:
3087 case dwarf::DW_TAG_template_alias:
3089 case dwarf::DW_TAG_namespace:
3091 case dwarf::DW_TAG_subprogram:
3093 case dwarf::DW_TAG_variable:
3095 case dwarf::DW_TAG_enumerator:
3105void DwarfDebug::emitDebugPubSections() {
3106 for (
const auto &NU : CUMap) {
3107 DwarfCompileUnit *TheU = NU.second;
3114 Asm->OutStreamer->switchSection(
3115 GnuStyle ?
Asm->getObjFileLowering().getDwarfGnuPubNamesSection()
3116 :
Asm->getObjFileLowering().getDwarfPubNamesSection());
3117 emitDebugPubSection(GnuStyle,
"Names", TheU, TheU->
getGlobalNames());
3119 Asm->OutStreamer->switchSection(
3120 GnuStyle ?
Asm->getObjFileLowering().getDwarfGnuPubTypesSection()
3121 :
Asm->getObjFileLowering().getDwarfPubTypesSection());
3122 emitDebugPubSection(GnuStyle,
"Types", TheU, TheU->
getGlobalTypes());
3128 Asm->emitDwarfOffset(
CU.getSection()->getBeginSymbol(),
3129 CU.getDebugSectionOffset());
3131 Asm->emitDwarfSymbolReference(
CU.getLabelBegin());
3134void DwarfDebug::emitDebugPubSection(
bool GnuStyle,
StringRef Name,
3142 "pub" + Name,
"Length of Public " + Name +
" Info");
3144 Asm->OutStreamer->AddComment(
"DWARF Version");
3147 Asm->OutStreamer->AddComment(
"Offset of Compilation Unit Info");
3148 emitSectionReference(*TheU);
3150 Asm->OutStreamer->AddComment(
"Compilation Unit Length");
3155 for (
const auto &GI : Globals)
3158 return A.second->getOffset() <
B.second->getOffset();
3160 for (
const auto &[Name, Entity] : Vec) {
3161 Asm->OutStreamer->AddComment(
"DIE offset");
3162 Asm->emitDwarfLengthOrOffset(Entity->getOffset());
3166 Asm->OutStreamer->AddComment(
3172 Asm->OutStreamer->AddComment(
"External Name");
3173 Asm->OutStreamer->emitBytes(StringRef(
Name.data(),
Name.size() + 1));
3176 Asm->OutStreamer->AddComment(
"End Mark");
3177 Asm->emitDwarfLengthOrOffset(0);
3178 Asm->OutStreamer->emitLabel(EndLabel);
3182void DwarfDebug::emitDebugStr() {
3183 MCSection *StringOffsetsSection =
nullptr;
3185 emitStringOffsetsTableHeader();
3186 StringOffsetsSection =
Asm->getObjFileLowering().getDwarfStrOffSection();
3189 Holder.
emitStrings(
Asm->getObjFileLowering().getDwarfStrSection(),
3190 StringOffsetsSection,
true);
3196 auto &&Comments = DebugLocs.getComments(Entry);
3197 auto Comment = Comments.begin();
3198 auto End = Comments.end();
3205 unsigned PtrSize =
Asm->MAI.getCodePointerSize();
3207 DebugLocs.getBytes(Entry).size()),
3208 Asm->getDataLayout().isLittleEndian(), PtrSize);
3213 for (
const auto &
Op : Expr) {
3214 assert(
Op.getCode() != dwarf::DW_OP_const_type &&
3215 "3 operand ops not yet supported");
3216 assert(!
Op.getSubCode() &&
"SubOps not yet supported");
3217 Streamer.
emitInt8(
Op.getCode(), Comment != End ? *(Comment++) :
"");
3219 for (
unsigned I = 0;
I <
Op.getDescription().
Op.size(); ++
I) {
3220 if (
Op.getDescription().Op[
I] == Encoding::BaseTypeRef) {
3222 Streamer.
emitDIERef(*
CU->ExprRefedBaseTypes[
Op.getRawOperand(
I)].Die);
3224 for (
unsigned J = 0; J <
Length; ++J)
3229 Streamer.
emitInt8(
Data.getData()[J], Comment != End ? *(Comment++) :
"");
3240 auto *DIExpr =
Value.getExpression();
3246 if (DIExpr && DIExpr->isEntryValue()) {
3263 auto EmitValueLocEntry = [&DwarfExpr, &
BT,
3266 if (Entry.isInt()) {
3267 if (
BT && (
BT->getEncoding() == dwarf::DW_ATE_boolean)) {
3272 bool IsSigned =
BT && (
BT->getEncoding() == dwarf::DW_ATE_signed ||
3273 BT->getEncoding() == dwarf::DW_ATE_signed_char);
3285 bool IsByteSized = TypeBitSize % 8 == 0;
3287 IsSigned ? !
isIntN(GenericBitSize, Entry.getInt())
3289 static_cast<uint64_t>(Entry.getInt()));
3290 if (TypeBitSize > GenericBitSize && IsByteSized && IsOutOfRange) {
3292 APInt(
static_cast<unsigned>(TypeBitSize),
3293 static_cast<uint64_t>(Entry.getInt()), IsSigned,
3304 }
else if (Entry.isLocation()) {
3306 if (Location.isIndirect())
3312 }
else if (Entry.isTargetIndexLocation()) {
3318 }
else if (Entry.isConstantFP()) {
3321 DwarfExpr.
addConstantFP(Entry.getConstantFP()->getValueAPF(), AP);
3322 }
else if (Entry.getConstantFP()
3325 .getBitWidth() <= 64 ) {
3327 Entry.getConstantFP()->getValueAPF().bitcastToAPInt());
3330 dbgs() <<
"Skipped DwarfExpression creation for ConstantFP of size"
3331 << Entry.getConstantFP()
3342 if (!
Value.isVariadic()) {
3343 if (!EmitValueLocEntry(
Value.getLocEntries()[0], ExprCursor))
3352 return Entry.isLocation() && !Entry.getLoc().getReg();
3357 std::move(ExprCursor),
3358 [EmitValueLocEntry, &
Value](
unsigned Idx,
3360 return EmitValueLocEntry(
Value.getLocEntries()[Idx], Cursor);
3368 assert(!Values.empty() &&
3369 "location list entries without values are redundant");
3370 assert(Begin != End &&
"unexpected location list entry with empty range");
3375 if (
Value.isFragment()) {
3378 return P.isFragment();
3379 }) &&
"all values are expected to be fragments");
3382 for (
const auto &Fragment : Values)
3386 assert(Values.size() == 1 &&
"only fragments may have >1 value");
3397 Asm->OutStreamer->AddComment(
"Loc expr size");
3399 Asm->emitULEB128(DebugLocs.getBytes(Entry).size());
3400 else if (DebugLocs.getBytes(Entry).size() <= std::numeric_limits<uint16_t>::max())
3401 Asm->emitInt16(DebugLocs.getBytes(Entry).size());
3420 Asm->OutStreamer->AddComment(
"Offset entry count");
3426 Asm->getDwarfOffsetByteSize());
3440 Asm->OutStreamer->AddComment(
"Offset entry count");
3441 Asm->emitInt32(DebugLocs.getLists().size());
3442 Asm->OutStreamer->emitLabel(DebugLocs.getSym());
3444 for (
const auto &List : DebugLocs.getLists())
3445 Asm->emitLabelDifference(List.Label, DebugLocs.getSym(),
3446 Asm->getDwarfOffsetByteSize());
3451template <
typename Ranges,
typename PayloadEmitter>
3455 unsigned OffsetPair,
unsigned StartxLength,
unsigned StartxEndx,
3457 bool ShouldUseBaseAddress, PayloadEmitter EmitPayload) {
3458 auto Size = Asm->MAI.getCodePointerSize();
3462 Asm->OutStreamer->emitLabel(Sym);
3469 for (
const auto &
Range : R)
3470 SectionRanges[&
Range.Begin->getSection()].push_back(&
Range);
3472 const MCSymbol *CUBase =
CU.getBaseAddress();
3473 bool BaseIsSet =
false;
3474 for (
const auto &
P : SectionRanges) {
3475 auto *
Base = CUBase;
3477 (DD.
useSplitDwarf() && UseDwarf5 &&
P.first->isLinkerRelaxable())) {
3480 }
else if (!
Base && ShouldUseBaseAddress) {
3481 const MCSymbol *Begin =
P.second.front()->Begin;
3486 Asm->OutStreamer->emitIntValue(-1,
Size);
3487 Asm->OutStreamer->AddComment(
" base address");
3488 Asm->OutStreamer->emitSymbolValue(
Base,
Size);
3489 }
else if (NewBase != Begin ||
P.second.size() > 1) {
3495 Asm->OutStreamer->AddComment(StringifyEnum(BaseAddressx));
3496 Asm->emitInt8(BaseAddressx);
3497 Asm->OutStreamer->AddComment(
" base address index");
3500 }
else if (BaseIsSet && !UseDwarf5) {
3503 Asm->OutStreamer->emitIntValue(-1,
Size);
3504 Asm->OutStreamer->emitIntValue(0,
Size);
3507 for (
const auto *RS :
P.second) {
3510 assert(Begin &&
"Range without a begin symbol?");
3511 assert(End &&
"Range without an end symbol?");
3515 Asm->OutStreamer->AddComment(StringifyEnum(OffsetPair));
3516 Asm->emitInt8(OffsetPair);
3517 Asm->OutStreamer->AddComment(
" starting offset");
3518 Asm->emitLabelDifferenceAsULEB128(Begin,
Base);
3519 Asm->OutStreamer->AddComment(
" ending offset");
3520 Asm->emitLabelDifferenceAsULEB128(End,
Base);
3522 Asm->emitLabelDifference(Begin,
Base,
Size);
3523 Asm->emitLabelDifference(End,
Base,
Size);
3525 }
else if (UseDwarf5) {
3533 Asm->OutStreamer->AddComment(StringifyEnum(StartxEndx));
3534 Asm->emitInt8(StartxEndx);
3535 Asm->OutStreamer->AddComment(
" start index");
3537 Asm->OutStreamer->AddComment(
" end index");
3540 Asm->OutStreamer->AddComment(StringifyEnum(StartxLength));
3541 Asm->emitInt8(StartxLength);
3542 Asm->OutStreamer->AddComment(
" start index");
3544 Asm->OutStreamer->AddComment(
" length");
3545 Asm->emitLabelDifferenceAsULEB128(End, Begin);
3548 Asm->OutStreamer->emitSymbolValue(Begin,
Size);
3549 Asm->OutStreamer->emitSymbolValue(End,
Size);
3556 Asm->OutStreamer->AddComment(StringifyEnum(
EndOfList));
3560 Asm->OutStreamer->emitIntValue(0,
Size);
3561 Asm->OutStreamer->emitIntValue(0,
Size);
3569 dwarf::DW_LLE_base_addressx, dwarf::DW_LLE_offset_pair,
3570 dwarf::DW_LLE_startx_length, dwarf::DW_LLE_startx_endx,
3573 DD.emitDebugLocEntryLocation(E, List.CU);
3577void DwarfDebug::emitDebugLocImpl(
MCSection *Sec) {
3578 if (DebugLocs.getLists().empty())
3581 Asm->OutStreamer->switchSection(Sec);
3587 for (
const auto &
List : DebugLocs.getLists())
3591 Asm->OutStreamer->emitLabel(TableEnd);
3595void DwarfDebug::emitDebugLoc() {
3598 ?
Asm->getObjFileLowering().getDwarfLoclistsSection()
3599 :
Asm->getObjFileLowering().getDwarfLocSection());
3603void DwarfDebug::emitDebugLocDWO() {
3606 Asm->getObjFileLowering().getDwarfLoclistsDWOSection());
3611 for (
const auto &
List : DebugLocs.getLists()) {
3612 Asm->OutStreamer->switchSection(
3613 Asm->getObjFileLowering().getDwarfLocDWOSection());
3614 Asm->OutStreamer->emitLabel(
List.Label);
3616 for (
const auto &Entry : DebugLocs.getEntries(
List)) {
3625 Asm->emitInt8(dwarf::DW_LLE_startx_length);
3626 unsigned idx = AddrPool.getIndex(
Entry.Begin);
3627 Asm->emitULEB128(idx);
3633 Asm->emitInt8(dwarf::DW_LLE_end_of_list);
3643void DwarfDebug::emitDebugARanges() {
3644 if (ArangeLabels.empty())
3651 for (
const SymbolCU &SCU : ArangeLabels) {
3652 if (SCU.Sym->isInSection()) {
3654 MCSection *Section = &SCU.Sym->getSection();
3655 SectionMap[Section].push_back(SCU);
3660 SectionMap[
nullptr].push_back(SCU);
3664 DenseMap<DwarfCompileUnit *, std::vector<ArangeSpan>> Spans;
3666 for (
auto &
I : SectionMap) {
3674 for (
const SymbolCU &Cur :
List) {
3676 Span.
Start = Cur.Sym;
3679 Spans[Cur.CU].push_back(Span);
3685 List.push_back(SymbolCU(
nullptr,
Asm->OutStreamer->endSection(Section)));
3689 for (
size_t n = 1, e =
List.size(); n < e; n++) {
3690 const SymbolCU &Prev =
List[n - 1];
3691 const SymbolCU &Cur =
List[n];
3694 if (Cur.
CU != Prev.
CU) {
3696 Span.
Start = StartSym;
3699 Spans[Prev.
CU].push_back(Span);
3706 Asm->OutStreamer->switchSection(
3707 Asm->getObjFileLowering().getDwarfARangesSection());
3709 unsigned PtrSize =
Asm->MAI.getCodePointerSize();
3712 std::vector<DwarfCompileUnit *> CUs;
3713 for (
const auto &it : Spans) {
3714 DwarfCompileUnit *
CU = it.first;
3719 llvm::sort(CUs, [](
const DwarfCompileUnit *
A,
const DwarfCompileUnit *
B) {
3720 return A->getUniqueID() <
B->getUniqueID();
3724 for (DwarfCompileUnit *
CU : CUs) {
3725 std::vector<ArangeSpan> &
List = Spans[
CU];
3728 if (
auto *Skel =
CU->getSkeleton())
3732 unsigned ContentSize =
3734 Asm->getDwarfOffsetByteSize() +
3739 unsigned TupleSize = PtrSize * 2;
3743 Asm->getUnitLengthFieldByteSize() + ContentSize,
Align(TupleSize));
3746 ContentSize += (
List.size() + 1) * TupleSize;
3749 Asm->emitDwarfUnitLength(ContentSize,
"Length of ARange Set");
3750 Asm->OutStreamer->AddComment(
"DWARF Arange version number");
3752 Asm->OutStreamer->AddComment(
"Offset Into Debug Info Section");
3753 emitSectionReference(*
CU);
3754 Asm->OutStreamer->AddComment(
"Address Size (in bytes)");
3755 Asm->emitInt8(PtrSize);
3756 Asm->OutStreamer->AddComment(
"Segment Size (in bytes)");
3759 Asm->OutStreamer->emitFill(Padding, 0xff);
3761 for (
const ArangeSpan &Span :
List) {
3762 Asm->emitLabelReference(Span.Start, PtrSize);
3769 auto SizeRef = SymSize.find(Span.Start);
3770 if ((SizeRef == SymSize.end() || SizeRef->second != 0) && Span.End) {
3771 Asm->emitLabelDifference(Span.End, Span.Start, PtrSize);
3776 if (SizeRef == SymSize.end() || SizeRef->second == 0)
3779 Size = SizeRef->second;
3781 Asm->OutStreamer->emitIntValue(
Size, PtrSize);
3785 Asm->OutStreamer->AddComment(
"ARange terminator");
3786 Asm->OutStreamer->emitIntValue(0, PtrSize);
3787 Asm->OutStreamer->emitIntValue(0, PtrSize);
3795 dwarf::DW_RLE_base_addressx, dwarf::DW_RLE_offset_pair,
3796 dwarf::DW_RLE_startx_length, dwarf::DW_RLE_startx_endx,
3798 List.CU->getCUNode()->getRangesBaseAddress() ||
3810 return !Pair.second->getCUNode()->isDebugDirectivesOnly();
3813 Asm->OutStreamer->switchSection(Section);
3823 Asm->OutStreamer->emitLabel(TableEnd);
3828void DwarfDebug::emitDebugRanges() {
3831 emitDebugRangesImpl(Holder,
3833 ?
Asm->getObjFileLowering().getDwarfRnglistsSection()
3834 :
Asm->getObjFileLowering().getDwarfRangesSection());
3837void DwarfDebug::emitDebugRangesDWO() {
3839 Asm->getObjFileLowering().getDwarfRnglistsDWOSection());
3846 enum HeaderFlagMask {
3847#define HANDLE_MACRO_FLAG(ID, NAME) MACRO_FLAG_##NAME = ID,
3848#include "llvm/BinaryFormat/Dwarf.def"
3850 Asm->OutStreamer->AddComment(
"Macro information version");
3851 Asm->emitInt16(DwarfVersion >= 5 ? DwarfVersion : 4);
3854 if (Asm->isDwarf64()) {
3855 Asm->OutStreamer->AddComment(
"Flags: 64 bit, debug_line_offset present");
3856 Asm->emitInt8(MACRO_FLAG_OFFSET_SIZE | MACRO_FLAG_DEBUG_LINE_OFFSET);
3858 Asm->OutStreamer->AddComment(
"Flags: 32 bit, debug_line_offset present");
3859 Asm->emitInt8(MACRO_FLAG_DEBUG_LINE_OFFSET);
3861 Asm->OutStreamer->AddComment(
"debug_line_offset");
3863 Asm->emitDwarfLengthOrOffset(0);
3865 Asm->emitDwarfSymbolReference(
CU.getLineTableStartSym());
3868void DwarfDebug::handleMacroNodes(DIMacroNodeArray Nodes,
DwarfCompileUnit &U) {
3869 for (
auto *MN : Nodes) {
3873 emitMacroFile(*
F, U);
3879void DwarfDebug::emitMacro(
DIMacro &M) {
3880 StringRef
Name =
M.getName();
3881 StringRef
Value =
M.getValue();
3887 if (UseDebugMacroSection) {
3890 ? dwarf::DW_MACRO_define_strx
3891 : dwarf::DW_MACRO_undef_strx;
3894 Asm->OutStreamer->AddComment(
"Line Number");
3895 Asm->emitULEB128(
M.getLine());
3896 Asm->OutStreamer->AddComment(
"Macro String");
3898 InfoHolder.getStringPool().getIndexedEntry(*
Asm, Str).getIndex());
3901 ? dwarf::DW_MACRO_GNU_define_indirect
3902 : dwarf::DW_MACRO_GNU_undef_indirect;
3905 Asm->OutStreamer->AddComment(
"Line Number");
3906 Asm->emitULEB128(
M.getLine());
3907 Asm->OutStreamer->AddComment(
"Macro String");
3908 Asm->emitDwarfSymbolReference(
3909 InfoHolder.getStringPool().getEntry(*
Asm, Str).getSymbol());
3913 Asm->emitULEB128(
M.getMacinfoType());
3914 Asm->OutStreamer->AddComment(
"Line Number");
3915 Asm->emitULEB128(
M.getLine());
3916 Asm->OutStreamer->AddComment(
"Macro String");
3917 Asm->OutStreamer->emitBytes(Str);
3918 Asm->emitInt8(
'\0');
3922void DwarfDebug::emitMacroFileImpl(
3924 StringRef (*MacroFormToString)(
unsigned Form)) {
3926 Asm->OutStreamer->AddComment(MacroFormToString(StartFile));
3927 Asm->emitULEB128(StartFile);
3928 Asm->OutStreamer->AddComment(
"Line Number");
3930 Asm->OutStreamer->AddComment(
"File Number");
3933 Asm->emitULEB128(getDwoLineTable(U)->getFile(
3935 Asm->OutContext.getDwarfVersion(),
F.getSource()));
3937 Asm->emitULEB128(
U.getOrCreateSourceID(&
F));
3939 Asm->OutStreamer->AddComment(MacroFormToString(EndFile));
3940 Asm->emitULEB128(EndFile);
3947 if (UseDebugMacroSection)
3949 F, U, dwarf::DW_MACRO_start_file, dwarf::DW_MACRO_end_file,
3956void DwarfDebug::emitDebugMacinfoImpl(
MCSection *Section) {
3957 for (
const auto &
P : CUMap) {
3958 auto &TheCU = *
P.second;
3960 DwarfCompileUnit &
U = SkCU ? *SkCU : TheCU;
3962 DIMacroNodeArray Macros = CUNode->getMacros();
3965 Asm->OutStreamer->switchSection(Section);
3966 Asm->OutStreamer->emitLabel(
U.getMacroLabelBegin());
3967 if (UseDebugMacroSection)
3969 handleMacroNodes(Macros, U);
3970 Asm->OutStreamer->AddComment(
"End Of Macro List Mark");
3976void DwarfDebug::emitDebugMacinfo() {
3977 auto &ObjLower =
Asm->getObjFileLowering();
3978 emitDebugMacinfoImpl(UseDebugMacroSection
3979 ? ObjLower.getDwarfMacroSection()
3980 : ObjLower.getDwarfMacinfoSection());
3983void DwarfDebug::emitDebugMacinfoDWO() {
3984 auto &ObjLower =
Asm->getObjFileLowering();
3985 emitDebugMacinfoImpl(UseDebugMacroSection
3986 ? ObjLower.getDwarfMacroDWOSection()
3987 : ObjLower.getDwarfMacinfoDWOSection());
3992void DwarfDebug::initSkeletonUnit(
const DwarfUnit &U,
DIE &Die,
3993 std::unique_ptr<DwarfCompileUnit> NewU) {
3995 if (!CompilationDir.empty())
3996 NewU->addString(Die, dwarf::DW_AT_comp_dir, CompilationDir);
3997 addGnuPubAttributes(*NewU, Die);
3999 SkeletonHolder.addUnit(std::move(NewU));
4004 auto OwnedUnit = std::make_unique<DwarfCompileUnit>(
4005 CU.getUniqueID(),
CU.getCUNode(),
Asm,
this, &SkeletonHolder,
4007 DwarfCompileUnit &NewCU = *OwnedUnit;
4008 NewCU.
setSection(
Asm->getObjFileLowering().getDwarfInfoSection());
4015 initSkeletonUnit(
CU, NewCU.
getUnitDie(), std::move(OwnedUnit));
4022void DwarfDebug::emitDebugInfoDWO() {
4030void DwarfDebug::emitDebugAbbrevDWO() {
4032 InfoHolder.emitAbbrevs(
Asm->getObjFileLowering().getDwarfAbbrevDWOSection());
4035void DwarfDebug::emitDebugLineDWO() {
4037 SplitTypeUnitFileTable.Emit(
4038 *
Asm->OutStreamer, MCDwarfLineTableParams(),
4039 Asm->getObjFileLowering().getDwarfLineDWOSection());
4042void DwarfDebug::emitStringOffsetsTableHeaderDWO() {
4044 InfoHolder.getStringPool().emitStringOffsetsTableHeader(
4045 *
Asm,
Asm->getObjFileLowering().getDwarfStrOffDWOSection(),
4052void DwarfDebug::emitDebugStrDWO() {
4054 emitStringOffsetsTableHeaderDWO();
4056 MCSection *OffSec =
Asm->getObjFileLowering().getDwarfStrOffDWOSection();
4057 InfoHolder.emitStrings(
Asm->getObjFileLowering().getDwarfStrDWOSection(),
4062void DwarfDebug::emitDebugAddr() {
4063 AddrPool.emit(*
Asm,
Asm->getObjFileLowering().getDwarfAddrSection());
4069 const DICompileUnit *DIUnit =
CU.getCUNode();
4070 SplitTypeUnitFileTable.maybeSetRootFile(
4073 return &SplitTypeUnitFileTable;
4084 return Result.high();
4093 if (!TypeUnitsUnderConstruction.empty() && AddrPool.hasBeenUsed())
4096 auto Ins = TypeSignatures.try_emplace(CTy);
4098 CU.addDIETypeSignature(RefDie, Ins.first->second);
4103 bool TopLevelType = TypeUnitsUnderConstruction.empty();
4104 AddrPool.resetUsedFlag();
4106 auto OwnedUnit = std::make_unique<DwarfTypeUnit>(
4110 TypeUnitsUnderConstruction.emplace_back(std::move(OwnedUnit), CTy);
4112 NewTU.
addUInt(UnitDie, dwarf::DW_AT_language, dwarf::DW_FORM_data2,
4113 CU.getSourceLanguage());
4117 Ins.first->second = Signature;
4125 if (!CompilationDir.empty())
4126 NewTU.
addString(UnitDie, dwarf::DW_AT_comp_dir, CompilationDir);
4127 NewTU.
addString(UnitDie, dwarf::DW_AT_dwo_name,
4128 Asm->TM.Options.MCOptions.SplitDwarfFile);
4132 ?
Asm->getObjFileLowering().getDwarfTypesDWOSection()
4133 :
Asm->getObjFileLowering().getDwarfInfoDWOSection();
4138 ?
Asm->getObjFileLowering().getDwarfTypesSection(Signature)
4139 :
Asm->getObjFileLowering().getDwarfInfoSection(Signature);
4142 CU.applyStmtList(UnitDie);
4153 auto TypeUnitsToAdd = std::move(TypeUnitsUnderConstruction);
4154 TypeUnitsUnderConstruction.clear();
4158 if (AddrPool.hasBeenUsed()) {
4159 AccelTypeUnitsDebugNames.clear();
4163 for (
const auto &
TU : TypeUnitsToAdd)
4164 TypeSignatures.erase(
TU.second);
4172 CU.updateAcceleratorTables(CTy->
getScope(), CTy, RefDie);
4178 for (
auto &
TU : TypeUnitsToAdd) {
4179 InfoHolder.computeSizeAndOffsetsForUnit(
TU.first.get());
4184 AccelDebugNames.addTypeUnitSignature(*
TU.first);
4186 AccelDebugNames.addTypeUnitSymbol(*
TU.first);
4189 AccelTypeUnitsDebugNames.convertDieToOffset();
4190 AccelDebugNames.addTypeEntries(AccelTypeUnitsDebugNames);
4191 AccelTypeUnitsDebugNames.clear();
4194 CU.addDIETypeSignature(RefDie, Signature);
4201template <
typename DataT>
4202void DwarfDebug::addAccelNameImpl(
4207 Unit.getUnitDie().getTag() == dwarf::DW_TAG_skeleton_unit || Name.empty())
4224 assert(((&Current == &AccelTypeUnitsDebugNames) ||
4225 ((&Current == &AccelDebugNames) &&
4226 (Unit.getUnitDie().getTag() != dwarf::DW_TAG_type_unit))) &&
4227 "Kind is CU but TU is being processed.");
4228 assert(((&Current == &AccelDebugNames) ||
4229 ((&Current == &AccelTypeUnitsDebugNames) &&
4230 (Unit.getUnitDie().getTag() == dwarf::DW_TAG_type_unit))) &&
4231 "Kind is TU but CU is being processed.");
4234 Current.
addName(
Ref, Die, Unit.getUniqueID(),
4235 Unit.getUnitDie().getTag() == dwarf::DW_TAG_type_unit);
4249 addAccelNameImpl(Unit, NameTableKind, AccelNames, Name, Die);
4258 addAccelNameImpl(Unit, NameTableKind, AccelObjC, Name, Die);
4265 addAccelNameImpl(Unit, NameTableKind, AccelNamespace, Name, Die);
4271 const DIE &Die,
char Flags) {
4272 addAccelNameImpl(Unit, NameTableKind, AccelTypes, Name, Die);
4276 return Asm->OutStreamer->getContext().getDwarfVersion();
4280 if (
Asm->getDwarfVersion() >= 4)
4281 return dwarf::Form::DW_FORM_sec_offset;
4282 assert((!
Asm->isDwarf64() || (
Asm->getDwarfVersion() == 3)) &&
4283 "DWARF64 is not defined prior DWARFv3");
4284 return Asm->isDwarf64() ? dwarf::Form::DW_FORM_data8
4285 : dwarf::Form::DW_FORM_data4;
4289 return SectionLabels.lookup(S);
4293 if (SectionLabels.insert(std::make_pair(&S->
getSection(), S)).second)
4298std::optional<MD5::MD5Result>
4302 return std::nullopt;
4303 std::optional<DIFile::ChecksumInfo<StringRef>> Checksum = File->getChecksum();
4305 return std::nullopt;
4310 std::string ChecksumString =
fromHex(Checksum->Value);
4327 if (
MBB.getAlignment() ==
Align(1))
4330 auto *SP =
MBB.getParent()->getFunction().getSubprogram();
4337 auto PrevLoc =
Asm->OutStreamer->getContext().getCurrentDwarfLoc();
4338 if (PrevLoc.getLine()) {
4339 Asm->OutStreamer->emitDwarfLocDirective(
4340 PrevLoc.getFileNum(), 0, PrevLoc.getColumn(), 0, 0, 0,
StringRef());
4342 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")
#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 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)
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
virtual unsigned emitDIERef(const DIE &D)=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 compile unit or type unit DIE that this DIE belongs to.
dwarf::Tag getTag() const
Holds a DIExpression and keeps track of how many operands have been consumed so far.
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
bool hasVersionedName() const
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
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.
iterator find(const_arg_type_t< KeyT > Val)
bool erase(const KeyT &Val)
std::pair< iterator, bool > insert(const std::pair< KeyT, ValueT > &KV)
Implements a dense probed hash-table based set.
void 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 the split dwarf proposal support.
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.
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.
void finalize()
This needs to be called last to commit any pending changes.
void addFragmentOffset(const DIExpression *Expr)
If applicable, emit an empty DW_OP_piece / DW_OP_bit_piece to advance to the fragment described by Ex...
void setMemoryLocationKind()
Lock this down to become a memory location description.
std::optional< uint8_t > TagOffset
void 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 addExpression(DIExpressionCursor &&Expr)
Emit all remaining operations in the DIExpressionCursor.
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 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.
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.