Skip to content

Commit 8cc4ca9

Browse files
committed
[OpenMP] Add Cuda path to linker wrapper tool
The linker wrapper tool uses the 'nvlink' and 'ptxas' binaries to link and assemble device files. Previously we searched for this using the binaries in the user's path. This didn't work in cases where the user passed in a specific Cuda path to Clang. This patch changes the linker wrapper to accept an argument for the Cuda path we can get from Clang. This should fix llvm#53573. Reviewed By: tianshilei1992 Differential Revision: https://reviews.llvm.org/D118944
1 parent 91a33ad commit 8cc4ca9

File tree

2 files changed

+43
-15
lines changed

2 files changed

+43
-15
lines changed

clang/lib/Driver/ToolChains/Clang.cpp

Lines changed: 25 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -8148,11 +8148,25 @@ void LinkerWrapper::ConstructJob(Compilation &C, const JobAction &JA,
81488148
const InputInfoList &Inputs,
81498149
const ArgList &Args,
81508150
const char *LinkingOutput) const {
8151+
const Driver &D = getToolChain().getDriver();
8152+
const llvm::Triple TheTriple = getToolChain().getTriple();
8153+
auto OpenMPTCRange = C.getOffloadToolChains<Action::OFK_OpenMP>();
81518154
ArgStringList CmdArgs;
81528155

8153-
if (getToolChain().getDriver().isUsingLTO(/* IsOffload */ true)) {
8156+
// Pass the CUDA path to the linker wrapper tool.
8157+
for (auto &I : llvm::make_range(OpenMPTCRange.first, OpenMPTCRange.second)) {
8158+
const ToolChain *TC = I.second;
8159+
if (TC->getTriple().isNVPTX()) {
8160+
CudaInstallationDetector CudaInstallation(D, TheTriple, Args);
8161+
if (CudaInstallation.isValid())
8162+
CmdArgs.push_back(Args.MakeArgString(
8163+
"--cuda-path=" + CudaInstallation.getInstallPath()));
8164+
break;
8165+
}
8166+
}
8167+
8168+
if (D.isUsingLTO(/* IsOffload */ true)) {
81548169
// Pass in target features for each toolchain.
8155-
auto OpenMPTCRange = C.getOffloadToolChains<Action::OFK_OpenMP>();
81568170
for (auto &I :
81578171
llvm::make_range(OpenMPTCRange.first, OpenMPTCRange.second)) {
81588172
const ToolChain *TC = I.second;
@@ -8165,9 +8179,10 @@ void LinkerWrapper::ConstructJob(Compilation &C, const JobAction &JA,
81658179
}
81668180

81678181
// Pass in the bitcode library to be linked during LTO.
8168-
for (auto &I : llvm::make_range(OpenMPTCRange.first, OpenMPTCRange.second)) {
8182+
for (auto &I :
8183+
llvm::make_range(OpenMPTCRange.first, OpenMPTCRange.second)) {
81698184
const ToolChain *TC = I.second;
8170-
const Driver &D = TC->getDriver();
8185+
const Driver &TCDriver = TC->getDriver();
81718186
const ArgList &TCArgs = C.getArgsForToolChain(TC, "", Action::OFK_OpenMP);
81728187
StringRef Arch = TCArgs.getLastArgValue(options::OPT_march_EQ);
81738188

@@ -8182,7 +8197,7 @@ void LinkerWrapper::ConstructJob(Compilation &C, const JobAction &JA,
81828197
BitcodeSuffix += Arch;
81838198

81848199
ArgStringList BitcodeLibrary;
8185-
addOpenMPDeviceRTL(D, TCArgs, BitcodeLibrary, BitcodeSuffix,
8200+
addOpenMPDeviceRTL(TCDriver, TCArgs, BitcodeLibrary, BitcodeSuffix,
81868201
TC->getTriple());
81878202

81888203
if (!BitcodeLibrary.empty())
@@ -8210,12 +8225,8 @@ void LinkerWrapper::ConstructJob(Compilation &C, const JobAction &JA,
82108225
}
82118226
}
82128227

8213-
// Construct the link job so we can wrap around it.
8214-
Linker->ConstructJob(C, JA, Output, Inputs, Args, LinkingOutput);
8215-
const auto &LinkCommand = C.getJobs().getJobs().back();
8216-
82178228
CmdArgs.push_back("-host-triple");
8218-
CmdArgs.push_back(Args.MakeArgString(getToolChain().getTripleString()));
8229+
CmdArgs.push_back(Args.MakeArgString(TheTriple.getTriple()));
82198230
if (Args.hasArg(options::OPT_v))
82208231
CmdArgs.push_back("-v");
82218232

@@ -8246,6 +8257,10 @@ void LinkerWrapper::ConstructJob(Compilation &C, const JobAction &JA,
82468257
if (Args.getLastArg(options::OPT_save_temps_EQ))
82478258
CmdArgs.push_back("-save-temps");
82488259

8260+
// Construct the link job so we can wrap around it.
8261+
Linker->ConstructJob(C, JA, Output, Inputs, Args, LinkingOutput);
8262+
const auto &LinkCommand = C.getJobs().getJobs().back();
8263+
82498264
// Add the linker arguments to be forwarded by the wrapper.
82508265
CmdArgs.push_back("-linker-path");
82518266
CmdArgs.push_back(LinkCommand->getExecutable());

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

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -99,8 +99,8 @@ static cl::opt<std::string>
9999

100100
static cl::list<std::string>
101101
PtxasArgs("ptxas-args", cl::ZeroOrMore,
102-
cl::desc("Argument to pass to the ptxas invocation"),
103-
cl::cat(ClangLinkerWrapperCategory));
102+
cl::desc("Argument to pass to the ptxas invocation"),
103+
cl::cat(ClangLinkerWrapperCategory));
104104

105105
static cl::opt<bool> Verbose("v", cl::ZeroOrMore,
106106
cl::desc("Verbose output from tools"),
@@ -118,6 +118,10 @@ static cl::opt<bool> SaveTemps("save-temps", cl::ZeroOrMore,
118118
cl::desc("Save intermediary results."),
119119
cl::cat(ClangLinkerWrapperCategory));
120120

121+
static cl::opt<std::string> CudaPath("cuda-path", cl::ZeroOrMore,
122+
cl::desc("Save intermediary results."),
123+
cl::cat(ClangLinkerWrapperCategory));
124+
121125
// Do not parse linker options.
122126
static cl::list<std::string>
123127
HostLinkerArgs(cl::Positional,
@@ -129,6 +133,9 @@ static const char *LinkerExecutable;
129133
/// Filename of the executable being created.
130134
static StringRef ExecutableName;
131135

136+
/// Binary path for the CUDA installation.
137+
static std::string CudaBinaryPath;
138+
132139
/// Temporary files created by the linker wrapper.
133140
static SmallVector<std::string, 16> TempFiles;
134141

@@ -507,9 +514,9 @@ extractFromBuffer(std::unique_ptr<MemoryBuffer> Buffer,
507514
namespace nvptx {
508515
Expected<std::string> assemble(StringRef InputFile, Triple TheTriple,
509516
StringRef Arch) {
510-
// NVPTX uses the nvlink binary to link device object files.
517+
// NVPTX uses the ptxas binary to create device object files.
511518
ErrorOr<std::string> PtxasPath =
512-
sys::findProgramByName("ptxas", sys::path::parent_path(LinkerExecutable));
519+
sys::findProgramByName("ptxas", {CudaBinaryPath});
513520
if (!PtxasPath)
514521
PtxasPath = sys::findProgramByName("ptxas");
515522
if (!PtxasPath)
@@ -554,7 +561,10 @@ Expected<std::string> assemble(StringRef InputFile, Triple TheTriple,
554561
Expected<std::string> link(ArrayRef<std::string> InputFiles, Triple TheTriple,
555562
StringRef Arch) {
556563
// NVPTX uses the nvlink binary to link device object files.
557-
ErrorOr<std::string> NvlinkPath = sys::findProgramByName("nvlink");
564+
ErrorOr<std::string> NvlinkPath =
565+
sys::findProgramByName("nvlink", {CudaBinaryPath});
566+
if (!NvlinkPath)
567+
NvlinkPath = sys::findProgramByName("nvlink");
558568
if (!NvlinkPath)
559569
return createStringError(NvlinkPath.getError(),
560570
"Unable to find 'nvlink' in path");
@@ -1097,6 +1107,9 @@ int main(int argc, const char **argv) {
10971107
return EXIT_FAILURE;
10981108
};
10991109

1110+
if (!CudaPath.empty())
1111+
CudaBinaryPath = CudaPath + "/bin";
1112+
11001113
ExecutableName = *(llvm::find(HostLinkerArgs, "-o") + 1);
11011114
SmallVector<std::string, 16> LinkerArgs;
11021115
for (const std::string &Arg : HostLinkerArgs)

0 commit comments

Comments
 (0)