10 #include "llvm/Support/CommandLine.h"
11 #include "llvm/Support/Debug.h"
12 #include "llvm/Support/Format.h"
13 #include "llvm/Support/ManagedStatic.h"
26 struct DebugCounterOptions {
27 llvm::cl::list<std::string> counters{
30 "Comma separated list of debug counter skip and count arguments"),
31 llvm::cl::CommaSeparated};
33 llvm::cl::opt<bool> printCounterInfo{
35 llvm::cl::desc(
"Print out debug counter information after all counters "
36 "have been accumulated")};
40 static llvm::ManagedStatic<DebugCounterOptions>
clOptions;
59 int64_t countToStopAfter) {
60 assert(!counters.count(actionTag) &&
61 "a counter for the given action was already registered");
62 counters.try_emplace(actionTag, countToSkip, countToStopAfter);
67 if (shouldExecute(action.
getTag()))
71 bool DebugCounter::shouldExecute(StringRef tag) {
72 auto counterIt = counters.find(tag);
73 if (counterIt == counters.end())
76 ++counterIt->second.count;
81 if (counterIt->second.countToSkip < 0)
83 if (counterIt->second.countToSkip >= counterIt->second.count)
85 if (counterIt->second.countToStopAfter < 0)
87 return counterIt->second.countToStopAfter + counterIt->second.countToSkip >=
88 counterIt->second.count;
94 llvm::make_pointer_range(counters));
95 llvm::array_pod_sort(sortedCounters.begin(), sortedCounters.end(),
96 [](
const decltype(sortedCounters)::value_type *lhs,
97 const decltype(sortedCounters)::value_type *rhs) {
98 return (*lhs)->getKey().compare((*rhs)->getKey());
101 os <<
"DebugCounter counters:\n";
102 for (
const llvm::StringMapEntry<Counter> *counter : sortedCounters) {
103 os << llvm::left_justify(counter->getKey(), 32) <<
": {"
104 << counter->second.count <<
"," << counter->second.countToSkip <<
","
105 << counter->second.countToStopAfter <<
"}\n";
118 return clOptions->counters.getNumOccurrences() ||
119 clOptions->printCounterInfo.getNumOccurrences();
124 void DebugCounter::applyCLOptions() {
128 for (StringRef arg :
clOptions->counters) {
133 auto [counterName, counterValueStr] = arg.split(
'=');
134 if (counterValueStr.empty()) {
135 llvm::errs() <<
"error: expected DebugCounter argument to have an `=` "
136 "separating the counter name and value, but the provided "
139 llvm::report_fatal_error(
140 "Invalid DebugCounter command-line configuration");
144 int64_t counterValue;
145 if (counterValueStr.getAsInteger(0, counterValue)) {
146 llvm::errs() <<
"error: expected DebugCounter counter value to be "
148 << counterValueStr <<
"`\n";
149 llvm::report_fatal_error(
150 "Invalid DebugCounter command-line configuration");
155 if (counterName.consume_back(
"-skip")) {
156 counters[counterName].countToSkip = counterValue;
158 }
else if (counterName.consume_back(
"-count")) {
159 counters[counterName].countToStopAfter = counterValue;
162 llvm::errs() <<
"error: expected DebugCounter counter name to end with "
163 "either `-skip` or `-count`, but got`"
164 << counterName <<
"`\n";
165 llvm::report_fatal_error(
166 "Invalid DebugCounter command-line configuration");
static llvm::ManagedStatic< DebugCounterOptions > clOptions
An action is a specific action that is to be taken by the compiler, that can be toggled and controlle...
virtual StringRef getTag() const =0
Return a string "tag" which intends to uniquely identify this type of action.
static void registerCLOptions()
Register the command line options for debug counters.
void print(raw_ostream &os) const
Print the counters that have been registered with this instance to the provided output stream.
void addCounter(StringRef actionTag, int64_t countToSkip, int64_t countToStopAfter)
Add a counter for the given action tag.
static bool isActivated()
Returns true if any of the CL options are activated.
void operator()(llvm::function_ref< void()> transform, const Action &action)
Entry point for handling actions.
Include the generated interface declarations.