[llvm] [OFFLOAD] Add interface to extend image validation (PR #185663)

Alex Duran via llvm-commits llvm-commits at lists.llvm.org
Tue Mar 10 08:54:01 PDT 2026


https://github.com/adurang updated https://github.com/llvm/llvm-project/pull/185663

>From 49960f1fcdb79ddcfa14fd5292137f31b907257b Mon Sep 17 00:00:00 2001
From: "Duran, Alex" <alejandro.duran at intel.com>
Date: Tue, 10 Mar 2026 07:59:45 -0700
Subject: [PATCH 1/5] [OFFLOAD] Add interface to extend image validation

---
 .../common/include/PluginInterface.h           | 18 ++++++++++++++++++
 .../common/src/PluginInterface.cpp             | 10 ++++++++--
 2 files changed, 26 insertions(+), 2 deletions(-)

diff --git a/offload/plugins-nextgen/common/include/PluginInterface.h b/offload/plugins-nextgen/common/include/PluginInterface.h
index 1c59ed1eda841..6da8389636077 100644
--- a/offload/plugins-nextgen/common/include/PluginInterface.h
+++ b/offload/plugins-nextgen/common/include/PluginInterface.h
@@ -1364,6 +1364,24 @@ struct GenericPluginTy {
   virtual Expected<bool> isELFCompatible(uint32_t DeviceID,
                                          StringRef Image) const = 0;
 
+  /// Indicate if an image is compatible with the plugin. This is called if
+  /// the image is not recognized as compatible by the common layer. This gives
+  /// the plugin a chance to inspect the image and decide if it is compatible.
+  virtual Expected<bool> isCompatibleImage(StringRef Image) const {
+    return false;
+  }
+
+  /// Indicate if an imaget is compatible with the plugin devices. This is
+  /// called if the image is not recognized as compatible by the common layer.
+  /// This gives the plugin a chance to inspect the image and decide if it is
+  /// compatible. Notice that this function may be called before actually
+  /// initializing the devices. So we could not move this function into
+  /// GenericDeviceTy.
+  virtual Expected<bool> isCompatibleImage(uint32_t DeviceID,
+                                           StringRef Image) const {
+    return isCompatibleImage(Image);
+  }
+
   virtual Error flushQueueImpl(omp_interop_val_t *Interop) {
     return Plugin::success();
   }
diff --git a/offload/plugins-nextgen/common/src/PluginInterface.cpp b/offload/plugins-nextgen/common/src/PluginInterface.cpp
index f681213b38794..0cc1c38e5481a 100644
--- a/offload/plugins-nextgen/common/src/PluginInterface.cpp
+++ b/offload/plugins-nextgen/common/src/PluginInterface.cpp
@@ -1652,7 +1652,10 @@ int32_t GenericPluginTy::isPluginCompatible(StringRef Image) {
     return *MatchOrErr;
   }
   default:
-    return false;
+    auto MatchOrErr = isCompatibleImage(Image);
+    if (Error Err = MatchOrErr.takeError())
+      return HandleError(std::move(Err));
+    return *MatchOrErr;
   }
 }
 
@@ -1689,7 +1692,10 @@ int32_t GenericPluginTy::isDeviceCompatible(int32_t DeviceId, StringRef Image) {
     return *MatchOrErr;
   }
   default:
-    return false;
+    auto MatchOrErr = isCompatibleImage(DeviceId, Image);
+    if (Error Err = MatchOrErr.takeError())
+      return HandleError(std::move(Err));
+    return *MatchOrErr;
   }
 }
 

>From bcdaf3c85efc849c2172872b44c1890fbcfce5c9 Mon Sep 17 00:00:00 2001
From: "Duran, Alex" <alejandro.duran at intel.com>
Date: Tue, 10 Mar 2026 08:00:05 -0700
Subject: [PATCH 2/5] Add SPIRV validation support to L0

---
 offload/plugins-nextgen/level_zero/include/L0Plugin.h | 2 ++
 offload/plugins-nextgen/level_zero/src/L0Plugin.cpp   | 7 +++++++
 2 files changed, 9 insertions(+)

diff --git a/offload/plugins-nextgen/level_zero/include/L0Plugin.h b/offload/plugins-nextgen/level_zero/include/L0Plugin.h
index cd964a0d46890..709d2d8d4e26e 100644
--- a/offload/plugins-nextgen/level_zero/include/L0Plugin.h
+++ b/offload/plugins-nextgen/level_zero/include/L0Plugin.h
@@ -107,6 +107,8 @@ class LevelZeroPluginTy final : public GenericPluginTy {
   Error flushQueueImpl(omp_interop_val_t *Interop) override;
   Error syncBarrierImpl(omp_interop_val_t *Interop) override;
   Error asyncBarrierImpl(omp_interop_val_t *Interop) override;
+
+  Expected<bool> isCompatibleImage(StringRef Image) const override;
 };
 
 } // namespace llvm::omp::target::plugin
diff --git a/offload/plugins-nextgen/level_zero/src/L0Plugin.cpp b/offload/plugins-nextgen/level_zero/src/L0Plugin.cpp
index 285fe797b5d7d..9a70ca3cfdf61 100644
--- a/offload/plugins-nextgen/level_zero/src/L0Plugin.cpp
+++ b/offload/plugins-nextgen/level_zero/src/L0Plugin.cpp
@@ -233,6 +233,13 @@ Error LevelZeroPluginTy::asyncBarrierImpl(omp_interop_val_t *Interop) {
   return Plugin::success();
 }
 
+// We only need to check for formats other than ELF here
+Expected<bool> LevelZeroPluginTy::isCompatibleImage(StringRef Image) const {
+  if (identify_magic(Image) == file_magic::spirv_object)
+    return true;
+  return false; 
+}
+
 } // namespace llvm::omp::target::plugin
 
 extern "C" {

>From 44ef65a222b872671d24cdf7852eee52d2c86141 Mon Sep 17 00:00:00 2001
From: "Duran, Alex" <alejandro.duran at intel.com>
Date: Tue, 10 Mar 2026 08:08:26 -0700
Subject: [PATCH 3/5] format

---
 offload/plugins-nextgen/level_zero/src/L0Plugin.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/offload/plugins-nextgen/level_zero/src/L0Plugin.cpp b/offload/plugins-nextgen/level_zero/src/L0Plugin.cpp
index 9a70ca3cfdf61..c86106ea080e0 100644
--- a/offload/plugins-nextgen/level_zero/src/L0Plugin.cpp
+++ b/offload/plugins-nextgen/level_zero/src/L0Plugin.cpp
@@ -237,7 +237,7 @@ Error LevelZeroPluginTy::asyncBarrierImpl(omp_interop_val_t *Interop) {
 Expected<bool> LevelZeroPluginTy::isCompatibleImage(StringRef Image) const {
   if (identify_magic(Image) == file_magic::spirv_object)
     return true;
-  return false; 
+  return false;
 }
 
 } // namespace llvm::omp::target::plugin

>From 99edd2ac3f46083451802ff9101bf3b852f1c33e Mon Sep 17 00:00:00 2001
From: "Duran, Alex" <alejandro.duran at intel.com>
Date: Tue, 10 Mar 2026 08:28:16 -0700
Subject: [PATCH 4/5] Align names with existing ones

---
 offload/plugins-nextgen/common/include/PluginInterface.h | 6 +++---
 offload/plugins-nextgen/common/src/PluginInterface.cpp   | 4 ++--
 offload/plugins-nextgen/level_zero/include/L0Plugin.h    | 2 +-
 offload/plugins-nextgen/level_zero/src/L0Plugin.cpp      | 2 +-
 4 files changed, 7 insertions(+), 7 deletions(-)

diff --git a/offload/plugins-nextgen/common/include/PluginInterface.h b/offload/plugins-nextgen/common/include/PluginInterface.h
index 6da8389636077..5c48fecfaa11a 100644
--- a/offload/plugins-nextgen/common/include/PluginInterface.h
+++ b/offload/plugins-nextgen/common/include/PluginInterface.h
@@ -1367,7 +1367,7 @@ struct GenericPluginTy {
   /// Indicate if an image is compatible with the plugin. This is called if
   /// the image is not recognized as compatible by the common layer. This gives
   /// the plugin a chance to inspect the image and decide if it is compatible.
-  virtual Expected<bool> isCompatibleImage(StringRef Image) const {
+  virtual Expected<bool> isImageCompatible(StringRef Image) const {
     return false;
   }
 
@@ -1377,9 +1377,9 @@ struct GenericPluginTy {
   /// compatible. Notice that this function may be called before actually
   /// initializing the devices. So we could not move this function into
   /// GenericDeviceTy.
-  virtual Expected<bool> isCompatibleImage(uint32_t DeviceID,
+  virtual Expected<bool> isImageCompatible(uint32_t DeviceID,
                                            StringRef Image) const {
-    return isCompatibleImage(Image);
+    return isImageCompatible(Image);
   }
 
   virtual Error flushQueueImpl(omp_interop_val_t *Interop) {
diff --git a/offload/plugins-nextgen/common/src/PluginInterface.cpp b/offload/plugins-nextgen/common/src/PluginInterface.cpp
index 0cc1c38e5481a..21ba9db292c4c 100644
--- a/offload/plugins-nextgen/common/src/PluginInterface.cpp
+++ b/offload/plugins-nextgen/common/src/PluginInterface.cpp
@@ -1652,7 +1652,7 @@ int32_t GenericPluginTy::isPluginCompatible(StringRef Image) {
     return *MatchOrErr;
   }
   default:
-    auto MatchOrErr = isCompatibleImage(Image);
+    auto MatchOrErr = isImageCompatible(Image);
     if (Error Err = MatchOrErr.takeError())
       return HandleError(std::move(Err));
     return *MatchOrErr;
@@ -1692,7 +1692,7 @@ int32_t GenericPluginTy::isDeviceCompatible(int32_t DeviceId, StringRef Image) {
     return *MatchOrErr;
   }
   default:
-    auto MatchOrErr = isCompatibleImage(DeviceId, Image);
+    auto MatchOrErr = isImageCompatible(DeviceId, Image);
     if (Error Err = MatchOrErr.takeError())
       return HandleError(std::move(Err));
     return *MatchOrErr;
diff --git a/offload/plugins-nextgen/level_zero/include/L0Plugin.h b/offload/plugins-nextgen/level_zero/include/L0Plugin.h
index 709d2d8d4e26e..7ab3696a49af6 100644
--- a/offload/plugins-nextgen/level_zero/include/L0Plugin.h
+++ b/offload/plugins-nextgen/level_zero/include/L0Plugin.h
@@ -108,7 +108,7 @@ class LevelZeroPluginTy final : public GenericPluginTy {
   Error syncBarrierImpl(omp_interop_val_t *Interop) override;
   Error asyncBarrierImpl(omp_interop_val_t *Interop) override;
 
-  Expected<bool> isCompatibleImage(StringRef Image) const override;
+  Expected<bool> isImageCompatible(StringRef Image) const override;
 };
 
 } // namespace llvm::omp::target::plugin
diff --git a/offload/plugins-nextgen/level_zero/src/L0Plugin.cpp b/offload/plugins-nextgen/level_zero/src/L0Plugin.cpp
index c86106ea080e0..9117d0e0439a4 100644
--- a/offload/plugins-nextgen/level_zero/src/L0Plugin.cpp
+++ b/offload/plugins-nextgen/level_zero/src/L0Plugin.cpp
@@ -234,7 +234,7 @@ Error LevelZeroPluginTy::asyncBarrierImpl(omp_interop_val_t *Interop) {
 }
 
 // We only need to check for formats other than ELF here
-Expected<bool> LevelZeroPluginTy::isCompatibleImage(StringRef Image) const {
+Expected<bool> LevelZeroPluginTy::isImageCompatible(StringRef Image) const {
   if (identify_magic(Image) == file_magic::spirv_object)
     return true;
   return false;

>From d6887ca4ce5e97325a865a3a7479d60b1104a80d Mon Sep 17 00:00:00 2001
From: "Duran, Alex" <alejandro.duran at intel.com>
Date: Tue, 10 Mar 2026 08:52:52 -0700
Subject: [PATCH 5/5] cleanup

---
 offload/plugins-nextgen/common/include/PluginInterface.h | 2 +-
 offload/plugins-nextgen/level_zero/src/L0Plugin.cpp      | 4 +---
 2 files changed, 2 insertions(+), 4 deletions(-)

diff --git a/offload/plugins-nextgen/common/include/PluginInterface.h b/offload/plugins-nextgen/common/include/PluginInterface.h
index 5c48fecfaa11a..b20282ae1cd52 100644
--- a/offload/plugins-nextgen/common/include/PluginInterface.h
+++ b/offload/plugins-nextgen/common/include/PluginInterface.h
@@ -1371,7 +1371,7 @@ struct GenericPluginTy {
     return false;
   }
 
-  /// Indicate if an imaget is compatible with the plugin devices. This is
+  /// Indicate if an image is compatible with the plugin devices. This is
   /// called if the image is not recognized as compatible by the common layer.
   /// This gives the plugin a chance to inspect the image and decide if it is
   /// compatible. Notice that this function may be called before actually
diff --git a/offload/plugins-nextgen/level_zero/src/L0Plugin.cpp b/offload/plugins-nextgen/level_zero/src/L0Plugin.cpp
index 9117d0e0439a4..2b3e612566391 100644
--- a/offload/plugins-nextgen/level_zero/src/L0Plugin.cpp
+++ b/offload/plugins-nextgen/level_zero/src/L0Plugin.cpp
@@ -235,9 +235,7 @@ Error LevelZeroPluginTy::asyncBarrierImpl(omp_interop_val_t *Interop) {
 
 // We only need to check for formats other than ELF here
 Expected<bool> LevelZeroPluginTy::isImageCompatible(StringRef Image) const {
-  if (identify_magic(Image) == file_magic::spirv_object)
-    return true;
-  return false;
+  return identify_magic(Image) == file_magic::spirv_object;
 }
 
 } // namespace llvm::omp::target::plugin



More information about the llvm-commits mailing list