Skip to content

Commit f969694

Browse files
authored
[ClangLinkerWrapper] Refactor target ID sanitization for Windows file… (#168744)
… names Fix non-RDC mode HIP compilation for the new driver on Windows due to invalid temporary file names when offload arch is a target ID containing ':', which is invalid in file names on Windows. Refactor the existing handling of ':' in file names on Windows from clang driver into a shared function sanitizeTargetIDInFileName in clang/Basic/TargetID.h. This function replaces ':' with '@' on Windows only, preserving the original behavior. Update both clang/lib/Driver/Driver.cpp and clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp to use this shared function, ensuring consistent handling across both tools.
1 parent def8ecb commit f969694

File tree

5 files changed

+44
-17
lines changed

5 files changed

+44
-17
lines changed

clang/include/clang/Basic/TargetID.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,11 @@ getConflictTargetIDCombination(const std::set<llvm::StringRef> &TargetIDs);
5656
/// Check whether the provided target ID is compatible with the requested
5757
/// target ID.
5858
bool isCompatibleTargetID(llvm::StringRef Provided, llvm::StringRef Requested);
59+
60+
/// Sanitize a target ID string for use in a file name.
61+
/// Replaces invalid characters (like ':') with safe characters (like '@').
62+
/// Currently only replaces ':' with '@' on Windows.
63+
std::string sanitizeTargetIDInFileName(llvm::StringRef TargetID);
5964
} // namespace clang
6065

6166
#endif

clang/lib/Basic/TargetID.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,13 @@
99
#include "clang/Basic/TargetID.h"
1010
#include "llvm/ADT/STLExtras.h"
1111
#include "llvm/ADT/SmallSet.h"
12+
#include "llvm/ADT/SmallVector.h"
13+
#include "llvm/Support/Path.h"
1214
#include "llvm/TargetParser/TargetParser.h"
1315
#include "llvm/TargetParser/Triple.h"
1416
#include <map>
1517
#include <optional>
18+
#include <string>
1619

1720
namespace clang {
1821

@@ -183,4 +186,11 @@ bool isCompatibleTargetID(llvm::StringRef Provided, llvm::StringRef Requested) {
183186
return true;
184187
}
185188

189+
std::string sanitizeTargetIDInFileName(llvm::StringRef TargetID) {
190+
std::string FileName = TargetID.str();
191+
if (llvm::sys::path::is_style_windows(llvm::sys::path::Style::native))
192+
llvm::replace(FileName, ':', '@');
193+
return FileName;
194+
}
195+
186196
} // namespace clang

clang/lib/Driver/Driver.cpp

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6285,12 +6285,7 @@ const char *Driver::GetNamedOutputPath(Compilation &C, const JobAction &JA,
62856285
StringRef OrigBoundArch, bool AtTopLevel,
62866286
bool MultipleArchs,
62876287
StringRef OffloadingPrefix) const {
6288-
std::string BoundArch = OrigBoundArch.str();
6289-
if (is_style_windows(llvm::sys::path::Style::native)) {
6290-
// BoundArch may contains ':', which is invalid in file names on Windows,
6291-
// therefore replace it with '%'.
6292-
llvm::replace(BoundArch, ':', '@');
6293-
}
6288+
std::string BoundArch = sanitizeTargetIDInFileName(OrigBoundArch);
62946289

62956290
llvm::PrettyStackTraceString CrashInfo("Computing output path");
62966291
// Output to a user requested destination?
Lines changed: 24 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
// UNSUPPORTED: system-windows
21
// REQUIRES: amdgpu-registered-target
32
// REQUIRES: lld
43

@@ -11,31 +10,48 @@ __attribute__((visibility("protected"), used)) int x;
1110
// Create device binaries and package them
1211
// RUN: %clang -cc1 %s -triple amdgcn-amd-amdhsa -emit-llvm-bc -o %t.amdgpu.bc
1312
// RUN: llvm-offload-binary -o %t.out \
14-
// RUN: --image=file=%t.amdgpu.bc,kind=hip,triple=amdgcn-amd-amdhsa,arch=gfx1100 \
13+
// RUN: --image=file=%t.amdgpu.bc,kind=hip,triple=amdgcn-amd-amdhsa,arch=gfx9-4-generic:xnack+ \
1514
// RUN: --image=file=%t.amdgpu.bc,kind=hip,triple=amdgcn-amd-amdhsa,arch=gfx1200
1615

1716
// Test that linker wrapper outputs .hipfb file without -r option for HIP non-RDC
1817
// The linker wrapper is called directly with the packaged device binary (not embedded in host object)
1918
// Note: When called directly (not through the driver), the linker wrapper processes architectures
2019
// from the packaged binary. The test verifies it can process at least one architecture correctly.
21-
// RUN: clang-linker-wrapper --emit-fatbin-only --linker-path=/usr/bin/ld %t.out -o %t.hipfb 2>&1
20+
// RUN: %if system-windows %{ \
21+
// RUN: clang-linker-wrapper --wrapper-verbose --device-linker=amdgcn-amd-amdhsa=-v --device-compiler=-v --emit-fatbin-only --linker-path=/usr/bin/ld %t.out -o %t.hipfb 2>&1 | FileCheck %s --check-prefix=CMD-WIN \
22+
// RUN: %} %else %{ \
23+
// RUN: clang-linker-wrapper --wrapper-verbose --device-linker=amdgcn-amd-amdhsa=-v --device-compiler=-v --emit-fatbin-only --linker-path=/usr/bin/ld %t.out -o %t.hipfb 2>&1 | FileCheck %s --check-prefix=CMD-LINUX \
24+
// RUN: %}
25+
26+
// On Linux, ':' is preserved in file names
27+
// CMD-LINUX-DAG: clang{{.*}} -o {{.*}}hipfb.amdgcn.gfx9-4-generic:xnack+{{.*}}.img
28+
// CMD-LINUX-DAG: clang{{.*}} -o {{.*}}hipfb.amdgcn.gfx1200{{.*}}.img
29+
// CMD-LINUX-DAG: ld.lld{{.*}} -o {{.*}}hipfb.amdgcn.gfx9-4-generic:xnack+{{.*}}.img
30+
// CMD-LINUX-DAG: ld.lld{{.*}} -o {{.*}}hipfb.amdgcn.gfx1200{{.*}}.img
31+
32+
// On Windows, ':' is replaced with '@' in file names
33+
// CMD-WIN-DAG: clang{{.*}} -o {{.*}}hipfb.amdgcn.gfx9-4-generic@xnack+{{.*}}.img
34+
// CMD-WIN-DAG: clang{{.*}} -o {{.*}}hipfb.amdgcn.gfx1200{{.*}}.img
35+
// CMD-WIN-DAG: ld.lld{{.*}} -o {{.*}}hipfb.amdgcn.gfx9-4-generic@xnack+{{.*}}.img
36+
// CMD-WIN-DAG: ld.lld{{.*}} -o {{.*}}hipfb.amdgcn.gfx1200{{.*}}.img
2237

2338
// Verify the fat binary was created
2439
// RUN: test -f %t.hipfb
2540

2641
// List code objects in the fat binary
2742
// RUN: clang-offload-bundler -type=o -input=%t.hipfb -list | FileCheck %s --check-prefix=HIP-FATBIN-LIST
2843

29-
// HIP-FATBIN-LIST-DAG: hip-amdgcn-amd-amdhsa--gfx1100
44+
// HIP-FATBIN-LIST-DAG: hip-amdgcn-amd-amdhsa--gfx9-4-generic:xnack+
3045
// HIP-FATBIN-LIST-DAG: hip-amdgcn-amd-amdhsa--gfx1200
3146
// HIP-FATBIN-LIST-DAG: host-x86_64-unknown-linux-gnu-
3247

3348
// Extract code objects for both architectures from the fat binary
34-
// RUN: clang-offload-bundler -type=o -targets=hip-amdgcn-amd-amdhsa--gfx1100,hip-amdgcn-amd-amdhsa--gfx1200 \
35-
// RUN: -output=%t.gfx1100.co -output=%t.gfx1200.co -input=%t.hipfb -unbundle
49+
// Use '-' instead of ':' in file names to avoid issues on Windows
50+
// RUN: clang-offload-bundler -type=o -targets=hip-amdgcn-amd-amdhsa--gfx9-4-generic:xnack+,hip-amdgcn-amd-amdhsa--gfx1200 \
51+
// RUN: -output=%t.gfx9-4-generic-xnack+.co -output=%t.gfx1200.co -input=%t.hipfb -unbundle
3652

3753
// Verify extracted code objects exist and are not empty
38-
// RUN: test -f %t.gfx1100.co
39-
// RUN: test -s %t.gfx1100.co
54+
// RUN: test -f %t.gfx9-4-generic-xnack+.co
55+
// RUN: test -s %t.gfx9-4-generic-xnack+.co
4056
// RUN: test -f %t.gfx1200.co
4157
// RUN: test -s %t.gfx1200.co

clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -228,11 +228,13 @@ std::string getMainExecutable(const char *Name) {
228228
Expected<StringRef> createOutputFile(const Twine &Prefix, StringRef Extension) {
229229
std::scoped_lock<decltype(TempFilesMutex)> Lock(TempFilesMutex);
230230
SmallString<128> OutputFile;
231+
std::string PrefixStr = clang::sanitizeTargetIDInFileName(Prefix.str());
232+
231233
if (SaveTemps) {
232-
(Prefix + "." + Extension).toNullTerminatedStringRef(OutputFile);
234+
(PrefixStr + "." + Extension).toNullTerminatedStringRef(OutputFile);
233235
} else {
234236
if (std::error_code EC =
235-
sys::fs::createTemporaryFile(Prefix, Extension, OutputFile))
237+
sys::fs::createTemporaryFile(PrefixStr, Extension, OutputFile))
236238
return createFileError(OutputFile, EC);
237239
}
238240

@@ -625,7 +627,6 @@ Expected<StringRef> writeOffloadFile(const OffloadFile &File) {
625627
SmallString<128> Filename;
626628
(Prefix + "-" + Binary.getTriple() + "-" + Binary.getArch())
627629
.toVector(Filename);
628-
llvm::replace(Filename, ':', '-');
629630
auto TempFileOrErr = createOutputFile(Filename, "o");
630631
if (!TempFileOrErr)
631632
return TempFileOrErr.takeError();

0 commit comments

Comments
 (0)