[llvm] [GOFF] Introduce GOFFWriter class (PR #131216)

Kai Nacke via llvm-commits llvm-commits at lists.llvm.org
Mon Mar 17 11:08:52 PDT 2025


https://github.com/redstar updated https://github.com/llvm/llvm-project/pull/131216

>From d3350544d0189509c3b505db1c68c2ced59d4dad Mon Sep 17 00:00:00 2001
From: Kai Nacke <kai.peter.nacke at ibm.com>
Date: Thu, 13 Mar 2025 09:30:22 -0400
Subject: [PATCH 1/2] [GOFF] Introduce GOFFWriter class

The GOFFWriter has 2 purposes:
- Simplify resource management
- Enable writing of split DWARF files

It follows the design of the other writer classes. No added functionality at this point.
---
 llvm/lib/MC/GOFFObjectWriter.cpp | 64 ++++++++++++++++++++------------
 1 file changed, 41 insertions(+), 23 deletions(-)

diff --git a/llvm/lib/MC/GOFFObjectWriter.cpp b/llvm/lib/MC/GOFFObjectWriter.cpp
index 85deebd89d1f6..4ee8e1487751f 100644
--- a/llvm/lib/MC/GOFFObjectWriter.cpp
+++ b/llvm/lib/MC/GOFFObjectWriter.cpp
@@ -223,34 +223,23 @@ void GOFFOstream::finalizeRecord() {
 }
 
 namespace {
-
-class GOFFObjectWriter : public MCObjectWriter {
-  // The target specific GOFF writer instance.
-  std::unique_ptr<MCGOFFObjectTargetWriter> TargetObjectWriter;
-
-  // The stream used to write the GOFF records.
+class GOFFWriter {
   GOFFOstream OS;
+  [[maybe_unused]] MCAssembler &Asm;
 
-public:
-  GOFFObjectWriter(std::unique_ptr<MCGOFFObjectTargetWriter> MOTW,
-                   raw_pwrite_stream &OS)
-      : TargetObjectWriter(std::move(MOTW)), OS(OS) {}
-
-  ~GOFFObjectWriter() override {}
-
-  // Write GOFF records.
   void writeHeader();
   void writeEnd();
 
-  // Implementation of the MCObjectWriter interface.
-  void recordRelocation(MCAssembler &Asm, const MCFragment *Fragment,
-                        const MCFixup &Fixup, MCValue Target,
-                        uint64_t &FixedValue) override {}
-  uint64_t writeObject(MCAssembler &Asm) override;
+public:
+  GOFFWriter(raw_pwrite_stream &OS, MCAssembler &Asm);
+  uint64_t writeObject();
 };
-} // end anonymous namespace
+} // namespace
+
+GOFFWriter::GOFFWriter(raw_pwrite_stream &OS, MCAssembler &Asm)
+    : OS(OS), Asm(Asm) {}
 
-void GOFFObjectWriter::writeHeader() {
+void GOFFWriter::writeHeader() {
   OS.newRecord(GOFF::RT_HDR);
   OS.write_zeros(1);       // Reserved
   OS.writebe<uint32_t>(0); // Target Hardware Environment
@@ -264,7 +253,7 @@ void GOFFObjectWriter::writeHeader() {
   OS.write_zeros(6);       // Reserved
 }
 
-void GOFFObjectWriter::writeEnd() {
+void GOFFWriter::writeEnd() {
   uint8_t F = GOFF::END_EPR_None;
   uint8_t AMODE = 0;
   uint32_t ESDID = 0;
@@ -282,7 +271,7 @@ void GOFFObjectWriter::writeEnd() {
   OS.writebe<uint32_t>(ESDID); // ESDID (of entry point)
 }
 
-uint64_t GOFFObjectWriter::writeObject(MCAssembler &Asm) {
+uint64_t GOFFWriter::writeObject() {
   writeHeader();
   writeEnd();
 
@@ -295,6 +284,35 @@ uint64_t GOFFObjectWriter::writeObject(MCAssembler &Asm) {
   return OS.getWrittenSize();
 }
 
+namespace {
+
+class GOFFObjectWriter : public MCObjectWriter {
+  // The target specific GOFF writer instance.
+  std::unique_ptr<MCGOFFObjectTargetWriter> TargetObjectWriter;
+
+  // The stream used to write the GOFF records.
+  raw_pwrite_stream &OS;
+
+public:
+  GOFFObjectWriter(std::unique_ptr<MCGOFFObjectTargetWriter> MOTW,
+                   raw_pwrite_stream &OS)
+      : TargetObjectWriter(std::move(MOTW)), OS(OS) {}
+
+  ~GOFFObjectWriter() override {}
+
+  // Implementation of the MCObjectWriter interface.
+  void recordRelocation(MCAssembler &Asm, const MCFragment *Fragment,
+                        const MCFixup &Fixup, MCValue Target,
+                        uint64_t &FixedValue) override {}
+  uint64_t writeObject(MCAssembler &Asm) override;
+};
+} // end anonymous namespace
+
+uint64_t GOFFObjectWriter::writeObject(MCAssembler &Asm) {
+  uint64_t Size = GOFFWriter(OS, Asm).writeObject();
+  return Size;
+}
+
 std::unique_ptr<MCObjectWriter>
 llvm::createGOFFObjectWriter(std::unique_ptr<MCGOFFObjectTargetWriter> MOTW,
                              raw_pwrite_stream &OS) {

>From 824ce7a69f29c91ea686e3a3563172a1b2091bcd Mon Sep 17 00:00:00 2001
From: Kai Nacke <kai.peter.nacke at ibm.com>
Date: Mon, 17 Mar 2025 14:08:29 -0400
Subject: [PATCH 2/2] Make GOFFWriter public

---
 llvm/include/llvm/MC/MCGOFFObjectWriter.h | 85 +++++++++++++++++++++
 llvm/lib/MC/GOFFObjectWriter.cpp          | 92 ++---------------------
 2 files changed, 93 insertions(+), 84 deletions(-)

diff --git a/llvm/include/llvm/MC/MCGOFFObjectWriter.h b/llvm/include/llvm/MC/MCGOFFObjectWriter.h
index 85316a6fd5d0e..7a11a8d135c12 100644
--- a/llvm/include/llvm/MC/MCGOFFObjectWriter.h
+++ b/llvm/include/llvm/MC/MCGOFFObjectWriter.h
@@ -9,12 +9,97 @@
 #ifndef LLVM_MC_MCGOFFOBJECTWRITER_H
 #define LLVM_MC_MCGOFFOBJECTWRITER_H
 
+#include "llvm/BinaryFormat/GOFF.h"
 #include "llvm/MC/MCObjectWriter.h"
+#include "llvm/Support/Endian.h"
 
 namespace llvm {
+class MCAssembler;
 class MCObjectWriter;
 class raw_pwrite_stream;
 
+// The GOFFOstream is responsible to write the data into the fixed physical
+// records of the format. A user of this class announces the begin of a new
+// logical record. While writing the payload, the physical records are created
+// for the data. Possible fill bytes at the end of a physical record are written
+// automatically. In principle, the GOFFOstream is agnostic of the endianness of
+// the payload. However, it also supports writing data in big endian byte order.
+//
+// The physical records use the flag field to indicate if the there is a
+// successor and predecessor record. To be able to set these flags while
+// writing, the basic implementation idea is to always buffer the last seen
+// physical record.
+class GOFFOstream {
+  /// The underlying raw_pwrite_stream.
+  raw_pwrite_stream &OS;
+
+  /// The number of logical records emitted so far.
+  uint32_t LogicalRecords = 0;
+
+  /// The number of physical records emitted so far.
+  uint32_t PhysicalRecords = 0;
+
+  /// The size of the buffer. Same as the payload size of a physical record.
+  static constexpr uint8_t BufferSize = GOFF::PayloadLength;
+
+  /// Current position in buffer.
+  char *BufferPtr = Buffer;
+
+  /// Static allocated buffer for the stream.
+  char Buffer[BufferSize];
+
+  /// The type of the current logical record, and the flags (aka continued and
+  /// continuation indicators) for the previous (physical) record.
+  uint8_t TypeAndFlags = 0;
+
+public:
+  GOFFOstream(raw_pwrite_stream &OS);
+  ~GOFFOstream();
+
+  raw_pwrite_stream &getOS();
+  size_t getWrittenSize() const;
+  uint32_t getNumLogicalRecords();
+
+  /// Write the specified bytes.
+  void write(const char *Ptr, size_t Size);
+
+  /// Write zeroes, up to a maximum of 16 bytes.
+  void write_zeros(unsigned NumZeros);
+
+  /// Support for endian-specific data.
+  template <typename value_type> void writebe(value_type Value) {
+    Value =
+        support::endian::byte_swap<value_type>(Value, llvm::endianness::big);
+    write((const char *)&Value, sizeof(value_type));
+  }
+
+  /// Begin a new logical record. Implies finalizing the previous record.
+  void newRecord(GOFF::RecordType Type);
+
+  /// Ends a logical record.
+  void finalizeRecord();
+
+private:
+  /// Updates the continued/continuation flags, and writes the record prefix of
+  /// a physical record.
+  void updateFlagsAndWritePrefix(bool IsContinued);
+
+  /// Returns the remaining size in the buffer.
+  size_t getRemainingSize();
+};
+
+class GOFFWriter {
+  GOFFOstream OS;
+  [[maybe_unused]] MCAssembler &Asm;
+
+  void writeHeader();
+  void writeEnd();
+
+public:
+  GOFFWriter(raw_pwrite_stream &OS, MCAssembler &Asm);
+  uint64_t writeObject();
+};
+
 class MCGOFFObjectTargetWriter : public MCObjectTargetWriter {
 protected:
   MCGOFFObjectTargetWriter() = default;
diff --git a/llvm/lib/MC/GOFFObjectWriter.cpp b/llvm/lib/MC/GOFFObjectWriter.cpp
index 4ee8e1487751f..b66c073a8e34c 100644
--- a/llvm/lib/MC/GOFFObjectWriter.cpp
+++ b/llvm/lib/MC/GOFFObjectWriter.cpp
@@ -61,82 +61,20 @@ constexpr uint8_t RecContinued = Flags(7, 1, 1);
 
 // Flag: This record is a continuation.
 constexpr uint8_t RecContinuation = Flags(6, 1, 1);
-
-// The GOFFOstream is responsible to write the data into the fixed physical
-// records of the format. A user of this class announces the begin of a new
-// logical record. While writing the payload, the physical records are created
-// for the data. Possible fill bytes at the end of a physical record are written
-// automatically. In principle, the GOFFOstream is agnostic of the endianness of
-// the payload. However, it also supports writing data in big endian byte order.
-//
-// The physical records use the flag field to indicate if the there is a
-// successor and predecessor record. To be able to set these flags while
-// writing, the basic implementation idea is to always buffer the last seen
-// physical record.
-class GOFFOstream {
-  /// The underlying raw_pwrite_stream.
-  raw_pwrite_stream &OS;
-
-  /// The number of logical records emitted so far.
-  uint32_t LogicalRecords = 0;
-
-  /// The number of physical records emitted so far.
-  uint32_t PhysicalRecords = 0;
-
-  /// The size of the buffer. Same as the payload size of a physical record.
-  static constexpr uint8_t BufferSize = GOFF::PayloadLength;
-
-  /// Current position in buffer.
-  char *BufferPtr = Buffer;
-
-  /// Static allocated buffer for the stream.
-  char Buffer[BufferSize];
-
-  /// The type of the current logical record, and the flags (aka continued and
-  /// continuation indicators) for the previous (physical) record.
-  uint8_t TypeAndFlags = 0;
-
-public:
-  GOFFOstream(raw_pwrite_stream &OS);
-  ~GOFFOstream();
-
-  raw_pwrite_stream &getOS() { return OS; }
-  size_t getWrittenSize() const { return PhysicalRecords * GOFF::RecordLength; }
-  uint32_t getNumLogicalRecords() { return LogicalRecords; }
-
-  /// Write the specified bytes.
-  void write(const char *Ptr, size_t Size);
-
-  /// Write zeroes, up to a maximum of 16 bytes.
-  void write_zeros(unsigned NumZeros);
-
-  /// Support for endian-specific data.
-  template <typename value_type> void writebe(value_type Value) {
-    Value =
-        support::endian::byte_swap<value_type>(Value, llvm::endianness::big);
-    write((const char *)&Value, sizeof(value_type));
-  }
-
-  /// Begin a new logical record. Implies finalizing the previous record.
-  void newRecord(GOFF::RecordType Type);
-
-  /// Ends a logical record.
-  void finalizeRecord();
-
-private:
-  /// Updates the continued/continuation flags, and writes the record prefix of
-  /// a physical record.
-  void updateFlagsAndWritePrefix(bool IsContinued);
-
-  /// Returns the remaining size in the buffer.
-  size_t getRemainingSize();
-};
 } // namespace
 
 GOFFOstream::GOFFOstream(raw_pwrite_stream &OS) : OS(OS) {}
 
 GOFFOstream::~GOFFOstream() { finalizeRecord(); }
 
+raw_pwrite_stream &GOFFOstream::getOS() { return OS; }
+
+size_t GOFFOstream::getWrittenSize() const {
+  return PhysicalRecords * GOFF::RecordLength;
+}
+
+uint32_t GOFFOstream::getNumLogicalRecords() { return LogicalRecords; }
+
 void GOFFOstream::updateFlagsAndWritePrefix(bool IsContinued) {
   // Update the flags based on the previous state and the flag IsContinued.
   if (TypeAndFlags & RecContinued)
@@ -222,20 +160,6 @@ void GOFFOstream::finalizeRecord() {
   BufferPtr = Buffer;
 }
 
-namespace {
-class GOFFWriter {
-  GOFFOstream OS;
-  [[maybe_unused]] MCAssembler &Asm;
-
-  void writeHeader();
-  void writeEnd();
-
-public:
-  GOFFWriter(raw_pwrite_stream &OS, MCAssembler &Asm);
-  uint64_t writeObject();
-};
-} // namespace
-
 GOFFWriter::GOFFWriter(raw_pwrite_stream &OS, MCAssembler &Asm)
     : OS(OS), Asm(Asm) {}
 



More information about the llvm-commits mailing list