[llvm] [OFFLOAD] Support host plugin on Windows (PR #180401)
via llvm-commits
llvm-commits at lists.llvm.org
Sun Feb 8 02:24:24 PST 2026
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-offload
Author: Alex Duran (adurang)
<details>
<summary>Changes</summary>
Changes to make host plugin compile on Windows:
* Change IO code to be portable
* Adjust Makefiles
Allow plugin to work partially when libffi support is not found dynamically (compilation works fine even on Windows because of the wrapper support).
---
Full diff: https://github.com/llvm/llvm-project/pull/180401.diff
3 Files Affected:
- (modified) offload/CMakeLists.txt (-5)
- (modified) offload/plugins-nextgen/host/CMakeLists.txt (+7-2)
- (modified) offload/plugins-nextgen/host/src/rtl.cpp (+42-32)
``````````diff
diff --git a/offload/CMakeLists.txt b/offload/CMakeLists.txt
index 81e246d9f8892..75a1bb435916b 100644
--- a/offload/CMakeLists.txt
+++ b/offload/CMakeLists.txt
@@ -158,11 +158,6 @@ if(LIBOMPTARGET_PLUGINS_TO_BUILD STREQUAL "all")
set(LIBOMPTARGET_PLUGINS_TO_BUILD ${LIBOMPTARGET_ALL_PLUGIN_TARGETS})
endif()
-if(NOT CMAKE_SYSTEM_NAME MATCHES "Linux" AND
- "host" IN_LIST LIBOMPTARGET_PLUGINS_TO_BUILD)
- message(STATUS "Not building host plugin: only Linux systems are supported")
- list(REMOVE_ITEM LIBOMPTARGET_PLUGINS_TO_BUILD "host")
-endif()
if(NOT (CMAKE_SYSTEM_PROCESSOR MATCHES "(x86_64)|(ppc64le)|(aarch64)$"
AND CMAKE_SYSTEM_NAME MATCHES "Linux"))
if("amdgpu" IN_LIST LIBOMPTARGET_PLUGINS_TO_BUILD)
diff --git a/offload/plugins-nextgen/host/CMakeLists.txt b/offload/plugins-nextgen/host/CMakeLists.txt
index 26750bd62d406..e1d66b67cbb53 100644
--- a/offload/plugins-nextgen/host/CMakeLists.txt
+++ b/offload/plugins-nextgen/host/CMakeLists.txt
@@ -1,10 +1,15 @@
+if(WIN32)
+set(supported_targets AMD64 IA64 ARM64 EM64T X86)
+else()
set(supported_targets x86_64 aarch64 ppc64 ppc64le riscv64 s390x loongarch64)
-if(NOT ${CMAKE_SYSTEM_PROCESSOR} IN_LIST supported_targets)
+endif()
+
+set(machine ${CMAKE_SYSTEM_PROCESSOR})
+if(NOT ${machine} IN_LIST supported_targets)
message(STATUS "Not building ${machine} NextGen offloading plugin")
return()
endif()
-set(machine ${CMAKE_SYSTEM_PROCESSOR})
if(CMAKE_SYSTEM_PROCESSOR MATCHES "ppc64le$")
set(machine ppc64)
endif()
diff --git a/offload/plugins-nextgen/host/src/rtl.cpp b/offload/plugins-nextgen/host/src/rtl.cpp
index 603379630ae8e..48e863afdee84 100644
--- a/offload/plugins-nextgen/host/src/rtl.cpp
+++ b/offload/plugins-nextgen/host/src/rtl.cpp
@@ -30,6 +30,8 @@
#include "llvm/Frontend/OpenMP/OMPDeviceConstants.h"
#include "llvm/Frontend/OpenMP/OMPGridValues.h"
#include "llvm/Support/DynamicLibrary.h"
+#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/raw_ostream.h"
#if !defined(__BYTE_ORDER__) || !defined(__ORDER_LITTLE_ENDIAN__) || \
!defined(__ORDER_BIG_ENDIAN__)
@@ -63,7 +65,8 @@ using namespace error;
/// Class implementing kernel functionalities for GenELF64.
struct GenELF64KernelTy : public GenericKernelTy {
/// Construct the kernel with a name and an execution mode.
- GenELF64KernelTy(const char *Name) : GenericKernelTy(Name), Func(nullptr) {}
+ GenELF64KernelTy(const char *Name, bool SupportsFFI)
+ : GenericKernelTy(Name), Func(nullptr), supportsFFI(SupportsFFI) {}
/// Initialize the kernel.
Error initImpl(GenericDeviceTy &Device, DeviceImageTy &Image) override {
@@ -97,6 +100,9 @@ struct GenELF64KernelTy : public GenericKernelTy {
uint32_t NumBlocks[3], KernelArgsTy &KernelArgs,
KernelLaunchParamsTy LaunchParams,
AsyncInfoWrapperTy &AsyncInfoWrapper) const override {
+ if (!supportsFFI)
+ return Plugin::error(ErrorCode::UNSUPPORTED,
+ "libffi is not available, cannot launch kernel");
// Create a vector of ffi_types, one per argument.
SmallVector<ffi_type *, 16> ArgTypes(KernelArgs.NumArgs, &ffi_type_pointer);
ffi_type **ArgTypesPtr = (ArgTypes.size()) ? &ArgTypes[0] : nullptr;
@@ -127,6 +133,8 @@ struct GenELF64KernelTy : public GenericKernelTy {
private:
/// The kernel function to execute.
void (*Func)(void);
+ /// Whether this kernel supports FFI-based launch.
+ bool supportsFFI;
};
/// Class implementing the GenELF64 device images properties.
@@ -149,8 +157,9 @@ struct GenELF64DeviceImageTy : public DeviceImageTy {
struct GenELF64DeviceTy : public GenericDeviceTy {
/// Create the device with a specific id.
GenELF64DeviceTy(GenericPluginTy &Plugin, int32_t DeviceId,
- int32_t NumDevices)
- : GenericDeviceTy(Plugin, DeviceId, NumDevices, GenELF64GridValues) {}
+ int32_t NumDevices, bool SupportsFFI)
+ : GenericDeviceTy(Plugin, DeviceId, NumDevices, GenELF64GridValues),
+ supportsFFI(SupportsFFI) {}
~GenELF64DeviceTy() {}
@@ -182,7 +191,7 @@ struct GenELF64DeviceTy : public GenericDeviceTy {
return Plugin::error(ErrorCode::OUT_OF_RESOURCES,
"failed to allocate memory for GenELF64 kernel");
- new (GenELF64Kernel) GenELF64KernelTy(Name);
+ new (GenELF64Kernel) GenELF64KernelTy(Name, supportsFFI);
return *GenELF64Kernel;
}
@@ -198,37 +207,30 @@ struct GenELF64DeviceTy : public GenericDeviceTy {
GenELF64DeviceImageTy *Image = Plugin.allocate<GenELF64DeviceImageTy>();
new (Image) GenELF64DeviceImageTy(ImageId, *this, std::move(TgtImage));
- // Create a temporary file.
- char TmpFileName[] = "/tmp/tmpfile_XXXXXX";
- int TmpFileFd = mkstemp(TmpFileName);
- if (TmpFileFd == -1)
- return Plugin::error(ErrorCode::HOST_IO,
- "failed to create tmpfile for loading target image");
-
- // Open the temporary file.
- FILE *TmpFile = fdopen(TmpFileFd, "wb");
- if (!TmpFile)
- return Plugin::error(ErrorCode::HOST_IO,
- "failed to open tmpfile %s for loading target image",
- TmpFileName);
+ SmallString<128> TmpFileName;
+ int TmpFileFd;
+ if (auto EC = llvm::sys::fs::createTemporaryFile("tmpfile", "tmp",
+ TmpFileFd, TmpFileName))
+ return Plugin::error(
+ ErrorCode::HOST_IO,
+ "failed to create tmpfile for loading target image: %s",
+ EC.message().c_str());
// Write the image into the temporary file.
- size_t Written = fwrite(Image->getStart(), Image->getSize(), 1, TmpFile);
- if (Written != 1)
- return Plugin::error(ErrorCode::HOST_IO,
- "failed to write target image to tmpfile %s",
- TmpFileName);
+ llvm::raw_fd_ostream TmpFile(TmpFileFd, /*shouldClose=*/true);
+ TmpFile.write(static_cast<const char *>(Image->getStart()),
+ Image->getSize());
+ TmpFile.close();
- // Close the temporary file.
- int Ret = fclose(TmpFile);
- if (Ret)
+ if (TmpFile.has_error())
return Plugin::error(ErrorCode::HOST_IO,
- "failed to close tmpfile %s with the target image",
- TmpFileName);
+ "failed to write target image to tmpfile %s",
+ TmpFileName.c_str());
// Load the temporary file as a dynamic library.
std::string ErrMsg;
- DynamicLibrary DynLib = DynamicLibrary::getLibrary(TmpFileName, &ErrMsg);
+ DynamicLibrary DynLib =
+ DynamicLibrary::getLibrary(TmpFileName.c_str(), &ErrMsg);
// Check if the loaded library is valid.
if (!DynLib.isValid())
@@ -405,6 +407,9 @@ struct GenELF64DeviceTy : public GenericDeviceTy {
1, // GV_Max_WG_Size
1, // GV_Default_WG_Size
};
+
+ /// Whether this device supports FFI-based launch.
+ bool supportsFFI;
};
class GenELF64GlobalHandlerTy final : public GenericGlobalHandlerTy {
@@ -441,12 +446,13 @@ struct GenELF64PluginTy final : public GenericPluginTy {
/// This class should not be copied.
GenELF64PluginTy(const GenELF64PluginTy &) = delete;
GenELF64PluginTy(GenELF64PluginTy &&) = delete;
-
/// Initialize the plugin and return the number of devices.
Expected<int32_t> initImpl() override {
#ifdef USES_DYNAMIC_FFI
- if (auto Err = Plugin::check(ffi_init(), "failed to initialize libffi"))
- return std::move(Err);
+ SupportsFFI = ffi_init() == FFI_OK ? true : false;
+ if (!SupportsFFI)
+ ODBG(OLDT_Init) << "libffi is not available, kernels will not be launched "
+ "through libffi, and some features may be unavailable";
#endif
ODBG(OLDT_Init) << "GenELF64 plugin detected " << ODBG_IF_LEVEL(2)
<< NUM_DEVICES << " " << ODBG_RESET_LEVEL() << "devices";
@@ -460,7 +466,7 @@ struct GenELF64PluginTy final : public GenericPluginTy {
/// Creates a generic ELF device.
GenericDeviceTy *createDevice(GenericPluginTy &Plugin, int32_t DeviceId,
int32_t NumDevices) override {
- return new GenELF64DeviceTy(Plugin, DeviceId, NumDevices);
+ return new GenELF64DeviceTy(Plugin, DeviceId, NumDevices, SupportsFFI);
}
/// Creates a generic global handler.
@@ -510,6 +516,10 @@ struct GenELF64PluginTy final : public GenericPluginTy {
}
const char *getName() const override { return GETNAME(TARGET_NAME); }
+
+private:
+ /// Whether this plugin supports FFI-based launch.
+ bool SupportsFFI = true;
};
template <typename... ArgsTy>
``````````
</details>
https://github.com/llvm/llvm-project/pull/180401
More information about the llvm-commits
mailing list