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

Reply via email to