diff options
-rw-r--r-- | docs/CommandGuide/clang.rst | 6 | ||||
-rw-r--r-- | include/clang/Basic/DiagnosticFrontendKinds.td | 2 | ||||
-rw-r--r-- | include/clang/Driver/CC1Options.td | 2 | ||||
-rw-r--r-- | include/clang/Driver/Options.td | 5 | ||||
-rw-r--r-- | include/clang/Frontend/FrontendOptions.h | 3 | ||||
-rw-r--r-- | lib/Driver/Tools.cpp | 27 | ||||
-rw-r--r-- | lib/Frontend/CompilerInstance.cpp | 23 | ||||
-rw-r--r-- | lib/Frontend/CompilerInvocation.cpp | 1 | ||||
-rw-r--r-- | lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp | 4 | ||||
-rw-r--r-- | test/Driver/save-stats.c | 20 | ||||
-rw-r--r-- | test/Frontend/stats-file.c | 8 | ||||
-rw-r--r-- | test/Misc/warning-flags.c | 3 |
12 files changed, 98 insertions, 6 deletions
diff --git a/docs/CommandGuide/clang.rst b/docs/CommandGuide/clang.rst index 7a616667dd..b4b607d5a2 100644 --- a/docs/CommandGuide/clang.rst +++ b/docs/CommandGuide/clang.rst @@ -408,6 +408,12 @@ Driver Options Save intermediate compilation results. +.. option:: -save-stats, -save-stats=cwd, -save-stats=obj + + Save internal code generation (LLVM) statistics to a file in the current + directory (:option:`-save-stats`/:option:`-save-stats=cwd`) or the directory + of the output file (:option:`-save-state=obj`). + .. option:: -integrated-as, -no-integrated-as Used to enable and disable, respectively, the use of the integrated diff --git a/include/clang/Basic/DiagnosticFrontendKinds.td b/include/clang/Basic/DiagnosticFrontendKinds.td index 43b5dfc83d..6be2f39186 100644 --- a/include/clang/Basic/DiagnosticFrontendKinds.td +++ b/include/clang/Basic/DiagnosticFrontendKinds.td @@ -107,6 +107,8 @@ def warn_fe_cc_print_header_failure : Warning< "unable to open CC_PRINT_HEADERS file: %0 (using stderr)">; def warn_fe_cc_log_diagnostics_failure : Warning< "unable to open CC_LOG_DIAGNOSTICS file: %0 (using stderr)">; +def warn_fe_unable_to_open_stats_file : Warning< + "unable to open statistics output file '%0': '%1'">; def err_fe_no_pch_in_dir : Error< "no suitable precompiled header file found in directory '%0'">; def err_fe_action_not_available : Error< diff --git a/include/clang/Driver/CC1Options.td b/include/clang/Driver/CC1Options.td index 65abc8f2ab..66e1ad6fc6 100644 --- a/include/clang/Driver/CC1Options.td +++ b/include/clang/Driver/CC1Options.td @@ -509,6 +509,8 @@ def arcmt_migrate : Flag<["-"], "arcmt-migrate">, def print_stats : Flag<["-"], "print-stats">, HelpText<"Print performance metrics and statistics">; +def stats_file : Joined<["-"], "stats-file=">, + HelpText<"Filename to write statistics to">; def fdump_record_layouts : Flag<["-"], "fdump-record-layouts">, HelpText<"Dump record layout information">; def fdump_record_layouts_simple : Flag<["-"], "fdump-record-layouts-simple">, diff --git a/include/clang/Driver/Options.td b/include/clang/Driver/Options.td index d017b0b1b2..a0e9a0d082 100644 --- a/include/clang/Driver/Options.td +++ b/include/clang/Driver/Options.td @@ -1876,6 +1876,11 @@ def save_temps_EQ : Joined<["-", "--"], "save-temps=">, Flags<[DriverOption]>, def save_temps : Flag<["-", "--"], "save-temps">, Flags<[DriverOption]>, Alias<save_temps_EQ>, AliasArgs<["cwd"]>, HelpText<"Save intermediate compilation results">; +def save_stats_EQ : Joined<["-", "--"], "save-stats=">, Flags<[DriverOption]>, + HelpText<"Save llvm statistics.">; +def save_stats : Flag<["-", "--"], "save-stats">, Flags<[DriverOption]>, + Alias<save_stats_EQ>, AliasArgs<["cwd"]>, + HelpText<"Save llvm statistics.">; def via_file_asm : Flag<["-", "--"], "via-file-asm">, InternalDebugOpt, HelpText<"Write assembly to file for input to assemble jobs">; def sectalign : MultiArg<["-"], "sectalign", 3>; diff --git a/include/clang/Frontend/FrontendOptions.h b/include/clang/Frontend/FrontendOptions.h index 4df5e2bb9b..aad397526a 100644 --- a/include/clang/Frontend/FrontendOptions.h +++ b/include/clang/Frontend/FrontendOptions.h @@ -273,6 +273,9 @@ public: // included by this file. std::string FindPchSource; + /// Filename to write statistics to. + std::string StatsFile; + public: FrontendOptions() : DisableFree(false), RelocatablePCH(false), ShowHelp(false), diff --git a/lib/Driver/Tools.cpp b/lib/Driver/Tools.cpp index dcdc92a130..d806efd9a2 100644 --- a/lib/Driver/Tools.cpp +++ b/lib/Driver/Tools.cpp @@ -6107,6 +6107,33 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, A->claim(); } + // 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)); + } + } + // Forward -Xclang arguments to -cc1, and -mllvm arguments to the LLVM option // parser. Args.AddAllArgValues(CmdArgs, options::OPT_Xclang); diff --git a/lib/Frontend/CompilerInstance.cpp b/lib/Frontend/CompilerInstance.cpp index 627134e8dd..67b0c2e074 100644 --- a/lib/Frontend/CompilerInstance.cpp +++ b/lib/Frontend/CompilerInstance.cpp @@ -858,7 +858,7 @@ bool CompilerInstance::ExecuteAction(FrontendAction &Act) { if (getFrontendOpts().ShowTimers) createFrontendTimer(); - if (getFrontendOpts().ShowStats) + if (getFrontendOpts().ShowStats || !getFrontendOpts().StatsFile.empty()) llvm::EnableStatistics(); for (const FrontendInputFile &FIF : getFrontendOpts().Inputs) { @@ -892,9 +892,24 @@ bool CompilerInstance::ExecuteAction(FrontendAction &Act) { OS << " generated.\n"; } - if (getFrontendOpts().ShowStats && hasFileManager()) { - getFileManager().PrintStats(); - OS << "\n"; + if (getFrontendOpts().ShowStats) { + if (hasFileManager()) { + getFileManager().PrintStats(); + OS << '\n'; + } + llvm::PrintStatistics(OS); + } + StringRef StatsFile = getFrontendOpts().StatsFile; + if (!StatsFile.empty()) { + std::error_code EC; + auto StatS = llvm::make_unique<llvm::raw_fd_ostream>(StatsFile, EC, + llvm::sys::fs::F_Text); + if (EC) { + getDiagnostics().Report(diag::warn_fe_unable_to_open_stats_file) + << StatsFile << EC.message(); + } else { + llvm::PrintStatisticsJSON(*StatS); + } } return !getDiagnostics().getClient()->getNumErrors(); diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp index c3fbda114e..6b2df349f8 100644 --- a/lib/Frontend/CompilerInvocation.cpp +++ b/lib/Frontend/CompilerInvocation.cpp @@ -1252,6 +1252,7 @@ static InputKind ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args, Opts.AuxTriple = llvm::Triple::normalize(Args.getLastArgValue(OPT_aux_triple)); Opts.FindPchSource = Args.getLastArgValue(OPT_find_pch_source_EQ); + Opts.StatsFile = Args.getLastArgValue(OPT_stats_file); if (const Arg *A = Args.getLastArg(OPT_arcmt_check, OPT_arcmt_modify, diff --git a/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp b/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp index 1dc490e1c7..751053b620 100644 --- a/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp +++ b/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp @@ -194,8 +194,10 @@ public: } ~AnalysisConsumer() override { - if (Opts->PrintStats) + if (Opts->PrintStats) { delete TUTotalTimer; + llvm::PrintStatistics(); + } } void DigestAnalyzerOptions() { diff --git a/test/Driver/save-stats.c b/test/Driver/save-stats.c new file mode 100644 index 0000000000..19a9d6d568 --- /dev/null +++ b/test/Driver/save-stats.c @@ -0,0 +1,20 @@ +// RUN: %clang -target x86_64-apple-darwin -save-stats %s -### 2>&1 | FileCheck %s +// RUN: %clang -target x86_64-apple-darwin -save-stats=cwd %s -### 2>&1 | FileCheck %s +// CHECK: "-stats-file=save-stats.stats" +// CHECK: "{{.*}}save-stats.c" + +// RUN: %clang -target x86_64-apple-darwin -S %s -### 2>&1 | FileCheck %s -check-prefix=NO-STATS +// NO-STATS-NO: -stats-file +// NO-STATS: "{{.*}}save-stats.c" +// NO-STATS-NO: -stats-file + +// RUN: %clang -target x86_64-apple-darwin -save-stats=obj -c -o obj/dir/save-stats.o %s -### 2>&1 | FileCheck %s -check-prefix=CHECK-OBJ +// CHECK-OBJ: "-stats-file=obj/dir{{.}}save-stats.stats" +// CHECK-OBJ: "-o" "obj/dir{{.}}save-stats.o" + +// RUN: %clang -target x86_64-apple-darwin -save-stats=obj -c %s -### 2>&1 | FileCheck %s -check-prefix=CHECK-OBJ-NOO +// CHECK-OBJ-NOO: "-stats-file=save-stats.stats" +// CHECK-OBJ-NOO: "-o" "save-stats.o" + +// 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' diff --git a/test/Frontend/stats-file.c b/test/Frontend/stats-file.c new file mode 100644 index 0000000000..1869eb3f76 --- /dev/null +++ b/test/Frontend/stats-file.c @@ -0,0 +1,8 @@ +// RUN: %clang_cc1 -emit-llvm -o /dev/null -stats-file=%t %s +// RUN: FileCheck -input-file=%t %s +// CHECK: { +// ... here come some json values ... +// CHECK: } + +// RUN: %clang_cc1 -emit-llvm -o %t -stats-file=%S/doesnotexist/bla %s 2>&1 | FileCheck -check-prefix=OUTPUTFAIL %s +// OUTPUTFAIL: warning: unable to open statistics output file '{{.*}}doesnotexist{{.}}bla': '{{[Nn]}}o such file or directory' diff --git a/test/Misc/warning-flags.c b/test/Misc/warning-flags.c index 69e820542a..1a216d59ef 100644 --- a/test/Misc/warning-flags.c +++ b/test/Misc/warning-flags.c @@ -18,7 +18,7 @@ This test serves two purposes: The list of warnings below should NEVER grow. It should gradually shrink to 0. -CHECK: Warnings without flags (84): +CHECK: Warnings without flags (85): CHECK-NEXT: ext_excess_initializers CHECK-NEXT: ext_excess_initializers_in_char_array_initializer CHECK-NEXT: ext_expected_semi_decl_list @@ -66,6 +66,7 @@ CHECK-NEXT: warn_extraneous_char_constant CHECK-NEXT: warn_fe_cc_log_diagnostics_failure CHECK-NEXT: warn_fe_cc_print_header_failure CHECK-NEXT: warn_fe_macro_contains_embedded_newline +CHECK-NEXT: warn_fe_unable_to_open_stats_file CHECK-NEXT: warn_file_asm_volatile CHECK-NEXT: warn_ignoring_ftabstop_value CHECK-NEXT: warn_implements_nscopying |