https://github.com/ScottTodd updated 
https://github.com/llvm/llvm-project/pull/209898

>From 81c581070eb82700ba431fad354b7ced801a712a Mon Sep 17 00:00:00 2001
From: Scott Todd <[email protected]>
Date: Wed, 15 Jul 2026 11:44:12 -0700
Subject: [PATCH 1/4] [offload-arch] Fix amdgpu HIP DLL search path on Windows

---
 clang/tools/offload-arch/AMDGPUArchByHIP.cpp | 13 ++++++++++++-
 1 file changed, 12 insertions(+), 1 deletion(-)

diff --git a/clang/tools/offload-arch/AMDGPUArchByHIP.cpp 
b/clang/tools/offload-arch/AMDGPUArchByHIP.cpp
index 9cfccf416f783..db4387db3c0c7 100644
--- a/clang/tools/offload-arch/AMDGPUArchByHIP.cpp
+++ b/clang/tools/offload-arch/AMDGPUArchByHIP.cpp
@@ -229,8 +229,19 @@ static void primeLibraryLoad(StringRef Path) {
   static HMODULE PinnedModule = nullptr;
   if (PinnedModule || !sys::path::is_absolute(Path))
     return;
+
+  // Other paths here use '/' for consistency, but LoadLibraryExW's altered
+  // search path needs '\\' to locate dependencies relative to the DLL.
+  //
+  // See 
https://learn.microsoft.com/windows/win32/api/libloaderapi/nf-libloaderapi-loadlibraryexw
+  // "If the string specifies a fully qualified path, the function searches 
only
+  //  that path for the module. When specifying a path, be sure to use
+  //  backslashes (\), not forward slashes (/)."
+  SmallString<256> NativePath;
+  sys::path::native(Path, NativePath, sys::path::Style::windows_backslash);
+
   SmallVector<UTF16, 256> WPath;
-  if (!convertUTF8ToUTF16String(Path, WPath))
+  if (!convertUTF8ToUTF16String(NativePath, WPath))
     return;
   WPath.push_back(0);
   PinnedModule = LoadLibraryExW(reinterpret_cast<LPCWSTR>(WPath.data()),

>From eb808f79208862569915d3018294735a699c9d05 Mon Sep 17 00:00:00 2001
From: Scott Todd <[email protected]>
Date: Wed, 15 Jul 2026 13:32:07 -0700
Subject: [PATCH 2/4] Add a unit test for primeLibraryLoad.

---
 clang/tools/offload-arch/AMDGPUArchByHIP.cpp  |  9 +++--
 .../offload-arch/OffloadArchTest.cpp          | 38 +++++++++++++++++++
 2 files changed, 44 insertions(+), 3 deletions(-)

diff --git a/clang/tools/offload-arch/AMDGPUArchByHIP.cpp 
b/clang/tools/offload-arch/AMDGPUArchByHIP.cpp
index db4387db3c0c7..b75471fec1c88 100644
--- a/clang/tools/offload-arch/AMDGPUArchByHIP.cpp
+++ b/clang/tools/offload-arch/AMDGPUArchByHIP.cpp
@@ -221,9 +221,12 @@ static std::pair<std::string, bool> findNewestHIPDLL() {
 }
 
 #ifdef _WIN32
+using LoadLibraryExWFn = decltype(&::LoadLibraryExW);
+
 // Pre-load DLL with LOAD_WITH_ALTERED_SEARCH_PATH so transitive deps
 // resolve from its directory. Pinned so getPermanentLibrary reuses it.
-static void primeLibraryLoad(StringRef Path) {
+void primeLibraryLoad(StringRef Path,
+                      LoadLibraryExWFn Loader = &::LoadLibraryExW) {
   // One DLL primed per process; subsequent calls are no-ops.
   // Not thread-safe, but offload-arch is single-threaded.
   static HMODULE PinnedModule = nullptr;
@@ -244,8 +247,8 @@ static void primeLibraryLoad(StringRef Path) {
   if (!convertUTF8ToUTF16String(NativePath, WPath))
     return;
   WPath.push_back(0);
-  PinnedModule = LoadLibraryExW(reinterpret_cast<LPCWSTR>(WPath.data()),
-                                nullptr, LOAD_WITH_ALTERED_SEARCH_PATH);
+  PinnedModule = Loader(reinterpret_cast<LPCWSTR>(WPath.data()), nullptr,
+                        LOAD_WITH_ALTERED_SEARCH_PATH);
   DWORD Err = GetLastError();
   if (!PinnedModule && Verbose)
     WithColor::note() << "priming LoadLibraryExW failed for " << Path
diff --git a/clang/unittests/offload-arch/OffloadArchTest.cpp 
b/clang/unittests/offload-arch/OffloadArchTest.cpp
index 4b07af39a918a..e845e7c8b434d 100644
--- a/clang/unittests/offload-arch/OffloadArchTest.cpp
+++ b/clang/unittests/offload-arch/OffloadArchTest.cpp
@@ -13,10 +13,17 @@
 #include <algorithm>
 #include <string>
 
+#ifdef _WIN32
+#include <windows.h>
+#endif
+
 // Defined in AMDGPUArchByHIP.cpp (non-static, compiled into this test).
 #ifdef _WIN32
+using LoadLibraryExWFn = decltype(&::LoadLibraryExW);
+
 bool compareVersions(llvm::StringRef A, llvm::StringRef B);
 llvm::SmallVector<std::string, 8> getCandidateBinPaths(llvm::StringRef ExeDir);
+void primeLibraryLoad(llvm::StringRef Path, LoadLibraryExWFn Loader);
 #endif
 
 using namespace llvm;
@@ -25,6 +32,37 @@ cl::opt<bool> Verbose("offload-arch-test-verbose", 
cl::Hidden, cl::init(false));
 
 #ifdef _WIN32
 
+// --- primeLibraryLoad ---
+
+namespace {
+std::wstring CapturedPath;
+HANDLE CapturedFile;
+DWORD CapturedFlags;
+
+HMODULE WINAPI mockLoadLibraryExW(LPCWSTR Path, HANDLE File, DWORD Flags) {
+  CapturedPath = Path;
+  CapturedFile = File;
+  CapturedFlags = Flags;
+  return reinterpret_cast<HMODULE>(1);
+}
+} // namespace
+
+TEST(PrimeLibraryLoad, UsesWindowsBackslashes) {
+  CapturedPath.clear();
+  CapturedFile = reinterpret_cast<HANDLE>(1);
+  CapturedFlags = 0;
+
+  primeLibraryLoad("C:/rocm\\bin/amdhip64_7.dll", mockLoadLibraryExW);
+
+  // The underlying LoadLibraryExW function should be called with backslashes,
+  // not forward slashes to ensure that it can discover and load dependent
+  // DLLs in the same directory.
+  EXPECT_EQ(CapturedPath, L"C:\\rocm\\bin\\amdhip64_7.dll");
+  EXPECT_EQ(CapturedPath.find(L'/'), std::wstring::npos);
+  EXPECT_EQ(CapturedFile, nullptr);
+  EXPECT_EQ(CapturedFlags, LOAD_WITH_ALTERED_SEARCH_PATH);
+}
+
 // --- compareVersions ---
 
 TEST(CompareVersions, HigherVersionWins) {

>From 8c4adee01c76afbfaa8e894dfb4fabe90e73acbe Mon Sep 17 00:00:00 2001
From: Scott Todd <[email protected]>
Date: Wed, 15 Jul 2026 14:05:54 -0700
Subject: [PATCH 3/4] Format

---
 clang/tools/offload-arch/AMDGPUArchByHIP.cpp | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/clang/tools/offload-arch/AMDGPUArchByHIP.cpp 
b/clang/tools/offload-arch/AMDGPUArchByHIP.cpp
index b75471fec1c88..220fc81021fb7 100644
--- a/clang/tools/offload-arch/AMDGPUArchByHIP.cpp
+++ b/clang/tools/offload-arch/AMDGPUArchByHIP.cpp
@@ -236,7 +236,8 @@ void primeLibraryLoad(StringRef Path,
   // Other paths here use '/' for consistency, but LoadLibraryExW's altered
   // search path needs '\\' to locate dependencies relative to the DLL.
   //
-  // See 
https://learn.microsoft.com/windows/win32/api/libloaderapi/nf-libloaderapi-loadlibraryexw
+  // See
+  // 
https://learn.microsoft.com/windows/win32/api/libloaderapi/nf-libloaderapi-loadlibraryexw
   // "If the string specifies a fully qualified path, the function searches 
only
   //  that path for the module. When specifying a path, be sure to use
   //  backslashes (\), not forward slashes (/)."

>From f214c2d7b0e5c810de31402fa1b36a68d11f8528 Mon Sep 17 00:00:00 2001
From: Scott Todd <[email protected]>
Date: Mon, 20 Jul 2026 08:13:22 -0700
Subject: [PATCH 4/4] Revert "Add a unit test for primeLibraryLoad."

This reverts commit eb808f79208862569915d3018294735a699c9d05.
---
 clang/tools/offload-arch/AMDGPUArchByHIP.cpp  |  9 ++---
 .../offload-arch/OffloadArchTest.cpp          | 38 -------------------
 2 files changed, 3 insertions(+), 44 deletions(-)

diff --git a/clang/tools/offload-arch/AMDGPUArchByHIP.cpp 
b/clang/tools/offload-arch/AMDGPUArchByHIP.cpp
index 220fc81021fb7..36c3c98002a31 100644
--- a/clang/tools/offload-arch/AMDGPUArchByHIP.cpp
+++ b/clang/tools/offload-arch/AMDGPUArchByHIP.cpp
@@ -221,12 +221,9 @@ static std::pair<std::string, bool> findNewestHIPDLL() {
 }
 
 #ifdef _WIN32
-using LoadLibraryExWFn = decltype(&::LoadLibraryExW);
-
 // Pre-load DLL with LOAD_WITH_ALTERED_SEARCH_PATH so transitive deps
 // resolve from its directory. Pinned so getPermanentLibrary reuses it.
-void primeLibraryLoad(StringRef Path,
-                      LoadLibraryExWFn Loader = &::LoadLibraryExW) {
+static void primeLibraryLoad(StringRef Path) {
   // One DLL primed per process; subsequent calls are no-ops.
   // Not thread-safe, but offload-arch is single-threaded.
   static HMODULE PinnedModule = nullptr;
@@ -248,8 +245,8 @@ void primeLibraryLoad(StringRef Path,
   if (!convertUTF8ToUTF16String(NativePath, WPath))
     return;
   WPath.push_back(0);
-  PinnedModule = Loader(reinterpret_cast<LPCWSTR>(WPath.data()), nullptr,
-                        LOAD_WITH_ALTERED_SEARCH_PATH);
+  PinnedModule = LoadLibraryExW(reinterpret_cast<LPCWSTR>(WPath.data()),
+                                nullptr, LOAD_WITH_ALTERED_SEARCH_PATH);
   DWORD Err = GetLastError();
   if (!PinnedModule && Verbose)
     WithColor::note() << "priming LoadLibraryExW failed for " << Path
diff --git a/clang/unittests/offload-arch/OffloadArchTest.cpp 
b/clang/unittests/offload-arch/OffloadArchTest.cpp
index e845e7c8b434d..4b07af39a918a 100644
--- a/clang/unittests/offload-arch/OffloadArchTest.cpp
+++ b/clang/unittests/offload-arch/OffloadArchTest.cpp
@@ -13,17 +13,10 @@
 #include <algorithm>
 #include <string>
 
-#ifdef _WIN32
-#include <windows.h>
-#endif
-
 // Defined in AMDGPUArchByHIP.cpp (non-static, compiled into this test).
 #ifdef _WIN32
-using LoadLibraryExWFn = decltype(&::LoadLibraryExW);
-
 bool compareVersions(llvm::StringRef A, llvm::StringRef B);
 llvm::SmallVector<std::string, 8> getCandidateBinPaths(llvm::StringRef ExeDir);
-void primeLibraryLoad(llvm::StringRef Path, LoadLibraryExWFn Loader);
 #endif
 
 using namespace llvm;
@@ -32,37 +25,6 @@ cl::opt<bool> Verbose("offload-arch-test-verbose", 
cl::Hidden, cl::init(false));
 
 #ifdef _WIN32
 
-// --- primeLibraryLoad ---
-
-namespace {
-std::wstring CapturedPath;
-HANDLE CapturedFile;
-DWORD CapturedFlags;
-
-HMODULE WINAPI mockLoadLibraryExW(LPCWSTR Path, HANDLE File, DWORD Flags) {
-  CapturedPath = Path;
-  CapturedFile = File;
-  CapturedFlags = Flags;
-  return reinterpret_cast<HMODULE>(1);
-}
-} // namespace
-
-TEST(PrimeLibraryLoad, UsesWindowsBackslashes) {
-  CapturedPath.clear();
-  CapturedFile = reinterpret_cast<HANDLE>(1);
-  CapturedFlags = 0;
-
-  primeLibraryLoad("C:/rocm\\bin/amdhip64_7.dll", mockLoadLibraryExW);
-
-  // The underlying LoadLibraryExW function should be called with backslashes,
-  // not forward slashes to ensure that it can discover and load dependent
-  // DLLs in the same directory.
-  EXPECT_EQ(CapturedPath, L"C:\\rocm\\bin\\amdhip64_7.dll");
-  EXPECT_EQ(CapturedPath.find(L'/'), std::wstring::npos);
-  EXPECT_EQ(CapturedFile, nullptr);
-  EXPECT_EQ(CapturedFlags, LOAD_WITH_ALTERED_SEARCH_PATH);
-}
-
 // --- compareVersions ---
 
 TEST(CompareVersions, HigherVersionWins) {

_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to