Author: Joseph Huber Date: 2026-09-13T07:41:14-05:00 New Revision: d283a555109576cd92b35a88b4d110166043fb77
URL: https://github.com/llvm/llvm-project/commit/d283a555109576cd92b35a88b4d110166043fb77 DIFF: https://github.com/llvm/llvm-project/commit/d283a555109576cd92b35a88b4d110166043fb77.diff LOG: [clang-nvlink-wrapper] Fix response file handling for the nvlink wrapper (#220249) Summary: Response files were not handled correctly because the copied support used the `nvlink` argument which is not supported by the argument parser. Pass to the nvlink wrapper using the canonical format and then reconstruct it when we execute the sub jobs Fixes: https://github.com/llvm/llvm-project/issues/219914 Added: Modified: clang/lib/Driver/ToolChains/Cuda.cpp clang/test/OffloadTools/clang-nvlink-wrapper/nvlink-wrapper.c clang/tools/clang-nvlink-wrapper/ClangNVLinkWrapper.cpp Removed: ################################################################################ diff --git a/clang/lib/Driver/ToolChains/Cuda.cpp b/clang/lib/Driver/ToolChains/Cuda.cpp index 08a06c175d8ec..54bc9b3f65e27 100644 --- a/clang/lib/Driver/ToolChains/Cuda.cpp +++ b/clang/lib/Driver/ToolChains/Cuda.cpp @@ -519,7 +519,7 @@ void NVPTX::Assembler::ConstructJob(Compilation &C, const JobAction &JA, C.addCommand(std::make_unique<Command>( JA, *this, ResponseFileSupport{ResponseFileSupport::RF_Full, llvm::sys::WEM_UTF8, - "--options-file"}, + "--options-file="}, Exec, CmdArgs, Inputs, Output)); } @@ -586,7 +586,7 @@ void NVPTX::FatBinary::ConstructJob(Compilation &C, const JobAction &JA, C.addCommand(std::make_unique<Command>( JA, *this, ResponseFileSupport{ResponseFileSupport::RF_Full, llvm::sys::WEM_UTF8, - "--options-file"}, + "--options-file="}, Exec, CmdArgs, Inputs, Output)); } @@ -684,9 +684,7 @@ void NVPTX::Linker::ConstructJob(Compilation &C, const JobAction &JA, } C.addCommand(std::make_unique<Command>( - JA, *this, - ResponseFileSupport{ResponseFileSupport::RF_Full, llvm::sys::WEM_UTF8, - "--options-file"}, + JA, *this, ResponseFileSupport::AtFileUTF8(), Args.MakeArgString(getToolChain().GetProgramPath("clang-nvlink-wrapper")), CmdArgs, Inputs, Output)); } diff --git a/clang/test/OffloadTools/clang-nvlink-wrapper/nvlink-wrapper.c b/clang/test/OffloadTools/clang-nvlink-wrapper/nvlink-wrapper.c index e5de6260ae61c..0aa6e8fc72349 100644 --- a/clang/test/OffloadTools/clang-nvlink-wrapper/nvlink-wrapper.c +++ b/clang/test/OffloadTools/clang-nvlink-wrapper/nvlink-wrapper.c @@ -46,6 +46,17 @@ int baz() { return y + x; } // RUN: | FileCheck %s --check-prefix=ARGS // ARGS: nvlink{{.*}} -arch sm_52 -foo -o a.out [[INPUT:.+]].cubin +// +// Check that GNU response files are expanded to nvlink. +// +// RUN: echo '-arch sm_52 %t-u.o -o a.out' > %t.rsp +// RUN: clang-nvlink-wrapper --dry-run --assume-device-object @%t.rsp 2>&1 \ +// RUN: | FileCheck %s --check-prefix=RSP +// RUN: echo '"-arch" "sm_52" "%t-u.o" "-o" "a.out"' > %t.quoted.rsp +// RUN: clang-nvlink-wrapper --dry-run --assume-device-object @%t.quoted.rsp 2>&1 \ +// RUN: | FileCheck %s --check-prefix=RSP +// RSP: nvlink{{.*}} -arch sm_52 -o a.out {{.*}}.cubin + // // Check the symbol resolution for static archives. We expect to only link // `libx.a` and `liby.a` because extern weak symbols do not extract and `libz.a` diff --git a/clang/tools/clang-nvlink-wrapper/ClangNVLinkWrapper.cpp b/clang/tools/clang-nvlink-wrapper/ClangNVLinkWrapper.cpp index bc1f510963321..4e06d1c149bb6 100644 --- a/clang/tools/clang-nvlink-wrapper/ClangNVLinkWrapper.cpp +++ b/clang/tools/clang-nvlink-wrapper/ClangNVLinkWrapper.cpp @@ -16,6 +16,8 @@ #include "clang/Basic/Version.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringExtras.h" #include "llvm/BinaryFormat/Magic.h" #include "llvm/Bitcode/BitcodeWriter.h" @@ -255,6 +257,44 @@ void printCommands(ArrayRef<StringRef> CmdArgs) { errs() << join(std::next(CmdArgs.begin()), CmdArgs.end(), " ") << "\n"; } +Error executeProgram(StringRef Executable, ArrayRef<StringRef> Args, + const ArgList &WrapperArgs) { + if (WrapperArgs.hasArg(OPT_dry_run) || WrapperArgs.hasArg(OPT_verbose)) + printCommands(Args); + if (WrapperArgs.hasArg(OPT_dry_run)) + return Error::success(); + + if (sys::commandLineFitsWithinSystemLimits(Executable, Args)) { + if (sys::ExecuteAndWait(Executable, Args)) + return createStringError("'%s' failed", + sys::path::filename(Executable).str().c_str()); + return Error::success(); + } + + auto TempFileOrErr = createTempFile(WrapperArgs, "response", "txt"); + if (!TempFileOrErr) + return TempFileOrErr.takeError(); + + SmallString<256> Contents; + raw_svector_ostream OS(Contents); + for (StringRef Arg : llvm::drop_begin(Args)) { + sys::printArg(OS, Arg, /*Quote=*/true); + OS << " "; + } + + if (std::error_code EC = sys::writeFileWithEncoding(*TempFileOrErr, Contents)) + return createStringError("failed to write response file: %s", + EC.message().c_str()); + + // How nvlink spells its response file support. + std::string ResponseFile = ("--options-file=" + *TempFileOrErr).str(); + SmallVector<StringRef, 2> NewArgs = {Args.front(), ResponseFile}; + if (sys::ExecuteAndWait(Executable, NewArgs)) + return createStringError("'%s' failed", + sys::path::filename(Executable).str().c_str()); + return Error::success(); +} + /// A minimum symbol interface that provides the necessary information to /// extract archive members and resolve LTO symbols. struct Symbol { @@ -336,13 +376,8 @@ Expected<StringRef> runPTXAs(StringRef File, const ArgList &Args) { AssemblerArgs.push_back(A->getValue()); AssemblerArgs.append({"-o", *TempFileOrErr}); - if (Args.hasArg(OPT_dry_run) || Args.hasArg(OPT_verbose)) - printCommands(AssemblerArgs); - if (Args.hasArg(OPT_dry_run)) - return Args.MakeArgString(*TempFileOrErr); - if (sys::ExecuteAndWait(*PTXAsPath, AssemblerArgs)) - return createStringError("'" + sys::path::filename(*PTXAsPath) + "'" + - " failed"); + if (Error Err = executeProgram(*PTXAsPath, AssemblerArgs, Args)) + return Err; return Args.MakeArgString(*TempFileOrErr); } @@ -753,14 +788,7 @@ Error runNVLink(ArrayRef<StringRef> Files, const ArgList &Args) { for (StringRef Arg : NewLinkerArgs) LinkerArgs.push_back(Arg); - if (Args.hasArg(OPT_dry_run) || Args.hasArg(OPT_verbose)) - printCommands(LinkerArgs); - if (Args.hasArg(OPT_dry_run)) - return Error::success(); - if (sys::ExecuteAndWait(*NVLinkPath, LinkerArgs)) - return createStringError("'" + sys::path::filename(*NVLinkPath) + "'" + - " failed"); - return Error::success(); + return executeProgram(*NVLinkPath, LinkerArgs, Args); } } // namespace _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
