diff --git a/clang/docs/CommandGuide/clang.rst b/clang/docs/CommandGuide/clang.rst --- a/clang/docs/CommandGuide/clang.rst +++ b/clang/docs/CommandGuide/clang.rst @@ -592,6 +592,16 @@ directory (:option:`-save-stats`/"-save-stats=cwd") or the directory of the output file ("-save-state=obj"). + You can also use environment variables to control the statistics reporting. + Setting ``CC_PRINT_INTERNAL_STAT`` to ``1`` enables the feature, the report + goes to stdout in JSON format. + + Setting ``CC_PRINT_INTERNAL_STAT_FILE`` to a file path makes it report + statistics to the given file in the JSON format. + + Note that ``-save-stats`` take precedence over ``CC_PRINT_INTERNAL_STAT`` + and ``CC_PRINT_INTERNAL_STAT_FILE``. + .. option:: -integrated-as, -no-integrated-as Used to enable and disable, respectively, the use of the integrated diff --git a/clang/include/clang/Driver/Driver.h b/clang/include/clang/Driver/Driver.h --- a/clang/include/clang/Driver/Driver.h +++ b/clang/include/clang/Driver/Driver.h @@ -194,6 +194,9 @@ /// The file to log CC_PRINT_PROC_STAT_FILE output to, if enabled. std::string CCPrintStatReportFilename; + /// The file to log CC_PRINT_INTERNAL_STAT_FILE output to, if enabled. + std::string CCPrintInternalStatReportFilename; + /// The file to log CC_PRINT_OPTIONS output to, if enabled. std::string CCPrintOptionsFilename; @@ -258,6 +261,10 @@ /// performance report to CC_PRINT_PROC_STAT_FILE or to stdout. unsigned CCPrintProcessStats : 1; + /// Set CC_PRINT_INTERNAL_STAT mode, which causes the driver to dump internal + /// performance report to CC_PRINT_INTERNAL_STAT_FILE or to stdout. + unsigned CCPrintInternalStats : 1; + /// Pointer to the ExecuteCC1Tool function, if available. /// When the clangDriver lib is used through clang.exe, this provides a /// shortcut for executing the -cc1 command-line directly, in the same diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -6149,6 +6149,9 @@ def stats_file : Joined<["-"], "stats-file=">, HelpText<"Filename to write statistics to">, MarshallingInfoString>; +def stats_file_append : Flag<["-"], "stats-file-append">, + HelpText<"If stats should be appended to stats-file instead of overwriting it">, + MarshallingInfoFlag>; def fdump_record_layouts_simple : Flag<["-"], "fdump-record-layouts-simple">, HelpText<"Dump record layout information in a simple form used for testing">, MarshallingInfoFlag>; diff --git a/clang/include/clang/Frontend/FrontendOptions.h b/clang/include/clang/Frontend/FrontendOptions.h --- a/clang/include/clang/Frontend/FrontendOptions.h +++ b/clang/include/clang/Frontend/FrontendOptions.h @@ -278,6 +278,8 @@ /// Show frontend performance metrics and statistics. unsigned ShowStats : 1; + unsigned AppendStats : 1; + /// print the supported cpus for the current target unsigned PrintSupportedCPUs : 1; @@ -510,16 +512,16 @@ public: FrontendOptions() : DisableFree(false), RelocatablePCH(false), ShowHelp(false), - ShowStats(false), TimeTrace(false), ShowVersion(false), - FixWhatYouCan(false), FixOnlyWarnings(false), FixAndRecompile(false), - FixToTemporaries(false), ARCMTMigrateEmitARCErrors(false), - SkipFunctionBodies(false), UseGlobalModuleIndex(true), - GenerateGlobalModuleIndex(true), ASTDumpDecls(false), - ASTDumpLookups(false), BuildingImplicitModule(false), - BuildingImplicitModuleUsesLock(true), ModulesEmbedAllFiles(false), - IncludeTimestamps(true), UseTemporary(true), - AllowPCMWithCompilerErrors(false), ModulesShareFileManager(true), - TimeTraceGranularity(500) {} + ShowStats(false), AppendStats(false), TimeTrace(false), + ShowVersion(false), FixWhatYouCan(false), FixOnlyWarnings(false), + FixAndRecompile(false), FixToTemporaries(false), + ARCMTMigrateEmitARCErrors(false), SkipFunctionBodies(false), + UseGlobalModuleIndex(true), GenerateGlobalModuleIndex(true), + ASTDumpDecls(false), ASTDumpLookups(false), + BuildingImplicitModule(false), BuildingImplicitModuleUsesLock(true), + ModulesEmbedAllFiles(false), IncludeTimestamps(true), + UseTemporary(true), AllowPCMWithCompilerErrors(false), + ModulesShareFileManager(true), TimeTraceGranularity(500) {} /// getInputKindForExtension - Return the appropriate input kind for a file /// extension. For example, "c" would return Language::C. diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp --- a/clang/lib/Driver/Driver.cpp +++ b/clang/lib/Driver/Driver.cpp @@ -199,8 +199,9 @@ ClangExecutable(ClangExecutable), SysRoot(DEFAULT_SYSROOT), DriverTitle(Title), CCCPrintBindings(false), CCPrintOptions(false), CCLogDiagnostics(false), CCGenDiagnostics(false), - CCPrintProcessStats(false), TargetTriple(TargetTriple), Saver(Alloc), - PrependArg(nullptr), CheckInputsExist(true), ProbePrecompiled(true), + CCPrintProcessStats(false), CCPrintInternalStats(false), + TargetTriple(TargetTriple), Saver(Alloc), PrependArg(nullptr), + CheckInputsExist(true), ProbePrecompiled(true), SuppressMissingInputWarning(false) { // Provide a sane fallback if no VFS is specified. if (!this->VFS) diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -7034,8 +7034,11 @@ // Setup statistics file output. SmallString<128> StatsFile = getStatsFileName(Args, Output, Input, D); - if (!StatsFile.empty()) + if (!StatsFile.empty()) { CmdArgs.push_back(Args.MakeArgString(Twine("-stats-file=") + StatsFile)); + if (D.CCPrintInternalStats) + CmdArgs.push_back("-stats-file-append"); + } // Forward -Xclang arguments to -cc1, and -mllvm arguments to the LLVM option // parser. diff --git a/clang/lib/Driver/ToolChains/CommonArgs.cpp b/clang/lib/Driver/ToolChains/CommonArgs.cpp --- a/clang/lib/Driver/ToolChains/CommonArgs.cpp +++ b/clang/lib/Driver/ToolChains/CommonArgs.cpp @@ -1785,22 +1785,29 @@ const InputInfo &Input, const Driver &D) { const Arg *A = Args.getLastArg(options::OPT_save_stats_EQ); - if (!A) + if (!A && !D.CCPrintInternalStats) return {}; - StringRef SaveStats = A->getValue(); SmallString<128> StatsFile; - if (SaveStats == "obj" && Output.isFilename()) { - StatsFile.assign(Output.getFilename()); - llvm::sys::path::remove_filename(StatsFile); - } else if (SaveStats != "cwd") { - D.Diag(diag::err_drv_invalid_value) << A->getAsString(Args) << SaveStats; - return {}; - } + if (A) { + StringRef SaveStats = A->getValue(); + if (SaveStats == "obj" && Output.isFilename()) { + StatsFile.assign(Output.getFilename()); + llvm::sys::path::remove_filename(StatsFile); + } else if (SaveStats != "cwd") { + D.Diag(diag::err_drv_invalid_value) << A->getAsString(Args) << SaveStats; + return {}; + } - StringRef BaseName = llvm::sys::path::filename(Input.getBaseInput()); - llvm::sys::path::append(StatsFile, BaseName); - llvm::sys::path::replace_extension(StatsFile, "stats"); + StringRef BaseName = llvm::sys::path::filename(Input.getBaseInput()); + llvm::sys::path::append(StatsFile, BaseName); + llvm::sys::path::replace_extension(StatsFile, "stats"); + } else { + assert(D.CCPrintInternalStats); + StatsFile.assign(D.CCPrintInternalStatReportFilename.empty() + ? "-" + : D.CCPrintInternalStatReportFilename); + } return StatsFile; } diff --git a/clang/lib/Frontend/CompilerInstance.cpp b/clang/lib/Frontend/CompilerInstance.cpp --- a/clang/lib/Frontend/CompilerInstance.cpp +++ b/clang/lib/Frontend/CompilerInstance.cpp @@ -1087,9 +1087,12 @@ } StringRef StatsFile = getFrontendOpts().StatsFile; if (!StatsFile.empty()) { + llvm::sys::fs::OpenFlags FileFlags = llvm::sys::fs::OF_TextWithCRLF; + if (getFrontendOpts().AppendStats) + FileFlags |= llvm::sys::fs::OF_Append; std::error_code EC; - auto StatS = std::make_unique( - StatsFile, EC, llvm::sys::fs::OF_TextWithCRLF); + auto StatS = + std::make_unique(StatsFile, EC, FileFlags); if (EC) { getDiagnostics().Report(diag::warn_fe_unable_to_open_stats_file) << StatsFile << EC.message(); diff --git a/clang/test/Driver/save-stats.c b/clang/test/Driver/save-stats.c --- a/clang/test/Driver/save-stats.c +++ b/clang/test/Driver/save-stats.c @@ -26,3 +26,14 @@ // 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" + +// RUN: env CC_PRINT_INTERNAL_STAT=1 \ +// RUN: %clang -target x86_64-apple-darwin %s -### 2>&1 | FileCheck %s -check-prefix=CHECK-ENV +// CHECK-ENV: "-stats-file=-" +// CHECK-ENV-NO: "stats-file-append" + +// RUN: env CC_PRINT_INTERNAL_STAT=1 \ +// RUN: CC_PRINT_INTERNAL_STAT_FILE=/tmp/stats.json \ +// RUN: %clang -target x86_64-apple-darwin %s -### 2>&1 | FileCheck %s -check-prefix=CHECK-ENV-FILE +// CHECK-ENV-FILE: "-stats-file=/tmp/stats.json" +// CHECK-ENV-FILE: "-stats-file-append" diff --git a/clang/tools/driver/driver.cpp b/clang/tools/driver/driver.cpp --- a/clang/tools/driver/driver.cpp +++ b/clang/tools/driver/driver.cpp @@ -307,6 +307,9 @@ TheDriver.CCPrintProcessStats = checkEnvVar("CC_PRINT_PROC_STAT", "CC_PRINT_PROC_STAT_FILE", TheDriver.CCPrintStatReportFilename); + TheDriver.CCPrintInternalStats = + checkEnvVar("CC_PRINT_INTERNAL_STAT", "CC_PRINT_INTERNAL_STAT_FILE", + TheDriver.CCPrintInternalStatReportFilename); return true; }