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

As discussed in #185404 we might want to provide a way for plugins to
validate images not recognized by the common layer.

This PR adds such extension and uses it to validate pure SPIRV images by
the Level Zero plugin.
This commit is contained in:
Alex Duran 2026-03-10 18:41:23 +01:00 committed by GitHub
parent 93d03f85d7
commit be021b8433
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 33 additions and 2 deletions

View File

@ -1367,6 +1367,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> isImageCompatible(StringRef Image) const {
return false;
}
/// 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
/// initializing the devices. So we could not move this function into
/// GenericDeviceTy.
virtual Expected<bool> isImageCompatible(uint32_t DeviceID,
StringRef Image) const {
return isImageCompatible(Image);
}
virtual Error flushQueueImpl(omp_interop_val_t *Interop) {
return Plugin::success();
}

View File

@ -1652,7 +1652,10 @@ int32_t GenericPluginTy::isPluginCompatible(StringRef Image) {
return *MatchOrErr;
}
default:
return false;
auto MatchOrErr = isImageCompatible(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 = isImageCompatible(DeviceId, Image);
if (Error Err = MatchOrErr.takeError())
return HandleError(std::move(Err));
return *MatchOrErr;
}
}

View File

@ -107,6 +107,8 @@ public:
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> isImageCompatible(StringRef Image) const override;
};
} // namespace llvm::omp::target::plugin

View File

@ -233,6 +233,11 @@ 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::isImageCompatible(StringRef Image) const {
return identify_magic(Image) == file_magic::spirv_object;
}
} // namespace llvm::omp::target::plugin
extern "C" {