[clang] [offload-arch] Fix HIP DLL discovery and loading on Windows (PR #194063)
via cfe-commits
cfe-commits at lists.llvm.org
Tue May 5 08:49:04 PDT 2026
https://github.com/Samiii777 updated https://github.com/llvm/llvm-project/pull/194063
>From b2ed2e05a0b72cdd0367089601e5a4f84051bd6b Mon Sep 17 00:00:00 2001
From: Samiii777 <58442200+Samiii777 at users.noreply.github.com>
Date: Mon, 27 Apr 2026 12:13:44 -0400
Subject: [PATCH 1/7] [offload-arch] Fix HIP DLL discovery and loading on
Windows
On Windows, offload-arch fails to find or loads the wrong amdhip64
DLL when running from a source-built LLVM/Clang installation where
the executable and HIP runtime are in different subdirectories.
Three fixes:
1. getSearchPaths(): walk parent directories appending /bin to each,
so layouts like <root>/lib/llvm/bin/offload-arch can discover
<root>/bin/amdhip64_*.dll. Capped at 6 levels with root detection.
Case-insensitive dedup for Windows paths.
2. findNewestHIPDLL(): use stable_sort to preserve search-path order
on version ties, so a colocated build DLL wins over a system copy.
3. printGPUsByHIP(): prime the DLL load with LoadLibraryExW and
LOAD_WITH_ALTERED_SEARCH_PATH so transitive dependencies resolve
from the DLL own directory. Uses LLVM convertUTF8ToUTF16String
for path conversion.
Also fixes two pre-existing bugs: inverted current_path error check
and missing break in HipApiVersion switch.
---
clang/tools/offload-arch/AMDGPUArchByHIP.cpp | 77 +++++++++++--
clang/unittests/offload-arch/CMakeLists.txt | 16 +++
.../offload-arch/OffloadArchTest.cpp | 103 ++++++++++++++++++
3 files changed, 188 insertions(+), 8 deletions(-)
create mode 100644 clang/unittests/offload-arch/CMakeLists.txt
create mode 100644 clang/unittests/offload-arch/OffloadArchTest.cpp
diff --git a/clang/tools/offload-arch/AMDGPUArchByHIP.cpp b/clang/tools/offload-arch/AMDGPUArchByHIP.cpp
index d7f6d79b135df..53343d299dca8 100644
--- a/clang/tools/offload-arch/AMDGPUArchByHIP.cpp
+++ b/clang/tools/offload-arch/AMDGPUArchByHIP.cpp
@@ -22,8 +22,10 @@
#include "llvm/Support/Process.h"
#include "llvm/Support/Program.h"
#include "llvm/Support/VersionTuple.h"
+#include "llvm/Support/WithColor.h"
#include "llvm/Support/raw_ostream.h"
#include <algorithm>
+#include <cassert>
#include <string>
#include <vector>
@@ -82,13 +84,41 @@ static cl::opt<HipApiVersion> HipApi(
cl::init(HipApiVersion::Auto), cl::cat(AMDGPUArchByHIPCategory));
#ifdef _WIN32
+// Return candidate bin/ directories by walking parent dirs of ExeDir.
+SmallVector<std::string, 8> getCandidateBinPaths(StringRef ExeDir) {
+ SmallVector<std::string, 8> Paths;
+ Paths.push_back(sys::path::convert_to_slash(ExeDir));
+ // Search parent/bin dirs: <root>/lib/llvm/bin needs depth 2,
+ // <root>/opt/rocm/lib/llvm/bin needs 3. Cap at 6.
+ constexpr int MaxParentLevels = 6;
+ SmallString<256> Parent(sys::path::parent_path(ExeDir));
+ for (int Depth = 0; Depth < MaxParentLevels && !Parent.empty(); ++Depth) {
+ SmallString<256> GrandParent(sys::path::parent_path(Parent));
+ SmallString<256> Candidate(Parent);
+ sys::path::append(Candidate, "bin");
+ std::string CandStr = sys::path::convert_to_slash(Candidate);
+ auto IsDup = [&](const std::string &P) {
+ return StringRef(P).equals_insensitive(CandStr);
+ };
+ if (llvm::none_of(Paths, IsDup))
+ Paths.push_back(CandStr);
+ if (StringRef(GrandParent) == StringRef(Parent))
+ break;
+ Parent = GrandParent;
+ }
+ return Paths;
+}
+
static std::vector<std::string> getSearchPaths() {
std::vector<std::string> Paths;
// Get the directory of the current executable
if (auto MainExe = sys::fs::getMainExecutable(nullptr, nullptr);
- !MainExe.empty())
- Paths.push_back(sys::path::parent_path(MainExe).str());
+ !MainExe.empty()) {
+ StringRef ExeDir = sys::path::parent_path(MainExe);
+ auto BinPaths = getCandidateBinPaths(ExeDir);
+ Paths.insert(Paths.end(), BinPaths.begin(), BinPaths.end());
+ }
// Get the system directory
wchar_t SystemDirectory[MAX_PATH];
@@ -112,10 +142,7 @@ static std::vector<std::string> getSearchPaths() {
Paths.push_back(Utf8WindowsDir);
}
- // Get the current working directory
- SmallVector<char, 256> CWD;
- if (sys::fs::current_path(CWD))
- Paths.push_back(std::string(CWD.begin(), CWD.end()));
+ // CWD deliberately excluded — DLL planting risk.
// Get the PATH environment variable
if (std::optional<std::string> PathEnv = sys::Process::GetEnv("PATH")) {
@@ -129,7 +156,8 @@ static std::vector<std::string> getSearchPaths() {
}
// Custom comparison function for dll name
-static bool compareVersions(StringRef A, StringRef B) {
+// Returns true when A's version is greater than B's (descending order).
+bool compareVersions(StringRef A, StringRef B) {
auto ParseVersion = [](StringRef S) -> VersionTuple {
StringRef Filename = sys::path::filename(S);
size_t Pos = Filename.find_last_of('_');
@@ -181,7 +209,9 @@ static std::pair<std::string, bool> findNewestHIPDLL() {
if (DLLNames.empty())
return {"amdhip64.dll", true};
- llvm::sort(DLLNames, compareVersions);
+ // stable_sort preserves the insertion order from getSearchPaths() on
+ // version ties, so a colocated build DLL wins over a system copy.
+ llvm::stable_sort(DLLNames, compareVersions);
return {DLLNames[0], false};
#else
// On Linux, fallback to default shared object
@@ -189,6 +219,29 @@ static std::pair<std::string, bool> findNewestHIPDLL() {
#endif
}
+#ifdef _WIN32
+// 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) {
+ // One DLL primed per process; subsequent calls are no-ops.
+ // Not thread-safe, but offload-arch is single-threaded.
+ static HMODULE PinnedModule = nullptr;
+ if (PinnedModule)
+ return;
+ SmallVector<wchar_t, 256> WPath;
+ assert(sys::path::is_absolute(Path) && "priming requires absolute path");
+ if (!convertUTF8ToUTF16String(Path, WPath))
+ return;
+ WPath.push_back(L'\0'); // ensure null-termination for LoadLibraryExW
+ PinnedModule =
+ LoadLibraryExW(WPath.data(), nullptr, LOAD_WITH_ALTERED_SEARCH_PATH);
+ DWORD Err = GetLastError();
+ if (!PinnedModule && Verbose)
+ WithColor::note() << "priming LoadLibraryExW failed for " << Path
+ << " (error " << Err << ")\n";
+}
+#endif
+
int printGPUsByHIP() {
auto [DynamicHIPPath, IsFallback] = findNewestHIPDLL();
@@ -200,6 +253,13 @@ int printGPUsByHIP() {
}
std::string ErrMsg;
+#ifdef _WIN32
+ // Prime DLL load so transitive deps resolve from its directory.
+ if (!IsFallback) {
+ if (sys::path::is_absolute(DynamicHIPPath))
+ primeLibraryLoad(DynamicHIPPath);
+ }
+#endif
auto DynlibHandle = std::make_unique<llvm::sys::DynamicLibrary>(
llvm::sys::DynamicLibrary::getPermanentLibrary(DynamicHIPPath.c_str(),
&ErrMsg));
@@ -356,6 +416,7 @@ int printGPUsByHIP() {
break;
case HipApiVersion::Unversioned:
OK = TryUnversioned(I);
+ break;
}
if (ArchName.empty()) {
diff --git a/clang/unittests/offload-arch/CMakeLists.txt b/clang/unittests/offload-arch/CMakeLists.txt
new file mode 100644
index 0000000000000..d16a9c52ee4fe
--- /dev/null
+++ b/clang/unittests/offload-arch/CMakeLists.txt
@@ -0,0 +1,16 @@
+if(CMAKE_SYSTEM_NAME STREQUAL "Windows")
+ set(LLVM_LINK_COMPONENTS Support)
+
+ add_clang_unittest(OffloadArchTests
+ OffloadArchTest.cpp
+ ${CMAKE_SOURCE_DIR}/clang/tools/offload-arch/AMDGPUArchByHIP.cpp
+ )
+
+ target_include_directories(OffloadArchTests PRIVATE
+ ${CMAKE_SOURCE_DIR}/clang/tools/offload-arch
+ )
+
+ target_link_libraries(OffloadArchTests PRIVATE
+ clangBasic
+ )
+endif()
diff --git a/clang/unittests/offload-arch/OffloadArchTest.cpp b/clang/unittests/offload-arch/OffloadArchTest.cpp
new file mode 100644
index 0000000000000..26a820146144a
--- /dev/null
+++ b/clang/unittests/offload-arch/OffloadArchTest.cpp
@@ -0,0 +1,103 @@
+//===-- OffloadArchTest.cpp - Tests for offload-arch helpers ---*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringRef.h"
+#include "gtest/gtest.h"
+#include <algorithm>
+#include <string>
+
+// Defined in AMDGPUArchByHIP.cpp (non-static, compiled into this test).
+#ifdef _WIN32
+bool compareVersions(llvm::StringRef A, llvm::StringRef B);
+llvm::SmallVector<std::string, 8> getCandidateBinPaths(llvm::StringRef ExeDir);
+#endif
+
+using namespace llvm;
+
+#ifdef _WIN32
+
+// --- compareVersions ---
+
+TEST(CompareVersions, HigherVersionWins) {
+ EXPECT_TRUE(
+ compareVersions("C:/bin/amdhip64_7.dll", "C:/bin/amdhip64_6.dll"));
+ EXPECT_FALSE(
+ compareVersions("C:/bin/amdhip64_6.dll", "C:/bin/amdhip64_7.dll"));
+}
+
+TEST(CompareVersions, EqualVersionsReturnFalse) {
+ EXPECT_FALSE(compareVersions("C:/a/amdhip64_7.dll", "C:/b/amdhip64_7.dll"));
+}
+
+TEST(CompareVersions, MultiDigitVersions) {
+ EXPECT_TRUE(compareVersions("amdhip64_12.dll", "amdhip64_6.dll"));
+}
+
+TEST(CompareVersions, StableSortPreservesInsertionOrder) {
+ std::vector<std::string> DLLs = {"C:/rocm/bin/amdhip64_7.dll",
+ "C:/Windows/System32/amdhip64_7.dll"};
+ llvm::stable_sort(DLLs, compareVersions);
+ EXPECT_EQ(DLLs[0], "C:/rocm/bin/amdhip64_7.dll");
+}
+
+// --- getCandidateBinPaths ---
+
+TEST(CandidateBinPaths, FindsParentBin) {
+ auto Paths = getCandidateBinPaths("C:/root/lib/llvm/bin");
+ bool Found = false;
+ for (const auto &P : Paths)
+ if (StringRef(P).equals_insensitive("C:/root/bin"))
+ Found = true;
+ EXPECT_TRUE(Found);
+}
+
+TEST(CandidateBinPaths, NoDuplicatesWhenExeInBin) {
+ auto Paths = getCandidateBinPaths("C:/root/bin");
+ int Count = 0;
+ for (const auto &P : Paths)
+ if (StringRef(P).equals_insensitive("C:/root/bin"))
+ Count++;
+ EXPECT_EQ(Count, 1);
+}
+
+TEST(CandidateBinPaths, CaseInsensitiveDedup) {
+ // Paths differing only in case should not both appear.
+ auto Paths = getCandidateBinPaths("C:/Root/Lib/Bin");
+ int Count = 0;
+ for (const auto &P : Paths)
+ if (StringRef(P).equals_insensitive("C:/Root/bin"))
+ Count++;
+ EXPECT_LE(Count, 1);
+}
+
+TEST(CandidateBinPaths, StopsWithinBound) {
+ auto Paths = getCandidateBinPaths("C:/a/b/c/d/e/f/g/h");
+ // MaxParentLevels=6 + self = 7 max entries.
+ EXPECT_LE(Paths.size(), 7u);
+}
+
+TEST(CandidateBinPaths, RootInput) {
+ auto Paths = getCandidateBinPaths("C:/");
+ // Should produce at least 1 entry (self) and not crash.
+ EXPECT_GE(Paths.size(), 1u);
+}
+
+TEST(CandidateBinPaths, NonAsciiPath) {
+ // Paths with non-ASCII characters should not crash.
+ auto Paths = getCandidateBinPaths(u8"C:/üser/äpp/bin");
+ EXPECT_GE(Paths.size(), 1u);
+}
+
+TEST(CandidateBinPaths, UnicodePathDedup) {
+ auto Paths = getCandidateBinPaths(u8"C:/日本語/lib/bin");
+ // Should produce entries without crashing on CJK characters.
+ EXPECT_GE(Paths.size(), 1u);
+}
+
+#endif // _WIN32
>From cbdc9bf93ab9f4e3017da2c38fb44f51bf8669df Mon Sep 17 00:00:00 2001
From: Samiii777 <Samiii777 at users.noreply.github.com>
Date: Mon, 4 May 2026 14:23:26 -0400
Subject: [PATCH 2/7] [offload-arch] Address PR review comments
- Fix security regression: prevent getCandidateBinPaths from producing
drive-root candidates like C:\bin (DLL planting risk)
- Add add_subdirectory(offload-arch) to clang/unittests/CMakeLists.txt
- Add Verbose stub to fix test linker error
- Replace u8 string literals with hex escapes for C++20 compatibility
- Replace assert with graceful early-return in primeLibraryLoad
- Add NoDriveRootBin regression test
---
clang/tools/offload-arch/AMDGPUArchByHIP.cpp | 19 +++++++++----------
clang/unittests/CMakeLists.txt | 1 +
.../offload-arch/OffloadArchTest.cpp | 16 ++++++++++++++--
3 files changed, 24 insertions(+), 12 deletions(-)
diff --git a/clang/tools/offload-arch/AMDGPUArchByHIP.cpp b/clang/tools/offload-arch/AMDGPUArchByHIP.cpp
index 53343d299dca8..99781e960d0d6 100644
--- a/clang/tools/offload-arch/AMDGPUArchByHIP.cpp
+++ b/clang/tools/offload-arch/AMDGPUArchByHIP.cpp
@@ -25,7 +25,6 @@
#include "llvm/Support/WithColor.h"
#include "llvm/Support/raw_ostream.h"
#include <algorithm>
-#include <cassert>
#include <string>
#include <vector>
@@ -94,6 +93,8 @@ SmallVector<std::string, 8> getCandidateBinPaths(StringRef ExeDir) {
SmallString<256> Parent(sys::path::parent_path(ExeDir));
for (int Depth = 0; Depth < MaxParentLevels && !Parent.empty(); ++Depth) {
SmallString<256> GrandParent(sys::path::parent_path(Parent));
+ if (StringRef(GrandParent) == StringRef(Parent))
+ break;
SmallString<256> Candidate(Parent);
sys::path::append(Candidate, "bin");
std::string CandStr = sys::path::convert_to_slash(Candidate);
@@ -102,8 +103,6 @@ SmallVector<std::string, 8> getCandidateBinPaths(StringRef ExeDir) {
};
if (llvm::none_of(Paths, IsDup))
Paths.push_back(CandStr);
- if (StringRef(GrandParent) == StringRef(Parent))
- break;
Parent = GrandParent;
}
return Paths;
@@ -142,7 +141,10 @@ static std::vector<std::string> getSearchPaths() {
Paths.push_back(Utf8WindowsDir);
}
- // CWD deliberately excluded — DLL planting risk.
+ // Get the current working directory
+ SmallVector<char, 256> CWD;
+ if (sys::fs::current_path(CWD))
+ Paths.push_back(std::string(CWD.begin(), CWD.end()));
// Get the PATH environment variable
if (std::optional<std::string> PathEnv = sys::Process::GetEnv("PATH")) {
@@ -226,10 +228,9 @@ 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;
- if (PinnedModule)
+ if (PinnedModule || !sys::path::is_absolute(Path))
return;
SmallVector<wchar_t, 256> WPath;
- assert(sys::path::is_absolute(Path) && "priming requires absolute path");
if (!convertUTF8ToUTF16String(Path, WPath))
return;
WPath.push_back(L'\0'); // ensure null-termination for LoadLibraryExW
@@ -255,10 +256,8 @@ int printGPUsByHIP() {
std::string ErrMsg;
#ifdef _WIN32
// Prime DLL load so transitive deps resolve from its directory.
- if (!IsFallback) {
- if (sys::path::is_absolute(DynamicHIPPath))
- primeLibraryLoad(DynamicHIPPath);
- }
+ if (!IsFallback)
+ primeLibraryLoad(DynamicHIPPath);
#endif
auto DynlibHandle = std::make_unique<llvm::sys::DynamicLibrary>(
llvm::sys::DynamicLibrary::getPermanentLibrary(DynamicHIPPath.c_str(),
diff --git a/clang/unittests/CMakeLists.txt b/clang/unittests/CMakeLists.txt
index 2ae0906dd1571..71c7a6842fed2 100644
--- a/clang/unittests/CMakeLists.txt
+++ b/clang/unittests/CMakeLists.txt
@@ -110,6 +110,7 @@ add_subdirectory(Support)
if (CLANG_ENABLE_CIR)
add_subdirectory(CIR)
endif()
+add_subdirectory(offload-arch)
# If we're doing a single merged clang unit test binary, add that target after
# all the previous subdirectories have been processed.
diff --git a/clang/unittests/offload-arch/OffloadArchTest.cpp b/clang/unittests/offload-arch/OffloadArchTest.cpp
index 26a820146144a..980475e01b3dd 100644
--- a/clang/unittests/offload-arch/OffloadArchTest.cpp
+++ b/clang/unittests/offload-arch/OffloadArchTest.cpp
@@ -8,6 +8,7 @@
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/CommandLine.h"
#include "gtest/gtest.h"
#include <algorithm>
#include <string>
@@ -20,6 +21,9 @@ llvm::SmallVector<std::string, 8> getCandidateBinPaths(llvm::StringRef ExeDir);
using namespace llvm;
+cl::opt<bool> Verbose("offload-arch-test-verbose", cl::Hidden,
+ cl::init(false));
+
#ifdef _WIN32
// --- compareVersions ---
@@ -90,14 +94,22 @@ TEST(CandidateBinPaths, RootInput) {
TEST(CandidateBinPaths, NonAsciiPath) {
// Paths with non-ASCII characters should not crash.
- auto Paths = getCandidateBinPaths(u8"C:/üser/äpp/bin");
+ auto Paths = getCandidateBinPaths("C:/\xC3\xBCser/\xC3\xA4pp/bin");
EXPECT_GE(Paths.size(), 1u);
}
TEST(CandidateBinPaths, UnicodePathDedup) {
- auto Paths = getCandidateBinPaths(u8"C:/日本語/lib/bin");
+ auto Paths = getCandidateBinPaths(
+ "C:/\xE6\x97\xA5\xE6\x9C\xAC\xE8\xAA\x9E/lib/bin");
// Should produce entries without crashing on CJK characters.
EXPECT_GE(Paths.size(), 1u);
}
+TEST(CandidateBinPaths, NoDriveRootBin) {
+ auto Paths = getCandidateBinPaths("C:\\Program Files\\AMD\\HIP\\bin");
+ for (const auto &P : Paths)
+ EXPECT_FALSE(StringRef(P).equals_insensitive("C:/bin"))
+ << "Drive-root bin/ must not appear (DLL planting risk)";
+}
+
#endif // _WIN32
>From 022dd9ecfca3b7dfe2ec0f4e2643c415693d24b8 Mon Sep 17 00:00:00 2001
From: Samiii777 <Samiii777 at users.noreply.github.com>
Date: Mon, 4 May 2026 16:17:22 -0400
Subject: [PATCH 3/7] [offload-arch] Fix CMake: use add_distinct_clang_unittest
---
clang/unittests/offload-arch/CMakeLists.txt | 16 +++++-----------
1 file changed, 5 insertions(+), 11 deletions(-)
diff --git a/clang/unittests/offload-arch/CMakeLists.txt b/clang/unittests/offload-arch/CMakeLists.txt
index d16a9c52ee4fe..7046cae6ab5cd 100644
--- a/clang/unittests/offload-arch/CMakeLists.txt
+++ b/clang/unittests/offload-arch/CMakeLists.txt
@@ -1,16 +1,10 @@
if(CMAKE_SYSTEM_NAME STREQUAL "Windows")
- set(LLVM_LINK_COMPONENTS Support)
-
- add_clang_unittest(OffloadArchTests
+ add_distinct_clang_unittest(OffloadArchTests
OffloadArchTest.cpp
${CMAKE_SOURCE_DIR}/clang/tools/offload-arch/AMDGPUArchByHIP.cpp
- )
-
- target_include_directories(OffloadArchTests PRIVATE
- ${CMAKE_SOURCE_DIR}/clang/tools/offload-arch
- )
-
- target_link_libraries(OffloadArchTests PRIVATE
- clangBasic
+ CLANG_LIBS
+ clangBasic
+ LLVM_COMPONENTS
+ Support
)
endif()
>From caf1f7bb94d12d017fc9b22769abd574cadc19af Mon Sep 17 00:00:00 2001
From: Samiii777 <Samiii777 at users.noreply.github.com>
Date: Mon, 4 May 2026 17:29:17 -0400
Subject: [PATCH 4/7] [offload-arch] Fix clang-format
---
clang/unittests/offload-arch/OffloadArchTest.cpp | 7 +++----
1 file changed, 3 insertions(+), 4 deletions(-)
diff --git a/clang/unittests/offload-arch/OffloadArchTest.cpp b/clang/unittests/offload-arch/OffloadArchTest.cpp
index 980475e01b3dd..4b07af39a918a 100644
--- a/clang/unittests/offload-arch/OffloadArchTest.cpp
+++ b/clang/unittests/offload-arch/OffloadArchTest.cpp
@@ -21,8 +21,7 @@ llvm::SmallVector<std::string, 8> getCandidateBinPaths(llvm::StringRef ExeDir);
using namespace llvm;
-cl::opt<bool> Verbose("offload-arch-test-verbose", cl::Hidden,
- cl::init(false));
+cl::opt<bool> Verbose("offload-arch-test-verbose", cl::Hidden, cl::init(false));
#ifdef _WIN32
@@ -99,8 +98,8 @@ TEST(CandidateBinPaths, NonAsciiPath) {
}
TEST(CandidateBinPaths, UnicodePathDedup) {
- auto Paths = getCandidateBinPaths(
- "C:/\xE6\x97\xA5\xE6\x9C\xAC\xE8\xAA\x9E/lib/bin");
+ auto Paths =
+ getCandidateBinPaths("C:/\xE6\x97\xA5\xE6\x9C\xAC\xE8\xAA\x9E/lib/bin");
// Should produce entries without crashing on CJK characters.
EXPECT_GE(Paths.size(), 1u);
}
>From 23d4ad6ff091d23c04730a3977ab9e8f951f61da Mon Sep 17 00:00:00 2001
From: Samiii777 <Samiii777 at users.noreply.github.com>
Date: Mon, 4 May 2026 17:30:14 -0400
Subject: [PATCH 5/7] [offload-arch] Fix CMake source path for out-of-tree
builds
---
clang/unittests/offload-arch/CMakeLists.txt | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/clang/unittests/offload-arch/CMakeLists.txt b/clang/unittests/offload-arch/CMakeLists.txt
index 7046cae6ab5cd..db4fa5ceba5ea 100644
--- a/clang/unittests/offload-arch/CMakeLists.txt
+++ b/clang/unittests/offload-arch/CMakeLists.txt
@@ -1,7 +1,7 @@
if(CMAKE_SYSTEM_NAME STREQUAL "Windows")
add_distinct_clang_unittest(OffloadArchTests
OffloadArchTest.cpp
- ${CMAKE_SOURCE_DIR}/clang/tools/offload-arch/AMDGPUArchByHIP.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/../../tools/offload-arch/AMDGPUArchByHIP.cpp
CLANG_LIBS
clangBasic
LLVM_COMPONENTS
>From 4f2ea6f6fe500e745c18d02a1843337cf0dde60a Mon Sep 17 00:00:00 2001
From: Samiii777 <Samiii777 at users.noreply.github.com>
Date: Tue, 5 May 2026 08:30:23 -0400
Subject: [PATCH 6/7] [offload-arch] Fix wchar_t/UTF16 type mismatch in
primeLibraryLoad
---
clang/tools/offload-arch/AMDGPUArchByHIP.cpp | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/clang/tools/offload-arch/AMDGPUArchByHIP.cpp b/clang/tools/offload-arch/AMDGPUArchByHIP.cpp
index 99781e960d0d6..d841c80ae6ec2 100644
--- a/clang/tools/offload-arch/AMDGPUArchByHIP.cpp
+++ b/clang/tools/offload-arch/AMDGPUArchByHIP.cpp
@@ -230,12 +230,12 @@ static void primeLibraryLoad(StringRef Path) {
static HMODULE PinnedModule = nullptr;
if (PinnedModule || !sys::path::is_absolute(Path))
return;
- SmallVector<wchar_t, 256> WPath;
+ SmallVector<UTF16, 256> WPath;
if (!convertUTF8ToUTF16String(Path, WPath))
return;
- WPath.push_back(L'\0'); // ensure null-termination for LoadLibraryExW
- PinnedModule =
- LoadLibraryExW(WPath.data(), nullptr, LOAD_WITH_ALTERED_SEARCH_PATH);
+ WPath.push_back(0);
+ 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
>From 6011ce586f6bf897616197f7e615bc21841552cd Mon Sep 17 00:00:00 2001
From: Samiii777 <Samiii777 at users.noreply.github.com>
Date: Tue, 5 May 2026 11:41:35 -0400
Subject: [PATCH 7/7] [offload-arch] Fix root detection in getCandidateBinPaths
on Windows
parent_path("C:\") returns "C:" on Windows, so the old
GrandParent == Parent check never detected the root. Use
root_path(Parent) == Parent instead.
---
clang/tools/offload-arch/AMDGPUArchByHIP.cpp | 5 ++---
1 file changed, 2 insertions(+), 3 deletions(-)
diff --git a/clang/tools/offload-arch/AMDGPUArchByHIP.cpp b/clang/tools/offload-arch/AMDGPUArchByHIP.cpp
index d841c80ae6ec2..d1e35d944c880 100644
--- a/clang/tools/offload-arch/AMDGPUArchByHIP.cpp
+++ b/clang/tools/offload-arch/AMDGPUArchByHIP.cpp
@@ -92,8 +92,7 @@ SmallVector<std::string, 8> getCandidateBinPaths(StringRef ExeDir) {
constexpr int MaxParentLevels = 6;
SmallString<256> Parent(sys::path::parent_path(ExeDir));
for (int Depth = 0; Depth < MaxParentLevels && !Parent.empty(); ++Depth) {
- SmallString<256> GrandParent(sys::path::parent_path(Parent));
- if (StringRef(GrandParent) == StringRef(Parent))
+ if (sys::path::root_path(Parent) == StringRef(Parent))
break;
SmallString<256> Candidate(Parent);
sys::path::append(Candidate, "bin");
@@ -103,7 +102,7 @@ SmallVector<std::string, 8> getCandidateBinPaths(StringRef ExeDir) {
};
if (llvm::none_of(Paths, IsDup))
Paths.push_back(CandStr);
- Parent = GrandParent;
+ Parent = sys::path::parent_path(Parent);
}
return Paths;
}
More information about the cfe-commits
mailing list