Linker->ConstructJob(C, JA, Output, Inputs, Args, LinkingOutput);
const auto &LinkCommand = C.getJobs().getJobs().back();
+ CmdArgs.push_back("-host-triple");
+ CmdArgs.push_back(Args.MakeArgString(getToolChain().getTripleString()));
+ if (Args.hasArg(options::OPT_v))
+ CmdArgs.push_back("-v");
+
+ // Add debug information if present.
+ if (const Arg *A = Args.getLastArg(options::OPT_g_Group)) {
+ const Option &Opt = A->getOption();
+ if (Opt.matches(options::OPT_gN_Group)) {
+ if (Opt.matches(options::OPT_gline_directives_only) ||
+ Opt.matches(options::OPT_gline_tables_only))
+ CmdArgs.push_back("-gline-directives-only");
+ } else
+ CmdArgs.push_back("-g");
+ }
+
+ for (const auto &A : Args.getAllArgValues(options::OPT_Xcuda_ptxas))
+ CmdArgs.push_back(Args.MakeArgString("-ptxas-option=" + A));
+
+ // Forward remarks passes to the LLVM backend in the wrapper.
+ if (const Arg *A = Args.getLastArg(options::OPT_Rpass_EQ))
+ CmdArgs.push_back(
+ Args.MakeArgString(Twine("-pass-remarks=") + A->getValue()));
+ if (const Arg *A = Args.getLastArg(options::OPT_Rpass_missed_EQ))
+ CmdArgs.push_back(
+ Args.MakeArgString(Twine("-pass-remarks-missed=") + A->getValue()));
+ if (const Arg *A = Args.getLastArg(options::OPT_Rpass_analysis_EQ))
+ CmdArgs.push_back(
+ Args.MakeArgString(Twine("-pass-remarks-analysis=") + A->getValue()));
+
+ // Add the linker arguments to be forwarded by the wrapper.
CmdArgs.push_back("-linker-path");
CmdArgs.push_back(LinkCommand->getExecutable());
CmdArgs.push_back("--");
const char *Exec =
Args.MakeArgString(getToolChain().GetProgramPath("clang-linker-wrapper"));
- // Replace the executable and arguments associated with the link job to the
+ // Replace the executable and arguments of the link job with the
// wrapper.
LinkCommand->replaceExecutable(Exec);
LinkCommand->replaceArguments(CmdArgs);
static cl::opt<bool> Help("h", cl::desc("Alias for -help"), cl::Hidden);
+enum DebugKind {
+ NoDebugInfo,
+ DirectivesOnly,
+ FullDebugInfo,
+};
+
// Mark all our options with this category, everything else (except for -help)
// will be hidden.
static cl::OptionCategory
cl::desc("Strip offloading sections from the host object file."),
cl::init(true), cl::cat(ClangLinkerWrapperCategory));
-static cl::opt<std::string> LinkerUserPath("linker-path",
+static cl::opt<std::string> LinkerUserPath("linker-path", cl::Required,
cl::desc("Path of linker binary"),
cl::cat(ClangLinkerWrapperCategory));
static cl::opt<std::string>
- TargetFeatures("target-feature", cl::desc("Target features for triple"),
+ TargetFeatures("target-feature", cl::ZeroOrMore,
+ cl::desc("Target features for triple"),
cl::cat(ClangLinkerWrapperCategory));
-static cl::opt<std::string> OptLevel("opt-level",
+static cl::opt<std::string> OptLevel("opt-level", cl::ZeroOrMore,
cl::desc("Optimization level for LTO"),
cl::init("O2"),
cl::cat(ClangLinkerWrapperCategory));
static cl::opt<std::string>
- BitcodeLibrary("target-library",
+ BitcodeLibrary("target-library", cl::ZeroOrMore,
cl::desc("Path for the target bitcode library"),
cl::cat(ClangLinkerWrapperCategory));
static cl::opt<bool> EmbedBC(
"target-embed-bc", cl::ZeroOrMore,
- cl::desc("Embed linked bitcode instead of an executable device image."),
+ cl::desc("Embed linked bitcode instead of an executable device image"),
cl::init(false), cl::cat(ClangLinkerWrapperCategory));
+static cl::opt<std::string>
+ HostTriple("host-triple", cl::ZeroOrMore,
+ cl::desc("Triple to use for the host compilation"),
+ cl::init(sys::getDefaultTargetTriple()),
+ cl::cat(ClangLinkerWrapperCategory));
+
+static cl::opt<std::string>
+ PtxasOption("ptxas-option", cl::ZeroOrMore,
+ cl::desc("Argument to pass to the ptxas invocation"),
+ cl::cat(ClangLinkerWrapperCategory));
+
+static cl::opt<bool> Verbose("v", cl::ZeroOrMore,
+ cl::desc("Verbose output from tools"),
+ cl::init(false),
+ cl::cat(ClangLinkerWrapperCategory));
+
+static cl::opt<DebugKind> DebugInfo(
+ cl::desc("Choose debugging level:"), cl::init(NoDebugInfo),
+ cl::values(clEnumValN(NoDebugInfo, "g0", "No debug information"),
+ clEnumValN(DirectivesOnly, "gline-directives-only",
+ "Direction information"),
+ clEnumValN(FullDebugInfo, "g", "Full debugging support")));
+
// Do not parse linker options.
static cl::list<std::string>
HostLinkerArgs(cl::Positional,
std::string Opt = "-" + OptLevel;
CmdArgs.push_back(*PtxasPath);
CmdArgs.push_back(TheTriple.isArch64Bit() ? "-m64" : "-m32");
+ if (Verbose)
+ CmdArgs.push_back("-v");
+ if (DebugInfo == DirectivesOnly && OptLevel[1] == '0')
+ CmdArgs.push_back("-lineinfo");
+ else if (DebugInfo == FullDebugInfo && OptLevel[1] == '0')
+ CmdArgs.push_back("-g");
+ if (!PtxasOption.empty())
+ CmdArgs.push_back(PtxasOption);
CmdArgs.push_back("-o");
CmdArgs.push_back(TempFile);
CmdArgs.push_back(Opt);
return createFileError(TempFile, EC);
TempFiles.push_back(static_cast<std::string>(TempFile));
- // TODO: Pass in arguments like `-g` and `-v` from the driver.
SmallVector<StringRef, 16> CmdArgs;
CmdArgs.push_back(*NvlinkPath);
CmdArgs.push_back(TheTriple.isArch64Bit() ? "-m64" : "-m32");
+ if (Verbose)
+ CmdArgs.push_back("-v");
+ if (DebugInfo != NoDebugInfo)
+ CmdArgs.push_back("-g");
CmdArgs.push_back("-o");
CmdArgs.push_back(TempFile);
CmdArgs.push_back("-arch");
switch (DI.getSeverity()) {
case DS_Error:
- WithColor::error(errs(), LinkerExecutable) << ErrStorage;
+ WithColor::error(errs(), LinkerExecutable) << ErrStorage << "\n";
break;
case DS_Warning:
- WithColor::warning(errs(), LinkerExecutable) << ErrStorage;
+ WithColor::warning(errs(), LinkerExecutable) << ErrStorage << "\n";
break;
case DS_Note:
- WithColor::note(errs(), LinkerExecutable) << ErrStorage;
+ WithColor::note(errs(), LinkerExecutable) << ErrStorage << "\n";
break;
case DS_Remark:
- WithColor::remark(errs(), LinkerExecutable) << ErrStorage;
+ WithColor::remark(errs(), LinkerExecutable) << ErrStorage << "\n";
break;
}
}