[llvm] [ObjectYAML][NFC] Hoist ContiguousBlobAccumulator into a shared header (PR #207306)

via llvm-commits llvm-commits at lists.llvm.org
Thu Jul 2 19:20:19 PDT 2026


llvmorg-github-actions[bot] wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-objectyaml

Author: Haohai Wen (HaohaiWen)

<details>
<summary>Changes</summary>

Move ContiguousBlobAccumulator out of ELFEmitter.cpp's anonymous
namespace so other yaml2obj emitters can reuse it.

---
Full diff: https://github.com/llvm/llvm-project/pull/207306.diff


4 Files Affected:

- (added) llvm/include/llvm/ObjectYAML/ContiguousBlobAccumulator.h (+101) 
- (modified) llvm/lib/ObjectYAML/CMakeLists.txt (+1) 
- (added) llvm/lib/ObjectYAML/ContiguousBlobAccumulator.cpp (+72) 
- (modified) llvm/lib/ObjectYAML/ELFEmitter.cpp (+2-103) 


``````````diff
diff --git a/llvm/include/llvm/ObjectYAML/ContiguousBlobAccumulator.h b/llvm/include/llvm/ObjectYAML/ContiguousBlobAccumulator.h
new file mode 100644
index 0000000000000..8ab506520e1a8
--- /dev/null
+++ b/llvm/include/llvm/ObjectYAML/ContiguousBlobAccumulator.h
@@ -0,0 +1,101 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// This file defines ContiguousBlobAccumulator, the size-limited output buffer
+/// shared by the yaml2obj emitters.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_OBJECTYAML_CONTIGUOUSBLOBACCUMULATOR_H
+#define LLVM_OBJECTYAML_CONTIGUOUSBLOBACCUMULATOR_H
+
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/Support/EndianStream.h"
+#include "llvm/Support/Error.h"
+#include "llvm/Support/raw_ostream.h"
+#include <cstdint>
+
+namespace llvm {
+namespace yaml {
+
+class BinaryRef;
+
+// This class is used to build up a contiguous binary blob while keeping
+// track of an offset in the output (which notionally begins at
+// `InitialOffset`).
+// The blob might be limited to an arbitrary size. All attempts to write data
+// are ignored and the error condition is remembered once the limit is reached.
+// Such an approach allows us to simplify the code by delaying error reporting
+// and doing it at a convenient time.
+class ContiguousBlobAccumulator {
+  const uint64_t InitialOffset;
+  const uint64_t MaxSize;
+
+  SmallVector<char, 128> Buf;
+  raw_svector_ostream OS;
+  Error ReachedLimitErr = Error::success();
+
+  bool checkLimit(uint64_t Size);
+
+public:
+  ContiguousBlobAccumulator(uint64_t BaseOffset, uint64_t SizeLimit)
+      : InitialOffset(BaseOffset), MaxSize(SizeLimit), OS(Buf) {}
+
+  uint64_t tell() const { return OS.tell(); }
+  uint64_t getOffset() const { return InitialOffset + OS.tell(); }
+  void writeBlobToStream(raw_ostream &Out) const { Out << OS.str(); }
+
+  Error takeLimitError() {
+    // Request to write 0 bytes to check we did not reach the limit.
+    checkLimit(0);
+    return std::move(ReachedLimitErr);
+  }
+
+  /// \returns The new offset.
+  uint64_t padToAlignment(unsigned Align);
+
+  raw_ostream *getRawOS(uint64_t Size) {
+    if (checkLimit(Size))
+      return &OS;
+    return nullptr;
+  }
+
+  void writeAsBinary(const BinaryRef &Bin, uint64_t N = UINT64_MAX);
+
+  void writeZeros(uint64_t Num) {
+    if (checkLimit(Num))
+      OS.write_zeros(Num);
+  }
+
+  void write(const char *Ptr, size_t Size) {
+    if (checkLimit(Size))
+      OS.write(Ptr, Size);
+  }
+
+  void write(unsigned char C) {
+    if (checkLimit(1))
+      OS.write(C);
+  }
+
+  unsigned writeULEB128(uint64_t Val);
+
+  unsigned writeSLEB128(int64_t Val);
+
+  template <typename T> void write(T Val, llvm::endianness E) {
+    if (checkLimit(sizeof(T)))
+      support::endian::write<T>(OS, Val, E);
+  }
+
+  void updateDataAt(uint64_t Pos, void *Data, size_t Size);
+};
+
+} // end namespace yaml
+} // end namespace llvm
+
+#endif // LLVM_OBJECTYAML_CONTIGUOUSBLOBACCUMULATOR_H
diff --git a/llvm/lib/ObjectYAML/CMakeLists.txt b/llvm/lib/ObjectYAML/CMakeLists.txt
index 44c60ed6378e5..588d68ebf9cb3 100644
--- a/llvm/lib/ObjectYAML/CMakeLists.txt
+++ b/llvm/lib/ObjectYAML/CMakeLists.txt
@@ -8,6 +8,7 @@ add_llvm_component_library(LLVMObjectYAML
   CodeViewYAMLTypes.cpp
   COFFEmitter.cpp
   COFFYAML.cpp
+  ContiguousBlobAccumulator.cpp
   DWARFEmitter.cpp
   DWARFYAML.cpp
   DXContainerEmitter.cpp
diff --git a/llvm/lib/ObjectYAML/ContiguousBlobAccumulator.cpp b/llvm/lib/ObjectYAML/ContiguousBlobAccumulator.cpp
new file mode 100644
index 0000000000000..018fdbf578563
--- /dev/null
+++ b/llvm/lib/ObjectYAML/ContiguousBlobAccumulator.cpp
@@ -0,0 +1,72 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// This file implements the ContiguousBlobAccumulator methods declared in
+/// ContiguousBlobAccumulator.h.
+///
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ObjectYAML/ContiguousBlobAccumulator.h"
+#include "llvm/ObjectYAML/YAML.h"
+#include "llvm/Support/Errc.h"
+#include "llvm/Support/LEB128.h"
+#include "llvm/Support/MathExtras.h"
+#include <cassert>
+#include <cstring>
+
+using namespace llvm;
+using namespace llvm::yaml;
+
+bool ContiguousBlobAccumulator::checkLimit(uint64_t Size) {
+  if (!ReachedLimitErr && getOffset() + Size <= MaxSize)
+    return true;
+  if (!ReachedLimitErr)
+    ReachedLimitErr = createStringError(errc::invalid_argument,
+                                        "reached the output size limit");
+  return false;
+}
+
+uint64_t ContiguousBlobAccumulator::padToAlignment(unsigned Align) {
+  uint64_t CurrentOffset = getOffset();
+  if (ReachedLimitErr)
+    return CurrentOffset;
+
+  uint64_t AlignedOffset = alignTo(CurrentOffset, Align == 0 ? 1 : Align);
+  uint64_t PaddingSize = AlignedOffset - CurrentOffset;
+  if (!checkLimit(PaddingSize))
+    return CurrentOffset;
+
+  writeZeros(PaddingSize);
+  return AlignedOffset;
+}
+
+void ContiguousBlobAccumulator::writeAsBinary(const BinaryRef &Bin,
+                                              uint64_t N) {
+  if (!checkLimit(Bin.binary_size()))
+    return;
+  Bin.writeAsBinary(OS, N);
+}
+
+unsigned ContiguousBlobAccumulator::writeULEB128(uint64_t Val) {
+  if (!checkLimit(sizeof(uint64_t)))
+    return 0;
+  return encodeULEB128(Val, OS);
+}
+
+unsigned ContiguousBlobAccumulator::writeSLEB128(int64_t Val) {
+  if (!checkLimit(10))
+    return 0;
+  return encodeSLEB128(Val, OS);
+}
+
+void ContiguousBlobAccumulator::updateDataAt(uint64_t Pos, void *Data,
+                                             size_t Size) {
+  assert(Pos >= InitialOffset && Pos + Size <= getOffset());
+  memcpy(&Buf[Pos - InitialOffset], Data, Size);
+}
diff --git a/llvm/lib/ObjectYAML/ELFEmitter.cpp b/llvm/lib/ObjectYAML/ELFEmitter.cpp
index 6dc162356ab40..1b40a54088313 100644
--- a/llvm/lib/ObjectYAML/ELFEmitter.cpp
+++ b/llvm/lib/ObjectYAML/ELFEmitter.cpp
@@ -18,6 +18,7 @@
 #include "llvm/BinaryFormat/ELF.h"
 #include "llvm/MC/StringTableBuilder.h"
 #include "llvm/Object/ELFTypes.h"
+#include "llvm/ObjectYAML/ContiguousBlobAccumulator.h"
 #include "llvm/ObjectYAML/DWARFEmitter.h"
 #include "llvm/ObjectYAML/DWARFYAML.h"
 #include "llvm/ObjectYAML/ELFYAML.h"
@@ -32,111 +33,9 @@
 #include <optional>
 
 using namespace llvm;
+using llvm::yaml::ContiguousBlobAccumulator;
 
-// This class is used to build up a contiguous binary blob while keeping
-// track of an offset in the output (which notionally begins at
-// `InitialOffset`).
-// The blob might be limited to an arbitrary size. All attempts to write data
-// are ignored and the error condition is remembered once the limit is reached.
-// Such an approach allows us to simplify the code by delaying error reporting
-// and doing it at a convenient time.
 namespace {
-class ContiguousBlobAccumulator {
-  const uint64_t InitialOffset;
-  const uint64_t MaxSize;
-
-  SmallVector<char, 128> Buf;
-  raw_svector_ostream OS;
-  Error ReachedLimitErr = Error::success();
-
-  bool checkLimit(uint64_t Size) {
-    if (!ReachedLimitErr && getOffset() + Size <= MaxSize)
-      return true;
-    if (!ReachedLimitErr)
-      ReachedLimitErr = createStringError(errc::invalid_argument,
-                                          "reached the output size limit");
-    return false;
-  }
-
-public:
-  ContiguousBlobAccumulator(uint64_t BaseOffset, uint64_t SizeLimit)
-      : InitialOffset(BaseOffset), MaxSize(SizeLimit), OS(Buf) {}
-
-  uint64_t tell() const { return OS.tell(); }
-  uint64_t getOffset() const { return InitialOffset + OS.tell(); }
-  void writeBlobToStream(raw_ostream &Out) const { Out << OS.str(); }
-
-  Error takeLimitError() {
-    // Request to write 0 bytes to check we did not reach the limit.
-    checkLimit(0);
-    return std::move(ReachedLimitErr);
-  }
-
-  /// \returns The new offset.
-  uint64_t padToAlignment(unsigned Align) {
-    uint64_t CurrentOffset = getOffset();
-    if (ReachedLimitErr)
-      return CurrentOffset;
-
-    uint64_t AlignedOffset = alignTo(CurrentOffset, Align == 0 ? 1 : Align);
-    uint64_t PaddingSize = AlignedOffset - CurrentOffset;
-    if (!checkLimit(PaddingSize))
-      return CurrentOffset;
-
-    writeZeros(PaddingSize);
-    return AlignedOffset;
-  }
-
-  raw_ostream *getRawOS(uint64_t Size) {
-    if (checkLimit(Size))
-      return &OS;
-    return nullptr;
-  }
-
-  void writeAsBinary(const yaml::BinaryRef &Bin, uint64_t N = UINT64_MAX) {
-    if (!checkLimit(Bin.binary_size()))
-      return;
-    Bin.writeAsBinary(OS, N);
-  }
-
-  void writeZeros(uint64_t Num) {
-    if (checkLimit(Num))
-      OS.write_zeros(Num);
-  }
-
-  void write(const char *Ptr, size_t Size) {
-    if (checkLimit(Size))
-      OS.write(Ptr, Size);
-  }
-
-  void write(unsigned char C) {
-    if (checkLimit(1))
-      OS.write(C);
-  }
-
-  unsigned writeULEB128(uint64_t Val) {
-    if (!checkLimit(sizeof(uint64_t)))
-      return 0;
-    return encodeULEB128(Val, OS);
-  }
-
-  unsigned writeSLEB128(int64_t Val) {
-    if (!checkLimit(10))
-      return 0;
-    return encodeSLEB128(Val, OS);
-  }
-
-  template <typename T> void write(T Val, llvm::endianness E) {
-    if (checkLimit(sizeof(T)))
-      support::endian::write<T>(OS, Val, E);
-  }
-
-  void updateDataAt(uint64_t Pos, void *Data, size_t Size) {
-    assert(Pos >= InitialOffset && Pos + Size <= getOffset());
-    memcpy(&Buf[Pos - InitialOffset], Data, Size);
-  }
-};
-
 // Used to keep track of section and symbol names, so that in the YAML file
 // sections and symbols can be referenced by name instead of by index.
 class NameToIdxMap {

``````````

</details>


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


More information about the llvm-commits mailing list