https://github.com/Samiii777 updated https://github.com/llvm/llvm-project/pull/194063
>From b2ed2e05a0b72cdd0367089601e5a4f84051bd6b Mon Sep 17 00:00:00 2001 From: Samiii777 <[email protected]> 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 <[email protected]> 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 <[email protected]> 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 <[email protected]> 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 <[email protected]> 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 <[email protected]> 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 <[email protected]> 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; } _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
