summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--docs/CommandGuide/clang.rst6
-rw-r--r--include/clang/Basic/DiagnosticFrontendKinds.td2
-rw-r--r--include/clang/Driver/CC1Options.td2
-rw-r--r--include/clang/Driver/Options.td5
-rw-r--r--include/clang/Frontend/FrontendOptions.h3
-rw-r--r--lib/Driver/Tools.cpp27
-rw-r--r--lib/Frontend/CompilerInstance.cpp23
-rw-r--r--lib/Frontend/CompilerInvocation.cpp1
-rw-r--r--lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp4
-rw-r--r--test/Driver/save-stats.c20
-rw-r--r--test/Frontend/stats-file.c8
-rw-r--r--test/Misc/warning-flags.c3
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