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 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"));
56 static ManagedStatic
<DebugCounter
> DC
;
58 // Print information when destroyed, iff command line option is specified.
59 DebugCounter::~DebugCounter() {
60 if (isCountingEnabled() && PrintDebugCounter
)
64 DebugCounter
&DebugCounter::instance() { return *DC
; }
66 // This is called by the command line parser when it sees a value for the
67 // debug-counter option defined above.
68 void DebugCounter::push_back(const std::string
&Val
) {
71 // The strings should come in as counter=value
72 auto CounterPair
= StringRef(Val
).split('=');
73 if (CounterPair
.second
.empty()) {
74 errs() << "DebugCounter Error: " << Val
<< " does not have an = in it\n";
77 // Now we have counter=value.
78 // First, process value.
80 if (CounterPair
.second
.getAsInteger(0, CounterVal
)) {
81 errs() << "DebugCounter Error: " << CounterPair
.second
82 << " is not a number\n";
85 // Now we need to see if this is the skip or the count, remove the suffix, and
86 // add it to the counter values.
87 if (CounterPair
.first
.endswith("-skip")) {
88 auto CounterName
= CounterPair
.first
.drop_back(5);
89 unsigned CounterID
= getCounterId(CounterName
);
91 errs() << "DebugCounter Error: " << CounterName
92 << " is not a registered counter\n";
97 CounterInfo
&Counter
= Counters
[CounterID
];
98 Counter
.Skip
= CounterVal
;
100 } else if (CounterPair
.first
.endswith("-count")) {
101 auto CounterName
= CounterPair
.first
.drop_back(6);
102 unsigned CounterID
= getCounterId(CounterName
);
104 errs() << "DebugCounter Error: " << CounterName
105 << " is not a registered counter\n";
110 CounterInfo
&Counter
= Counters
[CounterID
];
111 Counter
.StopAfter
= CounterVal
;
112 Counter
.IsSet
= true;
114 errs() << "DebugCounter Error: " << CounterPair
.first
115 << " does not end with -skip or -count\n";
119 void DebugCounter::print(raw_ostream
&OS
) const {
120 SmallVector
<StringRef
, 16> CounterNames(RegisteredCounters
.begin(),
121 RegisteredCounters
.end());
122 sort(CounterNames
.begin(), CounterNames
.end());
124 auto &Us
= instance();
125 OS
<< "Counters and values:\n";
126 for (auto &CounterName
: CounterNames
) {
127 unsigned CounterID
= getCounterId(CounterName
);
128 OS
<< left_justify(RegisteredCounters
[CounterID
], 32) << ": {"
129 << Us
.Counters
[CounterID
].Count
<< "," << Us
.Counters
[CounterID
].Skip
130 << "," << Us
.Counters
[CounterID
].StopAfter
<< "}\n";
134 LLVM_DUMP_METHOD
void DebugCounter::dump() const {