// Copyright 2023 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
//
//     https://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 "mpact/sim/decoder/opcode.h"

#include <functional>
#include <string>
#include <utility>

#include "absl/status/status.h"
#include "absl/status/statusor.h"
#include "absl/strings/str_cat.h"
#include "absl/strings/string_view.h"
#include "mpact/sim/decoder/format_name.h"
#include "mpact/sim/decoder/template_expression.h"

namespace mpact {
namespace sim {
namespace machine_description {
namespace instruction_set {

// There is not much to the Opcode class. Note that the AppendSourceOpName
// method use emplace since a string_view can be passed to a std::string
// constructor but cannot be passed directly to push_back().
Opcode::Opcode(absl::string_view name, int value)
    : name_(name), pascal_name_(ToPascalCase(name)), value_(value) {}

Opcode::~Opcode() {
  for (auto* dest_op : dest_op_vec_) {
    delete dest_op;
  }
  dest_op_vec_.clear();
  dest_op_map_.clear();
}

void Opcode::AppendSourceOp(absl::string_view op_name, bool is_array,
                            bool is_reloc) {
  source_op_vec_.emplace_back(std::string(op_name), is_array, is_reloc);
}

void Opcode::AppendDestOp(absl::string_view op_name, bool is_array,
                          bool is_reloc) {
  auto* op = new DestinationOperand(std::string(op_name), is_array, is_reloc);
  dest_op_vec_.push_back(op);
  dest_op_map_.insert(std::make_pair(std::string(op_name), op));
}

void Opcode::AppendDestOp(absl::string_view op_name, bool is_array,
                          bool is_reloc, TemplateExpression* expression) {
  auto* op = new DestinationOperand(std::string(op_name), is_array, is_reloc,
                                    expression);
  dest_op_vec_.push_back(op);
  dest_op_map_.insert(std::make_pair(std::string(op_name), op));
}

DestinationOperand* Opcode::GetDestOp(absl::string_view op_name) {
  auto iter = dest_op_map_.find(op_name);
  if (iter != dest_op_map_.end()) return iter->second;

  return nullptr;
}

bool Opcode::ValidateDestLatencies(
    const std::function<bool(int)>& validator) const {
  for (auto const* dest_op : dest_op_vec_) {
    if (dest_op->expression() != nullptr) {
      auto result = dest_op->GetLatency();
      if (!result.ok()) return false;
      if (!validator(result.value())) return false;
    }
  }
  return true;
}

Opcode* OpcodeFactory::CreateDefaultOpcode() { return new Opcode("", -1); }

absl::StatusOr<Opcode*> OpcodeFactory::CreateOpcode(absl::string_view name) {
  if (opcode_names_.contains(name)) {
    return absl::InternalError(
        absl::StrCat("Opcode '", name, "' already declared"));
  }
  // Using emplace since name is a string_view which insert doesn't accept.
  opcode_names_.emplace(name);
  auto opcode = new Opcode(name, opcode_value_++);
  opcode_vec_.push_back(opcode);
  return opcode;
}

Opcode* OpcodeFactory::CreateChildOpcode(Opcode* opcode) const {
  if (opcode == nullptr) return nullptr;
  auto* child = new Opcode(opcode->name(), -1);
  return child;
}

absl::StatusOr<Opcode*> OpcodeFactory::CreateDerivedOpcode(
    const Opcode* opcode, TemplateInstantiationArgs* args) {
  // Allocate a new opcode. Copy the basic information.
  auto new_opcode = new Opcode(opcode->name(), opcode->value());
  new_opcode->set_instruction_size(opcode->instruction_size());
  new_opcode->predicate_op_name_ = opcode->predicate_op_name();
  new_opcode->op_locator_map_ = opcode->op_locator_map();
  for (auto const& src_op : opcode->source_op_vec()) {
    new_opcode->AppendSourceOp(src_op.name, src_op.is_array, src_op.is_reloc);
  }

  // Copy destination operands, but evaluate any latencies using the template
  // instantiation arguments, in case those expressions use them.
  for (auto const* dest_op : opcode->dest_op_vec()) {
    if (dest_op->expression() == nullptr) {
      new_opcode->AppendDestOp(dest_op->name(), dest_op->is_array(),
                               dest_op->is_reloc());
    } else {
      // For each destination operand that has an expression, evaluate it in the
      // context of the passed in TemplateInstantiationArgs. This creates a copy
      // of the expression tree where any constant subexpressions are
      // recursively folded into constant nodes.
      auto result = dest_op->expression()->Evaluate(args);
      if (result.ok()) {
        new_opcode->AppendDestOp(dest_op->name(), dest_op->is_array(),
                                 dest_op->is_reloc(), result.value());
      } else {
        delete new_opcode;
        return absl::InternalError(absl::StrCat(
            "Failed to create derived opcode for '", opcode->name(), "'"));
      }
    }
  }

  return new_opcode;
}

}  // namespace instruction_set
}  // namespace machine_description
}  // namespace sim
}  // namespace mpact
