[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