[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