// Copyright 2024 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "cheriot/cheriot_instrumentation_control.h"

#include <cstddef>
#include <cstdint>
#include <string>
#include <utility>

#include "absl/functional/any_invocable.h"
#include "absl/status/status.h"
#include "absl/strings/str_cat.h"
#include "absl/strings/string_view.h"
#include "cheriot/cheriot_top.h"
#include "cheriot/debug_command_shell.h"
#include "cheriot/memory_use_profiler.h"
#include "re2/re2.h"
#include "riscv//stoull_wrapper.h"

namespace mpact::sim::cheriot {

CheriotInstrumentationControl::CheriotInstrumentationControl(
    DebugCommandShell *shell, CheriotTop *cheriot_top,
    TaggedMemoryUseProfiler *mem_profiler)
    : shell_(shell),
      top_(cheriot_top),
      mem_profiler_(mem_profiler),
      pattern_re_{
          R"(\s*stats\s+(enable|disable)\s+(counters|iprofile|mprofile|all)(?:\s+(\w+))?\s*)"} {
}

bool CheriotInstrumentationControl::PerformShellCommand(
    absl::string_view input, const DebugCommandShell::CoreAccess &core_access,
    std::string &output) {
  std::string cmd;
  std::string what;
  std::string where;
  absl::AnyInvocable<void(uint64_t, int)> function;
  if (!RE2::FullMatch(input, *pattern_re_, &cmd, &what, &where)) return false;
  // See what the pattern matched and set up an appropriate lambda.
  if (cmd == "enable") {
    if (what == "counters") {
      function = [this](uint64_t, int) { top_->EnableStatistics(); };
    } else if (what == "iprofile") {
      function = [this](uint64_t, int) {
        top_->counter_pc()->SetIsEnabled(true);
      };
    } else if (what == "mprofile") {
      function = [this](uint64_t, int) { mem_profiler_->set_is_enabled(true); };
    } else if (what == "all") {
      function = [this](uint64_t, int) {
        top_->EnableStatistics();
        top_->counter_pc()->SetIsEnabled(true);
        mem_profiler_->set_is_enabled(true);
      };
    } else {
      output = absl::StrCat("Error: Unknown instrumentation: '", what, "'");
      return true;
    }
  } else if (cmd == "disable") {
    if (what == "counters") {
      function = [this](uint64_t, int) { top_->DisableStatistics(); };
    } else if (what == "iprofile") {
      function = [this](uint64_t, int) {
        top_->counter_pc()->SetIsEnabled(false);
      };
    } else if (what == "mprofile") {
      function = [this](uint64_t, int) {
        mem_profiler_->set_is_enabled(false);
      };
    } else if (what == "all") {
      function = [this](uint64_t, int) {
        top_->DisableStatistics();
        top_->counter_pc()->SetIsEnabled(false);
        mem_profiler_->set_is_enabled(false);
      };
    } else {
      output = absl::StrCat("Error: Unknown instrumentation: '", what, "'");
      return true;
    }
  }
  // If 'where' is empty, we just execute the callable. It is not attached
  // to any instruction.
  if (where.empty()) {
    function(0, 0);
    return true;
  }
  // At this point we need to set the function to be executed upon execution
  // of an instruction a specified in 'where'.
  size_t index;
  uint64_t address = 0;
  // Attempt to convert to a number.
  auto convert_result = riscv::internal::stoull(where, &index, 0);
  // If successful and the entire string was consumed, the number is good and
  // we use that as the address.
  if (convert_result.ok() && (index >= where.size())) {
    address = convert_result.value();
  } else {
    // If it's out of range, signal an error.
    if (convert_result.status().code() == absl::StatusCode::kOutOfRange) {
      output = absl::StrCat("Error: ", where, " is out of range");
      return true;
    }
    // Let's see if it is a symbol.
    if (core_access.loader == nullptr) {
      output = "Error: cannot perform symbol lookup";
      return true;
    }
    auto result = core_access.loader->GetSymbol(where);
    if (!result.ok()) {
      output = absl::StrCat("Error: symbol ", where, " not found");
      return true;
    }
    address = result.value().first;
  }
  // Now we set an action for the function.
  std::string action_name = absl::StrCat(cmd, "-", what, "-", where);
  auto status =
      shell_->SetActionPoint(address, action_name, std::move(function));
  if (!status.ok()) {
    output = absl::StrCat("Error: ", status.message());
  }
  return true;
}

std::string CheriotInstrumentationControl::Usage() const {
  return
      R"raw(
  stats enable (counters|iprofile|mprofile|all) [VALUE|SYMBOL]
                                   - enable counters, iprofile, mprofile, or all
                                     when executing instruction at address VALUE
                                     or value of SYMBOL, or immediately if
                                     neither is specified.
  stats disable (counters|iprofile|mprofile|all) [VALUE|SYMBOL]
                                   - disable counters, iprofile, mprofile, or all
                                     when executing instruction at address VALUE
                                     or value of SYMBOL, or immediately if
                                     neither is specified.
    )raw";
}

}  // namespace mpact::sim::cheriot
