https://github.com/bader updated https://github.com/llvm/llvm-project/pull/200096
>From 1e79dde1493ea29e293d576e9861c501ef77a775 Mon Sep 17 00:00:00 2001 From: Alexey Bader <[email protected]> Date: Wed, 27 May 2026 10:26:39 -0700 Subject: [PATCH 1/4] [clang-sycl-linker] Fix --version exit code and empty-input error - --version now returns EXIT_SUCCESS immediately after printing; previously it fell through into the rest of main. - Report an error early when no input files are provided rather than hitting the assert inside linkDeviceCode. Co-Authored-By: Claude Sonnet 4.6 <[email protected]> --- .../OffloadTools/clang-sycl-linker/options.ll | 40 +++++++++++++++++++ .../clang-sycl-linker/ClangSYCLLinker.cpp | 7 +++- 2 files changed, 46 insertions(+), 1 deletion(-) create mode 100644 clang/test/OffloadTools/clang-sycl-linker/options.ll diff --git a/clang/test/OffloadTools/clang-sycl-linker/options.ll b/clang/test/OffloadTools/clang-sycl-linker/options.ll new file mode 100644 index 0000000000000..55b691187028f --- /dev/null +++ b/clang/test/OffloadTools/clang-sycl-linker/options.ll @@ -0,0 +1,40 @@ +; Tests non-functional command line options of the clang-sycl-linker tool. +; +; REQUIRES: spirv-registered-target +; +; Test --help +; RUN: clang-sycl-linker --help | FileCheck %s --check-prefix=HELP +; HELP: OVERVIEW: A utility that wraps around several steps required to link SYCL device files. +; HELP: USAGE: clang-sycl-linker +; HELP: OPTIONS: +; +; Test --version +; RUN: clang-sycl-linker --version | FileCheck %s --check-prefix=VERSION +; VERSION: clang-sycl-linker version +; +; Test missing input files +; RUN: not clang-sycl-linker --dry-run -triple=spirv64 -o %t.out 2>&1 | FileCheck %s --check-prefix=NO-INPUT +; NO-INPUT: No input files provided +; +; Create a simple bitcode file for subsequent tests +; RUN: llvm-as %s -o %t.bc +; +; Test --print-linked-module +; RUN: clang-sycl-linker --dry-run -triple=spirv64 %t.bc --print-linked-module -o %t.out > %t.ll +; RUN: FileCheck %s --check-prefix=PRINT-LINKED < %t.ll +; PRINT-LINKED: target triple = "spirv64" +; +; Test --save-temps +; RUN: rm -rf %t.dir && mkdir -p %t.dir +; RUN: cd %t.dir && clang-sycl-linker --dry-run -triple=spirv64 %t.bc --save-temps -o out.spv +; RUN: ls %t.dir/out.spv-*.bc | count 1 +; +; Test --spirv-dump-device-code (should parse without error) +; RUN: clang-sycl-linker --dry-run -triple=spirv64 %t.bc --spirv-dump-device-code=%t.dir -o %t.out +; +; Test --spirv-dump-device-code with no value (fallback to ./) +; RUN: clang-sycl-linker --dry-run -triple=spirv64 %t.bc --spirv-dump-device-code= -o %t.out + +target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-n8:16:32:64-G1" +target triple = "spirv64" + diff --git a/clang/tools/clang-sycl-linker/ClangSYCLLinker.cpp b/clang/tools/clang-sycl-linker/ClangSYCLLinker.cpp index 88a09d0a3ecc7..0d83c93065e3f 100644 --- a/clang/tools/clang-sycl-linker/ClangSYCLLinker.cpp +++ b/clang/tools/clang-sycl-linker/ClangSYCLLinker.cpp @@ -786,8 +786,10 @@ int main(int argc, char **argv) { return EXIT_SUCCESS; } - if (Args.hasArg(OPT_version)) + if (Args.hasArg(OPT_version)) { printVersion(outs()); + return EXIT_SUCCESS; + } Verbose = Args.hasArg(OPT_verbose); DryRun = Args.hasArg(OPT_dry_run); @@ -812,6 +814,9 @@ int main(int argc, char **argv) { if (!FilesOrErr) reportError(FilesOrErr.takeError()); + if (FilesOrErr->empty()) + reportError(createStringError("No input files provided")); + // Run SYCL linking process on the generated inputs. if (Error Err = runSYCLLink(*FilesOrErr, Args)) reportError(std::move(Err)); >From 288b27251a5d80cb9dc152a22daaed7189904166 Mon Sep 17 00:00:00 2001 From: Alexey Bader <[email protected]> Date: Thu, 28 May 2026 16:06:56 -0700 Subject: [PATCH 2/4] [clang-sycl-linker] Implement --spirv-dump-device-code and fix tests Implement the previously unfinished --spirv-dump-device-code option by copying each generated .spv file into the requested directory after code generation; SPIRVDumpDir was set but never consumed before this change. Fix the options.ll tests: drop --dry-run (tests now exercise real code paths), verify that dump/save-temps output files actually exist, and isolate each test into its own subdirectory to prevent interference. Co-Authored-By: Claude Sonnet 4.6 <[email protected]> --- .../OffloadTools/clang-sycl-linker/options.ll | 21 ++++++++++++------- .../clang-sycl-linker/ClangSYCLLinker.cpp | 7 +++++++ 2 files changed, 20 insertions(+), 8 deletions(-) diff --git a/clang/test/OffloadTools/clang-sycl-linker/options.ll b/clang/test/OffloadTools/clang-sycl-linker/options.ll index 55b691187028f..c3712c927624d 100644 --- a/clang/test/OffloadTools/clang-sycl-linker/options.ll +++ b/clang/test/OffloadTools/clang-sycl-linker/options.ll @@ -13,27 +13,32 @@ ; VERSION: clang-sycl-linker version ; ; Test missing input files -; RUN: not clang-sycl-linker --dry-run -triple=spirv64 -o %t.out 2>&1 | FileCheck %s --check-prefix=NO-INPUT +; RUN: not clang-sycl-linker -triple=spirv64 -o %t.out 2>&1 | FileCheck %s --check-prefix=NO-INPUT ; NO-INPUT: No input files provided ; ; Create a simple bitcode file for subsequent tests ; RUN: llvm-as %s -o %t.bc ; ; Test --print-linked-module -; RUN: clang-sycl-linker --dry-run -triple=spirv64 %t.bc --print-linked-module -o %t.out > %t.ll +; RUN: clang-sycl-linker -triple=spirv64 %t.bc --print-linked-module -o %t.out > %t.ll ; RUN: FileCheck %s --check-prefix=PRINT-LINKED < %t.ll ; PRINT-LINKED: target triple = "spirv64" ; -; Test --save-temps ; RUN: rm -rf %t.dir && mkdir -p %t.dir -; RUN: cd %t.dir && clang-sycl-linker --dry-run -triple=spirv64 %t.bc --save-temps -o out.spv -; RUN: ls %t.dir/out.spv-*.bc | count 1 ; -; Test --spirv-dump-device-code (should parse without error) -; RUN: clang-sycl-linker --dry-run -triple=spirv64 %t.bc --spirv-dump-device-code=%t.dir -o %t.out +; Test --spirv-dump-device-code (copies SPIR-V output to given directory) +; RUN: clang-sycl-linker -triple=spirv64 %t.bc --spirv-dump-device-code=%t.dir -o out.spv +; RUN: ls %t.dir/out_0.spv | count 1 ; ; Test --spirv-dump-device-code with no value (fallback to ./) -; RUN: clang-sycl-linker --dry-run -triple=spirv64 %t.bc --spirv-dump-device-code= -o %t.out +; RUN: mkdir -p %t.dir/fallback +; RUN: cd %t.dir/fallback && clang-sycl-linker -triple=spirv64 %t.bc --spirv-dump-device-code= -o out.spv +; RUN: ls %t.dir/fallback/out_0.spv | count 1 +; +; Test --save-temps (keeps intermediate .bc files in current directory) +; RUN: mkdir -p %t.dir/save-temps +; RUN: cd %t.dir/save-temps && clang-sycl-linker -triple=spirv64 %t.bc --save-temps -o out.spv +; RUN: ls %t.dir/save-temps/out.spv-*.bc | count 1 target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-n8:16:32:64-G1" target triple = "spirv64" diff --git a/clang/tools/clang-sycl-linker/ClangSYCLLinker.cpp b/clang/tools/clang-sycl-linker/ClangSYCLLinker.cpp index 0d83c93065e3f..c2080a5468529 100644 --- a/clang/tools/clang-sycl-linker/ClangSYCLLinker.cpp +++ b/clang/tools/clang-sycl-linker/ClangSYCLLinker.cpp @@ -712,6 +712,13 @@ Error runSYCLLink(ArrayRef<std::string> Files, const ArgList &Args) { Result.TargetTriple, Args, CodeGenFile, C)) return Err; + if (!SPIRVDumpDir.empty()) { + SmallString<256> DumpFile(SPIRVDumpDir); + sys::path::append(DumpFile, sys::path::filename(CodeGenFile)); + if (std::error_code EC = sys::fs::copy_file(CodeGenFile, DumpFile)) + return createFileError(DumpFile, EC); + } + SplitModules[I].ModuleFilePath = CodeGenFile; if (IsAOTCompileNeeded) { std::string AOTFile = (Stem + "_" + Twine(I) + ".out").str(); >From 33d53947a856e336d6bbbb23e781f5386563e7bc Mon Sep 17 00:00:00 2001 From: Alexey Bader <[email protected]> Date: Thu, 28 May 2026 16:32:56 -0700 Subject: [PATCH 3/4] [clang-sycl-linker] Address review feedback - Create the SPIR-V dump directory up-front so users get a clear error instead of a low-level copy failure when the path doesn't exist. - Move the empty-input check into getInput so main has a single error path. - Drop -triple=spirv64 from the options test (the IR module already sets the triple) and unify SmallString sizing for the dump path. Co-Authored-By: Claude Opus 4.7 <[email protected]> --- .../OffloadTools/clang-sycl-linker/options.ll | 15 ++++++++------- clang/tools/clang-sycl-linker/ClangSYCLLinker.cpp | 11 +++++++---- 2 files changed, 15 insertions(+), 11 deletions(-) diff --git a/clang/test/OffloadTools/clang-sycl-linker/options.ll b/clang/test/OffloadTools/clang-sycl-linker/options.ll index c3712c927624d..b57a1b0515fa1 100644 --- a/clang/test/OffloadTools/clang-sycl-linker/options.ll +++ b/clang/test/OffloadTools/clang-sycl-linker/options.ll @@ -13,31 +13,32 @@ ; VERSION: clang-sycl-linker version ; ; Test missing input files -; RUN: not clang-sycl-linker -triple=spirv64 -o %t.out 2>&1 | FileCheck %s --check-prefix=NO-INPUT +; RUN: not clang-sycl-linker -o %t.out 2>&1 | FileCheck %s --check-prefix=NO-INPUT ; NO-INPUT: No input files provided ; ; Create a simple bitcode file for subsequent tests ; RUN: llvm-as %s -o %t.bc ; ; Test --print-linked-module -; RUN: clang-sycl-linker -triple=spirv64 %t.bc --print-linked-module -o %t.out > %t.ll +; RUN: clang-sycl-linker %t.bc --print-linked-module -o %t.out > %t.ll ; RUN: FileCheck %s --check-prefix=PRINT-LINKED < %t.ll ; PRINT-LINKED: target triple = "spirv64" ; ; RUN: rm -rf %t.dir && mkdir -p %t.dir ; -; Test --spirv-dump-device-code (copies SPIR-V output to given directory) -; RUN: clang-sycl-linker -triple=spirv64 %t.bc --spirv-dump-device-code=%t.dir -o out.spv -; RUN: ls %t.dir/out_0.spv | count 1 +; Test --spirv-dump-device-code (creates the directory if missing and copies +; SPIR-V output into it) +; RUN: clang-sycl-linker %t.bc --spirv-dump-device-code=%t.dir/nested -o out.spv +; RUN: ls %t.dir/nested/out_0.spv | count 1 ; ; Test --spirv-dump-device-code with no value (fallback to ./) ; RUN: mkdir -p %t.dir/fallback -; RUN: cd %t.dir/fallback && clang-sycl-linker -triple=spirv64 %t.bc --spirv-dump-device-code= -o out.spv +; RUN: cd %t.dir/fallback && clang-sycl-linker %t.bc --spirv-dump-device-code= -o out.spv ; RUN: ls %t.dir/fallback/out_0.spv | count 1 ; ; Test --save-temps (keeps intermediate .bc files in current directory) ; RUN: mkdir -p %t.dir/save-temps -; RUN: cd %t.dir/save-temps && clang-sycl-linker -triple=spirv64 %t.bc --save-temps -o out.spv +; RUN: cd %t.dir/save-temps && clang-sycl-linker %t.bc --save-temps -o out.spv ; RUN: ls %t.dir/save-temps/out.spv-*.bc | count 1 target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-n8:16:32:64-G1" diff --git a/clang/tools/clang-sycl-linker/ClangSYCLLinker.cpp b/clang/tools/clang-sycl-linker/ClangSYCLLinker.cpp index c2080a5468529..66ac47cd4b2ac 100644 --- a/clang/tools/clang-sycl-linker/ClangSYCLLinker.cpp +++ b/clang/tools/clang-sycl-linker/ClangSYCLLinker.cpp @@ -200,6 +200,8 @@ Expected<SmallVector<std::string>> getInput(const ArgList &Args) { return createStringError("Unsupported file type"); BitcodeFiles.push_back(*Filename); } + if (BitcodeFiles.empty()) + return createStringError("No input files provided"); return BitcodeFiles; } @@ -713,7 +715,7 @@ Error runSYCLLink(ArrayRef<std::string> Files, const ArgList &Args) { return Err; if (!SPIRVDumpDir.empty()) { - SmallString<256> DumpFile(SPIRVDumpDir); + SmallString<128> DumpFile(SPIRVDumpDir); sys::path::append(DumpFile, sys::path::filename(CodeGenFile)); if (std::error_code EC = sys::fs::copy_file(CodeGenFile, DumpFile)) return createFileError(DumpFile, EC); @@ -813,6 +815,10 @@ int main(int argc, char **argv) { else Dir.append(llvm::sys::path::get_separator()); + if (std::error_code EC = sys::fs::create_directories(Dir)) + reportError(createStringError( + EC, "cannot create SPIR-V dump directory '" + Dir + "'")); + SPIRVDumpDir = Dir; } @@ -821,9 +827,6 @@ int main(int argc, char **argv) { if (!FilesOrErr) reportError(FilesOrErr.takeError()); - if (FilesOrErr->empty()) - reportError(createStringError("No input files provided")); - // Run SYCL linking process on the generated inputs. if (Error Err = runSYCLLink(*FilesOrErr, Args)) reportError(std::move(Err)); >From fa99331e07a73ecd1e1ff1dc8c4c22c1023d3a99 Mon Sep 17 00:00:00 2001 From: Alexey Bader <[email protected]> Date: Thu, 28 May 2026 16:47:05 -0700 Subject: [PATCH 4/4] Simplify the code. --- .../tools/clang-sycl-linker/ClangSYCLLinker.cpp | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) diff --git a/clang/tools/clang-sycl-linker/ClangSYCLLinker.cpp b/clang/tools/clang-sycl-linker/ClangSYCLLinker.cpp index 66ac47cd4b2ac..a535b68e4f997 100644 --- a/clang/tools/clang-sycl-linker/ClangSYCLLinker.cpp +++ b/clang/tools/clang-sycl-linker/ClangSYCLLinker.cpp @@ -807,19 +807,12 @@ int main(int argc, char **argv) { reportError(createStringError("Output file must be specified")); OutputFile = Args.getLastArgValue(OPT_o); - if (Args.hasArg(OPT_spirv_dump_device_code_EQ)) { - Arg *A = Args.getLastArg(OPT_spirv_dump_device_code_EQ); - SmallString<128> Dir(A->getValue()); - if (Dir.empty()) - llvm::sys::path::native(Dir = "./"); - else - Dir.append(llvm::sys::path::get_separator()); - - if (std::error_code EC = sys::fs::create_directories(Dir)) + if (auto *A = Args.getLastArg(OPT_spirv_dump_device_code_EQ)) { + StringRef V = A->getValue(); + SPIRVDumpDir = V.empty() ? "." : V; + if (std::error_code EC = sys::fs::create_directories(SPIRVDumpDir)) reportError(createStringError( - EC, "cannot create SPIR-V dump directory '" + Dir + "'")); - - SPIRVDumpDir = Dir; + EC, "cannot create SPIR-V dump directory '" + SPIRVDumpDir + "'")); } // Get the input files to pass to the linking stage. _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
