//===- DebugCounter.cpp - Debug Counter Facilities ------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#include "mlir/Support/DebugCounter.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/Format.h"
#include "llvm/Support/ManagedStatic.h"

using namespace mlir;

//===----------------------------------------------------------------------===//
// DebugCounter CommandLine Options
//===----------------------------------------------------------------------===//

namespace {
/// This struct contains command line options that can be used to initialize
/// various bits of a DebugCounter. This uses a struct wrapper to avoid the need
/// for global command line options.
struct DebugCounterOptions {
  llvm::cl::list<std::string> counters{
      "mlir-debug-counter",
      llvm::cl::desc(
          "Comma separated list of debug counter skip and count arguments"),
      llvm::cl::CommaSeparated, llvm::cl::ZeroOrMore};

  llvm::cl::opt<bool> printCounterInfo{
      "mlir-print-debug-counter", llvm::cl::init(false), llvm::cl::Optional,
      llvm::cl::desc("Print out debug counter information after all counters "
                     "have been accumulated")};
};
} // end anonymous namespace

static llvm::ManagedStatic<DebugCounterOptions> clOptions;

//===----------------------------------------------------------------------===//
// DebugCounter
//===----------------------------------------------------------------------===//

DebugCounter::DebugCounter() { applyCLOptions(); }

DebugCounter::~DebugCounter() {
  // Print information when destroyed, iff command line option is specified.
  if (clOptions.isConstructed() && clOptions->printCounterInfo)
    print(llvm::dbgs());
}

/// Add a counter for the given debug action tag. `countToSkip` is the number
/// of counter executions to skip before enabling execution of the action.
/// `countToStopAfter` is the number of executions of the counter to allow
/// before preventing the action from executing any more.
void DebugCounter::addCounter(StringRef actionTag, int64_t countToSkip,
                              int64_t countToStopAfter) {
  assert(!counters.count(actionTag) &&
         "a counter for the given action was already registered");
  counters.try_emplace(actionTag, countToSkip, countToStopAfter);
}

// Register a counter with the specified name.
FailureOr<bool> DebugCounter::shouldExecute(StringRef tag,
                                            StringRef description) {
  auto counterIt = counters.find(tag);
  if (counterIt == counters.end())
    return true;

  ++counterIt->second.count;

  // We only execute while the `countToSkip` is not smaller than `count`, and
  // `countToStopAfter + countToSkip` is larger than `count`. Negative counters
  // always execute.
  if (counterIt->second.countToSkip < 0)
    return true;
  if (counterIt->second.countToSkip >= counterIt->second.count)
    return false;
  if (counterIt->second.countToStopAfter < 0)
    return true;
  return counterIt->second.countToStopAfter + counterIt->second.countToSkip >=
         counterIt->second.count;
}

void DebugCounter::print(raw_ostream &os) const {
  // Order the registered counters by name.
  SmallVector<const llvm::StringMapEntry<Counter> *, 16> sortedCounters(
      llvm::make_pointer_range(counters));
  llvm::sort(sortedCounters, [](const llvm::StringMapEntry<Counter> *lhs,
                                const llvm::StringMapEntry<Counter> *rhs) {
    return lhs->getKey() < rhs->getKey();
  });

  os << "DebugCounter counters:\n";
  for (const llvm::StringMapEntry<Counter> *counter : sortedCounters) {
    os << llvm::left_justify(counter->getKey(), 32) << ": {"
       << counter->second.count << "," << counter->second.countToSkip << ","
       << counter->second.countToStopAfter << "}\n";
  }
}

/// Register a set of useful command-line options that can be used to configure
/// various flags within the DebugCounter. These flags are used when
/// constructing a DebugCounter for initialization.
void DebugCounter::registerCLOptions() {
#ifndef NDEBUG
  // Make sure that the options struct has been initialized.
  *clOptions;
#endif
}

// This is called by the command line parser when it sees a value for the
// debug-counter option defined above.
void DebugCounter::applyCLOptions() {
  if (!clOptions.isConstructed())
    return;

  for (StringRef arg : clOptions->counters) {
    if (arg.empty())
      continue;

    // Debug counter arguments are expected to be in the form: `counter=value`.
    StringRef counterName, counterValueStr;
    std::tie(counterName, counterValueStr) = arg.split('=');
    if (counterValueStr.empty()) {
      llvm::errs() << "error: expected DebugCounter argument to have an `=` "
                      "separating the counter name and value, but the provided "
                      "argument was: `"
                   << arg << "`\n";
      llvm::report_fatal_error(
          "Invalid DebugCounter command-line configuration");
    }

    // Extract the counter value.
    int64_t counterValue;
    if (counterValueStr.getAsInteger(0, counterValue)) {
      llvm::errs() << "error: expected DebugCounter counter value to be "
                      "numeric, but got `"
                   << counterValueStr << "`\n";
      llvm::report_fatal_error(
          "Invalid DebugCounter command-line configuration");
    }

    // Now we need to see if this is the skip or the count, remove the suffix,
    // and add it to the counter values.
    if (counterName.consume_back("-skip")) {
      counters[counterName].countToSkip = counterValue;

    } else if (counterName.consume_back("-count")) {
      counters[counterName].countToStopAfter = counterValue;

    } else {
      llvm::errs() << "error: expected DebugCounter counter name to end with "
                      "either `-skip` or `-count`, but got`"
                   << counterName << "`\n";
      llvm::report_fatal_error(
          "Invalid DebugCounter command-line configuration");
    }
  }
}
