[ObjectYAML] Add offloading binary implementations for obj2yaml and yaml2obj
This patchs adds the necessary code for inspecting or creating offloading
binaries using the standing `obj2yaml` and `yaml2obj` features in LLVM.
Depends on D127774
Reviewed By: jhenderson
Differential Revision: https://reviews.llvm.org/D127776
GitOrigin-RevId: 228c8f9cc0b2bf615706567f121a422b1b0e7f83
diff --git a/lib/ObjectYAML/CMakeLists.txt b/lib/ObjectYAML/CMakeLists.txt
index 818a174..15f8d85 100644
--- a/lib/ObjectYAML/CMakeLists.txt
+++ b/lib/ObjectYAML/CMakeLists.txt
@@ -18,6 +18,8 @@
ObjectYAML.cpp
MinidumpEmitter.cpp
MinidumpYAML.cpp
+ OffloadEmitter.cpp
+ OffloadYAML.cpp
WasmEmitter.cpp
WasmYAML.cpp
XCOFFEmitter.cpp
diff --git a/lib/ObjectYAML/ObjectYAML.cpp b/lib/ObjectYAML/ObjectYAML.cpp
index 8d72205..d57e558 100644
--- a/lib/ObjectYAML/ObjectYAML.cpp
+++ b/lib/ObjectYAML/ObjectYAML.cpp
@@ -56,6 +56,9 @@
} else if (IO.mapTag("!minidump")) {
ObjectFile.Minidump.reset(new MinidumpYAML::Object());
MappingTraits<MinidumpYAML::Object>::mapping(IO, *ObjectFile.Minidump);
+ } else if (IO.mapTag("!Offload")) {
+ ObjectFile.Offload.reset(new OffloadYAML::Binary());
+ MappingTraits<OffloadYAML::Binary>::mapping(IO, *ObjectFile.Offload);
} else if (IO.mapTag("!WASM")) {
ObjectFile.Wasm.reset(new WasmYAML::Object());
MappingTraits<WasmYAML::Object>::mapping(IO, *ObjectFile.Wasm);
diff --git a/lib/ObjectYAML/OffloadEmitter.cpp b/lib/ObjectYAML/OffloadEmitter.cpp
new file mode 100644
index 0000000..3ffbc4f
--- /dev/null
+++ b/lib/ObjectYAML/OffloadEmitter.cpp
@@ -0,0 +1,68 @@
+//===- OffloadEmitter.cpp -------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Object/OffloadBinary.h"
+#include "llvm/ObjectYAML/OffloadYAML.h"
+#include "llvm/ObjectYAML/yaml2obj.h"
+#include "llvm/Support/Error.h"
+#include "llvm/Support/raw_ostream.h"
+
+using namespace llvm;
+using namespace OffloadYAML;
+
+namespace llvm {
+namespace yaml {
+
+bool yaml2offload(Binary &Doc, raw_ostream &Out, ErrorHandler EH) {
+ for (const auto &Member : Doc.Members) {
+ object::OffloadBinary::OffloadingImage Image{};
+ if (Member.ImageKind)
+ Image.TheImageKind = *Member.ImageKind;
+ if (Member.OffloadKind)
+ Image.TheOffloadKind = *Member.OffloadKind;
+ if (Member.Flags)
+ Image.Flags = *Member.Flags;
+
+ StringMap<StringRef> &StringData = Image.StringData;
+ if (Member.StringEntries) {
+ for (const auto &Entry : *Member.StringEntries) {
+ StringData[Entry.Key] = Entry.Value;
+ }
+ }
+
+ SmallVector<char, 1024> Data;
+ raw_svector_ostream OS(Data);
+ if (Member.Content)
+ Member.Content->writeAsBinary(OS);
+ Image.Image = MemoryBuffer::getMemBufferCopy(OS.str());
+
+ std::unique_ptr<MemoryBuffer> Binary = object::OffloadBinary::write(Image);
+
+ // Copy the data to a new buffer so we can modify the bytes directly.
+ SmallVector<char> NewBuffer;
+ std::copy(Binary->getBufferStart(), Binary->getBufferEnd(),
+ std::back_inserter(NewBuffer));
+ auto *TheHeader =
+ reinterpret_cast<object::OffloadBinary::Header *>(&NewBuffer[0]);
+ if (Doc.Version)
+ 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;
+
+ Out.write(NewBuffer.begin(), NewBuffer.size());
+ }
+
+ return true;
+}
+
+} // namespace yaml
+} // namespace llvm
diff --git a/lib/ObjectYAML/OffloadYAML.cpp b/lib/ObjectYAML/OffloadYAML.cpp
new file mode 100644
index 0000000..d5a0edd
--- /dev/null
+++ b/lib/ObjectYAML/OffloadYAML.cpp
@@ -0,0 +1,78 @@
+//===- OffloadYAML.cpp - Offload Binary YAMLIO implementation -------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines classes for handling the YAML representation of offload
+// binaries.
+//
+//===----------------------------------------------------------------------===//
+
+#include <llvm/ObjectYAML/OffloadYAML.h>
+
+namespace llvm {
+
+namespace yaml {
+
+void ScalarEnumerationTraits<object::ImageKind>::enumeration(
+ IO &IO, object::ImageKind &Value) {
+#define ECase(X) IO.enumCase(Value, #X, object::X)
+ ECase(IMG_None);
+ ECase(IMG_Object);
+ ECase(IMG_Bitcode);
+ ECase(IMG_Cubin);
+ ECase(IMG_Fatbinary);
+ ECase(IMG_PTX);
+ ECase(IMG_LAST);
+#undef ECase
+ IO.enumFallback<Hex16>(Value);
+}
+
+void ScalarEnumerationTraits<object::OffloadKind>::enumeration(
+ IO &IO, object::OffloadKind &Value) {
+#define ECase(X) IO.enumCase(Value, #X, object::X)
+ ECase(OFK_None);
+ ECase(OFK_OpenMP);
+ ECase(OFK_Cuda);
+ ECase(OFK_HIP);
+ ECase(OFK_LAST);
+#undef ECase
+ IO.enumFallback<Hex16>(Value);
+}
+
+void MappingTraits<OffloadYAML::Binary>::mapping(IO &IO,
+ OffloadYAML::Binary &O) {
+ assert(!IO.getContext() && "The IO context is initialized already");
+ IO.setContext(&O);
+ 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.mapRequired("Members", O.Members);
+ IO.setContext(nullptr);
+}
+
+void MappingTraits<OffloadYAML::Binary::StringEntry>::mapping(
+ IO &IO, OffloadYAML::Binary::StringEntry &SE) {
+ assert(IO.getContext() && "The IO context is not initialized");
+ IO.mapRequired("Key", SE.Key);
+ IO.mapRequired("Value", SE.Value);
+}
+
+void MappingTraits<OffloadYAML::Binary::Member>::mapping(
+ IO &IO, OffloadYAML::Binary::Member &M) {
+ assert(IO.getContext() && "The IO context is not initialized");
+ IO.mapOptional("ImageKind", M.ImageKind);
+ IO.mapOptional("OffloadKind", M.OffloadKind);
+ IO.mapOptional("Flags", M.Flags);
+ IO.mapOptional("String", M.StringEntries);
+ IO.mapOptional("Content", M.Content);
+}
+
+} // namespace yaml
+
+} // namespace llvm
diff --git a/lib/ObjectYAML/yaml2obj.cpp b/lib/ObjectYAML/yaml2obj.cpp
index 64c2599..06050e2 100644
--- a/lib/ObjectYAML/yaml2obj.cpp
+++ b/lib/ObjectYAML/yaml2obj.cpp
@@ -42,6 +42,8 @@
return yaml2macho(Doc, Out, ErrHandler);
if (Doc.Minidump)
return yaml2minidump(*Doc.Minidump, Out, ErrHandler);
+ if (Doc.Offload)
+ return yaml2offload(*Doc.Offload, Out, ErrHandler);
if (Doc.Wasm)
return yaml2wasm(*Doc.Wasm, Out, ErrHandler);
if (Doc.Xcoff)