|
13 | 13 | //===----------------------------------------------------------------------===// |
14 | 14 |
|
15 | 15 | #include "llvm/CodeGen/CommandFlags.h" |
| 16 | +#include "llvm/ADT/SmallString.h" |
| 17 | +#include "llvm/ADT/Statistic.h" |
16 | 18 | #include "llvm/ADT/StringExtras.h" |
| 19 | +#include "llvm/ADT/StringRef.h" |
17 | 20 | #include "llvm/IR/Instructions.h" |
18 | 21 | #include "llvm/IR/Intrinsics.h" |
19 | 22 | #include "llvm/IR/Module.h" |
20 | 23 | #include "llvm/MC/MCTargetOptionsCommandFlags.h" |
21 | 24 | #include "llvm/MC/TargetRegistry.h" |
22 | 25 | #include "llvm/Support/CommandLine.h" |
| 26 | +#include "llvm/Support/FileSystem.h" |
23 | 27 | #include "llvm/Support/MemoryBuffer.h" |
| 28 | +#include "llvm/Support/Path.h" |
| 29 | +#include "llvm/Support/WithColor.h" |
| 30 | +#include "llvm/Support/raw_ostream.h" |
24 | 31 | #include "llvm/Target/TargetMachine.h" |
25 | 32 | #include "llvm/TargetParser/Host.h" |
26 | 33 | #include "llvm/TargetParser/SubtargetFeature.h" |
27 | 34 | #include "llvm/TargetParser/Triple.h" |
| 35 | +#include <cassert> |
| 36 | +#include <memory> |
28 | 37 | #include <optional> |
| 38 | +#include <system_error> |
29 | 39 |
|
30 | 40 | using namespace llvm; |
31 | 41 |
|
32 | 42 | #define CGOPT(TY, NAME) \ |
33 | 43 | static cl::opt<TY> *NAME##View; \ |
34 | 44 | TY codegen::get##NAME() { \ |
35 | | - assert(NAME##View && "RegisterCodeGenFlags not created."); \ |
| 45 | + assert(NAME##View && "Flag not registered."); \ |
36 | 46 | return *NAME##View; \ |
37 | 47 | } |
38 | 48 |
|
39 | 49 | #define CGLIST(TY, NAME) \ |
40 | 50 | static cl::list<TY> *NAME##View; \ |
41 | 51 | std::vector<TY> codegen::get##NAME() { \ |
42 | | - assert(NAME##View && "RegisterCodeGenFlags not created."); \ |
| 52 | + assert(NAME##View && "Flag not registered."); \ |
43 | 53 | return *NAME##View; \ |
44 | 54 | } |
45 | 55 |
|
@@ -111,13 +121,14 @@ CGOPT(bool, DebugStrictDwarf) |
111 | 121 | CGOPT(unsigned, AlignLoops) |
112 | 122 | CGOPT(bool, JMCInstrument) |
113 | 123 | CGOPT(bool, XCOFFReadOnlyPointers) |
| 124 | +CGOPT(codegen::SaveStatsMode, SaveStats) |
114 | 125 |
|
115 | | -codegen::RegisterCodeGenFlags::RegisterCodeGenFlags() { |
116 | 126 | #define CGBINDOPT(NAME) \ |
117 | 127 | do { \ |
118 | 128 | NAME##View = std::addressof(NAME); \ |
119 | 129 | } while (0) |
120 | 130 |
|
| 131 | +codegen::RegisterCodeGenFlags::RegisterCodeGenFlags() { |
121 | 132 | static cl::opt<std::string> MArch( |
122 | 133 | "march", cl::desc("Architecture to generate code for (see --version)")); |
123 | 134 | CGBINDOPT(MArch); |
@@ -523,11 +534,25 @@ codegen::RegisterCodeGenFlags::RegisterCodeGenFlags() { |
523 | 534 | cl::init(false)); |
524 | 535 | CGBINDOPT(DisableIntegratedAS); |
525 | 536 |
|
526 | | -#undef CGBINDOPT |
527 | | - |
528 | 537 | mc::RegisterMCTargetOptionsFlags(); |
529 | 538 | } |
530 | 539 |
|
| 540 | +codegen::RegisterSaveStatsFlag::RegisterSaveStatsFlag() { |
| 541 | + static cl::opt<SaveStatsMode> SaveStats( |
| 542 | + "save-stats", |
| 543 | + cl::desc( |
| 544 | + "Save LLVM statistics to a file in the current directory" |
| 545 | + "(`-save-stats`/`-save-stats=cwd`) or the directory of the output" |
| 546 | + "file (`-save-stats=obj`). (default: cwd)"), |
| 547 | + cl::values(clEnumValN(SaveStatsMode::Cwd, "cwd", |
| 548 | + "Save to the current working directory"), |
| 549 | + clEnumValN(SaveStatsMode::Cwd, "", ""), |
| 550 | + clEnumValN(SaveStatsMode::Obj, "obj", |
| 551 | + "Save to the output file directory")), |
| 552 | + cl::init(SaveStatsMode::None), cl::ValueOptional); |
| 553 | + CGBINDOPT(SaveStats); |
| 554 | +} |
| 555 | + |
531 | 556 | llvm::BasicBlockSection |
532 | 557 | codegen::getBBSectionsMode(llvm::TargetOptions &Options) { |
533 | 558 | if (getBBSections() == "all") |
@@ -774,3 +799,42 @@ codegen::createTargetMachineForTriple(StringRef TargetTriple, |
774 | 799 | TargetTriple); |
775 | 800 | return std::unique_ptr<TargetMachine>(Target); |
776 | 801 | } |
| 802 | + |
| 803 | +void codegen::MaybeEnableStatistics() { |
| 804 | + if (getSaveStats() == SaveStatsMode::None) |
| 805 | + return; |
| 806 | + |
| 807 | + llvm::EnableStatistics(false); |
| 808 | +} |
| 809 | + |
| 810 | +int codegen::MaybeSaveStatistics(StringRef OutputFilename, StringRef ToolName) { |
| 811 | + auto SaveStatsValue = getSaveStats(); |
| 812 | + if (SaveStatsValue == codegen::SaveStatsMode::None) |
| 813 | + return 0; |
| 814 | + |
| 815 | + SmallString<128> StatsFilename; |
| 816 | + if (SaveStatsValue == codegen::SaveStatsMode::Obj) { |
| 817 | + StatsFilename = OutputFilename; |
| 818 | + llvm::sys::path::remove_filename(StatsFilename); |
| 819 | + } else { |
| 820 | + assert(SaveStatsValue == codegen::SaveStatsMode::Cwd && |
| 821 | + "Should have been a valid --save-stats value"); |
| 822 | + } |
| 823 | + |
| 824 | + auto BaseName = llvm::sys::path::filename(OutputFilename); |
| 825 | + llvm::sys::path::append(StatsFilename, BaseName); |
| 826 | + llvm::sys::path::replace_extension(StatsFilename, "stats"); |
| 827 | + |
| 828 | + auto FileFlags = llvm::sys::fs::OF_TextWithCRLF; |
| 829 | + std::error_code EC; |
| 830 | + auto StatsOS = |
| 831 | + std::make_unique<llvm::raw_fd_ostream>(StatsFilename, EC, FileFlags); |
| 832 | + if (EC) { |
| 833 | + WithColor::error(errs(), ToolName) |
| 834 | + << "Unable to open statistics file: " << EC.message() << "\n"; |
| 835 | + return 1; |
| 836 | + } |
| 837 | + |
| 838 | + llvm::PrintStatisticsJSON(*StatsOS); |
| 839 | + return 0; |
| 840 | +} |
0 commit comments