[llvm] [Offload][L0][NFC] Remove old ELF format support (PR #228011)
via llvm-commits
llvm-commits at lists.llvm.org
Thu Oct 1 02:44:28 PDT 2026
llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-offload
Author: Alex Duran (adurang)
<details>
<summary>Changes</summary>
After we switched to using Offload Binary (for OpenMP) or direct SPIR-V images (for SYCL) this support is not used anymore.
Assisted by Claude.
---
Full diff: https://github.com/llvm/llvm-project/pull/228011.diff
4 Files Affected:
- (modified) offload/plugins-nextgen/level_zero/include/L0Plugin.h (+4-1)
- (modified) offload/plugins-nextgen/level_zero/include/L0Program.h (-2)
- (modified) offload/plugins-nextgen/level_zero/src/L0Plugin.cpp (-7)
- (modified) offload/plugins-nextgen/level_zero/src/L0Program.cpp (+1-303)
``````````diff
diff --git a/offload/plugins-nextgen/level_zero/include/L0Plugin.h b/offload/plugins-nextgen/level_zero/include/L0Plugin.h
index d6656cb4cf792e1..5d5d4f8ac63739b 100644
--- a/offload/plugins-nextgen/level_zero/include/L0Plugin.h
+++ b/offload/plugins-nextgen/level_zero/include/L0Plugin.h
@@ -129,7 +129,10 @@ class LevelZeroPluginTy final : public GenericPluginTy {
const char *getName() const override { return GETNAME(TARGET_NAME); }
Expected<bool> isELFCompatible(uint32_t DeviceId,
- StringRef Image) const override;
+ StringRef Image) const override {
+ // ELF images are not supported. Images must be SPIR-V or OffloadBinary.
+ return false;
+ }
Error flushQueueImpl(omp_interop_val_t *Interop) override;
Error syncBarrierImpl(omp_interop_val_t *Interop) override;
diff --git a/offload/plugins-nextgen/level_zero/include/L0Program.h b/offload/plugins-nextgen/level_zero/include/L0Program.h
index 5e29e4463e4dbdb..98453fec3b2689a 100644
--- a/offload/plugins-nextgen/level_zero/include/L0Program.h
+++ b/offload/plugins-nextgen/level_zero/include/L0Program.h
@@ -143,8 +143,6 @@ struct L0GlobalHandlerTy final : public GenericGlobalHandlerTy {
bool isExportedSymbol(uint32_t Flags) override;
};
-bool isValidOneOmpImage(StringRef Image, uint64_t &MajorVer,
- uint64_t &MinorVer);
} // namespace llvm::omp::target::plugin
#endif // OPENMP_LIBOMPTARGET_PLUGINS_NEXTGEN_LEVEL_ZERO_L0PROGRAM_H
diff --git a/offload/plugins-nextgen/level_zero/src/L0Plugin.cpp b/offload/plugins-nextgen/level_zero/src/L0Plugin.cpp
index a09ca28ad6df8f3..607239acbbae0c9 100644
--- a/offload/plugins-nextgen/level_zero/src/L0Plugin.cpp
+++ b/offload/plugins-nextgen/level_zero/src/L0Plugin.cpp
@@ -171,13 +171,6 @@ Error LevelZeroPluginTy::flushQueueImpl(omp_interop_val_t *Interop) {
return Plugin::success();
}
-Expected<bool> LevelZeroPluginTy::isELFCompatible(uint32_t DeviceId,
- StringRef Image) const {
- uint64_t MajorVer, MinorVer;
- return isValidOneOmpImage(Image, MajorVer, MinorVer);
-}
-
-// We only need to check for formats other than ELF here.
Expected<bool> LevelZeroPluginTy::isImageCompatible(StringRef Image) const {
switch (identify_magic(Image)) {
case file_magic::spirv_object:
diff --git a/offload/plugins-nextgen/level_zero/src/L0Program.cpp b/offload/plugins-nextgen/level_zero/src/L0Program.cpp
index 654ac9a03a0507e..c5d92e76a06b712 100644
--- a/offload/plugins-nextgen/level_zero/src/L0Program.cpp
+++ b/offload/plugins-nextgen/level_zero/src/L0Program.cpp
@@ -10,15 +10,6 @@
//
//===----------------------------------------------------------------------===//
-#ifdef _WIN32
-#include <fcntl.h>
-#include <io.h>
-#else
-#include <dlfcn.h>
-#include <sys/stat.h>
-#include <unistd.h>
-#endif // !_WIN32
-
#include "L0Plugin.h"
#include "L0Program.h"
@@ -168,82 +159,6 @@ static void replaceDriverOptsWithBackendOpts(const L0DeviceTy &Device,
}
}
-// FIXME: move this to llvm/BinaryFormat/ELF.h and elf.h:
-#define NT_INTEL_ONEOMP_OFFLOAD_VERSION 1
-#define NT_INTEL_ONEOMP_OFFLOAD_IMAGE_COUNT 2
-#define NT_INTEL_ONEOMP_OFFLOAD_IMAGE_AUX 3
-
-bool isValidOneOmpImage(StringRef Image, uint64_t &MajorVer,
- uint64_t &MinorVer) {
- const auto MB = MemoryBuffer::getMemBuffer(Image,
- /*BufferName=*/"",
- /*RequiresNullTerminator=*/false);
- auto ExpectedNewE =
- ELFObjectFileBase::createELFObjectFile(MB->getMemBufferRef());
- if (!ExpectedNewE) {
- std::string ErrMsg = toString(ExpectedNewE.takeError());
- ODBG(OLDT_Module) << "Warning: unable to get ELF handle: " << ErrMsg;
- return false;
- }
- bool Res = false;
- auto ProcessObjF = [&](const auto ELFObjF) {
- if (!ELFObjF) {
- ODBG(OLDT_Module) << "Warning: Unexpected ELF type!";
- return false;
- }
- const auto &ELFF = ELFObjF->getELFFile();
- auto Sections = ELFF.sections();
- if (!Sections) {
- std::string ErrMsg = toString(Sections.takeError());
- ODBG(OLDT_Module) << "Warning: unable to get ELF sections: " << ErrMsg;
- return false;
- }
- bool SeenOffloadSection = false;
- for (auto Sec : *Sections) {
- if (Sec.sh_type != ELF::SHT_NOTE)
- continue;
- Error Err = Plugin::success();
- for (auto Note : ELFF.notes(Sec, Err)) {
- if (Err) {
- std::string ErrMsg = toString(std::move(Err));
- ODBG(OLDT_Module)
- << "Warning: unable to get ELF notes handle: " << ErrMsg;
- return false;
- }
- if (Note.getName() != "INTELONEOMPOFFLOAD")
- continue;
- SeenOffloadSection = true;
- if (Note.getType() != NT_INTEL_ONEOMP_OFFLOAD_VERSION)
- continue;
-
- std::string DescStr(std::move(Note.getDescAsStringRef(4).str()));
- const auto DelimPos = DescStr.find('.');
- if (DelimPos == std::string::npos) {
- // The version has to look like "Major#.Minor#".
- ODBG(OLDT_Module)
- << "Invalid NT_INTEL_ONEOMP_OFFLOAD_VERSION: '" << DescStr << "'";
- return false;
- }
- const std::string MajorVerStr = DescStr.substr(0, DelimPos);
- DescStr.erase(0, DelimPos + 1);
- MajorVer = std::stoull(MajorVerStr);
- MinorVer = std::stoull(DescStr);
- return (MajorVer == 1 && MinorVer == 0);
- }
- }
- return SeenOffloadSection;
- };
- if (const auto *O = dyn_cast<ELF64LEObjectFile>((*ExpectedNewE).get())) {
- Res = ProcessObjF(O);
- } else if (const auto *O =
- dyn_cast<ELF32LEObjectFile>((*ExpectedNewE).get())) {
- Res = ProcessObjF(O);
- } else {
- assert(false && "Unexpected ELF format");
- }
- return Res;
-}
-
Error L0ProgramBuilderTy::buildModules(const std::string_view BuildOptions) {
auto &L0Device = getL0Device();
auto Image = getMemoryBuffer();
@@ -341,225 +256,8 @@ Error L0ProgramBuilderTy::buildModules(const std::string_view BuildOptions) {
return Plugin::success();
}
- uint64_t MajorVer, MinorVer;
- if (!isValidOneOmpImage(Image.getBuffer(), MajorVer, MinorVer)) {
- ODBG(OLDT_Module) << "Warning: image is not a valid oneAPI OpenMP image.";
- return Plugin::error(ErrorCode::INVALID_BINARY,
- "Invalid oneAPI OpenMP image");
- }
- ODBG(OLDT_Module) << "Processing ELF-wrapped SPIR-V image";
-
- // Iterate over the images and pick the first one that fits.
- uint64_t ImageCount = 0;
- struct V1ImageInfo {
- // 0 - native, 1 - SPIR-V.
- uint64_t Format = std::numeric_limits<uint64_t>::max();
- std::string CompileOpts;
- std::string LinkOpts;
- // We may have multiple sections created from split-kernel mode.
- std::vector<const uint8_t *> PartBegin;
- std::vector<uint64_t> PartSize;
-
- V1ImageInfo(uint64_t Format, std::string CompileOpts, std::string LinkOpts)
- : Format(Format), CompileOpts(std::move(CompileOpts)),
- LinkOpts(std::move(LinkOpts)) {}
- };
- std::unordered_map<uint64_t, V1ImageInfo> AuxInfo;
-
- auto ExpectedNewE = ELFObjectFileBase::createELFObjectFile(Image);
- assert(ExpectedNewE &&
- "isValidOneOmpImage() returns true for invalid ELF image");
- auto ProcessELF = [&](auto *EObj) {
- assert(EObj && "isValidOneOmpImage() returns true for invalid ELF image.");
- const auto &E = EObj->getELFFile();
- // Collect auxiliary information.
- uint64_t MaxImageIdx = 0;
-
- auto Sections = E.sections();
- assert(Sections && "isValidOneOmpImage() returns true for ELF image with "
- "invalid sections.");
-
- for (auto Sec : *Sections) {
- if (Sec.sh_type != ELF::SHT_NOTE)
- continue;
- Error Err = Plugin::success();
- for (auto Note : E.notes(Sec, Err)) {
- assert(!Err && "isValidOneOmpImage() returns true for ELF image with "
- "invalid notes.");
- if (Note.getName().str() != "INTELONEOMPOFFLOAD")
- continue;
-
- const uint64_t Type = Note.getType();
- auto DescStrRef = Note.getDescAsStringRef(4);
- switch (Type) {
- default:
- ODBG(OLDT_Module) << "Warning: unrecognized INTELONEOMPOFFLOAD note.";
- break;
- case NT_INTEL_ONEOMP_OFFLOAD_VERSION:
- break;
- case NT_INTEL_ONEOMP_OFFLOAD_IMAGE_COUNT:
- if (DescStrRef.getAsInteger(10, ImageCount)) {
- ODBG(OLDT_Module) << "Warning: invalid "
- << "NT_INTEL_ONEOMP_OFFLOAD_IMAGE_COUNT: '"
- << DescStrRef.str() << "'";
- ImageCount = 0;
- }
- break;
- case NT_INTEL_ONEOMP_OFFLOAD_IMAGE_AUX:
- llvm::SmallVector<llvm::StringRef, 4> Parts;
- DescStrRef.split(Parts, '\0', /* MaxSplit = */ 4,
- /* KeepEmpty = */ true);
-
- // Ignore records with less than 4 strings.
- if (Parts.size() != 4) {
- ODBG(OLDT_Module) << "Warning: short "
- << "NT_INTEL_ONEOMP_OFFLOAD_IMAGE_AUX "
- << "record is ignored.";
- continue;
- }
-
- uint64_t Idx = 0;
- if (Parts[0].getAsInteger(10, Idx)) {
- ODBG(OLDT_Module) << "Warning: ignoring auxiliary information "
- << "(invalid index '" << Parts[0].str() << "').";
- continue;
- }
- MaxImageIdx = (std::max)(MaxImageIdx, Idx);
- if (AuxInfo.find(Idx) != AuxInfo.end()) {
- ODBG(OLDT_Module) << "Warning: duplicate auxiliary information for "
- << "image " << Idx << " is ignored.";
- continue;
- }
-
- uint64_t Part1Id;
- if (Parts[1].getAsInteger(10, Part1Id)) {
- ODBG(OLDT_Module)
- << "Warning: ignoring auxiliary information "
- << "(invalid part id '" << Parts[1].str() << "').";
- continue;
- }
-
- AuxInfo.emplace(
- std::piecewise_construct, std::forward_as_tuple(Idx),
- std::forward_as_tuple(Part1Id, Parts[2].str(), Parts[3].str()));
- // Image pointer and size will be initialized later.
- }
- }
- }
-
- if (MaxImageIdx >= ImageCount)
- ODBG(OLDT_Module) << "Warning: invalid image index found in auxiliary "
- << "information.";
-
- for (auto Sec : *Sections) {
- const char *Prefix = "__openmp_offload_spirv_";
- auto ExpectedSectionName = E.getSectionName(Sec);
- assert(ExpectedSectionName && "isValidOneOmpImage() returns true for ELF "
- "image with invalid section names");
- auto &SectionNameRef = *ExpectedSectionName;
- if (!SectionNameRef.consume_front(Prefix))
- continue;
-
- // Expected section name in split-kernel mode with the following pattern:
- // __openmp_offload_spirv_<image_id>_<part_id>
- auto Parts = SectionNameRef.split('_');
- // It seems that we do not need part ID as long as they are ordered
- // in the image and we keep the ordering in the runtime.
- SectionNameRef = Parts.first;
- if (Parts.second.empty()) {
- ODBG(OLDT_Module) << "Found a single section in the image";
- } else {
- ODBG(OLDT_Module) << "Found a split section in the image";
- }
-
- uint64_t Idx = 0;
- if (SectionNameRef.getAsInteger(10, Idx)) {
- ODBG(OLDT_Module) << "Warning: ignoring image section (invalid index '"
- << SectionNameRef.str() << "').";
- continue;
- }
- if (Idx >= ImageCount) {
- ODBG(OLDT_Module) << "Warning: ignoring image section (index " << Idx
- << " is out of range).";
- continue;
- }
-
- auto AuxInfoIt = AuxInfo.find(Idx);
- if (AuxInfoIt == AuxInfo.end()) {
- ODBG(OLDT_Module) << "Warning: ignoring image section (no aux info).";
- continue;
- }
- auto Contents = E.getSectionContents(Sec);
- assert(Contents);
- AuxInfoIt->second.PartBegin.push_back((*Contents).data());
- AuxInfoIt->second.PartSize.push_back(Sec.sh_size);
- }
- };
-
- if (auto *O = dyn_cast<ELF64LEObjectFile>((*ExpectedNewE).get())) {
- ProcessELF(O);
- } else if (auto *O = dyn_cast<ELF32LEObjectFile>((*ExpectedNewE).get())) {
- ProcessELF(O);
- } else {
- assert(false && "Unexpected ELF format");
- }
-
- for (uint64_t Idx = 0; Idx < ImageCount; ++Idx) {
- const auto It = AuxInfo.find(Idx);
- if (It == AuxInfo.end()) {
- ODBG(OLDT_Module) << "Warning: image " << Idx
- << " without auxiliary information is ingored.";
- continue;
- }
-
- const auto NumParts = It->second.PartBegin.size();
- // Split-kernel is not supported in SPIRV format.
- if (NumParts > 1 && It->second.Format != 0) {
- ODBG(OLDT_Module) << "Warning: split-kernel images are not supported in "
- << "SPIRV format";
- continue;
- }
-
- // Skip unknown image format.
- if (It->second.Format != 0 && It->second.Format != 1) {
- ODBG(OLDT_Module) << "Warning: image " << Idx << " is ignored due to "
- << "unknown format.";
- continue;
- }
-
- const bool IsBinary = (It->second.Format == 0);
- const auto ModuleFormat =
- IsBinary ? ZE_MODULE_FORMAT_NATIVE : ZE_MODULE_FORMAT_IL_SPIRV;
- std::string Options(BuildOptions);
- {
- Options += " " + It->second.CompileOpts + " " + It->second.LinkOpts;
- replaceDriverOptsWithBackendOpts(L0Device, Options);
- }
-
- for (size_t I = 0; I < NumParts; I++) {
- const unsigned char *ImgBegin =
- reinterpret_cast<const unsigned char *>(It->second.PartBegin[I]);
- size_t ImgSize = It->second.PartSize[I];
-
- ODBG(OLDT_Module) << "Creating module from "
- << (IsBinary ? "Binary" : "SPIR-V") << " image part #"
- << Idx << "-" << I << ".";
- if (auto Err = addModule(ImgSize, ImgBegin, Options, ModuleFormat))
- return Err;
- }
- ODBG(OLDT_Module) << "Created module from image #" << Idx << ".";
-
- if (RequiresModuleLink) {
- ODBG(OLDT_Module) << "Linking modules after adding image #" << Idx << ".";
- if (auto Err = linkModules())
- return Err;
- }
-
- return Plugin::success();
- }
-
return Plugin::error(ErrorCode::INVALID_BINARY,
- "Failed to create program modules.");
+ "Unsupported image format for L0 plugin");
}
Expected<std::unique_ptr<MemoryBuffer>> L0ProgramBuilderTy::getELF() {
``````````
</details>
https://github.com/llvm/llvm-project/pull/228011
More information about the llvm-commits
mailing list