[clang] [llvm] [Offloading] Extend OffloadBinary format to support multiple metadata entries (PR #169425)
Yury Plyakhin via llvm-commits
llvm-commits at lists.llvm.org
Tue Nov 25 18:17:43 PST 2025
https://github.com/YuriPlyakhin updated https://github.com/llvm/llvm-project/pull/169425
>From ce7ab7652cf29469a8addea8ebe67f408b4b03af Mon Sep 17 00:00:00 2001
From: "Plyakhin, Yury" <yury.plyakhin at intel.com>
Date: Tue, 25 Nov 2025 00:40:45 +0100
Subject: [PATCH 1/3] [Offloading] Extend OffloadBinary format to support
multiple metadata entries
---
llvm/include/llvm/Object/OffloadBinary.h | 12 ++++++++----
1 file changed, 8 insertions(+), 4 deletions(-)
diff --git a/llvm/include/llvm/Object/OffloadBinary.h b/llvm/include/llvm/Object/OffloadBinary.h
index f3847c1624977..cf25c02bc43fd 100644
--- a/llvm/include/llvm/Object/OffloadBinary.h
+++ b/llvm/include/llvm/Object/OffloadBinary.h
@@ -67,7 +67,7 @@ class OffloadBinary : public Binary {
using string_iterator_range = iterator_range<string_iterator>;
/// The current version of the binary used for backwards compatibility.
- static const uint32_t Version = 1;
+ static const uint32_t Version = 2;
/// The offloading metadata that will be serialized to a memory buffer.
struct OffloadingImage {
@@ -109,9 +109,12 @@ class OffloadBinary : public Binary {
struct Header {
uint8_t Magic[4] = {0x10, 0xFF, 0x10, 0xAD}; // 0x10FF10AD magic bytes.
uint32_t Version = OffloadBinary::Version; // Version identifier.
- uint64_t Size; // Size in bytes of this entire binary.
- uint64_t EntryOffset; // Offset of the metadata entry in bytes.
- uint64_t EntrySize; // Size of the metadata entry in bytes.
+ uint64_t Size; // Size in bytes of this entire binary.
+ uint64_t EntriesCount; // Number of metadata entries in the binary.
+ uint64_t EntriesOffset; // Offset in bytes to the start of entries block.
+ uint64_t EntriesSize; // Size of the entries block in bytes.
+ uint64_t StringOffset; // Offset in bytes to the global string map
+ uint64_t NumStrings; // Number of entries in the global string map.
};
struct Entry {
@@ -127,6 +130,7 @@ class OffloadBinary : public Binary {
struct StringEntry {
uint64_t KeyOffset;
uint64_t ValueOffset;
+ uint64_t ValueSize; // Size of the value in bytes.
};
private:
>From f66ae8cca8d7678ba900c15eef1fa5fdb83a70dc Mon Sep 17 00:00:00 2001
From: "Plyakhin, Yury" <yury.plyakhin at intel.com>
Date: Tue, 25 Nov 2025 21:04:43 +0100
Subject: [PATCH 2/3] updated offloadbinary per discussion
---
llvm/include/llvm/Object/OffloadBinary.h | 14 +++++++++-----
1 file changed, 9 insertions(+), 5 deletions(-)
diff --git a/llvm/include/llvm/Object/OffloadBinary.h b/llvm/include/llvm/Object/OffloadBinary.h
index cf25c02bc43fd..bdcacce204966 100644
--- a/llvm/include/llvm/Object/OffloadBinary.h
+++ b/llvm/include/llvm/Object/OffloadBinary.h
@@ -52,6 +52,13 @@ enum ImageKind : uint16_t {
IMG_LAST,
};
+/// Flags associated with the Entry.
+enum OffloadEntryFlags : uint32_t {
+ OIF_None = 0,
+ // Entry doesn't contain image. Used to keep metadata only entries.
+ OIF_NoImage = (1 << 0),
+};
+
/// A simple binary serialization of an offloading file. We use this format to
/// embed the offloading image into the host executable so it can be extracted
/// and used by the linker.
@@ -110,17 +117,14 @@ class OffloadBinary : public Binary {
uint8_t Magic[4] = {0x10, 0xFF, 0x10, 0xAD}; // 0x10FF10AD magic bytes.
uint32_t Version = OffloadBinary::Version; // Version identifier.
uint64_t Size; // Size in bytes of this entire binary.
- uint64_t EntriesCount; // Number of metadata entries in the binary.
uint64_t EntriesOffset; // Offset in bytes to the start of entries block.
- uint64_t EntriesSize; // Size of the entries block in bytes.
- uint64_t StringOffset; // Offset in bytes to the global string map
- uint64_t NumStrings; // Number of entries in the global string map.
+ uint64_t EntriesCount; // Number of metadata entries in the binary.
};
struct Entry {
ImageKind TheImageKind; // The kind of the image stored.
OffloadKind TheOffloadKind; // The producer of this image.
- uint32_t Flags; // Additional flags associated with the image.
+ uint32_t Flags; // Additional flags associated with the entry.
uint64_t StringOffset; // Offset in bytes to the string map.
uint64_t NumStrings; // Number of entries in the string map.
uint64_t ImageOffset; // Offset in bytes of the actual binary image.
>From 98ad7e9b818a68029b4f8d1b274d5165d8dd1bdf Mon Sep 17 00:00:00 2001
From: "Plyakhin, Yury" <yury.plyakhin at intel.com>
Date: Wed, 26 Nov 2025 03:16:48 +0100
Subject: [PATCH 3/3] Minimal changes to make build and lit tests pass with new
OffloadBinary format.
---
clang/test/Driver/linker-wrapper-image.c | 2 +-
llvm/include/llvm/Object/OffloadBinary.h | 2 +-
llvm/include/llvm/ObjectYAML/OffloadYAML.h | 4 ++--
.../Frontend/Offloading/OffloadWrapper.cpp | 2 +-
llvm/lib/Object/OffloadBinary.cpp | 24 +++++++++++--------
llvm/lib/ObjectYAML/OffloadEmitter.cpp | 8 +++----
llvm/lib/ObjectYAML/OffloadYAML.cpp | 4 ++--
...size.yaml => malformed-entries-count.yaml} | 2 +-
.../ObjectYAML/Offload/malformed-offset.yaml | 2 +-
.../ObjectYAML/Offload/malformed-version.yaml | 2 +-
10 files changed, 28 insertions(+), 24 deletions(-)
rename llvm/test/ObjectYAML/Offload/{malformed-entry-size.yaml => malformed-entries-count.yaml} (94%)
diff --git a/clang/test/Driver/linker-wrapper-image.c b/clang/test/Driver/linker-wrapper-image.c
index b9327121edcf9..2c0df8c6be925 100644
--- a/clang/test/Driver/linker-wrapper-image.c
+++ b/clang/test/Driver/linker-wrapper-image.c
@@ -25,7 +25,7 @@
// OPENMP-REL: @.omp_offloading.device_image = internal unnamed_addr constant [[[SIZE:[0-9]+]] x i8] c"\10\FF\10\AD{{.*}}", section ".llvm.offloading.relocatable", align 8
// OPENMP: @.omp_offloading.device_image = internal unnamed_addr constant [[[SIZE:[0-9]+]] x i8] c"\10\FF\10\AD{{.*}}", section ".llvm.offloading", align 8
-// OPENMP-NEXT: @.omp_offloading.device_images = internal unnamed_addr constant [1 x %__tgt_device_image] [%__tgt_device_image { ptr getelementptr ([[[BEGIN:[0-9]+]] x i8], ptr @.omp_offloading.device_image, i64 0, i64 144), ptr getelementptr ([[[END:[0-9]+]] x i8], ptr @.omp_offloading.device_image, i64 0, i64 144), ptr @__start_llvm_offload_entries, ptr @__stop_llvm_offload_entries }]
+// OPENMP-NEXT: @.omp_offloading.device_images = internal unnamed_addr constant [1 x %__tgt_device_image] [%__tgt_device_image { ptr getelementptr ([[[IMG_OFF:[0-9]+]] x i8], ptr @.omp_offloading.device_image, i64 0, i64 [[IMG_OFF]]), ptr getelementptr ([[[IMG_OFF]] x i8], ptr @.omp_offloading.device_image, i64 0, i64 [[IMG_OFF]]), ptr @__start_llvm_offload_entries, ptr @__stop_llvm_offload_entries }]
// OPENMP-NEXT: @.omp_offloading.descriptor = internal constant %__tgt_bin_desc { i32 1, ptr @.omp_offloading.device_images, ptr @__start_llvm_offload_entries, ptr @__stop_llvm_offload_entries }
// OPENMP-NEXT: @llvm.global_ctors = appending global [1 x { i32, ptr, ptr }] [{ i32, ptr, ptr } { i32 101, ptr @.omp_offloading.descriptor_reg, ptr null }]
diff --git a/llvm/include/llvm/Object/OffloadBinary.h b/llvm/include/llvm/Object/OffloadBinary.h
index bdcacce204966..74dcd5cc7384b 100644
--- a/llvm/include/llvm/Object/OffloadBinary.h
+++ b/llvm/include/llvm/Object/OffloadBinary.h
@@ -134,7 +134,7 @@ class OffloadBinary : public Binary {
struct StringEntry {
uint64_t KeyOffset;
uint64_t ValueOffset;
- uint64_t ValueSize; // Size of the value in bytes.
+ uint64_t ValueSize; // Size of the value in bytes.
};
private:
diff --git a/llvm/include/llvm/ObjectYAML/OffloadYAML.h b/llvm/include/llvm/ObjectYAML/OffloadYAML.h
index f897b52aa8b0e..63ff561f3fcbf 100644
--- a/llvm/include/llvm/ObjectYAML/OffloadYAML.h
+++ b/llvm/include/llvm/ObjectYAML/OffloadYAML.h
@@ -39,8 +39,8 @@ struct Binary {
std::optional<uint32_t> Version;
std::optional<uint64_t> Size;
- std::optional<uint64_t> EntryOffset;
- std::optional<uint64_t> EntrySize;
+ std::optional<uint64_t> EntriesOffset;
+ std::optional<uint64_t> EntriesCount;
std::vector<Member> Members;
};
diff --git a/llvm/lib/Frontend/Offloading/OffloadWrapper.cpp b/llvm/lib/Frontend/Offloading/OffloadWrapper.cpp
index 288fa10fc04bb..f1602765dbaa7 100644
--- a/llvm/lib/Frontend/Offloading/OffloadWrapper.cpp
+++ b/llvm/lib/Frontend/Offloading/OffloadWrapper.cpp
@@ -161,7 +161,7 @@ GlobalVariable *createBinDesc(Module &M, ArrayRef<ArrayRef<char>> Bufs,
Binary.bytes_begin());
const auto *Entry =
reinterpret_cast<const object::OffloadBinary::Entry *>(
- Binary.bytes_begin() + Header->EntryOffset);
+ Binary.bytes_begin() + Header->EntriesOffset);
BeginOffset = Entry->ImageOffset;
EndOffset = Entry->ImageOffset + Entry->ImageSize;
}
diff --git a/llvm/lib/Object/OffloadBinary.cpp b/llvm/lib/Object/OffloadBinary.cpp
index 3fff6b6a09e08..8e51b94b92951 100644
--- a/llvm/lib/Object/OffloadBinary.cpp
+++ b/llvm/lib/Object/OffloadBinary.cpp
@@ -189,19 +189,23 @@ OffloadBinary::create(MemoryBufferRef Buf) {
TheHeader->Size < sizeof(Entry) || TheHeader->Size < sizeof(Header))
return errorCodeToError(object_error::unexpected_eof);
- if (TheHeader->EntryOffset > TheHeader->Size - sizeof(Entry) ||
- TheHeader->EntrySize > TheHeader->Size - sizeof(Header))
+ uint64_t EntriesSize = sizeof(Entry) * TheHeader->EntriesCount;
+ if (TheHeader->EntriesOffset > TheHeader->Size - EntriesSize ||
+ EntriesSize > TheHeader->Size - sizeof(Header))
return errorCodeToError(object_error::unexpected_eof);
- const Entry *TheEntry =
- reinterpret_cast<const Entry *>(&Start[TheHeader->EntryOffset]);
+ const Entry *Entries =
+ reinterpret_cast<const Entry *>(&Start[TheHeader->EntriesOffset]);
+ for (uint32_t I = 0; I < TheHeader->EntriesCount; ++I) {
+ const Entry *TheEntry = &Entries[I];
- if (TheEntry->ImageOffset > Buf.getBufferSize() ||
- TheEntry->StringOffset > Buf.getBufferSize())
- return errorCodeToError(object_error::unexpected_eof);
+ if (TheEntry->ImageOffset > Buf.getBufferSize() ||
+ TheEntry->StringOffset > Buf.getBufferSize())
+ return errorCodeToError(object_error::unexpected_eof);
+ }
return std::unique_ptr<OffloadBinary>(
- new OffloadBinary(Buf, TheHeader, TheEntry));
+ new OffloadBinary(Buf, TheHeader, Entries));
}
SmallString<0> OffloadBinary::write(const OffloadingImage &OffloadingData) {
@@ -227,8 +231,8 @@ SmallString<0> OffloadBinary::write(const OffloadingImage &OffloadingData) {
Header TheHeader;
TheHeader.Size = alignTo(
BinaryDataSize + OffloadingData.Image->getBufferSize(), getAlignment());
- TheHeader.EntryOffset = sizeof(Header);
- TheHeader.EntrySize = sizeof(Entry);
+ TheHeader.EntriesOffset = sizeof(Header);
+ TheHeader.EntriesCount = 1;
// Create the entry using the string table offsets. The string table will be
// placed directly after the entry in memory, and the image after that.
diff --git a/llvm/lib/ObjectYAML/OffloadEmitter.cpp b/llvm/lib/ObjectYAML/OffloadEmitter.cpp
index 131da68d77506..34eca4d61a410 100644
--- a/llvm/lib/ObjectYAML/OffloadEmitter.cpp
+++ b/llvm/lib/ObjectYAML/OffloadEmitter.cpp
@@ -45,10 +45,10 @@ bool yaml2offload(Binary &Doc, raw_ostream &Out, ErrorHandler EH) {
TheHeader->Version = *Doc.Version;
if (Doc.Size)
TheHeader->Size = *Doc.Size;
- if (Doc.EntryOffset)
- TheHeader->EntryOffset = *Doc.EntryOffset;
- if (Doc.EntrySize)
- TheHeader->EntrySize = *Doc.EntrySize;
+ if (Doc.EntriesOffset)
+ TheHeader->EntriesOffset = *Doc.EntriesOffset;
+ if (Doc.EntriesCount)
+ TheHeader->EntriesCount = *Doc.EntriesCount;
Out.write(Buffer.begin(), Buffer.size());
}
diff --git a/llvm/lib/ObjectYAML/OffloadYAML.cpp b/llvm/lib/ObjectYAML/OffloadYAML.cpp
index d5a0edde2179f..cab5a39741294 100644
--- a/llvm/lib/ObjectYAML/OffloadYAML.cpp
+++ b/llvm/lib/ObjectYAML/OffloadYAML.cpp
@@ -50,8 +50,8 @@ void MappingTraits<OffloadYAML::Binary>::mapping(IO &IO,
IO.mapTag("!Offload", true);
IO.mapOptional("Version", O.Version);
IO.mapOptional("Size", O.Size);
- IO.mapOptional("EntryOffset", O.EntryOffset);
- IO.mapOptional("EntrySize", O.EntrySize);
+ IO.mapOptional("EntriesOffset", O.EntriesOffset);
+ IO.mapOptional("EntriesCount", O.EntriesCount);
IO.mapRequired("Members", O.Members);
IO.setContext(nullptr);
}
diff --git a/llvm/test/ObjectYAML/Offload/malformed-entry-size.yaml b/llvm/test/ObjectYAML/Offload/malformed-entries-count.yaml
similarity index 94%
rename from llvm/test/ObjectYAML/Offload/malformed-entry-size.yaml
rename to llvm/test/ObjectYAML/Offload/malformed-entries-count.yaml
index 3194607ae39a5..bb2a34277963f 100644
--- a/llvm/test/ObjectYAML/Offload/malformed-entry-size.yaml
+++ b/llvm/test/ObjectYAML/Offload/malformed-entries-count.yaml
@@ -1,6 +1,6 @@
# RUN: yaml2obj %s | not obj2yaml 2>&1 | FileCheck %s
!Offload
-EntrySize: 999999999
+EntriesCount: 999999999
Members:
- ImageKind: IMG_Cubin
OffloadKind: OFK_OpenMP
diff --git a/llvm/test/ObjectYAML/Offload/malformed-offset.yaml b/llvm/test/ObjectYAML/Offload/malformed-offset.yaml
index 03c0431053cce..5aecfffd937bf 100644
--- a/llvm/test/ObjectYAML/Offload/malformed-offset.yaml
+++ b/llvm/test/ObjectYAML/Offload/malformed-offset.yaml
@@ -1,6 +1,6 @@
# RUN: yaml2obj %s | not obj2yaml 2>&1 | FileCheck %s
!Offload
-EntryOffset: 999999999
+EntriesOffset: 999999999
Members:
- ImageKind: IMG_Cubin
OffloadKind: OFK_OpenMP
diff --git a/llvm/test/ObjectYAML/Offload/malformed-version.yaml b/llvm/test/ObjectYAML/Offload/malformed-version.yaml
index f9279a52e2764..99383491acce0 100644
--- a/llvm/test/ObjectYAML/Offload/malformed-version.yaml
+++ b/llvm/test/ObjectYAML/Offload/malformed-version.yaml
@@ -1,6 +1,6 @@
# RUN: yaml2obj %s | not obj2yaml 2>&1 | FileCheck %s
!Offload
-Version: 2
+Version: 3
Members:
- ImageKind: IMG_Cubin
OffloadKind: OFK_OpenMP
More information about the llvm-commits
mailing list