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.sar...@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.sar...@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@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@R>Ns_x-F+OXg9@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@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.sar...@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.sar...@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@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@R>Ns_x-F+OXg9@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@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(); } _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits