/Users/buildslave/jenkins/workspace/clang-stage2-coverage-R/llvm/lib/Support/DebugCounter.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | #include "llvm/Support/DebugCounter.h" |
2 | | #include "llvm/Support/CommandLine.h" |
3 | | #include "llvm/Support/Format.h" |
4 | | #include "llvm/Support/ManagedStatic.h" |
5 | | #include "llvm/Support/Options.h" |
6 | | |
7 | | using namespace llvm; |
8 | | |
9 | | namespace { |
10 | | // This class overrides the default list implementation of printing so we |
11 | | // can pretty print the list of debug counter options. This type of |
12 | | // dynamic option is pretty rare (basically this and pass lists). |
13 | | class DebugCounterList : public cl::list<std::string, DebugCounter> { |
14 | | private: |
15 | | using Base = cl::list<std::string, DebugCounter>; |
16 | | |
17 | | public: |
18 | | template <class... Mods> |
19 | 104k | explicit DebugCounterList(Mods &&... Ms) : Base(std::forward<Mods>(Ms)...) {} |
20 | | |
21 | | private: |
22 | 1 | void printOptionInfo(size_t GlobalWidth) const override { |
23 | 1 | // This is a variant of from generic_parser_base::printOptionInfo. Sadly, |
24 | 1 | // it's not easy to make it more usable. We could get it to print these as |
25 | 1 | // options if we were a cl::opt and registered them, but lists don't have |
26 | 1 | // options, nor does the parser for std::string. The other mechanisms for |
27 | 1 | // options are global and would pollute the global namespace with our |
28 | 1 | // counters. Rather than go that route, we have just overridden the |
29 | 1 | // printing, which only a few things call anyway. |
30 | 1 | outs() << " -" << ArgStr; |
31 | 1 | // All of the other options in CommandLine.cpp use ArgStr.size() + 6 for |
32 | 1 | // width, so we do the same. |
33 | 1 | Option::printHelpStr(HelpStr, GlobalWidth, ArgStr.size() + 6); |
34 | 1 | const auto &CounterInstance = DebugCounter::instance(); |
35 | 14 | for (auto Name : CounterInstance) { |
36 | 14 | const auto Info = |
37 | 14 | CounterInstance.getCounterInfo(CounterInstance.getCounterId(Name)); |
38 | 14 | size_t NumSpaces = GlobalWidth - Info.first.size() - 8; |
39 | 14 | outs() << " =" << Info.first; |
40 | 14 | outs().indent(NumSpaces) << " - " << Info.second << '\n'; |
41 | 14 | } |
42 | 1 | } |
43 | | }; |
44 | | } // namespace |
45 | | |
46 | | // Create our command line option. |
47 | | static DebugCounterList DebugCounterOption( |
48 | | "debug-counter", cl::Hidden, |
49 | | cl::desc("Comma separated list of debug counter skip and count"), |
50 | | cl::CommaSeparated, cl::ZeroOrMore, cl::location(DebugCounter::instance())); |
51 | | |
52 | | static cl::opt<bool> PrintDebugCounter( |
53 | | "print-debug-counter", cl::Hidden, cl::init(false), cl::Optional, |
54 | | cl::desc("Print out debug counter info after all counters accumulated")); |
55 | | |
56 | | static ManagedStatic<DebugCounter> DC; |
57 | | |
58 | | // Print information when destroyed, iff command line option is specified. |
59 | 100k | DebugCounter::~DebugCounter() { |
60 | 100k | if (isCountingEnabled() && PrintDebugCounter0 ) |
61 | 0 | print(dbgs()); |
62 | 100k | } |
63 | | |
64 | 1.55M | DebugCounter &DebugCounter::instance() { return *DC; } |
65 | | |
66 | | // This is called by the command line parser when it sees a value for the |
67 | | // debug-counter option defined above. |
68 | 0 | void DebugCounter::push_back(const std::string &Val) { |
69 | 0 | if (Val.empty()) |
70 | 0 | return; |
71 | 0 | // The strings should come in as counter=value |
72 | 0 | auto CounterPair = StringRef(Val).split('='); |
73 | 0 | if (CounterPair.second.empty()) { |
74 | 0 | errs() << "DebugCounter Error: " << Val << " does not have an = in it\n"; |
75 | 0 | return; |
76 | 0 | } |
77 | 0 | // Now we have counter=value. |
78 | 0 | // First, process value. |
79 | 0 | int64_t CounterVal; |
80 | 0 | if (CounterPair.second.getAsInteger(0, CounterVal)) { |
81 | 0 | errs() << "DebugCounter Error: " << CounterPair.second |
82 | 0 | << " is not a number\n"; |
83 | 0 | return; |
84 | 0 | } |
85 | 0 | // Now we need to see if this is the skip or the count, remove the suffix, and |
86 | 0 | // add it to the counter values. |
87 | 0 | if (CounterPair.first.endswith("-skip")) { |
88 | 0 | auto CounterName = CounterPair.first.drop_back(5); |
89 | 0 | unsigned CounterID = getCounterId(CounterName); |
90 | 0 | if (!CounterID) { |
91 | 0 | errs() << "DebugCounter Error: " << CounterName |
92 | 0 | << " is not a registered counter\n"; |
93 | 0 | return; |
94 | 0 | } |
95 | 0 | enableAllCounters(); |
96 | 0 |
|
97 | 0 | CounterInfo &Counter = Counters[CounterID]; |
98 | 0 | Counter.Skip = CounterVal; |
99 | 0 | Counter.IsSet = true; |
100 | 0 | } else if (CounterPair.first.endswith("-count")) { |
101 | 0 | auto CounterName = CounterPair.first.drop_back(6); |
102 | 0 | unsigned CounterID = getCounterId(CounterName); |
103 | 0 | if (!CounterID) { |
104 | 0 | errs() << "DebugCounter Error: " << CounterName |
105 | 0 | << " is not a registered counter\n"; |
106 | 0 | return; |
107 | 0 | } |
108 | 0 | enableAllCounters(); |
109 | 0 |
|
110 | 0 | CounterInfo &Counter = Counters[CounterID]; |
111 | 0 | Counter.StopAfter = CounterVal; |
112 | 0 | Counter.IsSet = true; |
113 | 0 | } else { |
114 | 0 | errs() << "DebugCounter Error: " << CounterPair.first |
115 | 0 | << " does not end with -skip or -count\n"; |
116 | 0 | } |
117 | 0 | } |
118 | | |
119 | 0 | void DebugCounter::print(raw_ostream &OS) const { |
120 | 0 | SmallVector<StringRef, 16> CounterNames(RegisteredCounters.begin(), |
121 | 0 | RegisteredCounters.end()); |
122 | 0 | sort(CounterNames.begin(), CounterNames.end()); |
123 | 0 |
|
124 | 0 | auto &Us = instance(); |
125 | 0 | OS << "Counters and values:\n"; |
126 | 0 | for (auto &CounterName : CounterNames) { |
127 | 0 | unsigned CounterID = getCounterId(CounterName); |
128 | 0 | OS << left_justify(RegisteredCounters[CounterID], 32) << ": {" |
129 | 0 | << Us.Counters[CounterID].Count << "," << Us.Counters[CounterID].Skip |
130 | 0 | << "," << Us.Counters[CounterID].StopAfter << "}\n"; |
131 | 0 | } |
132 | 0 | } |
133 | | |
134 | 0 | LLVM_DUMP_METHOD void DebugCounter::dump() const { |
135 | 0 | print(dbgs()); |
136 | 0 | } |