Index: lib/Driver/ToolChains/Ananas.cpp =================================================================== --- lib/Driver/ToolChains/Ananas.cpp +++ lib/Driver/ToolChains/Ananas.cpp @@ -103,8 +103,11 @@ {options::OPT_T_Group, options::OPT_e, options::OPT_s, options::OPT_t, options::OPT_Z_Flag, options::OPT_r}); - if (D.isUsingLTO()) - AddGoldPlugin(ToolChain, Args, CmdArgs, D.getLTOMode() == LTOK_Thin, D); + if (D.isUsingLTO()) { + assert(!Inputs.empty() && "Must have at least one input."); + AddGoldPlugin(ToolChain, Output, Inputs[0], Args, CmdArgs, + D.getLTOMode() == LTOK_Thin, D); + } AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs, JA); Index: lib/Driver/ToolChains/Clang.cpp =================================================================== --- lib/Driver/ToolChains/Clang.cpp +++ lib/Driver/ToolChains/Clang.cpp @@ -4582,31 +4582,10 @@ } // Setup statistics file output. - if (const Arg *A = Args.getLastArg(options::OPT_save_stats_EQ)) { - StringRef SaveStats = A->getValue(); - - SmallString<128> StatsFile; - bool DoSaveStats = false; - if (SaveStats == "obj") { - if (Output.isFilename()) { - StatsFile.assign(Output.getFilename()); - llvm::sys::path::remove_filename(StatsFile); - } - DoSaveStats = true; - } else if (SaveStats == "cwd") { - DoSaveStats = true; - } else { - D.Diag(diag::err_drv_invalid_value) << A->getAsString(Args) << SaveStats; - } - - if (DoSaveStats) { - StringRef BaseName = llvm::sys::path::filename(Input.getBaseInput()); - llvm::sys::path::append(StatsFile, BaseName); - llvm::sys::path::replace_extension(StatsFile, "stats"); - CmdArgs.push_back(Args.MakeArgString(Twine("-stats-file=") + - StatsFile)); - } - } + SmallString<128> StatsFile = + std::move(getStatsFileName(Output, Input, Args, D)); + if (!StatsFile.empty()) + CmdArgs.push_back(Args.MakeArgString(Twine("-stats-file=") + StatsFile)); // Forward -Xclang arguments to -cc1, and -mllvm arguments to the LLVM option // parser. Index: lib/Driver/ToolChains/CloudABI.cpp =================================================================== --- lib/Driver/ToolChains/CloudABI.cpp +++ lib/Driver/ToolChains/CloudABI.cpp @@ -75,8 +75,11 @@ {options::OPT_T_Group, options::OPT_e, options::OPT_s, options::OPT_t, options::OPT_Z_Flag, options::OPT_r}); - if (D.isUsingLTO()) - AddGoldPlugin(ToolChain, Args, CmdArgs, D.getLTOMode() == LTOK_Thin, D); + if (D.isUsingLTO()) { + assert(!Inputs.empty() && "Must have at least one input."); + AddGoldPlugin(ToolChain, Output, Inputs[0], Args, CmdArgs, + D.getLTOMode() == LTOK_Thin, D); + } AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs, JA); Index: lib/Driver/ToolChains/CommonArgs.h =================================================================== --- lib/Driver/ToolChains/CommonArgs.h +++ lib/Driver/ToolChains/CommonArgs.h @@ -59,7 +59,8 @@ const JobAction &JA, const llvm::opt::ArgList &Args, const InputInfo &Output, const char *OutFile); -void AddGoldPlugin(const ToolChain &ToolChain, const llvm::opt::ArgList &Args, +void AddGoldPlugin(const ToolChain &ToolChain, const InputInfo &Output, + const InputInfo &Input, const llvm::opt::ArgList &Args, llvm::opt::ArgStringList &CmdArgs, bool IsThinLTO, const Driver &D); @@ -103,6 +104,10 @@ void handleTargetFeaturesGroup(const llvm::opt::ArgList &Args, std::vector &Features, llvm::opt::OptSpecifier Group); +SmallString<128> getStatsFileName(const InputInfo &Output, + const InputInfo &Input, + const llvm::opt::ArgList &Args, + const Driver &D); } // end namespace tools } // end namespace driver Index: lib/Driver/ToolChains/CommonArgs.cpp =================================================================== --- lib/Driver/ToolChains/CommonArgs.cpp +++ lib/Driver/ToolChains/CommonArgs.cpp @@ -8,14 +8,14 @@ //===----------------------------------------------------------------------===// #include "CommonArgs.h" -#include "InputInfo.h" -#include "Hexagon.h" #include "Arch/AArch64.h" #include "Arch/ARM.h" #include "Arch/Mips.h" #include "Arch/PPC.h" #include "Arch/SystemZ.h" #include "Arch/X86.h" +#include "Hexagon.h" +#include "InputInfo.h" #include "clang/Basic/CharInfo.h" #include "clang/Basic/LangOptions.h" #include "clang/Basic/ObjCRuntime.h" @@ -42,6 +42,7 @@ #include "llvm/Option/Option.h" #include "llvm/Support/CodeGen.h" #include "llvm/Support/Compression.h" +#include "llvm/Support/Debug.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/FileSystem.h" #include "llvm/Support/Host.h" @@ -369,7 +370,8 @@ return Triple.getOS() == llvm::Triple::CloudABI; } -void tools::AddGoldPlugin(const ToolChain &ToolChain, const ArgList &Args, +void tools::AddGoldPlugin(const ToolChain &ToolChain, const InputInfo &Output, + const InputInfo &Input, const ArgList &Args, ArgStringList &CmdArgs, bool IsThinLTO, const Driver &D) { // Tell the linker to load the plugin. This has to come before AddLinkerInputs @@ -460,6 +462,12 @@ CmdArgs.push_back("-plugin-opt=new-pass-manager"); } + // Setup statistics file output. + SmallString<128> StatsFile = + std::move(getStatsFileName(Output, Input, Args, D)); + if (!StatsFile.empty()) + CmdArgs.push_back( + Args.MakeArgString(Twine("-plugin-opt=stats-file=") + StatsFile)); } void tools::addArchSpecificRPath(const ToolChain &TC, const ArgList &Args, @@ -1233,3 +1241,35 @@ Lksf << LksBuffer; } + +SmallString<128> tools::getStatsFileName(const InputInfo &Output, + const InputInfo &Input, + const llvm::opt::ArgList &Args, + const Driver &D) { + // Setup statistics file output. + if (const Arg *A = Args.getLastArg(options::OPT_save_stats_EQ)) { + StringRef SaveStats = A->getValue(); + + SmallString<128> StatsFile; + bool DoSaveStats = false; + if (SaveStats == "obj") { + if (Output.isFilename()) { + StatsFile.assign(Output.getFilename()); + llvm::sys::path::remove_filename(StatsFile); + } + DoSaveStats = true; + } else if (SaveStats == "cwd") { + DoSaveStats = true; + } else { + D.Diag(diag::err_drv_invalid_value) << A->getAsString(Args) << SaveStats; + } + + if (DoSaveStats) { + StringRef BaseName = llvm::sys::path::filename(Input.getBaseInput()); + llvm::sys::path::append(StatsFile, BaseName); + llvm::sys::path::replace_extension(StatsFile, "stats"); + } + return std::move(StatsFile); + } + return {}; +} Index: lib/Driver/ToolChains/FreeBSD.cpp =================================================================== --- lib/Driver/ToolChains/FreeBSD.cpp +++ lib/Driver/ToolChains/FreeBSD.cpp @@ -231,8 +231,11 @@ Args.AddAllArgs(CmdArgs, options::OPT_Z_Flag); Args.AddAllArgs(CmdArgs, options::OPT_r); - if (D.isUsingLTO()) - AddGoldPlugin(ToolChain, Args, CmdArgs, D.getLTOMode() == LTOK_Thin, D); + if (D.isUsingLTO()) { + assert(!Inputs.empty() && "Must have at least one input."); + AddGoldPlugin(ToolChain, Output, Inputs[0], Args, CmdArgs, + D.getLTOMode() == LTOK_Thin, D); + } bool NeedsSanitizerDeps = addSanitizerRuntimes(ToolChain, Args, CmdArgs); bool NeedsXRayDeps = addXRayRuntime(ToolChain, Args, CmdArgs); Index: lib/Driver/ToolChains/Gnu.cpp =================================================================== --- lib/Driver/ToolChains/Gnu.cpp +++ lib/Driver/ToolChains/Gnu.cpp @@ -435,8 +435,11 @@ ToolChain.AddFilePathLibArgs(Args, CmdArgs); - if (D.isUsingLTO()) - AddGoldPlugin(ToolChain, Args, CmdArgs, D.getLTOMode() == LTOK_Thin, D); + if (D.isUsingLTO()) { + assert(!Inputs.empty() && "Must have at least one input."); + AddGoldPlugin(ToolChain, Output, Inputs[0], Args, CmdArgs, + D.getLTOMode() == LTOK_Thin, D); + } if (Args.hasArg(options::OPT_Z_Xlinker__no_demangle)) CmdArgs.push_back("--no-demangle"); Index: test/Driver/save-stats.c =================================================================== --- test/Driver/save-stats.c +++ test/Driver/save-stats.c @@ -18,3 +18,11 @@ // RUN: %clang -target x86_64-apple-darwin -save-stats=bla -c %s -### 2>&1 | FileCheck %s -check-prefix=CHECK-INVALID // CHECK-INVALID: invalid value 'bla' in '-save-stats=bla' + +// RUN: %clang -target x86_64-linux-unknown -save-stats -flto -o obj/dir/save-stats.exe %s -### 2>&1 | FileCheck %s -check-prefix=CHECK-LTO +// CHECK-LTO: "-stats-file=save-stats.stats" +// CHECK-LTO: "-o" "obj/dir{{/|\\\\}}save-stats.exe" +// CHECK-LTO: "-plugin-opt=stats-file=save-stats.stats" + +// RUN: %clang -target x86_64-linux-unknown -save-stats=obj -flto -o obj/dir/save-stats.exe %s -### 2>&1 | FileCheck %s -check-prefix=CHECK-LTO-OBJ +// CHECK-LTO-OBJ: "-plugin-opt=stats-file=obj/dir/save-stats.stats"