[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