[llvm] fa2a03d - [NFC][DWARFLinker] Refactor address emitting code.
Alexey Lapshin via llvm-commits
llvm-commits at lists.llvm.org
Fri Jan 20 08:47:54 PST 2023
Author: Alexey Lapshin
Date: 2023-01-20T17:44:07+01:00
New Revision: fa2a03dc7acd0ba551a3328a2d9d5d313e9043d1
URL: https://github.com/llvm/llvm-project/commit/fa2a03dc7acd0ba551a3328a2d9d5d313e9043d1
DIFF: https://github.com/llvm/llvm-project/commit/fa2a03dc7acd0ba551a3328a2d9d5d313e9043d1.diff
LOG: [NFC][DWARFLinker] Refactor address emitting code.
As a preparation for implementing DWARFv5 address ranges generation,
this patch refactors existing address ranges generation code:
Split emitUnitRangesEntries into two functions emitDwarfDebugArangesTable
and emitDwarfDebugRangesTableFragment. Use AddressRanges to prepare linked
address ranges. Refactor Unit.getLowPc(), to use std::nullopt as undefined value.
Reviewed By: JDevlieghere
Differential Revision: https://reviews.llvm.org/D141943
Added:
Modified:
llvm/include/llvm/DWARFLinker/DWARFLinker.h
llvm/include/llvm/DWARFLinker/DWARFLinkerCompileUnit.h
llvm/include/llvm/DWARFLinker/DWARFStreamer.h
llvm/lib/DWARFLinker/DWARFLinker.cpp
llvm/lib/DWARFLinker/DWARFLinkerCompileUnit.cpp
llvm/lib/DWARFLinker/DWARFStreamer.cpp
Removed:
################################################################################
diff --git a/llvm/include/llvm/DWARFLinker/DWARFLinker.h b/llvm/include/llvm/DWARFLinker/DWARFLinker.h
index 619d878b7b5d..5b2f798b784a 100644
--- a/llvm/include/llvm/DWARFLinker/DWARFLinker.h
+++ b/llvm/include/llvm/DWARFLinker/DWARFLinker.h
@@ -121,13 +121,10 @@ class DwarfEmitter {
virtual void
emitAppleTypes(AccelTable<AppleAccelTableStaticTypeData> &Table) = 0;
- /// Emit .debug_ranges for \p FuncRange by translating the
- /// original \p Entries.
- virtual void emitRangesEntries(
- int64_t UnitPcOffset, uint64_t OrigLowPc,
- std::optional<std::pair<AddressRange, int64_t>> FuncRange,
- const std::vector<DWARFDebugRangeList::RangeListEntry> &Entries,
- unsigned AddressSize) = 0;
+ /// Emit piece of .debug_ranges for \p Ranges.
+ virtual void
+ emitDwarfDebugRangesTableFragment(const CompileUnit &Unit,
+ const AddressRanges &LinkedRanges) = 0;
/// Emit .debug_aranges entries for \p Unit and if \p DoRangesSection is true,
/// also emit the .debug_ranges entries for the DW_TAG_compile_unit's
diff --git a/llvm/include/llvm/DWARFLinker/DWARFLinkerCompileUnit.h b/llvm/include/llvm/DWARFLinker/DWARFLinkerCompileUnit.h
index d21126f3ef3b..5b0ea339c4d6 100644
--- a/llvm/include/llvm/DWARFLinker/DWARFLinkerCompileUnit.h
+++ b/llvm/include/llvm/DWARFLinker/DWARFLinkerCompileUnit.h
@@ -139,7 +139,7 @@ class CompileUnit {
uint64_t getNextUnitOffset() const { return NextUnitOffset; }
void setStartOffset(uint64_t DebugInfoSize) { StartOffset = DebugInfoSize; }
- uint64_t getLowPc() const { return LowPc; }
+ std::optional<uint64_t> getLowPc() const { return LowPc; }
uint64_t getHighPc() const { return HighPc; }
bool hasLabelAt(uint64_t Addr) const { return Labels.count(Addr); }
@@ -257,7 +257,7 @@ class CompileUnit {
uint64_t StartOffset;
uint64_t NextUnitOffset;
- uint64_t LowPc = std::numeric_limits<uint64_t>::max();
+ std::optional<uint64_t> LowPc;
uint64_t HighPc = 0;
/// A list of attributes to fixup with the absolute offset of
diff --git a/llvm/include/llvm/DWARFLinker/DWARFStreamer.h b/llvm/include/llvm/DWARFLinker/DWARFStreamer.h
index c28a50001ade..24248c8dffd0 100644
--- a/llvm/include/llvm/DWARFLinker/DWARFStreamer.h
+++ b/llvm/include/llvm/DWARFLinker/DWARFStreamer.h
@@ -93,13 +93,10 @@ class DwarfStreamer : public DwarfEmitter {
llvm::binaryformat::Swift5ReflectionSectionKind ReflSectionKind,
StringRef Buffer, uint32_t Alignment, uint32_t Size);
- /// Emit debug_ranges for \p FuncRange by translating the
- /// original \p Entries.
- void emitRangesEntries(
- int64_t UnitPcOffset, uint64_t OrigLowPc,
- std::optional<std::pair<AddressRange, int64_t>> FuncRange,
- const std::vector<DWARFDebugRangeList::RangeListEntry> &Entries,
- unsigned AddressSize) override;
+ /// Emit piece of .debug_ranges for \p Ranges.
+ virtual void
+ emitDwarfDebugRangesTableFragment(const CompileUnit &Unit,
+ const AddressRanges &LinkedRanges) override;
/// Emit debug_aranges entries for \p Unit and if \p DoRangesSection is true,
/// also emit the debug_ranges entries for the DW_TAG_compile_unit's
@@ -192,6 +189,8 @@ class DwarfStreamer : public DwarfEmitter {
void emitMacroTableImpl(const DWARFDebugMacro *MacroTable,
const Offset2UnitMap &UnitMacroMap,
OffsetsStringPool &StringPool, uint64_t &OutOffset);
+ void emitDwarfDebugArangesTable(const CompileUnit &Unit,
+ const AddressRanges &LinkedRanges);
/// \defgroup MCObjects MC layer objects constructed by the streamer
/// @{
diff --git a/llvm/lib/DWARFLinker/DWARFLinker.cpp b/llvm/lib/DWARFLinker/DWARFLinker.cpp
index 2d1282455b6b..9f6e54377ede 100644
--- a/llvm/lib/DWARFLinker/DWARFLinker.cpp
+++ b/llvm/lib/DWARFLinker/DWARFLinker.cpp
@@ -1198,8 +1198,9 @@ unsigned DWARFLinker::DIECloner::cloneAddressAttribute(
: Addr) +
Info.PCOffset;
} else if (Die.getTag() == dwarf::DW_TAG_compile_unit) {
- Addr = Unit.getLowPc();
- if (Addr == std::numeric_limits<uint64_t>::max())
+ if (std::optional<uint64_t> LowPC = Unit.getLowPc())
+ Addr = *LowPC;
+ else
return 0;
}
Info.HasLowPc = true;
@@ -1276,10 +1277,11 @@ unsigned DWARFLinker::DIECloner::cloneScalarAttribute(
if (AttrSpec.Attr == dwarf::DW_AT_high_pc &&
Die.getTag() == dwarf::DW_TAG_compile_unit) {
- if (Unit.getLowPc() == -1ULL)
+ std::optional<uint64_t> LowPC = Unit.getLowPc();
+ if (!LowPC)
return 0;
// Dwarf >= 4 high_pc is an size, not an address.
- Value = Unit.getHighPc() - Unit.getLowPc();
+ Value = Unit.getHighPc() - *LowPC;
} else if (AttrSpec.Form == dwarf::DW_FORM_sec_offset)
Value = *Val.getAsSectionOffset();
else if (AttrSpec.Form == dwarf::DW_FORM_sdata)
@@ -1657,16 +1659,11 @@ void DWARFLinker::patchRangesForUnit(const CompileUnit &Unit,
DWARFDataExtractor RangeExtractor(OrigDwarf.getDWARFObj(),
OrigDwarf.getDWARFObj().getRangesSection(),
OrigDwarf.isLittleEndian(), AddressSize);
- std::optional<std::pair<AddressRange, int64_t>> CurrRange;
+ std::optional<std::pair<AddressRange, int64_t>> CachedRange;
DWARFUnit &OrigUnit = Unit.getOrigUnit();
auto OrigUnitDie = OrigUnit.getUnitDIE(false);
- uint64_t OrigLowPc =
- dwarf::toAddress(OrigUnitDie.find(dwarf::DW_AT_low_pc), -1ULL);
- // Ranges addresses are based on the unit's low_pc. Compute the
- // offset we need to apply to adapt to the new unit's low_pc.
- int64_t UnitPcOffset = 0;
- if (OrigLowPc != -1ULL)
- UnitPcOffset = int64_t(OrigLowPc) - Unit.getLowPc();
+ uint64_t UnitBaseAddress =
+ dwarf::toAddress(OrigUnitDie.find(dwarf::DW_AT_low_pc), 0);
for (const auto &RangeAttribute : Unit.getRangesAttributes()) {
uint64_t Offset = RangeAttribute.get();
@@ -1677,22 +1674,36 @@ void DWARFLinker::patchRangesForUnit(const CompileUnit &Unit,
RangeList.clear();
}
const auto &Entries = RangeList.getEntries();
+
+ uint64_t BaseAddress = UnitBaseAddress;
+ AddressRanges LinkedRanges;
+
if (!Entries.empty()) {
- const DWARFDebugRangeList::RangeListEntry &First = Entries.front();
-
- if (!CurrRange ||
- !CurrRange->first.contains(First.StartAddress + OrigLowPc)) {
- CurrRange = FunctionRanges.getRangeValueThatContains(
- First.StartAddress + OrigLowPc);
- if (!CurrRange) {
- reportWarning("no mapping for range.", File);
+ for (const auto &Range : Entries) {
+ if (Range.isBaseAddressSelectionEntry(
+ Unit.getOrigUnit().getAddressByteSize())) {
+ BaseAddress = Range.EndAddress;
continue;
}
+
+ if (!CachedRange ||
+ !CachedRange->first.contains(Range.StartAddress + BaseAddress))
+ CachedRange = FunctionRanges.getRangeValueThatContains(
+ Range.StartAddress + BaseAddress);
+
+ // All range entries should lie in the function range.
+ if (!CachedRange) {
+ reportWarning("inconsistent range data.", File);
+ continue;
+ }
+
+ LinkedRanges.insert(
+ {Range.StartAddress + BaseAddress + CachedRange->second,
+ Range.EndAddress + BaseAddress + CachedRange->second});
}
}
- TheDwarfEmitter->emitRangesEntries(UnitPcOffset, OrigLowPc, CurrRange,
- Entries, AddressSize);
+ TheDwarfEmitter->emitDwarfDebugRangesTableFragment(Unit, LinkedRanges);
}
}
diff --git a/llvm/lib/DWARFLinker/DWARFLinkerCompileUnit.cpp b/llvm/lib/DWARFLinker/DWARFLinkerCompileUnit.cpp
index 72cb95fc7804..6c9e0529154b 100644
--- a/llvm/lib/DWARFLinker/DWARFLinkerCompileUnit.cpp
+++ b/llvm/lib/DWARFLinker/DWARFLinkerCompileUnit.cpp
@@ -127,7 +127,10 @@ void CompileUnit::addLabelLowPc(uint64_t LabelLowPc, int64_t PcOffset) {
void CompileUnit::addFunctionRange(uint64_t FuncLowPc, uint64_t FuncHighPc,
int64_t PcOffset) {
Ranges.insert({FuncLowPc, FuncHighPc}, PcOffset);
- this->LowPc = std::min(LowPc, FuncLowPc + PcOffset);
+ if (LowPc)
+ LowPc = std::min(*LowPc, FuncLowPc + PcOffset);
+ else
+ LowPc = FuncLowPc + PcOffset;
this->HighPc = std::max(HighPc, FuncHighPc + PcOffset);
}
diff --git a/llvm/lib/DWARFLinker/DWARFStreamer.cpp b/llvm/lib/DWARFLinker/DWARFStreamer.cpp
index 94dcd78f98b4..5cad267fd845 100644
--- a/llvm/lib/DWARFLinker/DWARFStreamer.cpp
+++ b/llvm/lib/DWARFLinker/DWARFStreamer.cpp
@@ -320,42 +320,74 @@ void DwarfStreamer::emitSwiftReflectionSection(
MS->emitBytes(Buffer);
}
-/// Emit the debug_range section contents for \p FuncRange by
-/// translating the original \p Entries. The debug_range section
-/// format is totally trivial, consisting just of pairs of address
-/// sized addresses describing the ranges.
-void DwarfStreamer::emitRangesEntries(
- int64_t UnitPcOffset, uint64_t OrigLowPc,
- std::optional<std::pair<AddressRange, int64_t>> FuncRange,
- const std::vector<DWARFDebugRangeList::RangeListEntry> &Entries,
- unsigned AddressSize) {
+void DwarfStreamer::emitDwarfDebugArangesTable(
+ const CompileUnit &Unit, const AddressRanges &LinkedRanges) {
+ unsigned AddressSize = Unit.getOrigUnit().getAddressByteSize();
+
+ // Make .debug_aranges to be current section.
+ MS->switchSection(MC->getObjectFileInfo()->getDwarfARangesSection());
+
+ // Emit Header.
+ MCSymbol *BeginLabel = Asm->createTempSymbol("Barange");
+ MCSymbol *EndLabel = Asm->createTempSymbol("Earange");
+
+ unsigned HeaderSize =
+ sizeof(int32_t) + // Size of contents (w/o this field
+ sizeof(int16_t) + // DWARF ARange version number
+ sizeof(int32_t) + // Offset of CU in the .debug_info section
+ sizeof(int8_t) + // Pointer Size (in bytes)
+ sizeof(int8_t); // Segment Size (in bytes)
+
+ unsigned TupleSize = AddressSize * 2;
+ unsigned Padding = offsetToAlignment(HeaderSize, Align(TupleSize));
+
+ Asm->emitLabelDifference(EndLabel, BeginLabel, 4); // Arange length
+ Asm->OutStreamer->emitLabel(BeginLabel);
+ Asm->emitInt16(dwarf::DW_ARANGES_VERSION); // Version number
+ Asm->emitInt32(Unit.getStartOffset()); // Corresponding unit's offset
+ Asm->emitInt8(AddressSize); // Address size
+ Asm->emitInt8(0); // Segment size
+
+ Asm->OutStreamer->emitFill(Padding, 0x0);
+
+ // Emit linked ranges.
+ for (const AddressRange &Range : LinkedRanges) {
+ MS->emitIntValue(Range.start(), AddressSize);
+ MS->emitIntValue(Range.end() - Range.start(), AddressSize);
+ }
+
+ // Emit terminator.
+ Asm->OutStreamer->emitIntValue(0, AddressSize);
+ Asm->OutStreamer->emitIntValue(0, AddressSize);
+ Asm->OutStreamer->emitLabel(EndLabel);
+}
+
+void DwarfStreamer::emitDwarfDebugRangesTableFragment(
+ const CompileUnit &Unit, const AddressRanges &LinkedRanges) {
+ unsigned AddressSize = Unit.getOrigUnit().getAddressByteSize();
+
+ // Make .debug_ranges to be current section.
MS->switchSection(MC->getObjectFileInfo()->getDwarfRangesSection());
- // Offset each range by the right amount.
- int64_t PcOffset =
- (Entries.empty() || !FuncRange) ? 0 : FuncRange->second + UnitPcOffset;
- for (const auto &Range : Entries) {
- if (Range.isBaseAddressSelectionEntry(AddressSize)) {
- warn("unsupported base address selection operation",
- "emitting debug_ranges");
- break;
- }
- // Do not emit empty ranges.
- if (Range.StartAddress == Range.EndAddress)
- continue;
+ // Emit ranges.
+ uint64_t BaseAddress = 0;
+ if (std::optional<uint64_t> LowPC = Unit.getLowPc())
+ BaseAddress = *LowPC;
+
+ for (const AddressRange &Range : LinkedRanges) {
+ MS->emitIntValue(Range.start() - BaseAddress, AddressSize);
+ MS->emitIntValue(Range.end() - BaseAddress, AddressSize);
- // All range entries should lie in the function range.
- if (!FuncRange->first.contains(Range.StartAddress + OrigLowPc))
- warn("inconsistent range data.", "emitting debug_ranges");
- MS->emitIntValue(Range.StartAddress + PcOffset, AddressSize);
- MS->emitIntValue(Range.EndAddress + PcOffset, AddressSize);
- RangesSectionSize += 2 * AddressSize;
+ RangesSectionSize += AddressSize;
+ RangesSectionSize += AddressSize;
}
// Add the terminator entry.
MS->emitIntValue(0, AddressSize);
MS->emitIntValue(0, AddressSize);
- RangesSectionSize += 2 * AddressSize;
+
+ RangesSectionSize += AddressSize;
+ RangesSectionSize += AddressSize;
}
/// Emit the debug_aranges contribution of a unit and
@@ -365,82 +397,21 @@ void DwarfStreamer::emitRangesEntries(
/// Just aggregate all the ranges gathered inside that unit.
void DwarfStreamer::emitUnitRangesEntries(CompileUnit &Unit,
bool DoDebugRanges) {
- unsigned AddressSize = Unit.getOrigUnit().getAddressByteSize();
- // Gather the ranges in a vector, so that we can simplify them. The
- // IntervalMap will have coalesced the non-linked ranges, but here
- // we want to coalesce the linked addresses.
- std::vector<std::pair<uint64_t, uint64_t>> Ranges;
const RangesTy &FunctionRanges = Unit.getFunctionRanges();
- for (size_t Idx = 0; Idx < FunctionRanges.size(); Idx++) {
- std::pair<AddressRange, int64_t> CurRange = FunctionRanges[Idx];
- Ranges.push_back(std::make_pair(CurRange.first.start() + CurRange.second,
- CurRange.first.end() + CurRange.second));
- }
+ // Linked addresses might end up in a
diff erent order.
+ // Build linked address ranges.
+ AddressRanges LinkedRanges;
+ for (size_t Idx = 0; Idx < FunctionRanges.size(); Idx++)
+ LinkedRanges.insert(
+ {FunctionRanges[Idx].first.start() + FunctionRanges[Idx].second,
+ FunctionRanges[Idx].first.end() + FunctionRanges[Idx].second});
- // The object addresses where sorted, but again, the linked
- // addresses might end up in a
diff erent order.
- llvm::sort(Ranges);
-
- if (!Ranges.empty()) {
- MS->switchSection(MC->getObjectFileInfo()->getDwarfARangesSection());
-
- MCSymbol *BeginLabel = Asm->createTempSymbol("Barange");
- MCSymbol *EndLabel = Asm->createTempSymbol("Earange");
-
- unsigned HeaderSize =
- sizeof(int32_t) + // Size of contents (w/o this field
- sizeof(int16_t) + // DWARF ARange version number
- sizeof(int32_t) + // Offset of CU in the .debug_info section
- sizeof(int8_t) + // Pointer Size (in bytes)
- sizeof(int8_t); // Segment Size (in bytes)
-
- unsigned TupleSize = AddressSize * 2;
- unsigned Padding = offsetToAlignment(HeaderSize, Align(TupleSize));
-
- Asm->emitLabelDifference(EndLabel, BeginLabel, 4); // Arange length
- Asm->OutStreamer->emitLabel(BeginLabel);
- Asm->emitInt16(dwarf::DW_ARANGES_VERSION); // Version number
- Asm->emitInt32(Unit.getStartOffset()); // Corresponding unit's offset
- Asm->emitInt8(AddressSize); // Address size
- Asm->emitInt8(0); // Segment size
-
- Asm->OutStreamer->emitFill(Padding, 0x0);
-
- for (auto Range = Ranges.begin(), End = Ranges.end(); Range != End;
- ++Range) {
- uint64_t RangeStart = Range->first;
- MS->emitIntValue(RangeStart, AddressSize);
- while ((Range + 1) != End && Range->second == (Range + 1)->first)
- ++Range;
- MS->emitIntValue(Range->second - RangeStart, AddressSize);
- }
-
- // Emit terminator
- Asm->OutStreamer->emitIntValue(0, AddressSize);
- Asm->OutStreamer->emitIntValue(0, AddressSize);
- Asm->OutStreamer->emitLabel(EndLabel);
- }
+ if (!FunctionRanges.empty())
+ emitDwarfDebugArangesTable(Unit, LinkedRanges);
- if (!DoDebugRanges)
- return;
-
- MS->switchSection(MC->getObjectFileInfo()->getDwarfRangesSection());
- // Offset each range by the right amount.
- int64_t PcOffset = -Unit.getLowPc();
- // Emit coalesced ranges.
- for (auto Range = Ranges.begin(), End = Ranges.end(); Range != End; ++Range) {
- MS->emitIntValue(Range->first + PcOffset, AddressSize);
- while (Range + 1 != End && Range->second == (Range + 1)->first)
- ++Range;
- MS->emitIntValue(Range->second + PcOffset, AddressSize);
- RangesSectionSize += 2 * AddressSize;
- }
-
- // Add the terminator entry.
- MS->emitIntValue(0, AddressSize);
- MS->emitIntValue(0, AddressSize);
- RangesSectionSize += 2 * AddressSize;
+ if (DoDebugRanges)
+ emitDwarfDebugRangesTableFragment(Unit, LinkedRanges);
}
/// Emit location lists for \p Unit and update attributes to point to the new
@@ -464,8 +435,11 @@ void DwarfStreamer::emitLocationsForUnit(
DWARFUnit &OrigUnit = Unit.getOrigUnit();
auto OrigUnitDie = OrigUnit.getUnitDIE(false);
int64_t UnitPcOffset = 0;
- if (auto OrigLowPc = dwarf::toAddress(OrigUnitDie.find(dwarf::DW_AT_low_pc)))
- UnitPcOffset = int64_t(*OrigLowPc) - Unit.getLowPc();
+ if (auto OrigLowPc =
+ dwarf::toAddress(OrigUnitDie.find(dwarf::DW_AT_low_pc))) {
+ assert(Unit.getLowPc());
+ UnitPcOffset = int64_t(*OrigLowPc) - *Unit.getLowPc();
+ }
SmallVector<uint8_t, 32> Buffer;
for (const auto &Attr : Attributes) {
More information about the llvm-commits
mailing list