//===- RemarkCounter.cpp --------------------------------------------------===//
//
// 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
//
//===----------------------------------------------------------------------===//
//
// Generic tool to count remarks based on properties
//
//===----------------------------------------------------------------------===//

#include "RemarkCounter.h"
#include "RemarkUtilRegistry.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Regex.h"

using namespace llvm;
using namespace remarks;
using namespace llvm::remarkutil;

static cl::SubCommand CountSub("count",
                               "Collect remarks based on specified criteria.");

INPUT_FORMAT_COMMAND_LINE_OPTIONS(CountSub)
INPUT_OUTPUT_COMMAND_LINE_OPTIONS(CountSub)

static cl::list<std::string>
    Keys("args", cl::desc("Specify remark argument/s to count by."),
         cl::value_desc("arguments"), cl::sub(CountSub), cl::ValueOptional);
static cl::list<std::string> RKeys(
    "rargs",
    cl::desc(
        "Specify remark argument/s to count (accepts regular expressions)."),
    cl::value_desc("arguments"), cl::sub(CountSub), cl::ValueOptional);
static cl::opt<std::string>
    RemarkNameOpt("remark-name",
                  cl::desc("Optional remark name to filter collection by."),
                  cl::ValueOptional, cl::sub(CountSub));
static cl::opt<std::string>
    PassNameOpt("pass-name", cl::ValueOptional,
                cl::desc("Optional remark pass name to filter collection by."),
                cl::sub(CountSub));

static cl::opt<std::string> RemarkFilterArgByOpt(
    "filter-arg-by", cl::desc("Optional remark arg to filter collection by."),
    cl::ValueOptional, cl::sub(CountSub));
static cl::opt<std::string>
    RemarkNameOptRE("rremark-name",
                    cl::desc("Optional remark name to filter collection by "
                             "(accepts regular expressions)."),
                    cl::ValueOptional, cl::sub(CountSub));
static cl::opt<std::string>
    RemarkArgFilterOptRE("rfilter-arg-by",
                         cl::desc("Optional remark arg to filter collection by "
                                  "(accepts regular expressions)."),
                         cl::sub(CountSub), cl::ValueOptional);
static cl::opt<std::string>
    PassNameOptRE("rpass-name", cl::ValueOptional,
                  cl::desc("Optional remark pass name to filter collection "
                           "by (accepts regular expressions)."),
                  cl::sub(CountSub));
static cl::opt<Type> RemarkTypeOpt(
    "remark-type", cl::desc("Optional remark type to filter collection by."),
    cl::values(clEnumValN(Type::Unknown, "unknown", "UNKOWN"),
               clEnumValN(Type::Passed, "passed", "PASSED"),
               clEnumValN(Type::Missed, "missed", "MISSED"),
               clEnumValN(Type::Analysis, "analysis", "ANALYSIS"),
               clEnumValN(Type::AnalysisFPCommute, "analysis-fp-commute",
                          "ANALYSIS_FP_COMMUTE"),
               clEnumValN(Type::AnalysisAliasing, "analysis-aliasing",
                          "ANALYSIS_ALIASING"),
               clEnumValN(Type::Failure, "failure", "FAILURE")),
    cl::init(Type::Failure), cl::sub(CountSub));
static cl::opt<CountBy> CountByOpt(
    "count-by", cl::desc("Specify the property to collect remarks by."),
    cl::values(
        clEnumValN(CountBy::REMARK, "remark-name",
                   "Counts individual remarks based on how many of the remark "
                   "exists."),
        clEnumValN(CountBy::ARGUMENT, "arg",
                   "Counts based on the value each specified argument has. The "
                   "argument has to have a number value to be considered.")),
    cl::init(CountBy::REMARK), cl::sub(CountSub));
static cl::opt<GroupBy> GroupByOpt(
    "group-by", cl::desc("Specify the property to group remarks by."),
    cl::values(
        clEnumValN(
            GroupBy::PER_SOURCE, "source",
            "Display the count broken down by the filepath of each remark "
            "emitted. Requires remarks to have DebugLoc information."),
        clEnumValN(GroupBy::PER_FUNCTION, "function",
                   "Breakdown the count by function name."),
        clEnumValN(
            GroupBy::PER_FUNCTION_WITH_DEBUG_LOC, "function-with-loc",
            "Breakdown the count by function name taking into consideration "
            "the filepath info from the DebugLoc of the remark."),
        clEnumValN(GroupBy::TOTAL, "total",
                   "Output the total number corresponding to the count for the "
                   "provided input file.")),
    cl::init(GroupBy::PER_SOURCE), cl::sub(CountSub));

/// Look for matching argument with \p Key in \p Remark and return the parsed
/// integer value or 0 if it is has no integer value.
static unsigned getValForKey(StringRef Key, const Remark &Remark) {
  auto *RemarkArg = find_if(Remark.Args, [&Key](const Argument &Arg) {
    return Arg.Key == Key && Arg.isValInt();
  });
  if (RemarkArg == Remark.Args.end())
    return 0;
  return *RemarkArg->getValAsInt();
}

Error Filters::regexArgumentsValid() {
  if (RemarkNameFilter && RemarkNameFilter->IsRegex)
    if (auto E = checkRegex(RemarkNameFilter->FilterRE))
      return E;
  if (PassNameFilter && PassNameFilter->IsRegex)
    if (auto E = checkRegex(PassNameFilter->FilterRE))
      return E;
  if (ArgFilter && ArgFilter->IsRegex)
    if (auto E = checkRegex(ArgFilter->FilterRE))
      return E;
  return Error::success();
}

bool Filters::filterRemark(const Remark &Remark) {
  if (RemarkNameFilter && !RemarkNameFilter->match(Remark.RemarkName))
    return false;
  if (PassNameFilter && !PassNameFilter->match(Remark.PassName))
    return false;
  if (RemarkTypeFilter)
    return *RemarkTypeFilter == Remark.RemarkType;
  if (ArgFilter) {
    if (!any_of(Remark.Args,
                [this](Argument Arg) { return ArgFilter->match(Arg.Val); }))
      return false;
  }
  return true;
}

Error ArgumentCounter::getAllMatchingArgumentsInRemark(
    StringRef Buffer, ArrayRef<FilterMatcher> Arguments, Filters &Filter) {
  auto MaybeParser = createRemarkParser(InputFormat, Buffer);
  if (!MaybeParser)
    return MaybeParser.takeError();
  auto &Parser = **MaybeParser;
  auto MaybeRemark = Parser.next();
  for (; MaybeRemark; MaybeRemark = Parser.next()) {
    auto &Remark = **MaybeRemark;
    // Only collect keys from remarks included in the filter.
    if (!Filter.filterRemark(Remark))
      continue;
    for (auto &Key : Arguments) {
      for (Argument Arg : Remark.Args)
        if (Key.match(Arg.Key) && Arg.isValInt())
          ArgumentSetIdxMap.insert({Arg.Key, ArgumentSetIdxMap.size()});
    }
  }

  auto E = MaybeRemark.takeError();
  if (!E.isA<EndOfFileError>())
    return E;
  consumeError(std::move(E));
  return Error::success();
}

std::optional<std::string> Counter::getGroupByKey(const Remark &Remark) {
  switch (Group) {
  case GroupBy::PER_FUNCTION:
    return Remark.FunctionName.str();
  case GroupBy::TOTAL:
    return "Total";
  case GroupBy::PER_SOURCE:
  case GroupBy::PER_FUNCTION_WITH_DEBUG_LOC:
    if (!Remark.Loc.has_value())
      return std::nullopt;

    if (Group == GroupBy::PER_FUNCTION_WITH_DEBUG_LOC)
      return Remark.Loc->SourceFilePath.str() + ":" + Remark.FunctionName.str();
    return Remark.Loc->SourceFilePath.str();
  }
  llvm_unreachable("Fully covered switch above!");
}

void ArgumentCounter::collect(const Remark &Remark) {
  SmallVector<unsigned, 4> Row(ArgumentSetIdxMap.size());
  std::optional<std::string> GroupByKey = getGroupByKey(Remark);
  // Early return if we don't have a value
  if (!GroupByKey)
    return;
  auto GroupVal = *GroupByKey;
  CountByKeysMap.insert({GroupVal, Row});
  for (auto [Key, Idx] : ArgumentSetIdxMap) {
    auto Count = getValForKey(Key, Remark);
    CountByKeysMap[GroupVal][Idx] += Count;
  }
}

void RemarkCounter::collect(const Remark &Remark) {
  if (std::optional<std::string> Key = getGroupByKey(Remark))
    ++CountedByRemarksMap[*Key];
}

Error ArgumentCounter::print(StringRef OutputFileName) {
  auto MaybeOF =
      getOutputFileWithFlags(OutputFileName, sys::fs::OF_TextWithCRLF);
  if (!MaybeOF)
    return MaybeOF.takeError();

  auto OF = std::move(*MaybeOF);
  OF->os() << groupByToStr(Group) << ",";
  unsigned Idx = 0;
  for (auto [Key, _] : ArgumentSetIdxMap) {
    OF->os() << Key;
    if (Idx != ArgumentSetIdxMap.size() - 1)
      OF->os() << ",";
    Idx++;
  }
  OF->os() << "\n";
  for (auto [Header, CountVector] : CountByKeysMap) {
    OF->os() << Header << ",";
    unsigned Idx = 0;
    for (auto Count : CountVector) {
      OF->os() << Count;
      if (Idx != ArgumentSetIdxMap.size() - 1)
        OF->os() << ",";
      Idx++;
    }
    OF->os() << "\n";
  }
  return Error::success();
}

Error RemarkCounter::print(StringRef OutputFileName) {
  auto MaybeOF =
      getOutputFileWithFlags(OutputFileName, sys::fs::OF_TextWithCRLF);
  if (!MaybeOF)
    return MaybeOF.takeError();

  auto OF = std::move(*MaybeOF);
  OF->os() << groupByToStr(Group) << ","
           << "Count\n";
  for (auto [Key, Count] : CountedByRemarksMap)
    OF->os() << Key << "," << Count << "\n";
  OF->keep();
  return Error::success();
}

Expected<Filters> getRemarkFilter() {
  // Create Filter properties.
  std::optional<FilterMatcher> RemarkNameFilter;
  std::optional<FilterMatcher> PassNameFilter;
  std::optional<FilterMatcher> RemarkArgFilter;
  std::optional<Type> RemarkType;
  if (!RemarkNameOpt.empty())
    RemarkNameFilter = {RemarkNameOpt, false};
  else if (!RemarkNameOptRE.empty())
    RemarkNameFilter = {RemarkNameOptRE, true};
  if (!PassNameOpt.empty())
    PassNameFilter = {PassNameOpt, false};
  else if (!PassNameOptRE.empty())
    PassNameFilter = {PassNameOptRE, true};
  if (RemarkTypeOpt != Type::Failure)
    RemarkType = RemarkTypeOpt;
  if (!RemarkFilterArgByOpt.empty())
    RemarkArgFilter = {RemarkFilterArgByOpt, false};
  else if (!RemarkArgFilterOptRE.empty())
    RemarkArgFilter = {RemarkArgFilterOptRE, true};
  // Create RemarkFilter.
  return Filters::createRemarkFilter(std::move(RemarkNameFilter),
                                     std::move(PassNameFilter),
                                     std::move(RemarkArgFilter), RemarkType);
}

Error useCollectRemark(StringRef Buffer, Counter &Counter, Filters &Filter) {
  // Create Parser.
  auto MaybeParser = createRemarkParser(InputFormat, Buffer);
  if (!MaybeParser)
    return MaybeParser.takeError();
  auto &Parser = **MaybeParser;
  auto MaybeRemark = Parser.next();
  for (; MaybeRemark; MaybeRemark = Parser.next()) {
    const Remark &Remark = **MaybeRemark;
    if (Filter.filterRemark(Remark))
      Counter.collect(Remark);
  }

  if (auto E = Counter.print(OutputFileName))
    return E;
  auto E = MaybeRemark.takeError();
  if (!E.isA<EndOfFileError>())
    return E;
  consumeError(std::move(E));
  return Error::success();
}

static Error collectRemarks() {
  // Create a parser for the user-specified input format.
  auto MaybeBuf = getInputMemoryBuffer(InputFileName);
  if (!MaybeBuf)
    return MaybeBuf.takeError();
  StringRef Buffer = (*MaybeBuf)->getBuffer();
  auto MaybeFilter = getRemarkFilter();
  if (!MaybeFilter)
    return MaybeFilter.takeError();
  auto &Filter = *MaybeFilter;
  if (CountByOpt == CountBy::REMARK) {
    RemarkCounter RC(GroupByOpt);
    if (auto E = useCollectRemark(Buffer, RC, Filter))
      return E;
  } else if (CountByOpt == CountBy::ARGUMENT) {
    SmallVector<FilterMatcher, 4> ArgumentsVector;
    if (!Keys.empty()) {
      for (auto &Key : Keys)
        ArgumentsVector.push_back({Key, false});
    } else if (!RKeys.empty())
      for (auto Key : RKeys)
        ArgumentsVector.push_back({Key, true});
    else
      ArgumentsVector.push_back({".*", true});

    Expected<ArgumentCounter> AC = ArgumentCounter::createArgumentCounter(
        GroupByOpt, ArgumentsVector, Buffer, Filter);
    if (!AC)
      return AC.takeError();
    if (auto E = useCollectRemark(Buffer, *AC, Filter))
      return E;
  }
  return Error::success();
}

static CommandRegistration CountReg(&CountSub, collectRemarks);
