[clang] [llvm] [clang-linker-wrapper] Add ELF packaging for spirv64-intel OpenMP images (PR #125737)

Nick Sarnie via llvm-commits llvm-commits at lists.llvm.org
Wed Feb 5 07:46:07 PST 2025


https://github.com/sarnex updated https://github.com/llvm/llvm-project/pull/125737

>From d4b3358e1ccbae6889aaef280431f06a115102e0 Mon Sep 17 00:00:00 2001
From: "Sarnie, Nick" <nick.sarnie at intel.com>
Date: Wed, 22 Jan 2025 08:35:49 -0800
Subject: [PATCH 1/2] [clang-linker-wrapper] Add ELF packaging for
 spirv64-intel OpenMP images

Signed-off-by: Sarnie, Nick <nick.sarnie at intel.com>
---
 .../Inputs/clang-linker-wrapper-spirv-elf.o   | Bin 0 -> 1344 bytes
 .../clang-linker-wrapper-spirv-elf.cpp        |  14 +++
 clang/test/Tooling/lit.local.cfg              |   6 ++
 clang/test/lit.site.cfg.py.in                 |   1 +
 .../ClangLinkerWrapper.cpp                    |  15 ++++
 .../llvm/Frontend/Offloading/Utility.h        |   6 ++
 llvm/lib/Frontend/Offloading/CMakeLists.txt   |   1 +
 llvm/lib/Frontend/Offloading/Utility.cpp      |  85 ++++++++++++++++++
 8 files changed, 128 insertions(+)
 create mode 100644 clang/test/Tooling/Inputs/clang-linker-wrapper-spirv-elf.o
 create mode 100644 clang/test/Tooling/clang-linker-wrapper-spirv-elf.cpp

diff --git a/clang/test/Tooling/Inputs/clang-linker-wrapper-spirv-elf.o b/clang/test/Tooling/Inputs/clang-linker-wrapper-spirv-elf.o
new file mode 100644
index 0000000000000000000000000000000000000000..3e5bddcedfff16395b215ef438b5c4ce7c4ada9b
GIT binary patch
literal 1344
zcmb_bPiqrV5T8wIs#a?%B0 at a`yi_Ecq)D2Mh(t=YlwgZc(1Wy_-M7iw{m14Rs|b1$
zz4-+MzkuJN;K8rpu@^spcOlN~&ZgT(y*W$v_kO>bc{4lj<=saAVL{U%GY#&;3CmP~
zqr%C$mn?g55hHguKmGc#@rRVg(ev+6o|eB+{xK<NmE;Yu!l?1?o6NIqKQe#H_=<7F
z_?FRSgmL7?leJdW4W#hEjI9yK*o{1q1{4do<^gLhLJ6`OOSqatH{m(P65;|f>Uld7
z!FpdGOB*n+nB-Az5uce^o*4`)6A_QyFsQ87b$o`dtgMWrjK+6sH6){#1KkS!n&(Z@
zS2c>m7s8S{MYgSGceT-K7;8<lRX6Nzr`u^ajJoX at R>Ns_x-F+OXg9 at es(FnIYj2)_
zc39SyFU_C-jLqIeoql9j==ET+{GqUZxwM4=#Q$Ms)aT&$^elJ!#iu>jkzSomkZYk<
z;V_y{Hs3_jr8ty8pYMx6f}>ke1itA8pa-E8`lH9Y)v+|K1JG$adgwS_XxeTtOoctu
zwsE$|V&R#(80|T+=?lPPiKRI}eC-qdCwqqb<W6_C>kfa^?7p#w?n&N=(~s^^-g-=u
zv&lJV{&~BDWT8I|5#HzZ9VW+l5!dS3;w4Y&*Oj<BH|i^T)_;b}oUeqzmn=YWsPcB2
zADy}bsD0%?L&;bB-$FnACwoeq!5iLS{Q at G*ILpuUd#Dx9nxE1T<&&xXo2V(FN!(8k
N+)r4VNB2an{}+mvb}|3}

literal 0
HcmV?d00001

diff --git a/clang/test/Tooling/clang-linker-wrapper-spirv-elf.cpp b/clang/test/Tooling/clang-linker-wrapper-spirv-elf.cpp
new file mode 100644
index 00000000000000..602132172d0248
--- /dev/null
+++ b/clang/test/Tooling/clang-linker-wrapper-spirv-elf.cpp
@@ -0,0 +1,14 @@
+// Verify the ELF packaging of OpenMP SPIR-V device images.
+// REQUIRES: system-linux
+// REQUIRES: spirv-tools
+// RUN: mkdir -p %t_tmp
+// RUN: cd %t_tmp
+// RUN: not clang-linker-wrapper -o a.out %S/Inputs/clang-linker-wrapper-spirv-elf.o --save-temps --linker-path=ld
+// RUN: clang-offload-packager --image=triple=spirv64-intel,kind=openmp,file=%t.elf  %t_tmp/a.out.openmp.image.wrapper.o
+// RUN: llvm-readelf -t %t.elf | FileCheck -check-prefix=CHECK-SECTION %s
+// RUN: llvm-readelf -n %t.elf | FileCheck -check-prefix=CHECK-NOTES %s
+
+// CHECK-SECTION: .note.inteloneompoffload
+// CHECK-SECTION: __openmp_offload_spirv_0
+
+// CHECK-NOTES-COUNT-3: INTELONEOMPOFFLOAD
diff --git a/clang/test/Tooling/lit.local.cfg b/clang/test/Tooling/lit.local.cfg
index 4cd8ba72fa7671..bc2a096c8f64f8 100644
--- a/clang/test/Tooling/lit.local.cfg
+++ b/clang/test/Tooling/lit.local.cfg
@@ -1,2 +1,8 @@
 if not config.root.clang_staticanalyzer:
     config.unsupported = True
+
+if config.spirv_tools_tests:
+    config.available_features.add("spirv-tools")
+    config.substitutions.append(("spirv-dis", os.path.join(config.llvm_tools_dir, "spirv-dis")))
+    config.substitutions.append(("spirv-val", os.path.join(config.llvm_tools_dir, "spirv-val")))
+    config.substitutions.append(("spirv-as", os.path.join(config.llvm_tools_dir, "spirv-as")))
diff --git a/clang/test/lit.site.cfg.py.in b/clang/test/lit.site.cfg.py.in
index ae8b927624e23f..ce10e9128a1dfe 100644
--- a/clang/test/lit.site.cfg.py.in
+++ b/clang/test/lit.site.cfg.py.in
@@ -43,6 +43,7 @@ config.llvm_external_lit = path(r"@LLVM_EXTERNAL_LIT@")
 config.standalone_build = @CLANG_BUILT_STANDALONE@
 config.ppc_linux_default_ieeelongdouble = @PPC_LINUX_DEFAULT_IEEELONGDOUBLE@
 config.have_llvm_driver = @LLVM_TOOL_LLVM_DRIVER_BUILD@
+config.spirv_tools_tests = "@LLVM_INCLUDE_SPIRV_TOOLS_TESTS@"
 config.substitutions.append(("%llvm-version-major", "@LLVM_VERSION_MAJOR@"))
 
 import lit.llvm
diff --git a/clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp b/clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp
index c92590581a645c..d7d6418a4b5e2e 100644
--- a/clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp
+++ b/clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp
@@ -605,6 +605,17 @@ Expected<StringRef> linkDevice(ArrayRef<StringRef> InputFiles,
   }
 }
 
+Error containerizeRawImage(std::unique_ptr<MemoryBuffer> &Img, OffloadKind Kind,
+                           const ArgList &Args) {
+  llvm::Triple Triple(Args.getLastArgValue(OPT_triple_EQ));
+  if (Kind != OFK_OpenMP || !Triple.isSPIRV() ||
+      Triple.getVendor() != llvm::Triple::Intel)
+    return Error::success();
+  if (Error E = offloading::intel::containerizeOpenMPSPIRVImage(Img))
+    return E;
+  return Error::success();
+}
+
 Expected<StringRef> writeOffloadFile(const OffloadFile &File) {
   const OffloadBinary &Binary = *File.getBinary();
 
@@ -960,6 +971,10 @@ Expected<SmallVector<StringRef>> linkAndWrapDeviceFiles(
           return createFileError(*OutputOrErr, EC);
       }
 
+      // Manually containerize offloading images not in ELF format.
+      if (Error E = containerizeRawImage(*FileOrErr, Kind, LinkerArgs))
+        return E;
+
       std::scoped_lock<decltype(ImageMtx)> Guard(ImageMtx);
       OffloadingImage TheImage{};
       TheImage.TheImageKind =
diff --git a/llvm/include/llvm/Frontend/Offloading/Utility.h b/llvm/include/llvm/Frontend/Offloading/Utility.h
index 7932fd5acbe1e2..9140371a8c2ed2 100644
--- a/llvm/include/llvm/Frontend/Offloading/Utility.h
+++ b/llvm/include/llvm/Frontend/Offloading/Utility.h
@@ -10,6 +10,7 @@
 #define LLVM_FRONTEND_OFFLOADING_UTILITY_H
 
 #include <cstdint>
+#include <memory>
 
 #include "llvm/ADT/StringMap.h"
 #include "llvm/ADT/StringRef.h"
@@ -152,6 +153,11 @@ Error getAMDGPUMetaDataFromImage(MemoryBufferRef MemBuffer,
                                  StringMap<AMDGPUKernelMetaData> &KernelInfoMap,
                                  uint16_t &ELFABIVersion);
 } // namespace amdgpu
+namespace intel {
+/// Containerizes an offloading binary into the ELF binary format expected by
+/// the Intel runtime offload plugin.
+Error containerizeOpenMPSPIRVImage(std::unique_ptr<MemoryBuffer> &Binary);
+} // namespace intel
 } // namespace offloading
 } // namespace llvm
 
diff --git a/llvm/lib/Frontend/Offloading/CMakeLists.txt b/llvm/lib/Frontend/Offloading/CMakeLists.txt
index ce445ad9cc4cb6..8e1ede9c72b391 100644
--- a/llvm/lib/Frontend/Offloading/CMakeLists.txt
+++ b/llvm/lib/Frontend/Offloading/CMakeLists.txt
@@ -12,6 +12,7 @@ add_llvm_component_library(LLVMFrontendOffloading
   Core
   BinaryFormat
   Object
+  ObjectYAML
   Support
   TransformUtils
   TargetParser
diff --git a/llvm/lib/Frontend/Offloading/Utility.cpp b/llvm/lib/Frontend/Offloading/Utility.cpp
index 8117a42b8a45cd..f9c74ab975d102 100644
--- a/llvm/lib/Frontend/Offloading/Utility.cpp
+++ b/llvm/lib/Frontend/Offloading/Utility.cpp
@@ -15,6 +15,8 @@
 #include "llvm/IR/GlobalVariable.h"
 #include "llvm/IR/Value.h"
 #include "llvm/Object/ELFObjectFile.h"
+#include "llvm/ObjectYAML/ELFYAML.h"
+#include "llvm/ObjectYAML/yaml2obj.h"
 #include "llvm/Support/MemoryBufferRef.h"
 #include "llvm/Transforms/Utils/ModuleUtils.h"
 
@@ -373,3 +375,86 @@ Error llvm::offloading::amdgpu::getAMDGPUMetaDataFromImage(
   }
   return Error::success();
 }
+Error offloading::intel::containerizeOpenMPSPIRVImage(
+    std::unique_ptr<MemoryBuffer> &Img) {
+  constexpr char INTEL_ONEOMP_OFFLOAD_VERSION[] = "1.0";
+  constexpr int NT_INTEL_ONEOMP_OFFLOAD_VERSION = 1;
+  constexpr int NT_INTEL_ONEOMP_OFFLOAD_IMAGE_COUNT = 2;
+  constexpr int NT_INTEL_ONEOMP_OFFLOAD_IMAGE_AUX = 3;
+
+  // Start creating notes for the ELF container.
+  std::vector<ELFYAML::NoteEntry> Notes;
+  std::string Version = toHex(INTEL_ONEOMP_OFFLOAD_VERSION);
+  Notes.emplace_back(ELFYAML::NoteEntry{"INTELONEOMPOFFLOAD",
+                                        yaml::BinaryRef(Version),
+                                        NT_INTEL_ONEOMP_OFFLOAD_VERSION});
+
+  // The AuxInfo string will hold auxiliary information for the image.
+  // ELFYAML::NoteEntry structures will hold references to the
+  // string, so we have to make sure the string is valid.
+  std::string AuxInfo;
+
+  // TODO: Pass compile/link opts
+  StringRef CompileOpts = "";
+  StringRef LinkOpts = "";
+
+  unsigned ImageFmt = 1; // SPIR-V format
+
+  AuxInfo = toHex((Twine(0) + Twine('\0') + Twine(ImageFmt) + Twine('\0') +
+                   CompileOpts + Twine('\0') + LinkOpts)
+                      .str());
+  Notes.emplace_back(ELFYAML::NoteEntry{"INTELONEOMPOFFLOAD",
+                                        yaml::BinaryRef(AuxInfo),
+                                        NT_INTEL_ONEOMP_OFFLOAD_IMAGE_AUX});
+
+  std::string ImgCount = toHex(Twine(1).str()); // always one image per ELF
+  Notes.emplace_back(ELFYAML::NoteEntry{"INTELONEOMPOFFLOAD",
+                                        yaml::BinaryRef(ImgCount),
+                                        NT_INTEL_ONEOMP_OFFLOAD_IMAGE_COUNT});
+
+  std::string YamlFile;
+  llvm::raw_string_ostream YamlFileStream(YamlFile);
+
+  // Write YAML template file.
+  {
+    // We use 64-bit little-endian ELF currently.
+    ELFYAML::FileHeader Header{};
+    Header.Class = ELF::ELFCLASS64;
+    Header.Data = ELF::ELFDATA2LSB;
+    Header.Type = ELF::ET_DYN;
+    // Use an existing Intel machine type as there is not one specifically for
+    // Intel GPUs.
+    Header.Machine = ELF::EM_IA_64;
+
+    // Create a section with notes.
+    ELFYAML::NoteSection Section{};
+    Section.Type = ELF::SHT_NOTE;
+    Section.AddressAlign = 0;
+    Section.Name = ".note.inteloneompoffload";
+    Section.Notes.emplace(std::move(Notes));
+
+    ELFYAML::Object Object{};
+    Object.Header = Header;
+    Object.Chunks.push_back(
+        std::make_unique<ELFYAML::NoteSection>(std::move(Section)));
+
+    // Create the section that will hold the image
+    ELFYAML::RawContentSection ImageSection{};
+    ImageSection.Type = ELF::SHT_PROGBITS;
+    ImageSection.AddressAlign = 0;
+    std::string Name = "__openmp_offload_spirv_0";
+    ImageSection.Name = Name;
+    ImageSection.Content =
+        llvm::yaml::BinaryRef(arrayRefFromStringRef(Img->getBuffer()));
+    Object.Chunks.push_back(
+        std::make_unique<ELFYAML::RawContentSection>(std::move(ImageSection)));
+    Error Err = Error::success();
+    llvm::yaml::yaml2elf(
+        Object, YamlFileStream,
+        [&Err](const Twine &Msg) { Err = createStringError(Msg); }, UINT64_MAX);
+    if (Err)
+      return Err;
+  }
+  Img = MemoryBuffer::getMemBufferCopy(YamlFile);
+  return Error::success();
+}

>From 442ed9f0575e027e17bb602050170a472622ba18 Mon Sep 17 00:00:00 2001
From: "Sarnie, Nick" <nick.sarnie at intel.com>
Date: Wed, 5 Feb 2025 07:42:32 -0800
Subject: [PATCH 2/2] improve lit test, apply code-style feedback

Signed-off-by: Sarnie, Nick <nick.sarnie at intel.com>
---
 .../Inputs/clang-linker-wrapper-spirv-elf.o   | Bin 1344 -> 0 bytes
 .../clang-linker-wrapper-spirv-elf.cpp        |   6 +-
 .../ClangLinkerWrapper.cpp                    |   4 +-
 .../llvm/Frontend/Offloading/Utility.h        |   1 +
 llvm/lib/Frontend/Offloading/Utility.cpp      |  80 +++++++++---------
 5 files changed, 47 insertions(+), 44 deletions(-)
 delete mode 100644 clang/test/Tooling/Inputs/clang-linker-wrapper-spirv-elf.o

diff --git a/clang/test/Tooling/Inputs/clang-linker-wrapper-spirv-elf.o b/clang/test/Tooling/Inputs/clang-linker-wrapper-spirv-elf.o
deleted file mode 100644
index 3e5bddcedfff16395b215ef438b5c4ce7c4ada9b..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 1344
zcmb_bPiqrV5T8wIs#a?%B0 at a`yi_Ecq)D2Mh(t=YlwgZc(1Wy_-M7iw{m14Rs|b1$
zz4-+MzkuJN;K8rpu@^spcOlN~&ZgT(y*W$v_kO>bc{4lj<=saAVL{U%GY#&;3CmP~
zqr%C$mn?g55hHguKmGc#@rRVg(ev+6o|eB+{xK<NmE;Yu!l?1?o6NIqKQe#H_=<7F
z_?FRSgmL7?leJdW4W#hEjI9yK*o{1q1{4do<^gLhLJ6`OOSqatH{m(P65;|f>Uld7
z!FpdGOB*n+nB-Az5uce^o*4`)6A_QyFsQ87b$o`dtgMWrjK+6sH6){#1KkS!n&(Z@
zS2c>m7s8S{MYgSGceT-K7;8<lRX6Nzr`u^ajJoX at R>Ns_x-F+OXg9 at es(FnIYj2)_
zc39SyFU_C-jLqIeoql9j==ET+{GqUZxwM4=#Q$Ms)aT&$^elJ!#iu>jkzSomkZYk<
z;V_y{Hs3_jr8ty8pYMx6f}>ke1itA8pa-E8`lH9Y)v+|K1JG$adgwS_XxeTtOoctu
zwsE$|V&R#(80|T+=?lPPiKRI}eC-qdCwqqb<W6_C>kfa^?7p#w?n&N=(~s^^-g-=u
zv&lJV{&~BDWT8I|5#HzZ9VW+l5!dS3;w4Y&*Oj<BH|i^T)_;b}oUeqzmn=YWsPcB2
zADy}bsD0%?L&;bB-$FnACwoeq!5iLS{Q at G*ILpuUd#Dx9nxE1T<&&xXo2V(FN!(8k
N+)r4VNB2an{}+mvb}|3}

diff --git a/clang/test/Tooling/clang-linker-wrapper-spirv-elf.cpp b/clang/test/Tooling/clang-linker-wrapper-spirv-elf.cpp
index 602132172d0248..4f8658064e857d 100644
--- a/clang/test/Tooling/clang-linker-wrapper-spirv-elf.cpp
+++ b/clang/test/Tooling/clang-linker-wrapper-spirv-elf.cpp
@@ -3,7 +3,8 @@
 // REQUIRES: spirv-tools
 // RUN: mkdir -p %t_tmp
 // RUN: cd %t_tmp
-// RUN: not clang-linker-wrapper -o a.out %S/Inputs/clang-linker-wrapper-spirv-elf.o --save-temps --linker-path=ld
+// RUN: %clangxx -fopenmp -fopenmp-targets=spirv64-intel -nogpulib -c -o %t_clang-linker-wrapper-spirv-elf.o %s
+// RUN: not clang-linker-wrapper -o a.out %t_clang-linker-wrapper-spirv-elf.o --save-temps --linker-path=ld
 // RUN: clang-offload-packager --image=triple=spirv64-intel,kind=openmp,file=%t.elf  %t_tmp/a.out.openmp.image.wrapper.o
 // RUN: llvm-readelf -t %t.elf | FileCheck -check-prefix=CHECK-SECTION %s
 // RUN: llvm-readelf -n %t.elf | FileCheck -check-prefix=CHECK-NOTES %s
@@ -12,3 +13,6 @@
 // CHECK-SECTION: __openmp_offload_spirv_0
 
 // CHECK-NOTES-COUNT-3: INTELONEOMPOFFLOAD
+int main(int argc, char** argv) {
+  return 0;
+}
diff --git a/clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp b/clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp
index d7d6418a4b5e2e..f4771f14af55c1 100644
--- a/clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp
+++ b/clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp
@@ -611,9 +611,7 @@ Error containerizeRawImage(std::unique_ptr<MemoryBuffer> &Img, OffloadKind Kind,
   if (Kind != OFK_OpenMP || !Triple.isSPIRV() ||
       Triple.getVendor() != llvm::Triple::Intel)
     return Error::success();
-  if (Error E = offloading::intel::containerizeOpenMPSPIRVImage(Img))
-    return E;
-  return Error::success();
+  return offloading::intel::containerizeOpenMPSPIRVImage(Img);
 }
 
 Expected<StringRef> writeOffloadFile(const OffloadFile &File) {
diff --git a/llvm/include/llvm/Frontend/Offloading/Utility.h b/llvm/include/llvm/Frontend/Offloading/Utility.h
index 9140371a8c2ed2..600621f34b4708 100644
--- a/llvm/include/llvm/Frontend/Offloading/Utility.h
+++ b/llvm/include/llvm/Frontend/Offloading/Utility.h
@@ -153,6 +153,7 @@ Error getAMDGPUMetaDataFromImage(MemoryBufferRef MemBuffer,
                                  StringMap<AMDGPUKernelMetaData> &KernelInfoMap,
                                  uint16_t &ELFABIVersion);
 } // namespace amdgpu
+
 namespace intel {
 /// Containerizes an offloading binary into the ELF binary format expected by
 /// the Intel runtime offload plugin.
diff --git a/llvm/lib/Frontend/Offloading/Utility.cpp b/llvm/lib/Frontend/Offloading/Utility.cpp
index f9c74ab975d102..1c731291e6b66b 100644
--- a/llvm/lib/Frontend/Offloading/Utility.cpp
+++ b/llvm/lib/Frontend/Offloading/Utility.cpp
@@ -415,46 +415,46 @@ Error offloading::intel::containerizeOpenMPSPIRVImage(
   std::string YamlFile;
   llvm::raw_string_ostream YamlFileStream(YamlFile);
 
-  // Write YAML template file.
-  {
-    // We use 64-bit little-endian ELF currently.
-    ELFYAML::FileHeader Header{};
-    Header.Class = ELF::ELFCLASS64;
-    Header.Data = ELF::ELFDATA2LSB;
-    Header.Type = ELF::ET_DYN;
-    // Use an existing Intel machine type as there is not one specifically for
-    // Intel GPUs.
-    Header.Machine = ELF::EM_IA_64;
-
-    // Create a section with notes.
-    ELFYAML::NoteSection Section{};
-    Section.Type = ELF::SHT_NOTE;
-    Section.AddressAlign = 0;
-    Section.Name = ".note.inteloneompoffload";
-    Section.Notes.emplace(std::move(Notes));
-
-    ELFYAML::Object Object{};
-    Object.Header = Header;
-    Object.Chunks.push_back(
-        std::make_unique<ELFYAML::NoteSection>(std::move(Section)));
-
-    // Create the section that will hold the image
-    ELFYAML::RawContentSection ImageSection{};
-    ImageSection.Type = ELF::SHT_PROGBITS;
-    ImageSection.AddressAlign = 0;
-    std::string Name = "__openmp_offload_spirv_0";
-    ImageSection.Name = Name;
-    ImageSection.Content =
-        llvm::yaml::BinaryRef(arrayRefFromStringRef(Img->getBuffer()));
-    Object.Chunks.push_back(
-        std::make_unique<ELFYAML::RawContentSection>(std::move(ImageSection)));
-    Error Err = Error::success();
-    llvm::yaml::yaml2elf(
-        Object, YamlFileStream,
-        [&Err](const Twine &Msg) { Err = createStringError(Msg); }, UINT64_MAX);
-    if (Err)
-      return Err;
-  }
+  // Write the YAML template file.
+
+  // We use 64-bit little-endian ELF currently.
+  ELFYAML::FileHeader Header{};
+  Header.Class = ELF::ELFCLASS64;
+  Header.Data = ELF::ELFDATA2LSB;
+  Header.Type = ELF::ET_DYN;
+  // Use an existing Intel machine type as there is not one specifically for
+  // Intel GPUs.
+  Header.Machine = ELF::EM_IA_64;
+
+  // Create a section with notes.
+  ELFYAML::NoteSection Section{};
+  Section.Type = ELF::SHT_NOTE;
+  Section.AddressAlign = 0;
+  Section.Name = ".note.inteloneompoffload";
+  Section.Notes.emplace(std::move(Notes));
+
+  ELFYAML::Object Object{};
+  Object.Header = Header;
+  Object.Chunks.push_back(
+      std::make_unique<ELFYAML::NoteSection>(std::move(Section)));
+
+  // Create the section that will hold the image
+  ELFYAML::RawContentSection ImageSection{};
+  ImageSection.Type = ELF::SHT_PROGBITS;
+  ImageSection.AddressAlign = 0;
+  std::string Name = "__openmp_offload_spirv_0";
+  ImageSection.Name = Name;
+  ImageSection.Content =
+      llvm::yaml::BinaryRef(arrayRefFromStringRef(Img->getBuffer()));
+  Object.Chunks.push_back(
+      std::make_unique<ELFYAML::RawContentSection>(std::move(ImageSection)));
+  Error Err = Error::success();
+  llvm::yaml::yaml2elf(
+      Object, YamlFileStream,
+      [&Err](const Twine &Msg) { Err = createStringError(Msg); }, UINT64_MAX);
+  if (Err)
+    return Err;
+
   Img = MemoryBuffer::getMemBufferCopy(YamlFile);
   return Error::success();
 }



More information about the llvm-commits mailing list