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"
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
> {
15 using Base
= cl::list
<std::string
, DebugCounter
>;
18 template <class... Mods
>
19 explicit DebugCounterList(Mods
&&... Ms
) : Base(std::forward
<Mods
>(Ms
)...) {}
22 void printOptionInfo(size_t GlobalWidth
) const override
{
23 // This is a variant of from generic_parser_base::printOptionInfo. Sadly,
24 // it's not easy to make it more usable. We could get it to print these as
25 // options if we were a cl::opt and registered them, but lists don't have
26 // options, nor does the parser for std::string. The other mechanisms for
27 // options are global and would pollute the global namespace with our
28 // counters. Rather than go that route, we have just overridden the
29 // printing, which only a few things call anyway.
30 outs() << " -" << ArgStr
;
31 // All of the other options in CommandLine.cpp use ArgStr.size() + 6 for
32 // width, so we do the same.
33 Option::printHelpStr(HelpStr
, GlobalWidth
, ArgStr
.size() + 6);
34 const auto &CounterInstance
= DebugCounter::instance();
35 for (auto Name
: CounterInstance
) {
37 CounterInstance
.getCounterInfo(CounterInstance
.getCounterId(Name
));
38 size_t NumSpaces
= GlobalWidth
- Info
.first
.size() - 8;
39 outs() << " =" << Info
.first
;
40 outs().indent(NumSpaces
) << " - " << Info
.second
<< '\n';
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()));
52 static ManagedStatic
<DebugCounter
> DC
;
54 DebugCounter
&DebugCounter::instance() { return *DC
; }
56 // This is called by the command line parser when it sees a value for the
57 // debug-counter option defined above.
58 void DebugCounter::push_back(const std::string
&Val
) {
61 // The strings should come in as counter=value
62 auto CounterPair
= StringRef(Val
).split('=');
63 if (CounterPair
.second
.empty()) {
64 errs() << "DebugCounter Error: " << Val
<< " does not have an = in it\n";
67 // Now we have counter=value.
68 // First, process value.
70 if (CounterPair
.second
.getAsInteger(0, CounterVal
)) {
71 errs() << "DebugCounter Error: " << CounterPair
.second
72 << " is not a number\n";
75 // Now we need to see if this is the skip or the count, remove the suffix, and
76 // add it to the counter values.
77 if (CounterPair
.first
.endswith("-skip")) {
78 auto CounterName
= CounterPair
.first
.drop_back(5);
79 unsigned CounterID
= getCounterId(CounterName
);
81 errs() << "DebugCounter Error: " << CounterName
82 << " is not a registered counter\n";
87 CounterInfo
&Counter
= Counters
[CounterID
];
88 Counter
.Skip
= CounterVal
;
90 } else if (CounterPair
.first
.endswith("-count")) {
91 auto CounterName
= CounterPair
.first
.drop_back(6);
92 unsigned CounterID
= getCounterId(CounterName
);
94 errs() << "DebugCounter Error: " << CounterName
95 << " is not a registered counter\n";
100 CounterInfo
&Counter
= Counters
[CounterID
];
101 Counter
.StopAfter
= CounterVal
;
102 Counter
.IsSet
= true;
104 errs() << "DebugCounter Error: " << CounterPair
.first
105 << " does not end with -skip or -count\n";
109 void DebugCounter::print(raw_ostream
&OS
) const {
110 OS
<< "Counters and values:\n";
111 for (const auto &KV
: Counters
)
112 OS
<< left_justify(RegisteredCounters
[KV
.first
], 32) << ": {"
113 << KV
.second
.Count
<< "," << KV
.second
.Skip
<< ","
114 << KV
.second
.StopAfter
<< "}\n";
117 LLVM_DUMP_METHOD
void DebugCounter::dump() const {