diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp index dd631339635a..1ddffcdc24f4 100644 --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -8215,6 +8215,37 @@ void LinkerWrapper::ConstructJob(Compilation &C, const JobAction &JA, 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("--"); @@ -8224,7 +8255,7 @@ void LinkerWrapper::ConstructJob(Compilation &C, const JobAction &JA, 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); diff --git a/clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp b/clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp index 63afbd834cb7..88dd1eed1711 100644 --- a/clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp +++ b/clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp @@ -48,6 +48,12 @@ using namespace llvm::object; static cl::opt 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 @@ -58,29 +64,53 @@ static cl::opt StripSections( cl::desc("Strip offloading sections from the host object file."), cl::init(true), cl::cat(ClangLinkerWrapperCategory)); -static cl::opt LinkerUserPath("linker-path", +static cl::opt LinkerUserPath("linker-path", cl::Required, cl::desc("Path of linker binary"), cl::cat(ClangLinkerWrapperCategory)); static cl::opt - 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 OptLevel("opt-level", +static cl::opt OptLevel("opt-level", cl::ZeroOrMore, cl::desc("Optimization level for LTO"), cl::init("O2"), cl::cat(ClangLinkerWrapperCategory)); static cl::opt - BitcodeLibrary("target-library", + BitcodeLibrary("target-library", cl::ZeroOrMore, cl::desc("Path for the target bitcode library"), cl::cat(ClangLinkerWrapperCategory)); static cl::opt 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 + HostTriple("host-triple", cl::ZeroOrMore, + cl::desc("Triple to use for the host compilation"), + cl::init(sys::getDefaultTargetTriple()), + cl::cat(ClangLinkerWrapperCategory)); + +static cl::opt + PtxasOption("ptxas-option", cl::ZeroOrMore, + cl::desc("Argument to pass to the ptxas invocation"), + cl::cat(ClangLinkerWrapperCategory)); + +static cl::opt Verbose("v", cl::ZeroOrMore, + cl::desc("Verbose output from tools"), + cl::init(false), + cl::cat(ClangLinkerWrapperCategory)); + +static cl::opt 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 HostLinkerArgs(cl::Positional, @@ -480,6 +510,14 @@ Expected assemble(StringRef InputFile, Triple TheTriple, 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); @@ -511,10 +549,13 @@ Expected link(ArrayRef InputFiles, return createFileError(TempFile, EC); TempFiles.push_back(static_cast(TempFile)); - // TODO: Pass in arguments like `-g` and `-v` from the driver. SmallVector 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"); @@ -563,16 +604,16 @@ void diagnosticHandler(const DiagnosticInfo &DI) { 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; } }