Author: Alex Duran Date: 2026-03-11T16:13:09+01:00 New Revision: 9348026ab434066babcce5ef7cf64281ed36bb83
URL: https://github.com/llvm/llvm-project/commit/9348026ab434066babcce5ef7cf64281ed36bb83 DIFF: https://github.com/llvm/llvm-project/commit/9348026ab434066babcce5ef7cf64281ed36bb83.diff LOG: [llvm][offload] Change Intel's SPIRV wrapper from ELF to OffloadBinary (#185413) Change SPIRV wrapping done in clang-linker-wrapper from custom ELF to OffloadBinary. Depends on: - #185404 (Accept OffloadBinary in liboffload & L0 plugin) Follow-up PRs: - #185425 (Adjusts llvm-objdump) - #184774 (Adjusts llvm-offload-binary) --------- Co-authored-by: Yury Plyakhin <[email protected]> Added: Modified: clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp llvm/include/llvm/Frontend/Offloading/Utility.h llvm/lib/Frontend/Offloading/Utility.cpp Removed: clang/test/Tooling/clang-linker-wrapper-spirv-elf.cpp ################################################################################ diff --git a/clang/test/Tooling/clang-linker-wrapper-spirv-elf.cpp b/clang/test/Tooling/clang-linker-wrapper-spirv-elf.cpp deleted file mode 100644 index 8a7d36d36b025..0000000000000 --- a/clang/test/Tooling/clang-linker-wrapper-spirv-elf.cpp +++ /dev/null @@ -1,22 +0,0 @@ -// Verify the ELF packaging of OpenMP SPIR-V device images. -// REQUIRES: system-linux -// REQUIRES: spirv-tools -// REQUIRES: spirv-registered-target -// RUN: mkdir -p %t_tmp -// RUN: cd %t_tmp -// 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: llvm-offload-binary --image=triple=spirv64-intel,kind=openmp,file=%t.elf %t_tmp/a.out.openmp.image.wrapper.o -// RUN: llvm-readelf -h %t.elf | FileCheck -check-prefix=CHECK-MACHINE %s -// 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-MACHINE: Machine: Intel Graphics Technology - -// CHECK-SECTION: .note.inteloneompoffload -// 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 54fad8a6ed5e7..9e24a9c26d897 100644 --- a/clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp +++ b/clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp @@ -652,7 +652,7 @@ Error containerizeRawImage(std::unique_ptr<MemoryBuffer> &Img, OffloadKind Kind, llvm::Triple Triple(Args.getLastArgValue(OPT_triple_EQ)); if (Kind == OFK_OpenMP && Triple.isSPIRV() && Triple.getVendor() == llvm::Triple::Intel) - return offloading::intel::containerizeOpenMPSPIRVImage(Img); + return offloading::intel::containerizeOpenMPSPIRVImage(Img, Triple); return Error::success(); } diff --git a/llvm/include/llvm/Frontend/Offloading/Utility.h b/llvm/include/llvm/Frontend/Offloading/Utility.h index 23e6702beb476..eb08e7ec661e4 100644 --- a/llvm/include/llvm/Frontend/Offloading/Utility.h +++ b/llvm/include/llvm/Frontend/Offloading/Utility.h @@ -157,11 +157,34 @@ LLVM_ABI Error getAMDGPUMetaDataFromImage( uint16_t &ELFABIVersion); } // namespace amdgpu +/// Containerizes an image within an OffloadBinary image. +/// Creates a nested OffloadBinary structure where the inner binary contains +/// the raw image and associated metadata (version, format, triple, etc.). +/// \param Binary The image to containerize. +/// \param Triple The target triple to be associated with the image. +/// \param ImageKind The format of the image, e.g. SPIR-V or CUBIN. +/// \param OffloadKind The expected consuming runtime of the image, e.g. CUDA or +/// OpenMP. +/// \param ImageFlags Flags associated with the image, e.g. for AMDGPU the +/// features. +/// \param MetaData The key-value map of metadata to be associated with the +/// image. +LLVM_ABI Error containerizeImage(std::unique_ptr<MemoryBuffer> &Binary, + llvm::Triple Triple, + object::ImageKind ImageKind, + object::OffloadKind OffloadKind, + int32_t ImageFlags, + MapVector<StringRef, StringRef> &MetaData); + namespace intel { -/// Containerizes an offloading binary into the ELF binary format expected by -/// the Intel runtime offload plugin. -LLVM_ABI Error -containerizeOpenMPSPIRVImage(std::unique_ptr<MemoryBuffer> &Binary); +/// Containerizes an OpenMP SPIR-V image into an OffloadBinary image. +/// \param Binary The SPIR-V binary to containerize. +/// \param Triple The target triple to be associated with the image. +/// \param CompileOpts Optional compilation options. +/// \param LinkOpts Optional linking options. +LLVM_ABI Error containerizeOpenMPSPIRVImage( + std::unique_ptr<MemoryBuffer> &Binary, llvm::Triple Triple, + StringRef CompileOpts = "", StringRef LinkOpts = ""); } // namespace intel } // namespace offloading } // namespace llvm diff --git a/llvm/lib/Frontend/Offloading/Utility.cpp b/llvm/lib/Frontend/Offloading/Utility.cpp index 5000488a52f37..44cef91bac495 100644 --- a/llvm/lib/Frontend/Offloading/Utility.cpp +++ b/llvm/lib/Frontend/Offloading/Utility.cpp @@ -15,6 +15,7 @@ #include "llvm/IR/GlobalVariable.h" #include "llvm/IR/Value.h" #include "llvm/Object/ELFObjectFile.h" +#include "llvm/Object/OffloadBinary.h" #include "llvm/ObjectYAML/ELFYAML.h" #include "llvm/ObjectYAML/yaml2obj.h" #include "llvm/Support/MemoryBufferRef.h" @@ -377,84 +378,49 @@ Error llvm::offloading::amdgpu::getAMDGPUMetaDataFromImage( } return Error::success(); } + +Error offloading::containerizeImage(std::unique_ptr<MemoryBuffer> &Img, + llvm::Triple Triple, + object::ImageKind ImageKind, + object::OffloadKind OffloadKind, + int32_t ImageFlags, + MapVector<StringRef, StringRef> &MetaData) { + using namespace object; + + // Create inner OffloadBinary containing the raw image. + OffloadBinary::OffloadingImage InnerImage; + InnerImage.TheImageKind = ImageKind; + InnerImage.TheOffloadKind = OffloadKind; + InnerImage.Flags = ImageFlags; + + InnerImage.StringData["triple"] = Triple.getTriple(); + for (const auto &[Key, Value] : MetaData) + InnerImage.StringData[Key] = Value; + + InnerImage.Image = std::move(Img); + + SmallString<0> InnerBinaryData = OffloadBinary::write(InnerImage); + + Img = MemoryBuffer::getMemBufferCopy(InnerBinaryData); + return Error::success(); +} + Error offloading::intel::containerizeOpenMPSPIRVImage( - std::unique_ptr<MemoryBuffer> &Img) { + std::unique_ptr<MemoryBuffer> &Binary, llvm::Triple Triple, + StringRef CompileOpts, StringRef LinkOpts) { 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 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; - Header.Machine = ELF::EM_INTELGT; - - // 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(); + assert(Triple.isSPIRV() && Triple.getVendor() == llvm::Triple::Intel && + "Expected SPIR-V triple with Intel vendor"); + + MapVector<StringRef, StringRef> MetaData; + MetaData["version"] = INTEL_ONEOMP_OFFLOAD_VERSION; + if (!CompileOpts.empty()) + MetaData["compile-opts"] = CompileOpts; + if (!LinkOpts.empty()) + MetaData["link-opts"] = LinkOpts; + + return containerizeImage(Binary, Triple, object::ImageKind::IMG_SPIRV, + object::OffloadKind::OFK_OpenMP, /*ImageFlags=*/0, + MetaData); } _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
