[llvm] [Offload] Add strong definitions of all L0 symbols for Windows (PR #228070)

via llvm-commits llvm-commits at lists.llvm.org
Thu Oct 1 06:09:22 PDT 2026


https://github.com/blazej-smorawski created https://github.com/llvm/llvm-project/pull/228070

This PR adds missing strong definitions that would fail on Windows. The patch also changes the way Level Zero plugin handles experimental APIs - now there's an internal fallback that is able to handle a case where API that is available in loader returns `UNSUPPORTED`, but there's experimental variant in compute runtime.

>From ac425b8929fbd2b637f144d39b38b53ef41ad7dc Mon Sep 17 00:00:00 2001
From: blazej-smorawski <blazej.smorawski at gmail.com>
Date: Wed, 23 Sep 2026 10:34:45 +0000
Subject: [PATCH] [Offload] Add strong definitions of  all L0 symbols for
 Windows

---
 .../level_zero/dynamic_l0/L0DynWrapper.cpp    |  5 +-
 .../level_zero/dynamic_l0/level_zero/ze_api.h |  9 ++++
 .../level_zero/include/L0CmdListManager.h     |  3 +-
 .../level_zero/include/L0Compat.h             |  2 +-
 .../level_zero/include/L0Context.h            | 50 ++++++++++++-------
 .../level_zero/include/L0Defs.h               |  3 ++
 .../level_zero/src/L0Context.cpp              | 26 ++++------
 7 files changed, 59 insertions(+), 39 deletions(-)

diff --git a/offload/plugins-nextgen/level_zero/dynamic_l0/L0DynWrapper.cpp b/offload/plugins-nextgen/level_zero/dynamic_l0/L0DynWrapper.cpp
index 70bc3aaf36512..066c878cba92c 100644
--- a/offload/plugins-nextgen/level_zero/dynamic_l0/L0DynWrapper.cpp
+++ b/offload/plugins-nextgen/level_zero/dynamic_l0/L0DynWrapper.cpp
@@ -60,6 +60,7 @@ DLWRAP(zeDriverGetApiVersion, 2)
 DLWRAP(zeDriverGetProperties, 2)
 DLWRAP(zeDriverGetExtensionFunctionAddress, 3)
 DLWRAP(zeDriverGetExtensionProperties, 3)
+DLWRAP(zeIntelGetDriverVersionString, 3)
 DLWRAP(zeEventCreate, 3)
 DLWRAP(zeEventDestroy, 1)
 DLWRAP(zeEventHostReset, 1)
@@ -79,6 +80,7 @@ DLWRAP(zeKernelSetGroupSize, 4)
 DLWRAP(zeKernelSetIndirectAccess, 2)
 DLWRAP(zeKernelSuggestGroupSize, 7)
 DLWRAP(zeKernelSuggestMaxCooperativeGroupCount, 2)
+DLWRAP(zexKernelGetArgumentSize, 3)
 DLWRAP(zeMemAllocDevice, 6)
 DLWRAP(zeMemAllocHost, 5)
 DLWRAP(zeMemAllocShared, 7)
@@ -91,9 +93,10 @@ DLWRAP(zeModuleGetNativeBinary, 3)
 DLWRAP(zeModuleGetFunctionPointer, 3)
 DLWRAP(zesDeviceEnumMemoryModules, 3)
 DLWRAP(zesMemoryGetState, 2)
-DLWRAP(zeCommandListHostSynchronize, 2)
+DLWRAP(zeCommandListAppendHostFunction, 7)
 DLWRAP(zeCommandListAppendSignalEvent, 2)
 DLWRAP(zeCommandListAppendWaitOnEvents, 3)
+DLWRAP(zeCommandListHostSynchronize, 2)
 DLWRAP(zeEventQueryStatus, 1)
 DLWRAP(zeDriverGetDefaultContext, 1)
 
diff --git a/offload/plugins-nextgen/level_zero/dynamic_l0/level_zero/ze_api.h b/offload/plugins-nextgen/level_zero/dynamic_l0/level_zero/ze_api.h
index be8ad9db758ee..f7ba9a7558a10 100644
--- a/offload/plugins-nextgen/level_zero/dynamic_l0/level_zero/ze_api.h
+++ b/offload/plugins-nextgen/level_zero/dynamic_l0/level_zero/ze_api.h
@@ -687,6 +687,8 @@ ZE_APIEXPORT ze_result_t ZE_APICALL zeDriverGetExtensionProperties(
     ze_driver_handle_t hDriver, uint32_t *pCount, void *pExtensionProperties);
 ZE_APIEXPORT ze_context_handle_t ZE_APICALL
 zeDriverGetDefaultContext(ze_driver_handle_t hDriver);
+ZE_APIEXPORT ze_result_t zeIntelGetDriverVersionString(
+    ze_driver_handle_t hDriver, char *pDriverVersion, size_t *pVersionSize);
 
 /* Device functions */
 ZE_APIEXPORT ze_result_t ZE_APICALL zeDeviceGet(ze_driver_handle_t hDriver,
@@ -759,6 +761,10 @@ ZE_APIEXPORT ze_result_t ZE_APICALL
 zeCommandListReset(ze_command_list_handle_t hCommandList);
 ZE_APIEXPORT ze_result_t ZE_APICALL zeCommandListHostSynchronize(
     ze_command_list_handle_t hCommandList, uint64_t timeout);
+ZE_APIEXPORT ze_result_t zeCommandListAppendHostFunction(
+    ze_command_list_handle_t hCommandList, void *pfnHostFunction,
+    void *pUserData, const void *pNext, ze_event_handle_t hSignalEvent,
+    uint32_t numWaitEvents, ze_event_handle_t *phWaitEvents);
 
 /* Command list append functions */
 ZE_APIEXPORT ze_result_t ZE_APICALL zeCommandListAppendBarrier(
@@ -876,6 +882,9 @@ ZE_APIEXPORT ze_result_t ZE_APICALL zeKernelSuggestMaxCooperativeGroupCount(
     ze_kernel_handle_t hKernel, uint32_t *totalGroupCount);
 ZE_APIEXPORT ze_result_t ZE_APICALL zeKernelSetIndirectAccess(
     ze_kernel_handle_t hKernel, ze_kernel_indirect_access_flags_t flags);
+ZE_APIEXPORT ze_result_t zexKernelGetArgumentSize(ze_kernel_handle_t hKernel,
+                                                  uint32_t argIndex,
+                                                  uint32_t *pArgSize);
 
 /* Event pool functions */
 ZE_APIEXPORT ze_result_t ZE_APICALL zeEventPoolCreate(
diff --git a/offload/plugins-nextgen/level_zero/include/L0CmdListManager.h b/offload/plugins-nextgen/level_zero/include/L0CmdListManager.h
index f6b3a42f4cd75..9112277303f2f 100644
--- a/offload/plugins-nextgen/level_zero/include/L0CmdListManager.h
+++ b/offload/plugins-nextgen/level_zero/include/L0CmdListManager.h
@@ -201,8 +201,7 @@ class L0CmdListManagerTy {
                            "available on this driver");
     std::lock_guard<std::mutex> Lock(Mtx);
 
-    // Alias for better error reporting
-    auto zeCommandListAppendHostFunction =
+    auto &zeCommandListAppendHostFunction =
         Context.CommandListAppendHostFunction;
     CALL_ZE_RET_ERROR(zeCommandListAppendHostFunction, CmdList,
                       reinterpret_cast<void *>(Callback), UserData,
diff --git a/offload/plugins-nextgen/level_zero/include/L0Compat.h b/offload/plugins-nextgen/level_zero/include/L0Compat.h
index c1580991bc5b4..079ca64fe37ff 100644
--- a/offload/plugins-nextgen/level_zero/include/L0Compat.h
+++ b/offload/plugins-nextgen/level_zero/include/L0Compat.h
@@ -31,7 +31,7 @@ API_HELPER_OPTIONAL(ze_result_t, zexKernelGetArgumentSize,
 
 API_HELPER_OPTIONAL(ze_result_t, zeCommandListAppendHostFunction,
                     ze_command_list_handle_t hCommandList,
-                    void *pfnHostFunction, void *pUserData, void *pReserved,
+                    void *pfnHostFunction, void *pUserData, const void *pNext,
                     ze_event_handle_t hSignalEvent, uint32_t numWaitEvents,
                     ze_event_handle_t *phWaitEvents)
 
diff --git a/offload/plugins-nextgen/level_zero/include/L0Context.h b/offload/plugins-nextgen/level_zero/include/L0Context.h
index 6f243cbdb4d13..2cb7521f3facb 100644
--- a/offload/plugins-nextgen/level_zero/include/L0Context.h
+++ b/offload/plugins-nextgen/level_zero/include/L0Context.h
@@ -15,11 +15,14 @@
 
 #include "APIHelpers.h"
 #include "L0Compat.h"
+#include "L0Defs.h"
 #include "L0Event.h"
 #include "L0Memory.h"
 #include "PerThreadTable.h"
 #include "level_zero/ze_api.h"
 
+#include <atomic>
+
 namespace llvm::omp::target::plugin {
 
 class LevelZeroPluginTy;
@@ -50,44 +53,55 @@ class ZeDispatcher {
 
   [[nodiscard]]
   bool available() const {
-    if (FuncPtr != nullptr)
-      return true;
-
-    return api_helper::canCall<Fn>();
+    return api_helper::canCall<Fn>() || ExperimentalFallbackPtr != nullptr;
   }
 
   explicit operator bool() const { return available(); }
 
-  template <typename... Args>
-  decltype(auto) operator()(Args &&...ArgsList) const {
+  template <typename... Args> decltype(auto) operator()(Args &&...ArgsList) {
     // Need to cast the type to avoid mismatch of return type deduction
     using ReturnTy = std::invoke_result_t<decltype(Fn), Args...>;
-    if (FuncPtr != nullptr)
-      return FuncPtr(std::forward<Args>(ArgsList)...);
 
-    if (!api_helper::canCall<Fn>())
+    if (!api_helper::canCall<Fn>() ||
+        AvailableButUnsupported.load(std::memory_order_relaxed)) {
+      if (ExperimentalFallbackPtr != nullptr) {
+        return ExperimentalFallbackPtr(std::forward<Args>(ArgsList)...);
+      }
+
       return static_cast<ReturnTy>(UnsupportedValue);
+    }
+
+    auto Ret = Fn(std::forward<Args>(ArgsList)...);
 
-    return Fn(std::forward<Args>(ArgsList)...);
+    if (Ret == UnsupportedValue) {
+      AvailableButUnsupported.store(true, std::memory_order_relaxed);
+
+      if (ExperimentalFallbackPtr != nullptr)
+        return ExperimentalFallbackPtr(std::forward<Args>(ArgsList)...);
+    }
+
+    return Ret;
   }
 
   bool loadExperimental(ze_driver_handle_t zeDriver, const char *FuncName) {
-    assert(!api_helper::canCall<Fn>() &&
-           "ZeDispatcher::loadExperimental called without "
-           "ZeDispatcher::available check!");
-
     ze_result_t Result = ZE_RESULT_SUCCESS;
-    CALL_ZE_RET(Result, zeDriverGetExtensionFunctionAddress, zeDriver, FuncName,
-                reinterpret_cast<void **>(&FuncPtr));
+    CALL_ZE(Result, zeDriverGetExtensionFunctionAddress, zeDriver, FuncName,
+            reinterpret_cast<void **>(&ExperimentalFallbackPtr));
 
-    if (Result != ZE_RESULT_SUCCESS || FuncPtr == nullptr)
+    if (Result != ZE_RESULT_SUCCESS || ExperimentalFallbackPtr == nullptr) {
+      ODBG(OLDT_ZeDispather) << "Failed to load experimental variant of "
+                             << __PRETTY_FUNCTION__ << "using: " << FuncName;
       return false;
+    }
 
+    ODBG(OLDT_ZeDispather) << "Loaded experimental variant of "
+                           << __PRETTY_FUNCTION__ << " using: " << FuncName;
     return true;
   }
 
 private:
-  decltype(Fn) FuncPtr = nullptr;
+  std::atomic<bool> AvailableButUnsupported = false;
+  decltype(Fn) ExperimentalFallbackPtr = nullptr;
 };
 
 struct L0ContextTLSTableTy
diff --git a/offload/plugins-nextgen/level_zero/include/L0Defs.h b/offload/plugins-nextgen/level_zero/include/L0Defs.h
index 1c616b93b779f..bd7af3e626456 100644
--- a/offload/plugins-nextgen/level_zero/include/L0Defs.h
+++ b/offload/plugins-nextgen/level_zero/include/L0Defs.h
@@ -23,6 +23,9 @@ enum class AllocOptionTy : int32_t {
   ALLOC_OPT_SLM = 4,
 };
 
+// Level Zero debug types
+constexpr const char *OLDT_ZeDispather = "ZeDispatcher";
+
 namespace llvm::omp::target::plugin {
 
 /// Default alignmnet for allocation.
diff --git a/offload/plugins-nextgen/level_zero/src/L0Context.cpp b/offload/plugins-nextgen/level_zero/src/L0Context.cpp
index 13afa04887689..67a02d11fc539 100644
--- a/offload/plugins-nextgen/level_zero/src/L0Context.cpp
+++ b/offload/plugins-nextgen/level_zero/src/L0Context.cpp
@@ -93,29 +93,21 @@ Error L0ContextTy::init() {
   ODBG(OLDT_Init) << "  zeDriverGetDefaultContext: "
                   << (DriverGetDefaultContext.available() ? "yes" : "no");
 
-  if (!LaunchKernelWithArguments)
-    LaunchKernelWithArguments.loadExperimental(
-        zeDriver, "zeCommandListAppendLaunchKernelWithArguments");
+  LaunchKernelWithArguments.loadExperimental(
+      zeDriver, "zeCommandListAppendLaunchKernelWithArguments");
 
-  if (!KernelGetArgumentSize)
-    KernelGetArgumentSize.loadExperimental(zeDriver,
-                                           "zexKernelGetArgumentSize");
+  KernelGetArgumentSize.loadExperimental(zeDriver, "zexKernelGetArgumentSize");
 
-  if (!CommandListAppendHostFunction)
-    CommandListAppendHostFunction.loadExperimental(
-        zeDriver, "zeCommandListAppendHostFunction");
-  if (!CommandListAppendHostFunction)
+  if (!CommandListAppendHostFunction.loadExperimental(
+          zeDriver, "zeCommandListAppendHostFunction"))
     // Try again with a name used in compute runtime 25.35 to 25.48
     CommandListAppendHostFunction.loadExperimental(
         zeDriver, "zexCommandListAppendHostFunction");
 
-  if (!DriverGetDefaultContext)
-    DriverGetDefaultContext.loadExperimental(zeDriver,
-                                             "zeDriverGetDefaultContext");
-
-  if (!IntelGetDriverVersionString)
-    IntelGetDriverVersionString.loadExperimental(
-        zeDriver, "zeIntelGetDriverVersionString");
+  DriverGetDefaultContext.loadExperimental(zeDriver,
+                                           "zeDriverGetDefaultContext");
+  IntelGetDriverVersionString.loadExperimental(zeDriver,
+                                               "zeIntelGetDriverVersionString");
 
   ODBG(OLDT_Init) << "APIs supported by the context with added extensions: ";
   ODBG(OLDT_Init) << "  zeCommandListAppendLaunchKernelWithArguments: "



More information about the llvm-commits mailing list