// 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 "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/instruction_set.h"
#include "mpact/sim/decoder/opcode.h"
#include "mpact/sim/decoder/slot.h"
#include "mpact/sim/decoder/template_expression.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-evaluating
// any expressions that depend on any slot template instantiation values.
absl::StatusOr<Instruction*> Instruction::CreateDerivedInstruction(
    TemplateInstantiationArgs* args, Slot* new_slot) 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_slot->AddAttributeName(attr_name);
      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, new_slot);
  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->is_array,
                                        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
