[llvm] [llvm-dwp] Replace MCStreamer with direct ELF writer for zero-copy output (PR #192112)

via llvm-commits llvm-commits at lists.llvm.org
Tue Apr 14 11:48:24 PDT 2026


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-debuginfo

Author: Farid Zakaria (fzakaria)

<details>
<summary>Changes</summary>

Replace the MCStreamer-based output pipeline with a lightweight direct ELF writer (DWPWriter). Section data is stored as zero-copy StringRef chunks pointing to the mmap'd input files, and written as a minimal ELF64 relocatable object directly to disk.

## Rationale
The MCStreamer pipeline copies all section data into 16KB MCDataFragment blocks, accumulates them in memory, then writes everything out during MCAssembler::Finish().  This can be cause lots of memory pressure and slow down llvm-dwp.

For instance, on a 3.3GB DWP file, this translates to rougly ~3.3GB of heap allocation and two full copies of the data. 

The new DWPWriter avoids this via:
- emitBytes() stores a StringRef chunk (zero-copy, no allocation)
- emitIntValue() writes to a small per-section buffer (index tables)
- writeELF() streams chunks directly from input mmap to output file
- for single-input DWP files, string deduplication is also skipped since all strings are already unique. (minor optimization)
 
Bonus: this also removes all MC library dependencies from llvm-dwp (AllTargetsCodeGens, AllTargetsDescs, AllTargetsInfos, MC, TargetParser), reducing the binary size.

## Benchmark
I benchmarked on a 3.3GB production DWP file (8638 CUs, ~981MB .debug_str.dwo):

Results:
    Before: 23.6s wall (19.6s user, 3.9s sys)
    After:   6.0s wall  (3.0s user, 2.9s sys)

**3.9x**  wall time improvement, 6x fewer page faults (178K vs ~1M).

---

Patch is 39.47 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/192112.diff


6 Files Affected:

- (modified) llvm/include/llvm/DWP/DWP.h (+88-35) 
- (modified) llvm/include/llvm/DWP/DWPStringPool.h (+10-31) 
- (modified) llvm/lib/DWP/CMakeLists.txt (-1) 
- (modified) llvm/lib/DWP/DWP.cpp (+312-112) 
- (modified) llvm/tools/llvm-dwp/CMakeLists.txt (-5) 
- (modified) llvm/tools/llvm-dwp/llvm-dwp.cpp (+7-93) 


``````````diff
diff --git a/llvm/include/llvm/DWP/DWP.h b/llvm/include/llvm/DWP/DWP.h
index 67c73afbfe5ac..af4463ae81377 100644
--- a/llvm/include/llvm/DWP/DWP.h
+++ b/llvm/include/llvm/DWP/DWP.h
@@ -4,11 +4,10 @@
 #include "DWPStringPool.h"
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/MapVector.h"
+#include "llvm/ADT/SmallVector.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/DebugInfo/DWARF/DWARFContext.h"
 #include "llvm/DebugInfo/DWARF/DWARFUnitIndex.h"
-#include "llvm/MC/MCSection.h"
-#include "llvm/MC/MCStreamer.h"
 #include "llvm/Object/ObjectFile.h"
 #include "llvm/Support/Compiler.h"
 #include "llvm/Support/Error.h"
@@ -16,6 +15,8 @@
 #include <vector>
 
 namespace llvm {
+class raw_pwrite_stream;
+
 enum OnCuIndexOverflow {
   HardStop,
   SoftStop,
@@ -28,6 +29,88 @@ enum Dwarf64StrOffsetsPromotion {
   Always,   ///< Always emit .debug_str_offsets talbes as DWARF64 for testing.
 };
 
+/// Section identifiers for DWP output.
+enum DWPSectionId : unsigned {
+  DS_Info,
+  DS_Types,
+  DS_Abbrev,
+  DS_Line,
+  DS_Loc,
+  DS_Loclists,
+  DS_Rnglists,
+  DS_Macro,
+  DS_Str,
+  DS_StrOffsets,
+  DS_CUIndex,
+  DS_TUIndex,
+  DS_NumSections
+};
+
+/// Direct ELF writer for DWP output, bypassing MCStreamer.
+///
+/// Section data is stored as zero-copy StringRef chunks pointing to the
+/// mmap'd input files, plus an inline buffer for constructed data
+/// (emitIntValue). This avoids copying gigabytes of debug section data
+/// through the MC infrastructure (MCContext, MCAssembler, MCDataFragment
+/// allocation, layout, etc.).
+class LLVM_ABI DWPWriter {
+  /// Per-section storage: zero-copy chunks + inline buffer for small writes.
+  struct SectionData {
+    SmallVector<StringRef, 4> Chunks; // zero-copy refs to input data
+    SmallVector<char, 0> Buffer;      // for emitIntValue / constructed data
+
+    uint64_t totalSize() const {
+      uint64_t Size = 0;
+      for (auto &C : Chunks)
+        Size += C.size();
+      Size += Buffer.size();
+      return Size;
+    }
+
+    bool empty() const { return Chunks.empty() && Buffer.empty(); }
+
+    void writeTo(raw_ostream &OS) const {
+      for (auto &C : Chunks)
+        OS.write(C.data(), C.size());
+      if (!Buffer.empty())
+        OS.write(Buffer.data(), Buffer.size());
+    }
+  };
+
+  SectionData Sections[DS_NumSections];
+  DWPSectionId CurrentSection = DS_Info;
+  uint16_t ELFMachine = 0;
+  uint8_t ELFOSABI = 0;
+
+public:
+  DWPWriter() = default;
+
+  void setMachine(uint16_t Machine) { ELFMachine = Machine; }
+  void setOSABI(uint8_t OSABI) { ELFOSABI = OSABI; }
+
+  SmallVectorImpl<char> &getSectionBuffer(DWPSectionId Id) {
+    return Sections[Id].Buffer;
+  }
+
+  void switchSection(DWPSectionId Id) { CurrentSection = Id; }
+
+  /// Zero-copy: stores a reference to the input data without copying.
+  void emitBytes(StringRef Data) {
+    if (!Data.empty())
+      Sections[CurrentSection].Chunks.push_back(Data);
+  }
+
+  void emitIntValue(uint64_t Value, unsigned Size) {
+    auto &Buf = Sections[CurrentSection].Buffer;
+    for (unsigned I = 0; I < Size; ++I) {
+      Buf.push_back(static_cast<char>(Value & 0xff));
+      Value >>= 8;
+    }
+  }
+
+  Error writeELF(raw_pwrite_stream &OS);
+};
+
 struct UnitIndexEntry {
   DWARFUnitIndex::Entry::SectionContribution Contributions[8];
   std::string Name;
@@ -73,45 +156,15 @@ struct CompileUnitIdentifiers {
   const char *DWOName = "";
 };
 
-LLVM_ABI Error write(MCStreamer &Out, ArrayRef<std::string> Inputs,
+LLVM_ABI Error write(DWPWriter &Out, ArrayRef<std::string> Inputs,
                      OnCuIndexOverflow OverflowOptValue,
-                     Dwarf64StrOffsetsPromotion StrOffsetsOptValue);
+                     Dwarf64StrOffsetsPromotion StrOffsetsOptValue,
+                     raw_pwrite_stream *OS = nullptr);
 
 typedef std::vector<std::pair<DWARFSectionKind, uint32_t>> SectionLengths;
 
-LLVM_ABI Error handleSection(
-    const StringMap<std::pair<MCSection *, DWARFSectionKind>> &KnownSections,
-    const MCSection *StrSection, const MCSection *StrOffsetSection,
-    const MCSection *TypesSection, const MCSection *CUIndexSection,
-    const MCSection *TUIndexSection, const MCSection *InfoSection,
-    const object::SectionRef &Section, MCStreamer &Out,
-    std::deque<SmallString<32>> &UncompressedSections,
-    uint32_t (&ContributionOffsets)[8], UnitIndexEntry &CurEntry,
-    StringRef &CurStrSection, StringRef &CurStrOffsetSection,
-    std::vector<StringRef> &CurTypesSection,
-    std::vector<StringRef> &CurInfoSection, StringRef &AbbrevSection,
-    StringRef &CurCUIndexSection, StringRef &CurTUIndexSection,
-    SectionLengths &SectionLength);
-
 LLVM_ABI Expected<InfoSectionUnitHeader>
 parseInfoSectionUnitHeader(StringRef Info);
 
-LLVM_ABI void
-writeStringsAndOffsets(MCStreamer &Out, DWPStringPool &Strings,
-                       MCSection *StrOffsetSection, StringRef CurStrSection,
-                       StringRef CurStrOffsetSection, uint16_t Version,
-                       SectionLengths &SectionLength,
-                       const Dwarf64StrOffsetsPromotion StrOffsetsOptValue);
-
-LLVM_ABI Error
-buildDuplicateError(const std::pair<uint64_t, UnitIndexEntry> &PrevE,
-                    const CompileUnitIdentifiers &ID, StringRef DWPName);
-
-LLVM_ABI void
-writeIndex(MCStreamer &Out, MCSection *Section,
-           ArrayRef<unsigned> ContributionOffsets,
-           const MapVector<uint64_t, UnitIndexEntry> &IndexEntries,
-           uint32_t IndexVersion);
-
 } // namespace llvm
 #endif // LLVM_DWP_DWP_H
diff --git a/llvm/include/llvm/DWP/DWPStringPool.h b/llvm/include/llvm/DWP/DWPStringPool.h
index d1486ff7872e1..7122e84cdfff5 100644
--- a/llvm/include/llvm/DWP/DWPStringPool.h
+++ b/llvm/include/llvm/DWP/DWPStringPool.h
@@ -2,49 +2,28 @@
 #define LLVM_DWP_DWPSTRINGPOOL_H
 
 #include "llvm/ADT/DenseMap.h"
-#include "llvm/MC/MCSection.h"
-#include "llvm/MC/MCStreamer.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringRef.h"
 #include <cassert>
 
 namespace llvm {
 class DWPStringPool {
-
-  struct CStrDenseMapInfo {
-    static inline const char *getEmptyKey() {
-      return reinterpret_cast<const char *>(~static_cast<uintptr_t>(0));
-    }
-    static inline const char *getTombstoneKey() {
-      return reinterpret_cast<const char *>(~static_cast<uintptr_t>(1));
-    }
-    static unsigned getHashValue(const char *Val) {
-      assert(Val != getEmptyKey() && "Cannot hash the empty key!");
-      assert(Val != getTombstoneKey() && "Cannot hash the tombstone key!");
-      return (unsigned)hash_value(StringRef(Val));
-    }
-    static bool isEqual(const char *LHS, const char *RHS) {
-      if (RHS == getEmptyKey())
-        return LHS == getEmptyKey();
-      if (RHS == getTombstoneKey())
-        return LHS == getTombstoneKey();
-      return strcmp(LHS, RHS) == 0;
-    }
-  };
-
-  MCStreamer &Out;
-  MCSection *Sec;
-  DenseMap<const char *, uint64_t, CStrDenseMapInfo> Pool;
+  SmallVectorImpl<char> &Buffer;
+  // Use StringRef keys instead of const char* to avoid redundant strlen
+  // on every hash computation and strcmp on every probe comparison.
+  DenseMap<StringRef, uint64_t> Pool;
   uint64_t Offset = 0;
 
 public:
-  DWPStringPool(MCStreamer &Out, MCSection *Sec) : Out(Out), Sec(Sec) {}
+  DWPStringPool(SmallVectorImpl<char> &Buffer) : Buffer(Buffer) {}
 
   uint64_t getOffset(const char *Str, unsigned Length) {
     assert(strlen(Str) + 1 == Length && "Ensure length hint is correct");
 
-    auto Pair = Pool.insert(std::make_pair(Str, Offset));
+    StringRef Key(Str, Length - 1);
+    auto Pair = Pool.insert(std::make_pair(Key, Offset));
     if (Pair.second) {
-      Out.switchSection(Sec);
-      Out.emitBytes(StringRef(Str, Length));
+      Buffer.insert(Buffer.end(), Str, Str + Length);
       Offset += Length;
     }
 
diff --git a/llvm/lib/DWP/CMakeLists.txt b/llvm/lib/DWP/CMakeLists.txt
index 777de1978dae3..56199dec94108 100644
--- a/llvm/lib/DWP/CMakeLists.txt
+++ b/llvm/lib/DWP/CMakeLists.txt
@@ -10,7 +10,6 @@ add_llvm_component_library(LLVMDWP
 
   LINK_COMPONENTS
   DebugInfoDWARF
-  MC
   Object
   Support
   )
diff --git a/llvm/lib/DWP/DWP.cpp b/llvm/lib/DWP/DWP.cpp
index ea029e97464bc..91afb930c9309 100644
--- a/llvm/lib/DWP/DWP.cpp
+++ b/llvm/lib/DWP/DWP.cpp
@@ -11,20 +11,20 @@
 //
 //===----------------------------------------------------------------------===//
 #include "llvm/DWP/DWP.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/SmallVector.h"
 #include "llvm/ADT/Twine.h"
+#include "llvm/BinaryFormat/ELF.h"
 #include "llvm/DWP/DWPError.h"
-#include "llvm/MC/MCContext.h"
-#include "llvm/MC/MCObjectFileInfo.h"
-#include "llvm/MC/MCTargetOptionsCommandFlags.h"
 #include "llvm/Object/Decompressor.h"
 #include "llvm/Object/ELFObjectFile.h"
+#include "llvm/Support/EndianStream.h"
+#include "llvm/Support/MathExtras.h"
 #include <limits>
 
 using namespace llvm;
 using namespace llvm::object;
 
-static mc::RegisterMCTargetOptionsFlags MCTargetOptionsFlags;
-
 // Returns the size of debug_str_offsets section headers in bytes.
 static uint64_t debugStrOffsetsHeaderSize(DataExtractor StrOffsetsData,
                                           uint16_t DwarfVersion) {
@@ -200,12 +200,12 @@ static Error sectionOverflowErrorOrWarning(uint32_t PrevOffset,
 }
 
 static Error addAllTypesFromDWP(
-    MCStreamer &Out, MapVector<uint64_t, UnitIndexEntry> &TypeIndexEntries,
-    const DWARFUnitIndex &TUIndex, MCSection *OutputTypes, StringRef Types,
+    DWPWriter &Out, MapVector<uint64_t, UnitIndexEntry> &TypeIndexEntries,
+    const DWARFUnitIndex &TUIndex, DWPSectionId OutputSection, StringRef Types,
     const UnitIndexEntry &TUEntry, uint32_t &TypesOffset,
     unsigned TypesContributionIndex, OnCuIndexOverflow OverflowOptValue,
     bool &AnySectionOverflow) {
-  Out.switchSection(OutputTypes);
+  Out.switchSection(OutputSection);
   for (const DWARFUnitIndex::Entry &E : TUIndex.getRows()) {
     auto *I = E.getContributions();
     if (!I)
@@ -249,12 +249,12 @@ static Error addAllTypesFromDWP(
 }
 
 static Error addAllTypesFromTypesSection(
-    MCStreamer &Out, MapVector<uint64_t, UnitIndexEntry> &TypeIndexEntries,
-    MCSection *OutputTypes, const std::vector<StringRef> &TypesSections,
+    DWPWriter &Out, MapVector<uint64_t, UnitIndexEntry> &TypeIndexEntries,
+    DWPSectionId OutputSection, const std::vector<StringRef> &TypesSections,
     const UnitIndexEntry &CUEntry, uint32_t &TypesOffset,
     OnCuIndexOverflow OverflowOptValue, bool &AnySectionOverflow) {
   for (StringRef Types : TypesSections) {
-    Out.switchSection(OutputTypes);
+    Out.switchSection(OutputSection);
     uint64_t Offset = 0;
     DataExtractor Data(Types, true, 0);
     while (Data.isValidOffset(Offset)) {
@@ -351,6 +351,32 @@ handleCompressedSection(std::deque<SmallString<32>> &UncompressedSections,
   return Error::success();
 }
 
+static Error buildDuplicateError(const std::pair<uint64_t, UnitIndexEntry> &PrevE,
+                                 const CompileUnitIdentifiers &ID,
+                                 StringRef DWPName) {
+  return make_error<DWPError>(
+      std::string("duplicate DWO ID (") + utohexstr(PrevE.first) + ") in " +
+      buildDWODescription(PrevE.second.Name, PrevE.second.DWPName,
+                          PrevE.second.DWOName) +
+      " and " + buildDWODescription(ID.Name, DWPName, ID.DWOName));
+}
+
+// Create a mask so we don't trigger a emitIntValue() assert below if the
+// NewOffset is over 4GB.
+static void writeNewOffsetsTo(DWPWriter &Out, DataExtractor &Data,
+                              DenseMap<uint64_t, uint64_t> &OffsetRemapping,
+                              uint64_t &Offset, const uint64_t Size,
+                              uint32_t OldOffsetSize, uint32_t NewOffsetSize) {
+  const uint64_t NewOffsetMask = NewOffsetSize == 8 ? UINT64_MAX : UINT32_MAX;
+  while (Offset < Size) {
+    const uint64_t OldOffset = Data.getUnsigned(&Offset, OldOffsetSize);
+    const uint64_t NewOffset = OffsetRemapping[OldOffset];
+    // Truncate the string offset like the old llvm-dwp would have if we aren't
+    // promoting the .debug_str_offsets to DWARF64.
+    Out.emitIntValue(NewOffset & NewOffsetMask, NewOffsetSize);
+  }
+}
+
 namespace llvm {
 // Parse and return the header of an info section compile/type unit.
 Expected<InfoSectionUnitHeader> parseInfoSectionUnitHeader(StringRef Info) {
@@ -412,33 +438,31 @@ Expected<InfoSectionUnitHeader> parseInfoSectionUnitHeader(StringRef Info) {
   return Header;
 }
 
-static void writeNewOffsetsTo(MCStreamer &Out, DataExtractor &Data,
-                              DenseMap<uint64_t, uint64_t> &OffsetRemapping,
-                              uint64_t &Offset, const uint64_t Size,
-                              uint32_t OldOffsetSize, uint32_t NewOffsetSize) {
-  // Create a mask so we don't trigger a emitIntValue() assert below if the
-  // NewOffset is over 4GB.
-  const uint64_t NewOffsetMask = NewOffsetSize == 8 ? UINT64_MAX : UINT32_MAX;
-  while (Offset < Size) {
-    const uint64_t OldOffset = Data.getUnsigned(&Offset, OldOffsetSize);
-    const uint64_t NewOffset = OffsetRemapping[OldOffset];
-    // Truncate the string offset like the old llvm-dwp would have if we aren't
-    // promoting the .debug_str_offsets to DWARF64.
-    Out.emitIntValue(NewOffset & NewOffsetMask, NewOffsetSize);
-  }
-}
-
-void writeStringsAndOffsets(
-    MCStreamer &Out, DWPStringPool &Strings, MCSection *StrOffsetSection,
-    StringRef CurStrSection, StringRef CurStrOffsetSection, uint16_t Version,
-    SectionLengths &SectionLength,
-    const Dwarf64StrOffsetsPromotion StrOffsetsOptValue) {
+static void
+writeStringsAndOffsets(DWPWriter &Out, DWPStringPool &Strings,
+                       StringRef CurStrSection, StringRef CurStrOffsetSection,
+                       uint16_t Version, SectionLengths &SectionLength,
+                       const Dwarf64StrOffsetsPromotion StrOffsetsOptValue,
+                       bool SingleInput) {
   // Could possibly produce an error or warning if one of these was non-null but
   // the other was null.
   if (CurStrSection.empty() || CurStrOffsetSection.empty())
     return;
 
+  // Fast path: when there is only one input, all strings are unique and offsets
+  // don't need remapping. Copy both sections directly without any hashing.
+  if (SingleInput &&
+      StrOffsetsOptValue != Dwarf64StrOffsetsPromotion::Always) {
+    Out.switchSection(DS_Str);
+    Out.emitBytes(CurStrSection);
+    Out.switchSection(DS_StrOffsets);
+    Out.emitBytes(CurStrOffsetSection);
+    return;
+  }
+
   DenseMap<uint64_t, uint64_t> OffsetRemapping;
+  // Pre-reserve based on estimated string count to avoid rehashing.
+  OffsetRemapping.reserve(CurStrSection.size() / 20);
 
   DataExtractor Data(CurStrSection, true, 0);
   uint64_t LocalOffset = 0;
@@ -464,7 +488,7 @@ void writeStringsAndOffsets(
 
   Data = DataExtractor(CurStrOffsetSection, true, 0);
 
-  Out.switchSection(StrOffsetSection);
+  Out.switchSection(DS_StrOffsets);
 
   uint64_t Offset = 0;
   uint64_t Size = CurStrOffsetSection.size();
@@ -530,9 +554,11 @@ void writeStringsAndOffsets(
 }
 
 enum AccessField { Offset, Length };
-void writeIndexTable(MCStreamer &Out, ArrayRef<unsigned> ContributionOffsets,
-                     const MapVector<uint64_t, UnitIndexEntry> &IndexEntries,
-                     const AccessField &Field) {
+
+static void
+writeIndexTable(DWPWriter &Out, ArrayRef<unsigned> ContributionOffsets,
+                const MapVector<uint64_t, UnitIndexEntry> &IndexEntries,
+                const AccessField &Field) {
   for (const auto &E : IndexEntries)
     for (size_t I = 0; I != std::size(E.second.Contributions); ++I)
       if (ContributionOffsets[I])
@@ -542,10 +568,10 @@ void writeIndexTable(MCStreamer &Out, ArrayRef<unsigned> ContributionOffsets,
                          4);
 }
 
-void writeIndex(MCStreamer &Out, MCSection *Section,
-                ArrayRef<unsigned> ContributionOffsets,
-                const MapVector<uint64_t, UnitIndexEntry> &IndexEntries,
-                uint32_t IndexVersion) {
+static void writeIndex(DWPWriter &Out, DWPSectionId Section,
+                       ArrayRef<unsigned> ContributionOffsets,
+                       const MapVector<uint64_t, UnitIndexEntry> &IndexEntries,
+                       uint32_t IndexVersion) {
   if (IndexEntries.empty())
     return;
 
@@ -596,21 +622,29 @@ void writeIndex(MCStreamer &Out, MCSection *Section,
   writeIndexTable(Out, ContributionOffsets, IndexEntries, AccessField::Length);
 }
 
-Error buildDuplicateError(const std::pair<uint64_t, UnitIndexEntry> &PrevE,
-                          const CompileUnitIdentifiers &ID, StringRef DWPName) {
-  return make_error<DWPError>(
-      std::string("duplicate DWO ID (") + utohexstr(PrevE.first) + ") in " +
-      buildDWODescription(PrevE.second.Name, PrevE.second.DWPName,
-                          PrevE.second.DWOName) +
-      " and " + buildDWODescription(ID.Name, DWPName, ID.DWOName));
+/// Map input ELF section names to DWP section IDs and DWARF section kinds.
+static const StringMap<std::pair<DWPSectionId, DWARFSectionKind>> &
+getKnownSections() {
+  static const StringMap<std::pair<DWPSectionId, DWARFSectionKind>> Map = {
+      {"debug_info.dwo", {DS_Info, DW_SECT_INFO}},
+      {"debug_types.dwo", {DS_Types, DW_SECT_EXT_TYPES}},
+      {"debug_str_offsets.dwo", {DS_StrOffsets, DW_SECT_STR_OFFSETS}},
+      {"debug_str.dwo", {DS_Str, static_cast<DWARFSectionKind>(0)}},
+      {"debug_loc.dwo", {DS_Loc, DW_SECT_EXT_LOC}},
+      {"debug_line.dwo", {DS_Line, DW_SECT_LINE}},
+      {"debug_macro.dwo", {DS_Macro, DW_SECT_MACRO}},
+      {"debug_abbrev.dwo", {DS_Abbrev, DW_SECT_ABBREV}},
+      {"debug_loclists.dwo", {DS_Loclists, DW_SECT_LOCLISTS}},
+      {"debug_rnglists.dwo", {DS_Rnglists, DW_SECT_RNGLISTS}},
+      {"debug_cu_index", {DS_CUIndex, static_cast<DWARFSectionKind>(0)}},
+      {"debug_tu_index", {DS_TUIndex, static_cast<DWARFSectionKind>(0)}},
+  };
+  return Map;
 }
 
-Error handleSection(
-    const StringMap<std::pair<MCSection *, DWARFSectionKind>> &KnownSections,
-    const MCSection *StrSection, const MCSection *StrOffsetSection,
-    const MCSection *TypesSection, const MCSection *CUIndexSection,
-    const MCSection *TUIndexSection, const MCSection *InfoSection,
-    const SectionRef &Section, MCStreamer &Out,
+static Error handleSection(
+    const StringMap<std::pair<DWPSectionId, DWARFSectionKind>> &KnownSections,
+    const SectionRef &Section, DWPWriter &Out,
     std::deque<SmallString<32>> &UncompressedSections,
     uint32_t (&ContributionOffsets)[8], UnitIndexEntry &CurEntry,
     StringRef &CurStrSection, StringRef &CurStrOffsetSection,
@@ -644,61 +678,49 @@ Error handleSection(
   if (SectionPair == KnownSections.end())
     return Error::success();
 
-  if (DWARFSectionKind Kind = SectionPair->second.second) {
-    if (Kind != DW_SECT_EXT_TYPES && Kind != DW_SECT_INFO) {
-      SectionLength.push_back(std::make_pair(Kind, Contents.size()));
-    }
+  DWPSectionId SectionId = SectionPair->second.first;
+  DWARFSectionKind Kind = SectionPair->second.second;
 
-    if (Kind == DW_SECT_ABBREV) {
+  if (Kind) {
+    if (Kind != DW_SECT_EXT_TYPES && Kind != DW_SECT_INFO)
+      SectionLength.push_back(std::make_pair(Kind, Contents.size()));
+    if (Kind == DW_SECT_ABBREV)
       AbbrevSection = Contents;
-    }
   }
 
-  MCSection *OutSection = SectionPair->second.first;
-  if (OutSection == StrOffsetSection)
+  switch (SectionId) {
+  case DS_StrOffsets:
     CurStrOffsetSection = Contents;
-  else if (OutSection == StrSection)
+    break;
+  case DS_Str:
     CurStrSection = Contents;
-  else if (OutSection == TypesSection)
+    break;
+  case DS_Types:
     CurTypesSection.push_back(Contents);
-  else if (OutSection == CUIndexSection)
+    break;
+  case DS_CUIndex:
     CurCUIndexSection = Contents;
-  else if (OutSection == TUIndexSection)
+    break;
+  case DS_TUIndex:
     CurTUIndexSection = Contents;
-  else if (OutSection == InfoSection)
+    break;
+  case DS_Info:
     CurInfoSection.push_back(Contents);
-  else {
-    Out.switchSection(OutSection);
+    break;
+  default:
+    // Pass-through: emit directly to output (zero-copy).
+    Out.switchSection(SectionId);
     Out.emitBytes(Contents);
+    break;
   }
   return Error::success();
 }
 
-Error write(MCStrea...
[truncated]

``````````

</details>


https://github.com/llvm/llvm-project/pull/192112


More information about the llvm-commits mailing list