// 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/instruction.h"

#include "mpact/sim/decoder/instruction_set.h"
#include "mpact/sim/decoder/slot.h"

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

Instruction::Instruction(Opcode *opcode, Slot *slot)
    : Instruction(opcode, nullptr, slot) {}
Instruction::Instruction(Opcode *opcode, Instruction *child, Slot *slot)
    : opcode_(opcode), child_(child), slot_(slot) {}

Instruction::~Instruction() {
  delete child_;
  delete opcode_;
  for (auto *ref : resource_use_vec_) {
    delete ref;
  }
  resource_use_vec_.clear();
  for (auto *ref : resource_acquire_vec_) {
    delete ref;
  }
  resource_acquire_vec_.clear();
  for (auto *disasm_format : disasm_format_vec_) {
    delete disasm_format;
  }
  disasm_format_vec_.clear();
  for (auto &[ignored, expr] : attribute_map_) {
    delete expr;
  }
  attribute_map_.clear();
}

// Append is implemented recursively. Few instructions have child instances,
// and when they do it's likely to be a very small number. Not concern for
// efficiency here.
void Instruction::AppendChild(Instruction *child) {
  if (child_ == nullptr) {
    child_ = child;
    return;
  }
  child_->AppendChild(child);
}

void Instruction::AppendResourceUse(const ResourceReference *resource_ref) {
  resource_use_vec_.push_back(resource_ref);
}

void Instruction::AppendResourceAcquire(const ResourceReference *resource_ref) {
  resource_acquire_vec_.push_back(resource_ref);
}

void Instruction::AddInstructionAttribute(absl::string_view attr_name,
                                          TemplateExpression *expression) {
  // See if the attribute is already defined. If not, create a new attribute
  // in the map, otherwise update the expression.
  auto iter = attribute_map_.find(attr_name);
  if (iter == attribute_map_.end()) {
    attribute_map_.emplace(attr_name, expression);
    return;
  }
  delete iter->second;
  iter->second = expression;
}

// Add an attribute with the default value 1.
void Instruction::AddInstructionAttribute(absl::string_view attr_name) {
  AddInstructionAttribute(attr_name, new TemplateConstant(1));
}

void Instruction::AppendDisasmFormat(DisasmFormat *disasm_format) {
  disasm_format_vec_.push_back(disasm_format);
}

// Creating a derived instruction involves copying attributes and re-evaulating
// any expressions that depend on any slot template instantiation values.
absl::StatusOr<Instruction *> Instruction::CreateDerivedInstruction(
    TemplateInstantiationArgs *args) const {
  // First try to create a derived opcode object. Fail if it fails.
  auto op_result =
      slot_->instruction_set()->opcode_factory()->CreateDerivedOpcode(opcode(),
                                                                      args);
  if (!op_result.ok()) return op_result.status();

  // Create a new instruction object with the derived opcode object.
  auto *new_inst = new Instruction(op_result.value(), slot_);

  // Disassembly format.
  for (auto const *disasm_fmt : disasm_format_vec()) {
    new_inst->AppendDisasmFormat(new DisasmFormat(*disasm_fmt));
  }
  // Semantic function string.
  new_inst->set_semfunc_code_string(semfunc_code_string());

  // Resource uses.
  for (auto const &resource_use : resource_use_vec()) {
    auto ref_result = CreateDerivedResourceRef(resource_use, args);
    if (!ref_result.status().ok()) {
      delete new_inst;
      return ref_result.status();
    }
    new_inst->AppendResourceUse(ref_result.value());
  }

  // Resource reservations.
  for (auto const *resource_def : resource_acquire_vec()) {
    auto ref_result = CreateDerivedResourceRef(resource_def, args);
    if (!ref_result.status().ok()) {
      delete new_inst;
      return ref_result.status();
    }
    new_inst->AppendResourceAcquire(ref_result.value());
  }

  // Instruction attributes.
  for (auto const &[attr_name, expr_ptr] : attribute_map_) {
    auto result = expr_ptr->Evaluate(args);
    if (result.ok()) {
      new_inst->AddInstructionAttribute(attr_name, result.value());
    } else {
      delete new_inst;
      return absl::InternalError(absl::StrCat(
          "Failed to create derived instruction for '", opcode()->name(), "'"));
    }
  }

  // Recursively hande child instructions.
  if (child() == nullptr) return new_inst;

  auto result = child()->CreateDerivedInstruction(args);
  if (result.ok()) {
    new_inst->AppendChild(result.value());
    return new_inst;
  }
  delete new_inst;
  return result.status();
}

absl::StatusOr<ResourceReference *> Instruction::CreateDerivedResourceRef(
    const ResourceReference *ref, TemplateInstantiationArgs *args) const {
  TemplateExpression *begin_expr = nullptr;
  TemplateExpression *end_expr = nullptr;
  // Evaluate the begin expression in the context of any template instantiation
  // arguments.
  if (ref->begin_expression != nullptr) {
    auto result = ref->begin_expression->Evaluate(args);
    if (!result.ok()) {
      return absl::InternalError(absl::StrCat(
          "Failed to create derived instruction for '", opcode()->name(),
          "': error evaluating begin expression"));
    }
    begin_expr = result.value();
  }
  // Evaluate the end expression in the context of any template instantiation
  // arguments.
  if (ref->end_expression != nullptr) {
    auto result = ref->end_expression->Evaluate(args);
    if (!result.ok()) {
      return absl::InternalError(absl::StrCat(
          "Failed to create derived instruction for '", opcode()->name(),
          "': error evaluating begin expression"));
    }
    end_expr = result.value();
  }
  auto *new_ref =
      new ResourceReference(ref->resource, ref->dest_op, begin_expr, end_expr);
  return new_ref;
}

// The destination op is stored in the opcode object, however, the child pointer
// is in the instruction object, so traverse the instructions along the child
// chain to find the destination operand.
DestinationOperand *Instruction::GetDestOp(absl::string_view op_name) const {
  auto dest_op = opcode()->GetDestOp(op_name);
  if (dest_op != nullptr) return dest_op;

  if (child() != nullptr) {
    return child()->GetDestOp(op_name);
  }
  return nullptr;
}

// The following methods are used to clear the different instruction attributes.
// This is called prior to overriding the attribute value to clean up any
// allocated memory.
void Instruction::ClearDisasmFormat() {
  for (auto *disasm_format : disasm_format_vec_) {
    delete disasm_format;
  }
  disasm_format_vec_.clear();
}

void Instruction::ClearSemfuncCodeString() { semfunc_code_string_.clear(); }

void Instruction::ClearResourceSpecs() {
  for (auto *ref : resource_use_vec_) {
    delete ref;
  }
  resource_use_vec_.clear();
  for (auto *ref : resource_acquire_vec_) {
    delete ref;
  }
  resource_acquire_vec_.clear();
}

void Instruction::ClearAttributeSpecs() {
  for (auto &[ignored, expr] : attribute_map_) {
    delete expr;
  }
  attribute_map_.clear();
}

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