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

#include <cctype>
#include <cstddef>
#include <filesystem>  // NOLINT: third party.
#include <fstream>
#include <iostream>
#include <istream>
#include <memory>
#include <new>
#include <optional>
#include <string>
#include <utility>
#include <variant>
#include <vector>

#include "absl/container/flat_hash_map.h"
#include "absl/container/flat_hash_set.h"
#include "absl/status/status.h"
#include "absl/status/statusor.h"
#include "absl/strings/str_cat.h"
#include "absl/strings/string_view.h"
#include "antlr4-runtime/ParserRuleContext.h"
#include "mpact/sim/decoder/bundle.h"
#include "mpact/sim/decoder/decoder_error_listener.h"
#include "mpact/sim/decoder/format_name.h"
#include "mpact/sim/decoder/instruction_set.h"
#include "mpact/sim/decoder/instruction_set_contexts.h"
#include "mpact/sim/decoder/opcode.h"
#include "mpact/sim/decoder/slot.h"
#include "mpact/sim/decoder/template_expression.h"
#include "re2/re2.h"

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

static absl::StatusOr<TemplateValue> AbsoluteValueTemplateFunc(
    TemplateInstantiationArgs *args) {
  if (args->size() != 1) {
    return absl::InternalError(absl::StrCat(
        "Wrong number of arguments, expected 1, was given ", args->size()));
  }
  auto result = (*args)[0]->GetValue();
  if (!result.ok()) return result.status();

  auto *value_ptr = std::get_if<int>(&result.value());
  if (value_ptr == nullptr) {
    return absl::InternalError("Type mismatch - int expected");
  }
  int return_value = (*value_ptr < 0) ? -(*value_ptr) : *value_ptr;
  return TemplateValue(return_value);
}

InstructionSetVisitor::InstructionSetVisitor() {
  template_function_evaluators_.insert(std::make_pair(
      "abs", TemplateFunctionEvaluator(AbsoluteValueTemplateFunc, 1)));
}

InstructionSetVisitor::~InstructionSetVisitor() {
  for (auto &[unused, expr_ptr] : constant_map_) {
    delete expr_ptr;
  }
  constant_map_.clear();
  for (auto *wrapper : antlr_parser_wrappers_) {
    delete wrapper;
  }
  antlr_parser_wrappers_.clear();
  for (auto *expr : disasm_field_widths_) delete expr;
  disasm_field_widths_.clear();
}

// Main entry point for processing the file.
absl::Status InstructionSetVisitor::Process(
    const std::vector<std::string> &file_names, const std::string &prefix,
    const std::string &isa_name, const std::vector<std::string> &include_roots,
    absl::string_view directory) {
  // Create and add the error listener.
  set_error_listener(std::make_unique<decoder::DecoderErrorListener>());
  if (isa_name.empty()) {
    error_listener()->semanticError(nullptr, "Isa name cannot be empty");
    return absl::InvalidArgumentError("Isa name cannot be empty");
  }

  for (auto &include_root : include_roots) {
    include_dir_vec_.push_back(include_root);
  }

  std::string isa_prefix = prefix;
  std::istream *source_stream = &std::cin;

  if (!file_names.empty()) {
    source_stream = new std::fstream(file_names[0], std::fstream::in);
  }
  // Create an antlr4 stream from the input stream.
  IsaAntlrParserWrapper parser_wrapper(source_stream);
  error_listener()->set_file_name(file_names[0]);
  parser_wrapper.parser()->removeErrorListeners();
  parser_wrapper.parser()->addErrorListener(error_listener());

  // Parse the file and then create the data structures.
  TopLevelCtx *top_level = parser_wrapper.parser()->top_level();

  if (!file_names.empty()) {
    delete source_stream;
    source_stream = nullptr;
  }

  if (error_listener()->HasError() > 0) {
    return absl::InternalError("Errors encountered - terminating.");
  }

  // Visit the parse tree starting at the namespaces declaration.
  VisitTopLevel(top_level);
  // Process additional source files.
  for (int i = 1; i < file_names.size(); ++i) {
    ParseIncludeFile(top_level, file_names[i], {});
  }
  // Now process the parse tree.
  auto instruction_set = ProcessTopLevel(isa_name);
  // Include files may generate additional syntax errors.
  if (instruction_set == nullptr) {
    return absl::InternalError("Errors encountered - terminating.");
  }
  // Verify that all referenced bundles and slots were defined.
  PerformBundleReferenceChecks(instruction_set.get(),
                               instruction_set->bundle());
  if (error_listener()->HasError() > 0) {
    return absl::InternalError("Errors encountered - terminating.");
  }
  // Analyze resource use and partition resources into simple and complex
  // resources.
  auto status = instruction_set->AnalyzeResourceUse();
  if (!status.ok()) {
    error_listener()->semanticError(nullptr, status.message());
  }

  // If the prefix is empty, use the source file name.
  if (isa_prefix.empty() && file_names.empty()) {
    error_listener()->semanticError(nullptr,
                                    "No prefix or file name specified");
  } else if (isa_prefix.empty()) {
    isa_prefix =
        ToSnakeCase(std::filesystem::path(file_names[0]).stem().string());
  }
  // Check for additional errors.
  if (error_listener()->HasError() > 0) {
    return absl::InternalError("Errors encountered - terminating.");
  }
  std::string encoding_type_name =
      absl::StrCat(ToPascalCase(isa_name), "EncodingBase");

  // Create output streams for .h and .cc files.
  std::string dot_h_name = absl::StrCat(isa_prefix, "_decoder.h");
  std::string dot_cc_name = absl::StrCat(isa_prefix, "_decoder.cc");
  std::string enum_h_name = absl::StrCat(isa_prefix, "_enums.h");
  std::string enum_cc_name = absl::StrCat(isa_prefix, "_enums.cc");
  std::ofstream dot_h_file(absl::StrCat(directory, "/", dot_h_name));
  std::ofstream dot_cc_file(absl::StrCat(directory, "/", dot_cc_name));
  std::ofstream enum_h_file(absl::StrCat(directory, "/", enum_h_name));
  std::ofstream enum_cc_file(absl::StrCat(directory, "/", enum_cc_name));
  // Generate the code, close the files and return.
  std::string guard_name = ToHeaderGuard(dot_h_name);
  dot_h_file << GenerateHdrFileProlog(dot_h_name, enum_h_name, guard_name,
                                      encoding_type_name,
                                      instruction_set->namespaces());
  dot_h_file << instruction_set->GenerateClassDeclarations(
      dot_h_name, enum_h_name, encoding_type_name);
  dot_h_file << GenerateHdrFileEpilog(guard_name,
                                      instruction_set->namespaces());
  dot_cc_file << GenerateCcFileProlog(dot_h_name,
                                      instruction_set->namespaces());
  dot_cc_file << instruction_set->GenerateClassDefinitions(dot_h_name,
                                                           encoding_type_name);
  dot_cc_file << GenerateNamespaceEpilog(instruction_set->namespaces());
  enum_cc_file << GenerateCcFileProlog(enum_h_name,
                                       instruction_set->namespaces());
  enum_h_file << GenerateSimpleHdrProlog(ToHeaderGuard(enum_h_name),
                                         instruction_set->namespaces());
  auto [h_output, cc_output] = instruction_set->GenerateEnums(enum_h_name);
  enum_h_file << h_output;
  enum_cc_file << cc_output;
  enum_h_file << GenerateHdrFileEpilog(ToHeaderGuard(enum_h_name),
                                       instruction_set->namespaces());
  enum_cc_file << GenerateNamespaceEpilog(instruction_set->namespaces());
  dot_h_file.close();
  dot_cc_file.close();
  enum_h_file.close();
  enum_cc_file.close();

  return absl::OkStatus();
}

void InstructionSetVisitor::PerformBundleReferenceChecks(
    InstructionSet *instruction_set, Bundle *bundle) {
  // Verify that all referenced bundles were declared.
  for (const auto &bundle_name : bundle->bundle_names()) {
    Bundle *bundle_ref = instruction_set->GetBundle(bundle_name);
    // Perform the check recursively on the referenced bundles.
    PerformBundleReferenceChecks(instruction_set, bundle_ref);
  }
  // Verify that all the slot uses were declared.
  for (auto &[slot_name, instance_vec] : bundle->slot_uses()) {
    Slot *slot = instruction_set->GetSlot(slot_name);
    // Verify that the instance number of the slot falls within valid range.
    for (auto &instance_number : instance_vec) {
      if (instance_number >= slot->size()) {
        auto *token = bundle->ctx() == nullptr ? nullptr : bundle->ctx()->start;
        error_listener()->semanticError(
            token,
            absl::StrCat("Index ", instance_number, " out of range for slot ",
                         slot_name, "' referenced in bundle '", bundle->name(),
                         "'"));
        continue;
      }
    }
    if (slot->is_referenced()) continue;
    if ((slot->default_instruction() == nullptr) ||
        slot->default_instruction()->semfunc_code_string().empty()) {
      error_listener()->semanticError(
          slot->ctx()->start,
          absl::StrCat("Slot '", slot->name(),
                       "' lacks a default semantic action"));
    }
    slot->set_is_referenced(true);
  }
  instruction_set->ComputeSlotAndBundleOrders();
}

void InstructionSetVisitor::VisitTopLevel(TopLevelCtx *ctx) {
  auto declarations = ctx->declaration();

  // Process disasm widths. Only the one in the top level file is used if there
  // are additional ones in included files.
  int count = 0;
  std::string location;
  for (auto *decl : declarations) {
    if (decl->disasm_widths() == nullptr) continue;
    if (count > 0) {
      error_listener()->semanticError(
          nullptr, absl::StrCat("Only one `disasm width` declaration allowed - "
                                "previous declaration on line: ",
                                location));
    }
    VisitDisasmWidthsDecl(decl->disasm_widths());
    location = absl::StrCat(decl->start->getLine());
    count++;
  }

  // Parse, but don't process all the slots, bundles, isas and include files.
  PreProcessDeclarations(declarations);
}

std::unique_ptr<InstructionSet> InstructionSetVisitor::ProcessTopLevel(
    absl::string_view isa_name) {
  // At this point we have the contexts for all isas, bundles, and slots.
  // First make sure that the named isa has been defined.
  auto isa_ptr = isa_decl_map_.find(isa_name);
  if (isa_ptr == isa_decl_map_.end()) {
    error_listener()->semanticError(
        nullptr, absl::StrCat("No isa '", isa_name, "' declared"));
    return nullptr;
  }
  // Visit the Isa.
  auto isa = VisitIsaDeclaration(isa_ptr->second);
  return isa;
}

void InstructionSetVisitor::PreProcessDeclarations(
    const std::vector<DeclarationCtx *> &ctx_vec) {
  std::vector<IncludeFileCtx *> include_files;
  // Get handles to the slot, bundle and isa declarations.

  // Create map from slot name to slot ctx.
  for (auto *decl : ctx_vec) {
    if (decl->slot_declaration() != nullptr) {
      auto *slot_ctx = decl->slot_declaration();
      auto name = slot_ctx->slot_name->getText();
      auto ptr = slot_decl_map_.find(name);
      if (ptr != slot_decl_map_.end()) {
        error_listener()->semanticError(
            slot_ctx->start,
            absl::StrCat("Slot '", name,
                         "' already declared - previous declaration on line: ",
                         slot_ctx->start->getLine()));
      }
      slot_decl_map_.emplace(name, slot_ctx);
    }
    // Create map from bundle name to bundle ctx.
    if (decl->bundle_declaration() != nullptr) {
      auto *bundle_ctx = decl->bundle_declaration();
      auto name = bundle_ctx->bundle_name->getText();
      auto ptr = bundle_decl_map_.find(name);
      if (ptr != bundle_decl_map_.end()) {
        error_listener()->semanticError(
            bundle_ctx->start,
            absl::StrCat("Bundle '", name,
                         "' already declared - previous declaration on line: ",
                         bundle_ctx->start->getLine()));
        continue;
      }
      bundle_decl_map_.emplace(name, bundle_ctx);
    }
    // Create map from isa name to isa ctx.
    if (decl->isa_declaration() != nullptr) {
      auto *isa_ctx = decl->isa_declaration();
      auto name = isa_ctx->instruction_set_name->getText();
      auto ptr = isa_decl_map_.find(name);
      if (ptr != isa_decl_map_.end()) {
        error_listener()->semanticError(
            isa_ctx->start,
            absl::StrCat("Isa '", name,
                         "' already declared - previous declaration on line: ",
                         isa_ctx->start->getLine()));
        continue;
      }
      isa_decl_map_.emplace(name, isa_ctx);
    }

    // Process global include file specifications.
    if (decl->include_file_list() != nullptr) {
      for (auto *include_file : decl->include_file_list()->include_file()) {
        // Insert the string - the call will always succeed, but the insertion
        // does not happen if it already exists.
        include_files_.insert(include_file->STRING_LITERAL()->getText());
      }
    }

    // Process global constants.
    if (decl->constant_def() != nullptr) {
      VisitConstantDef(decl->constant_def());
    }

    // Process .isa include file.
    if (decl->include_file() != nullptr) {
      include_files.push_back(decl->include_file());
    }
  }
  // Process all include files - this adds to all isa, slot and bundle
  // context maps, as well as all global variables, etc.
  for (auto *include_file_ctx : include_files) {
    VisitIncludeFile(include_file_ctx);
  }
}

std::unique_ptr<InstructionSet> InstructionSetVisitor::VisitIsaDeclaration(
    IsaDeclCtx *ctx) {
  if (ctx == nullptr) return nullptr;
  auto instruction_set =
      std::make_unique<InstructionSet>(ctx->instruction_set_name->getText());
  // An InstructionSet also acts as (has-a bundle) - it's the top level
  // bundle.
  instruction_set->set_bundle(
      new Bundle(instruction_set->name(), instruction_set.get(), nullptr));
  // Visit the namespace declaration, and the bundle and slot references that
  // are part of the instruction_set declaration.
  VisitNamespaceDecl(ctx->namespace_decl(), instruction_set.get());
  VisitBundleList(ctx->bundle_list(), instruction_set->bundle());
  VisitSlotList(ctx->slot_list(), instruction_set->bundle());
  return instruction_set;
}

void InstructionSetVisitor::VisitNamespaceDecl(NamespaceDeclCtx *ctx,
                                               InstructionSet *isa) {
  if (ctx == nullptr) return;
  for (auto *namespace_name : ctx->namespace_ident()) {
    isa->namespaces().push_back(namespace_name->getText());
  }
}

void InstructionSetVisitor::VisitBundleList(BundleListCtx *ctx,
                                            Bundle *bundle) {
  if (ctx == nullptr) return;
  // Append the list of named bundles referenced within the containing bundle.
  auto bundle_specs_vec = ctx->bundle_spec();
  for (auto bundle_spec : bundle_specs_vec) {
    auto bundle_name = bundle_spec->IDENT()->getText();
    auto iter = bundle_decl_map_.find(bundle_name);
    // If the name hasn't been seen, flag an error.
    if (iter == bundle_decl_map_.end()) {
      error_listener()->semanticError(
          bundle_spec->start,
          absl::StrCat("Reference to undefined bundle: '", bundle_name, "'"));
      continue;
    }
    // If the bundle hasn't been processed yet, visit its declaration.
    if (!bundle->instruction_set()->bundle_map().contains(bundle_name)) {
      VisitBundleDeclaration(iter->second, bundle->instruction_set());
    }
    bundle->AppendBundleName(bundle_spec->IDENT()->getText());
  }
}

void InstructionSetVisitor::VisitSlotList(SlotListCtx *ctx, Bundle *bundle) {
  if (ctx == nullptr) return;
  // Append the list of named slots referenced within the containing bundle.
  auto slot_specs_vec = ctx->slot_spec();
  for (auto slot_spec : slot_specs_vec) {
    auto slot_name = slot_spec->IDENT()->getText();
    auto iter = slot_decl_map_.find(slot_name);
    // If the slot hasn't been seen, flag an error.
    if (iter == slot_decl_map_.end()) {
      error_listener()->semanticError(
          slot_spec->start,
          absl::StrCat("Reference to undefined slot: '", slot_name, "'"));
      continue;
    }
    // If the slot hasn't been processed yet, visit its declaration.
    if (!bundle->instruction_set()->slot_map().contains(slot_name)) {
      VisitSlotDeclaration(iter->second, bundle->instruction_set());
    }
    // First obtain the vector of instance indices specified before appending.
    std::vector<int> instances = VisitArraySpec(slot_spec->array_spec());
    bundle->AppendSlot(slot_name, instances);
  }
}

std::vector<int> InstructionSetVisitor::VisitArraySpec(ArraySpecCtx *ctx) {
  std::vector<int> instances;

  // If there are not array specifications, return the empty vector.
  if (ctx == nullptr) return instances;

  auto range_spec_vec = ctx->range_spec();
  for (auto range_spec : range_spec_vec) {
    // The range spec is on the form of n, or m..n. Add the appropriate
    // indices to the instances vector.
    int range_start;
    int range_end;
    range_end = range_start = std::stoi(range_spec->range_start->getText());
    if (range_spec->range_end != nullptr) {
      range_end = std::stoi(range_spec->range_end->getText());
    }
    for (int instance = range_start; instance <= range_end; instance++) {
      instances.push_back(instance);
    }
  }
  return instances;
}

void InstructionSetVisitor::VisitConstantDef(ConstantDefCtx *ctx) {
  if (ctx == nullptr) return;
  std::string ident = ctx->ident()->getText();
  std::string type = ctx->template_parameter_type()->getText();
  auto *expr = VisitExpression(ctx->expression(), nullptr, nullptr);
  auto status = AddConstant(ident, type, expr);
  if (!status.ok()) {
    delete expr;
    error_listener()->semanticError(ctx->ident()->start, status.message());
  }
}

void InstructionSetVisitor::VisitIncludeFile(IncludeFileCtx *ctx) {
  // The literal includes the double quotes.
  std::string literal = ctx->STRING_LITERAL()->getText();
  // Remove the double quotes from the literal and construct the full file
  // name.
  std::string file_name = literal.substr(1, literal.length() - 2);
  // Check for recursive include.
  for (auto const &name : include_file_stack_) {
    if (name == file_name) {
      error_listener()->semanticError(
          ctx->start,
          absl::StrCat(": ", "Recursive include of '", file_name, "'"));
      return;
    }
  }
  ParseIncludeFile(ctx, file_name, include_dir_vec_);
}

void InstructionSetVisitor::ParseIncludeFile(
    antlr4::ParserRuleContext *ctx, const std::string &file_name,
    const std::vector<std::string> &dirs) {
  std::fstream include_file;
  // Open include file.
  include_file.open(file_name, std::fstream::in);
  if (!include_file.is_open()) {
    // Try each of the include file directories.
    for (auto const &dir : dirs) {
      std::string include_name = dir + "/" + file_name;
      include_file.open(include_name, std::fstream::in);
      if (include_file.is_open()) break;
    }
    if (!include_file.is_open()) {
      error_listener()->semanticError(
          ctx == nullptr ? nullptr : ctx->start,
          absl::StrCat("Failed to open '", file_name, "'", " ", dirs.size()));
      return;
    }
  }
  std::string previous_file_name = error_listener()->file_name();
  error_listener()->set_file_name(file_name);
  // Create an antlr4 stream from the input stream.
  auto *include_parser = new IsaAntlrParserWrapper(&include_file);
  // We need to save the parser state so it's available for analysis after
  // we are done with building the parse trees.
  antlr_parser_wrappers_.push_back(include_parser);
  // Add the error listener.
  include_parser->parser()->removeErrorListeners();
  include_parser->parser()->addErrorListener(error_listener());
  // Start parsing at the include_top_level rule.
  auto declaration_vec =
      include_parser->parser()->include_top_level()->declaration();
  include_file.close();
  error_listener()->set_file_name(previous_file_name);
  if (error_listener()->syntax_error_count() > 0) {
    return;
  }
  include_file_stack_.push_back(file_name);
  PreProcessDeclarations(declaration_vec);
  include_file_stack_.pop_back();
}

void InstructionSetVisitor::VisitBundleDeclaration(
    BundleDeclCtx *ctx, InstructionSet *instruction_set) {
  if (ctx == nullptr) return;
  Bundle *bundle =
      new Bundle(ctx->bundle_name->getText(), instruction_set, ctx);
  instruction_set->AddBundle(bundle);
  VisitBundleList(ctx->bundle_list(), bundle);
  VisitSlotList(ctx->slot_list(), bundle);
}

void InstructionSetVisitor::VisitSlotDeclaration(
    SlotDeclCtx *ctx, InstructionSet *instruction_set) {
  bool is_templated = ctx->template_decl() != nullptr;
  Slot *slot =
      new Slot(ctx->slot_name->getText(), instruction_set, is_templated, ctx);
  if (is_templated) {
    for (auto const &param : ctx->template_decl()->template_parameter_decl()) {
      auto status = slot->AddTemplateFormal(param->IDENT()->getText());
      if (!status.ok()) {
        error_listener()->semanticError(param->start, status.message());
      }
    }
  }
  // Set the base slot if it inherits.
  if (ctx->base_item_list() != nullptr) {
    // For each entry in the list of slots to derive from.
    for (auto *base_item : ctx->base_item_list()->base_item()) {
      std::string base_name = base_item->IDENT()->getText();
      // If the base slot does has not been seen - undefined error.
      auto slot_iter = slot_decl_map_.find(base_name);
      if (slot_iter == slot_decl_map_.end()) {
        error_listener()->semanticError(
            base_item->start, absl::StrCat("Undefined base slot: ", base_name));
        continue;
      }
      // If the slot hasn't been visited, visit it.
      auto *base = instruction_set->GetSlot(base_name);
      if (base == nullptr) {
        VisitSlotDeclaration(slot_iter->second, instruction_set);
        base = instruction_set->GetSlot(base_name);
      }
      // Now check if the base slot is templated or not, and if the template
      // arguments are present or not.
      auto *template_spec = base_item->template_spec();
      if ((template_spec != nullptr) && !base->is_templated()) {
        // Template arguments are present but the slot isn't templated.
        error_listener()->semanticError(
            base_item->start,
            absl::StrCat("'", base_name, "' is not a templated slot"));
        continue;
      }
      if ((template_spec == nullptr) && base->is_templated()) {
        // The slot is templated, but no template arguments.
        error_listener()->semanticError(
            base_item->start,
            absl::StrCat("Missing template arguments for slot '", base_name,
                         "'"));
        continue;
      }
      if (template_spec != nullptr) {
        // Check that the number of arguments match.
        int arg_count = template_spec->expression().size();
        int param_count = base->template_parameters().size();
        if (arg_count != param_count) {
          error_listener()->semanticError(
              template_spec->start,
              absl::StrCat("Wrong number of arguments: ", param_count,
                           " were expected, ", arg_count, " were provided"));
          continue;
        }
        bool has_error = false;
        // Build up the argument vector.
        auto *arguments = new TemplateInstantiationArgs;
        for (auto *template_arg : template_spec->expression()) {
          auto *expr = VisitExpression(template_arg, slot, nullptr);
          if (expr == nullptr) {
            error_listener()->semanticError(template_arg->start,
                                            "Error in template expression");
            has_error = true;
            break;
          }
          arguments->push_back(expr);
        }
        if (has_error) {
          for (auto *expr : *arguments) {
            delete expr;
          }
          delete arguments;
          continue;
        }
        auto result = slot->AddBase(base, arguments);
        if (!result.ok()) {
          error_listener()->semanticError(base_item->start, result.message());
        }
      } else {
        // No template arguments.
        auto result = slot->AddBase(base);
        if (!result.ok()) {
          error_listener()->semanticError(base_item->start, result.message());
        }
      }
    }
  }
  // Set the size if it is replicated.
  if (ctx->size_spec() != nullptr) {
    int size = std::stoi(ctx->size_spec()->NUMBER()->getText(), nullptr, 0);
    slot->set_size(size);
  }
  // Add the slot to the ISA.
  instruction_set->AddSlot(slot);
  for (auto *decl_ctx : ctx->const_and_default_decl()) {
    VisitConstAndDefaultDecls(decl_ctx, slot);
  }
  VisitOpcodeList(ctx->opcode_list(), slot);
}

void InstructionSetVisitor::VisitDisasmWidthsDecl(DisasmWidthsCtx *ctx) {
  for (auto *expr : ctx->expression()) {
    auto *width_expr = VisitExpression(expr, nullptr, nullptr);
    if ((width_expr == nullptr) || (!width_expr->IsConstant())) {
      error_listener()->semanticError(expr->start,
                                      "Expression must be constant");
      continue;
    }
    disasm_field_widths_.push_back(width_expr);
  }
}

void InstructionSetVisitor::VisitConstAndDefaultDecls(ConstAndDefaultCtx *ctx,
                                                      Slot *slot) {
  if (ctx == nullptr) return;
  // A constant declaration.
  auto *const_def = ctx->constant_def();
  if (const_def != nullptr) {  // Constant declaration.
    std::string ident = const_def->ident()->getText();
    std::string type = const_def->template_parameter_type()->getText();
    auto *expr = VisitExpression(const_def->expression(), slot, nullptr);
    if (expr == nullptr) {
      delete expr;
      error_listener()->semanticError(const_def->expression()->start,
                                      "Error in expression");
      return;
    }
    auto status = slot->AddConstant(ident, type, expr);
    if (!status.ok()) {
      delete expr;
      error_listener()->semanticError(const_def->ident()->start,
                                      status.message());
    }
    return;
  }
  if (ctx->SIZE() != nullptr) {  // Default size.
    int value = std::stoi(ctx->NUMBER()->getText(), nullptr, 0);
    slot->set_default_instruction_size(value);
    return;
  }
  if (ctx->LATENCY() != nullptr) {  // Default latency.
    auto *expr = VisitExpression(ctx->expression(), slot, nullptr);
    if (expr == nullptr) {
      delete expr;
      error_listener()->semanticError(ctx->expression()->start,
                                      "Error in expression");
      return;
    }
    slot->set_default_latency(expr);
    return;
  }
  if (ctx->ATTRIBUTES() != nullptr) {  // Default attributes.
    VisitInstructionAttributeList(ctx->instruction_attribute_list(), slot,
                                  nullptr);
    return;
  }
  // Add any include files to our set of includes.
  if (ctx->include_file_list() != nullptr) {
    for (auto *include_file : ctx->include_file_list()->include_file()) {
      // Insert the string - the call will always succeed, but the insertion
      // does not happen if it already exists.
      include_files_.insert(include_file->STRING_LITERAL()->getText());
    }
  }
  if (ctx->OPCODE() != nullptr) {  // Default opcode.
    // Process the "default" instruction, which is used to specify disassembly
    // and semantic function for when no valid opcode is found during decode.
    if (slot->default_instruction() != nullptr) {
      error_listener()->semanticError(
          ctx->start, "Multiple definitions of 'default' opcode");
      return;
    }
    auto *default_instruction = new Instruction(
        slot->instruction_set()->opcode_factory()->CreateDefaultOpcode(), slot);
    bool has_disasm = false;
    bool has_semfunc = false;
    for (auto *attribute : ctx->opcode_attribute_list()->opcode_attribute()) {
      // Disasm spec.
      if (attribute->disasm_spec() != nullptr) {
        if (has_disasm) {
          error_listener()->semanticError(attribute->start,
                                          "Duplicate disasm declaration");
          continue;
        }
        has_disasm = true;
        for (auto *format_str : attribute->disasm_spec()->STRING_LITERAL()) {
          std::string format = format_str->getText();
          // Trim the double quotes.
          format.erase(format.size() - 1, 1);
          format.erase(0, 1);
          auto status = ParseDisasmFormat(format, default_instruction);
          if (!status.ok()) {
            error_listener()->semanticError(attribute->disasm_spec()->start,
                                            status.message());
          }
        }
        continue;
      }
      // Semfunc spec.
      // If a semfunc has already been declared, signal an error.
      if (has_semfunc) {
        error_listener()->semanticError(attribute->start,
                                        "Duplicate semfunc declaration");
        continue;
      }
      has_semfunc = true;
      auto semfunc_code = attribute->semfunc_spec()->STRING_LITERAL();
      // Only one semfunc specification (no child instructions) for default
      // opcode.
      if (semfunc_code.size() > 1) {
        error_listener()->semanticError(
            ctx->start, "Only one semfunc specification per default opcode");
        continue;
      }
      std::string string_literal = semfunc_code[0]->getText();
      // Strip double quotes.
      std::string code_string =
          string_literal.substr(1, string_literal.length() - 2);
      default_instruction->set_semfunc_code_string(code_string);
    }
    if (has_semfunc) {
      slot->set_default_instruction(default_instruction);
    } else {
      delete default_instruction;
      error_listener()->semanticError(
          ctx->start, "Default opcode lacks mandatory semfunc specification");
    }
  }
  if (ctx->resource_details() != nullptr) {
    std::string ident = ctx->ident()->getText();
    if (slot->resource_spec_map().contains(ident)) {
      error_listener()->semanticError(
          ctx->ident()->start,
          absl::StrCat("Resources '", ident, "': duplicate definition"));
      return;
    }
    // Save the context. It will be re-visited at each point of use.
    slot->resource_spec_map().insert(
        std::make_pair(ident, ctx->resource_details()));
  }
}

// Visit the template argument recursively to create an expression tree that
// can be evaluated later. No need to coalesce constant expression trees, the
// savings aren't that great.
TemplateExpression *InstructionSetVisitor::VisitExpression(ExpressionCtx *ctx,
                                                           Slot *slot,
                                                           Instruction *inst) {
  if (ctx == nullptr) return nullptr;
  if (ctx->negop() != nullptr) {
    TemplateExpression *expr = VisitExpression(ctx->expr, slot, inst);
    if (expr == nullptr) return nullptr;
    return new TemplateNegate(expr);
  }

  if (ctx->mulop() != nullptr) {
    std::string op = ctx->mulop()->getText();
    TemplateExpression *lhs = VisitExpression(ctx->lhs, slot, inst);
    if (lhs == nullptr) return nullptr;
    TemplateExpression *rhs = VisitExpression(ctx->rhs, slot, inst);
    if (rhs == nullptr) {
      delete lhs;
      return nullptr;
    }
    if (op == "*") return new TemplateMultiply(lhs, rhs);
    return new TemplateDivide(lhs, rhs);
  }

  if (ctx->addop() != nullptr) {
    std::string op = ctx->addop()->getText();
    TemplateExpression *lhs = VisitExpression(ctx->lhs, slot, inst);
    if (lhs == nullptr) return nullptr;
    TemplateExpression *rhs = VisitExpression(ctx->rhs, slot, inst);
    if (rhs == nullptr) {
      delete lhs;
      return nullptr;
    }
    if (op == "+") return new TemplateAdd(lhs, rhs);
    return new TemplateSubtract(lhs, rhs);
  }

  if (ctx->func != nullptr) {
    std::string function = ctx->func->getText();
    auto iter = template_function_evaluators_.find(function);
    if (iter == template_function_evaluators_.end()) {
      error_listener()->semanticError(
          ctx->start, absl::StrCat("No function '", function, "' supported"));
      return nullptr;
    }
    auto evaluator = iter->second;
    if (ctx->expression().size() != evaluator.arity) {
      error_listener()->semanticError(
          ctx->start, absl::StrCat("Function '", function, "' takes ",
                                   evaluator.arity, " parameters, but ",
                                   ctx->expression().size(), " were given"));
    }
    auto *args = new TemplateInstantiationArgs;
    bool has_error = false;
    for (auto *expr_ctx : ctx->expression()) {
      auto *expr = VisitExpression(expr_ctx, slot, inst);
      if (expr == nullptr) {
        has_error = true;
        break;
      }
      args->push_back(expr);
    }
    if (has_error) {
      for (auto *expr : *args) {
        delete expr;
      }
      delete args;
      return nullptr;
    }
    return new TemplateFunction(evaluator.function, args);
  }

  if (ctx->paren_expr != nullptr) {
    return VisitExpression(ctx->paren_expr, slot, inst);
  }

  if (ctx->NUMBER() != nullptr) {
    auto *expr =
        new TemplateConstant(std::stoi(ctx->NUMBER()->getText(), nullptr, 0));
    return expr;
  }

  if (ctx->IDENT() != nullptr) {
    std::string ident = ctx->IDENT()->getText();
    // Four possibilities. A global constant, a slot local constant, a
    // template formal, or a reference to a destination operand.
    if (slot != nullptr) {
      TemplateFormal *param = slot->GetTemplateFormal(ident);
      if (param != nullptr) return new TemplateParam(param);

      // Check if it's a slot const expression.
      auto *expr = slot->GetConstExpression(ident);
      if (expr != nullptr) return expr->DeepCopy();
    }

    // It should be an opcode operand term, which means it should be a
    // destination operand with a latency. That is the value/expression that
    // is needed here.
    if (inst != nullptr) {
      auto *op = inst->GetDestOp(ident);
      if (op == nullptr) {
        error_listener()->semanticError(
            ctx->start,
            absl::StrCat("'", ident,
                         "' is not a valid destination operand for opcode '",
                         inst->opcode()->name(), "'"));
        return nullptr;
      }

      auto *expr = op->expression();
      if (expr != nullptr) return expr->DeepCopy();

      // expr is null, this means that the destination operand has a decode
      // time computed latency. This is a special case that will be addressed
      // later. For now, signal an unsupported error.
      error_listener()->semanticError(ctx->start,
                                      "Decode time evaluation of latency "
                                      "expression not supported for resources");
      return nullptr;
    }

    auto *expr = GetConstExpression(ident);
    if (expr != nullptr) return expr->DeepCopy();

    error_listener()->semanticError(
        ctx->start, absl::StrCat("Unable to evaluate expression: ", "'",
                                 ctx->getText(), "'"));
  }

  return nullptr;
}

DestinationOperand *InstructionSetVisitor::FindDestinationOpInExpression(
    ExpressionCtx *ctx, const Slot *slot, const Instruction *inst) const {
  if (ctx == nullptr) return nullptr;
  if (ctx->negop() != nullptr) {
    return FindDestinationOpInExpression(ctx->expr, slot, inst);
  }
  if ((ctx->mulop() != nullptr) || (ctx->addop() != nullptr)) {
    auto *lhs = FindDestinationOpInExpression(ctx->lhs, slot, inst);
    auto *rhs = FindDestinationOpInExpression(ctx->rhs, slot, inst);
    if (lhs == nullptr) return rhs;
    if (rhs == nullptr) return lhs;
    if (lhs == rhs) return lhs;

    error_listener()->semanticError(
        ctx->start,
        "Resource reference can only reference a single "
        "destination operand");
    return nullptr;
  }
  if (ctx->paren_expr != nullptr) {
    return FindDestinationOpInExpression(ctx->paren_expr, slot, inst);
  }
  if (ctx->NUMBER() != nullptr) {
    return nullptr;
  }
  if (ctx->func != nullptr) {
    DestinationOperand *dest_op = nullptr;
    DestinationOperand *tmp_op;
    for (auto *expr_ctx : ctx->expression()) {
      tmp_op = FindDestinationOpInExpression(expr_ctx, slot, inst);
      if (dest_op == nullptr) {
        dest_op = tmp_op;
        continue;
      }
      if (tmp_op != nullptr) {
        if (dest_op != tmp_op) {
          error_listener()->semanticError(
              ctx->start,
              "Resource reference can only reference a single "
              "destination operand");
        }
      }
    }
    return dest_op;
  }
  std::string ident = ctx->IDENT()->getText();
  // It is either a slot local constant, a template formal, or a reference
  // to a destination operand.
  TemplateFormal *param = slot->GetTemplateFormal(ident);
  if (param != nullptr) return nullptr;
  // Check if it's a slot const expression.
  auto *expr = slot->GetConstExpression(ident);
  if (expr != nullptr) return nullptr;
  // It should be an opcode operand term.
  return inst->GetDestOp(ident);
}

void InstructionSetVisitor::VisitOpcodeList(OpcodeListCtx *ctx, Slot *slot) {
  absl::flat_hash_set<std::string> deleted_ops_set;
  absl::flat_hash_set<OpcodeSpecCtx *> overridden_ops_set;
  std::vector<Instruction *> instruction_vec;
  if (ctx != nullptr) {
    ProcessOpcodeList(ctx, slot, instruction_vec, deleted_ops_set,
                      overridden_ops_set);
  }
  // For all base slots, and all opcodes that aren't excluded, add the opcodes
  // to the current slot. When adding the instruction, pass in any template
  // instantiation arguments to the base slot so that any expressions for
  // destination operand latencies can be evaluated.
  for (auto const &base_slot : slot->base_slots()) {
    if (base_slot.base->min_instruction_size() < slot->min_instruction_size()) {
      slot->set_min_instruction_size(base_slot.base->min_instruction_size());
    }
    // Copy over the instructions that were not deleted.
    for (auto &[unused, inst_ptr] : base_slot.base->instruction_map()) {
      if (!deleted_ops_set.contains(inst_ptr->opcode()->name())) {
        absl::Status status =
            slot->AppendInheritedInstruction(inst_ptr, base_slot.arguments);
        if (!status.ok()) {
          error_listener()->semanticError(ctx->start, status.message());
        }
      }
    }
    // Perform the overrides.
    PerformOpcodeOverrides(overridden_ops_set, slot);
  }
  // Add the declared opcodes.
  for (auto *inst : instruction_vec) {
    absl::Status status = slot->AppendInstruction(inst);
    if (!status.ok()) {
      error_listener()->semanticError(ctx->start, status.message());
    }
  }
}

void InstructionSetVisitor::PerformOpcodeOverrides(
    absl::flat_hash_set<OpcodeSpecCtx *> overridden_ops_set, Slot *slot) {
  for (auto *override_ctx : overridden_ops_set) {
    std::string name = override_ctx->name->getText();
    auto *inst = slot->instruction_map().at(name);
    VisitOpcodeAttributes(override_ctx->opcode_attribute_list(), inst, slot);
  }
}

void InstructionSetVisitor::VisitOpcodeAttributes(OpcodeAttributeListCtx *ctx,
                                                  Instruction *inst,
                                                  Slot *slot) {
  if (ctx == nullptr) return;
  // These flags are used to detect multiple instances of each attribute.
  bool has_disasm = false;
  bool has_semfunc = false;
  bool has_resources = false;
  bool has_attributes = false;
  // Visit the opcode attributes.
  for (auto *attribute_ctx : ctx->opcode_attribute()) {
    // Process any disassembly specifications.
    if (attribute_ctx->disasm_spec() != nullptr) {
      // In case of override, need to clear any disasm info in instruction.
      inst->ClearDisasmFormat();
      // Signal error if there is more than one disassembly spec.
      if (has_disasm) {
        error_listener()->semanticError(attribute_ctx->start,
                                        "Multiple disasm specifications");
        continue;
      }
      has_disasm = true;
      for (auto *disasm_fmt : attribute_ctx->disasm_spec()->STRING_LITERAL()) {
        std::string format = disasm_fmt->getText();
        // Trim the double quotes.
        format.erase(format.size() - 1, 1);
        format.erase(0, 1);
        auto status = ParseDisasmFormat(format, inst);
        if (!status.ok()) {
          error_listener()->semanticError(attribute_ctx->disasm_spec()->start,
                                          status.message());
          has_disasm = false;
          break;
        }
      }
      continue;
    }

    // Process the semantic function specification.
    if (attribute_ctx->semfunc_spec() != nullptr) {
      // In case of override, need to clear the semantic function string.
      inst->ClearSemfuncCodeString();
      // Signal error if there is more than one semantic function spec.
      if (has_semfunc) {
        error_listener()->semanticError(attribute_ctx->start,
                                        "Multiple semfunc specifications");
        continue;
      }
      has_semfunc = true;
      VisitSemfuncSpec(attribute_ctx->semfunc_spec(), inst);
      continue;
    }

    // Process resource specification.
    if (attribute_ctx->resource_spec() != nullptr) {
      // In case of override, need to clear the resource specifications.
      inst->ClearResourceSpecs();
      // Signal error if there is more than one resource specification.
      if (has_resources) {
        error_listener()->semanticError(attribute_ctx->start,
                                        "Multiple resource specifications");
        continue;
      }
      has_resources = true;
      VisitResourceDetails(attribute_ctx->resource_spec()->resource_details(),
                           inst, slot);
      continue;
    }

    // Process instruction attribute specification.
    if (attribute_ctx->instruction_attribute_spec() != nullptr) {
      // In case of override, need to clear the attribute specification.
      inst->ClearAttributeSpecs();
      // Signal error if there is more than one attribute specification.
      if (has_attributes) {
        error_listener()->semanticError(attribute_ctx->start,
                                        "Multiple attribute specifications");
        continue;
      }
      has_attributes = true;
      auto attr_list_ctx = attribute_ctx->instruction_attribute_spec()
                               ->instruction_attribute_list();
      VisitInstructionAttributeList(attr_list_ctx, slot, inst);
      continue;
    }

    // Unknown attribute type.
    error_listener()->semanticError(attribute_ctx->start,
                                    "Unknown attribute type");
  }
}

void InstructionSetVisitor::VisitInstructionAttributeList(
    InstructionAttributeListCtx *ctx, Slot *slot, Instruction *inst) {
  absl::flat_hash_map<std::string, TemplateExpression *> attributes;
  for (auto *attribute : ctx->instruction_attribute()) {
    std::string name = attribute->IDENT()->getText();
    if (attributes.find(name) != attributes.end()) {
      error_listener()->semanticError(
          attribute->start,
          absl::StrCat("Duplicate attribute name '", name, "' in list"));
      continue;
    }
    InstructionSet::AddAttributeName(name);
    if (attribute->expression() != nullptr) {
      auto *expr = VisitExpression(attribute->expression(), slot, inst);
      attributes.emplace(name, expr);
      continue;
    }
    attributes.emplace(name, new TemplateConstant(1));
  }
  // Are we parsing attributes for an instruction?
  if (inst != nullptr) {
    for (auto *child = inst; child != nullptr; child = child->child()) {
      for (auto &[name, expr] : attributes) {
        child->AddInstructionAttribute(name, expr);
      }
    }
    // Ownership of expr objects transferred to opcode.
    attributes.clear();
    return;
  }
  // Attributes are default attributes for the current slot.
  for (auto &[name, expr] : attributes) {
    slot->AddInstructionAttribute(name, expr);
  }
  attributes.clear();
}

void InstructionSetVisitor::VisitSemfuncSpec(SemfuncSpecCtx *semfunc_spec,
                                             Instruction *inst) {
  auto *child = inst;
  // Parse each string in the list of semantic function specifications. There
  // should be one the opcode and one for each child opcode.
  for (auto *sem_func : semfunc_spec->STRING_LITERAL()) {
    if (child == nullptr) {
      error_listener()->semanticWarning(sem_func->getSymbol(),
                                        "Ignoring extra semfunc spec");
      break;
    }
    std::string literal = sem_func->getText();
    std::string code_string = literal.substr(1, literal.length() - 2);
    child->set_semfunc_code_string(code_string);
    child = child->child();
  }
  // Are there fewer specifier strings than child instructions?
  if (child != nullptr) {
    error_listener()->semanticError(
        semfunc_spec->start,
        absl::StrCat("Fewer semfunc specifiers than expected for opcode '",
                     inst->opcode()->name(), "'"));
  }
}

void InstructionSetVisitor::VisitResourceDetails(ResourceDetailsCtx *ctx,
                                                 Instruction *inst,
                                                 Slot *slot) {
  if (ctx->ident() != nullptr) {
    // This is a reference to a resource spec defined earlier.
    std::string name = ctx->ident()->getText();
    auto iter = slot->resource_spec_map().find(name);
    if (iter == slot->resource_spec_map().end()) {
      // This should never happen.
      error_listener()->semanticError(
          ctx->start,
          absl::StrCat("Internal error: Undefined resources name: '", name,
                       "'"));
      return;
    }
    ctx = iter->second;
  }
  ResourceSpec spec;
  VisitResourceDetailsLists(ctx, slot, inst, &spec);
  for (auto *use : spec.use_vec) {
    inst->AppendResourceUse(use);
  }
  for (auto *acquire : spec.acquire_vec) {
    inst->AppendResourceAcquire(acquire);
  }
}

std::optional<ResourceReference *>
InstructionSetVisitor::ProcessResourceReference(
    Slot *slot, Instruction *inst, ResourceItemCtx *resource_item) {
  // Empty optional object.
  std::optional<ResourceReference *> return_value;

  auto *factory = slot->instruction_set()->resource_factory();
  DestinationOperand *dest_op = nullptr;
  // Extract the text from the resource reference.
  std::string ident_text = resource_item->name->getText();
  dest_op = inst->GetDestOp(ident_text);
  auto *resource = factory->GetOrInsertResource(ident_text);
  // Compute begin and end values.
  TemplateExpression *begin_expr;
  TemplateExpression *end_expr;
  DestinationOperand *tmp_op;
  if (resource_item->begin_cycle == nullptr) {
    begin_expr = new TemplateConstant(0);
  } else {
    tmp_op =
        FindDestinationOpInExpression(resource_item->begin_cycle, slot, inst);
    if (tmp_op != nullptr) {
      if (dest_op == nullptr) {
        dest_op = tmp_op;
      } else if (dest_op != tmp_op) {
        error_listener()->semanticError(
            resource_item->start,
            "Resource reference can only reference a single "
            "destination operand");
        return return_value;
      }
    }
    begin_expr = VisitExpression(resource_item->begin_cycle, slot, inst);
  }

  if (resource_item->end_cycle == nullptr) {
    // If there is no end_cycle specified, then it inherits from the dest_op
    // if available.
    // TODO(torerik): Handle case where the dest latency is '*'.
    if ((dest_op != nullptr) && (dest_op->expression() != nullptr)) {
      end_expr = dest_op->expression()->DeepCopy();
    } else {
      end_expr = new TemplateConstant(0);
    }
  } else {
    tmp_op =
        FindDestinationOpInExpression(resource_item->end_cycle, slot, inst);
    if (tmp_op != nullptr) {
      if (dest_op == nullptr) {
        dest_op = tmp_op;
      } else if (dest_op != tmp_op) {
        error_listener()->semanticError(
            resource_item->start,
            "Resource reference can only reference a single "
            "destination operand");
        delete begin_expr;
        return return_value;
      }
    }
    end_expr = VisitExpression(resource_item->end_cycle, slot, inst);
  }
  auto *ref = new ResourceReference(resource, dest_op, begin_expr, end_expr);
  return std::optional<ResourceReference *>(ref);
}

void InstructionSetVisitor::VisitResourceDetailsLists(ResourceDetailsCtx *ctx,
                                                      Slot *slot,
                                                      Instruction *inst,
                                                      ResourceSpec *spec) {
  if (ctx == nullptr) return;

  if ((ctx->use_list == nullptr) && (ctx->acquire_list == nullptr) &&
      (ctx->hold_list == nullptr))
    return;

  // The resource details consists of three lists: use, acquire, and
  // hold. The "use" list specifies the resources that have to only be
  // available at instruction dispatch time. The "acquire" list specifies the
  // list of resources that the instruction must be available to acquire, and
  // hold for a certain set of cycles. The hold list specifies the list of
  // resources that will be marked held (regardless of their status) for the
  // set of cycles specified.

  // Use list.
  auto *use_list = ctx->use_list;
  if (use_list != nullptr) {
    for (auto *resource_item : use_list->resource_item()) {
      auto ref_optional = ProcessResourceReference(slot, inst, resource_item);
      if (!ref_optional) continue;
      spec->use_vec.push_back(ref_optional.value());
    }
  }

  // Reserve list.
  auto *acquire_list = ctx->acquire_list;
  if (acquire_list != nullptr) {
    for (auto *resource_item : acquire_list->resource_item()) {
      auto ref_optional = ProcessResourceReference(slot, inst, resource_item);
      if (!ref_optional) continue;
      // Only add to use_vec if it isn't already there.
      bool found = false;
      for (auto *ref : spec->use_vec) {
        if (ref->resource->name() == ref_optional.value()->resource->name()) {
          found = true;
          break;
        }
      }
      if (!found) {
        spec->use_vec.push_back(new ResourceReference(*ref_optional.value()));
      }
      spec->acquire_vec.push_back(ref_optional.value());
    }
  }

  // Hold list.
  auto *hold_list = ctx->hold_list;
  if (hold_list != nullptr) {
    for (auto *resource_item : hold_list->resource_item()) {
      auto ref_optional = ProcessResourceReference(slot, inst, resource_item);
      if (!ref_optional) continue;
      spec->acquire_vec.push_back(ref_optional.value());
    }
  }
}

void InstructionSetVisitor::ProcessOpcodeList(
    OpcodeListCtx *ctx, Slot *slot, std::vector<Instruction *> &instruction_vec,
    absl::flat_hash_set<std::string> &deleted_ops_set,
    absl::flat_hash_set<OpcodeSpecCtx *> &overridden_ops_set) {
  // Obtain the list of opcodes specifications.
  auto opcode_spec = ctx->opcode_spec();
  for (auto *opcode_ctx : opcode_spec) {
    ProcessOpcodeSpec(opcode_ctx, slot, instruction_vec, deleted_ops_set,
                      overridden_ops_set);
  }
}

void InstructionSetVisitor::ProcessOpcodeSpec(
    OpcodeSpecCtx *opcode_ctx, Slot *slot,
    std::vector<Instruction *> &instruction_vec,
    absl::flat_hash_set<std::string> &deleted_ops_set,
    absl::flat_hash_set<OpcodeSpecCtx *> &overridden_ops_set) {
  auto *opcode_factory = slot->instruction_set()->opcode_factory();
  if (opcode_ctx->generate != nullptr) {
    auto status = ProcessOpcodeGenerator(opcode_ctx, slot, instruction_vec,
                                         deleted_ops_set, overridden_ops_set);
    if (!status.ok()) {
      error_listener()->semanticError(opcode_ctx->name, status.message());
    }
    return;
  }
  // Process the regular opcode specification.
  std::string opcode_name = opcode_ctx->name->getText();
  // Check to see if this opcode is deleted, meaning it should not be
  // inherited from a base slot.
  if (opcode_ctx->deleted != nullptr) {
    // If there is no base slot, this is an error.
    if (slot->base_slots().empty()) {
      error_listener()->semanticError(
          opcode_ctx->deleted,
          absl::StrCat("Invalid deleted opcode '", opcode_name, "', slot '",
                       slot->name(), "' does not inherit from a base slot"));
      return;
    }
    bool found = false;
    // Check to see if one of the base slots has this opcode.
    for (auto const &base_slot : slot->base_slots()) {
      found |= base_slot.base->HasInstruction(opcode_name);
      if (found) break;
    }
    // If the opcode was not defined in any of the base slots, it is an error.
    if (!found) {
      error_listener()->semanticError(
          opcode_ctx->deleted,
          absl::StrCat("Base slot does not define or inherit opcode '",
                       opcode_name, "'"));
      return;
    }
    deleted_ops_set.insert(opcode_name);
    return;
  }

  // Check to see if this opcode is overridden, this means that some of the
  // "attributes" (semantic function, disasm, etc.) are changed.
  if (opcode_ctx->overridden != nullptr) {
    int found = 0;
    for (auto const &base_slot : slot->base_slots()) {
      found += base_slot.base->HasInstruction(opcode_name);
    }
    // Check that the opcode is indeed inherited from one base class only.
    // Multiple inheritance is not supported.
    if (found == 0) {
      error_listener()->semanticError(
          opcode_ctx->deleted,
          absl::StrCat("Base slot does not define or inherit opcode '",
                       opcode_name, "'"));
      return;
    } else if (found > 1) {
      error_listener()->semanticError(
          opcode_ctx->deleted,
          absl::StrCat("Multiple inheritance of opcodes is not supported: ",
                       opcode_name));
      return;
    }
    overridden_ops_set.insert(opcode_ctx);
    return;
  }

  // This is a new opcode, so let's create it. Signal failure if error.
  absl::StatusOr<Opcode *> result = opcode_factory->CreateOpcode(opcode_name);
  if (!result.ok()) {
    error_listener()->semanticError(opcode_ctx->name,
                                    result.status().message());
    return;
  }

  Opcode *top = result.value();
  auto inst = new Instruction(top, slot);

  // Get the size of the instruction if specified, otherwise use default size.
  if (opcode_ctx->size_spec() != nullptr) {
    int size =
        std::stoi(opcode_ctx->size_spec()->NUMBER()->getText(), nullptr, 0);
    top->set_instruction_size(size);
  } else {
    top->set_instruction_size(slot->default_instruction_size());
  }
  if (top->instruction_size() < slot->min_instruction_size()) {
    slot->set_min_instruction_size(top->instruction_size());
  }

  int op_spec_number = 0;
  auto op_spec = opcode_ctx->operand_spec();
  // Process the top instruction.
  for (auto &[name, expr] : slot->attribute_map()) {
    inst->AddInstructionAttribute(name, expr->DeepCopy());
  }

  // Visit the opcode specification of the top instruction.
  if (op_spec->opcode_operands() != nullptr) {
    VisitOpcodeOperands(op_spec->opcode_operands(), op_spec_number, inst, inst,
                        slot);
  } else {
    VisitOpcodeOperands(op_spec->opcode_operands_list()->opcode_operands()[0],
                        op_spec_number, inst, inst, slot);
  }
  op_spec_number++;

  // If there are child instructions process them.
  if (opcode_ctx->operand_spec()->opcode_operands_list() != nullptr) {
    Opcode *parent = top;
    auto opcode_operands = op_spec->opcode_operands_list()->opcode_operands();

    Instruction *child_inst = nullptr;
    // Process child instructions.
    for (size_t i = 1; i < opcode_operands.size(); ++i) {
      // Create child opcode.
      auto *op = opcode_factory->CreateChildOpcode(parent);
      // Create child instruction.
      child_inst = new Instruction(op, slot);
      inst->AppendChild(child_inst);
      // Add default attributes.
      for (auto &[name, expr] : slot->attribute_map()) {
        child_inst->AddInstructionAttribute(name, expr->DeepCopy());
      }
      VisitOpcodeOperands(opcode_operands[i], op_spec_number, inst, child_inst,
                          slot);
      op_spec_number++;
    }
  }
  instruction_vec.push_back(inst);
  VisitOpcodeAttributes(opcode_ctx->opcode_attribute_list(), inst, slot);
}

void InstructionSetVisitor::VisitOpcodeOperands(OpcodeOperandsCtx *ctx,
                                                int op_spec_number,
                                                Instruction *parent,
                                                Instruction *child,
                                                Slot *slot) {
  if (ctx == nullptr) return;
  if (ctx->pred != nullptr) {
    std::string name = ctx->pred->getText();
    child->opcode()->set_predicate_op_name(name);
    parent->opcode()->op_locator_map().insert(
        std::make_pair(name, OperandLocator(op_spec_number, 'p', 0)));
  }
  if (ctx->source != nullptr) {
    int instance = 0;
    for (auto *ident : ctx->source->IDENT()) {
      std::string name = ident->getText();
      child->opcode()->AppendSourceOpName(name);
      parent->opcode()->op_locator_map().insert(
          std::make_pair(name, OperandLocator(op_spec_number, 's', instance)));
      instance++;
    }
  }
  if (ctx->dest_list() != nullptr) {
    int instance = 0;
    for (auto *dest_op : ctx->dest_list()->dest_operand()) {
      std::string ident = dest_op->dest->getText();
      // The latency of the destination operand is either specified by an
      // expression, by '*' (wildcard), or omitted, in which case it
      // defaults to 1.
      if (dest_op->expression() != nullptr) {
        child->opcode()->AppendDestOp(
            ident, VisitExpression(dest_op->expression(), slot, child));
      } else if (dest_op->wildcard != nullptr) {
        child->opcode()->AppendDestOp(ident);
      } else if (slot->default_latency() != nullptr) {
        child->opcode()->AppendDestOp(ident,
                                      slot->default_latency()->DeepCopy());
      } else {
        child->opcode()->AppendDestOp(ident, new TemplateConstant(1));
      }
      parent->opcode()->op_locator_map().insert(
          std::make_pair(ident, OperandLocator(op_spec_number, 'd', instance)));
      instance++;
    }
  }
}

absl::Status InstructionSetVisitor::ProcessOpcodeGenerator(
    OpcodeSpecCtx *ctx, Slot *slot, std::vector<Instruction *> &instruction_vec,
    absl::flat_hash_set<std::string> &deleted_ops_set,
    absl::flat_hash_set<OpcodeSpecCtx *> &overridden_ops_set) {
  if (ctx == nullptr) return absl::InternalError("OpcodeSpecCtx is null");
  absl::flat_hash_set<std::string> range_variable_names;
  std::vector<RangeAssignmentInfo *> range_info_vec;
  // Process range assignment lists. The range assignment is either a single
  // value or a structured binding assignment. If it's a binding assignment we
  // need to make sure each tuple has the same number of values as there are
  // idents to assign them to.
  for (auto *assign_ctx : ctx->range_assignment()) {
    auto *range_info = new RangeAssignmentInfo();
    range_info_vec.push_back(range_info);
    for (auto *ident_ctx : assign_ctx->IDENT()) {
      std::string name = ident_ctx->getText();
      if (range_variable_names.contains(name)) {
        error_listener()->semanticError(
            assign_ctx->start,
            absl::StrCat("Duplicate binding variable name '", name, "'"));
        continue;
      }
      range_variable_names.insert(name);
      range_info->range_names.push_back(ident_ctx->getText());
      range_info->range_values.push_back({});
      range_info->range_regexes.emplace_back(
          absl::StrCat("\\$\\(", name, "\\)"));
      // Verify that the range variable is used in the string.
      if (!RE2::PartialMatch(ctx->generator_opcode_spec_list()->getText(),
                             range_info->range_regexes.back())) {
        error_listener()->semanticWarning(
            assign_ctx->start,
            absl::StrCat("Unreferenced binding variable '", name, "'"));
      }
    }
    // See if it's a list of simple values.
    if (!assign_ctx->gen_value().empty()) {
      for (auto *gen_value_ctx : assign_ctx->gen_value()) {
        if (gen_value_ctx->simple != nullptr) {
          range_info->range_values[0].push_back(
              gen_value_ctx->simple->getText());
        } else {
          // Strip off double quotes.
          std::string value = gen_value_ctx->string->getText();
          range_info->range_values[0].push_back(
              value.substr(1, value.size() - 2));
        }
      }
      continue;
    }
    // It's a list of tuples with a structured binding assignment.
    for (auto *tuple_ctx : assign_ctx->tuple()) {
      if (tuple_ctx->gen_value().size() != range_info->range_names.size()) {
        for (auto *info : range_info_vec) delete info;
        return absl::InternalError(
            "Number of values differs from number of identifiers");
      }
      for (int i = 0; i < tuple_ctx->gen_value().size(); ++i) {
        if (tuple_ctx->gen_value(i)->simple != nullptr) {
          range_info->range_values[i].push_back(
              tuple_ctx->gen_value(i)->simple->getText());
        } else {
          // Strip off double quotes.
          std::string value = tuple_ctx->gen_value(i)->string->getText();
          range_info->range_values[i].push_back(
              value.substr(1, value.size() - 2));
        }
      }
    }
  }
  // Check that all binding variable references are valid.
  std::string input_text = ctx->generator_opcode_spec_list()->getText();
  std::string::size_type start_pos = 0;
  auto pos = input_text.find_first_of('$', start_pos);
  while (pos != std::string::npos) {
    // Skip past the '$('
    start_pos = pos + 2;
    auto end_pos = input_text.find_first_of(')', pos);
    // Extract the ident.
    auto ident = input_text.substr(start_pos, end_pos - start_pos);
    if (!range_variable_names.contains(ident)) {
      error_listener()->semanticError(
          ctx->generator_opcode_spec_list()->start,
          absl::StrCat("Undefined binding variable '", ident, "'"));
    }
    start_pos = end_pos;
    pos = input_text.find_first_of('$', start_pos);
  }
  if (error_listener()->HasError()) {
    for (auto *info : range_info_vec) delete info;
    return absl::InternalError("Found undefined binding variable name(s)");
  }
  // Now we need to iterate over the range_info instances and substitution
  // ranges. This will produce new text that will be parsed and processed.
  std::string generated_text =
      GenerateOpcodeSpec(range_info_vec, 0, input_text);
  // Parse and process the generated text.
  auto *parser = new IsaAntlrParserWrapper(generated_text);
  antlr_parser_wrappers_.push_back(parser);
  // Parse the text starting at the opcode_spec_list rule.
  auto opcode_spec_vec = parser->parser()->opcode_spec_list()->opcode_spec();
  // Process the opcode spec.
  for (auto *opcode_spec : opcode_spec_vec) {
    ProcessOpcodeSpec(opcode_spec, slot, instruction_vec, deleted_ops_set,
                      overridden_ops_set);
  }
  // Clean up.
  for (auto *info : range_info_vec) delete info;
  return absl::OkStatus();
}

// Helper function to recursively generate the text for the GENERATE opcode
// spec.
std::string InstructionSetVisitor::GenerateOpcodeSpec(
    const std::vector<RangeAssignmentInfo *> &range_info_vec, int index,
    const std::string &template_str_in) const {
  std::string generated;
  // Iterate for the number of values.
  for (int i = 0; i < range_info_vec[index]->range_values[0].size(); ++i) {
    // Copy the template string.
    std::string template_str = template_str_in;
    // For each ident, perform substitutions in the template copy with the
    // current set of values.
    int var_index = 0;
    int replace_count = 0;
    for (auto &re : range_info_vec[index]->range_regexes) {
      replace_count += RE2::GlobalReplace(
          &template_str, re,
          range_info_vec[index]->range_values[var_index++][i]);
    }
    // If there are multiple range specifications, then recursively call to
    // generate the cartesian product with the values of the next value range
    // substitutions.
    if (range_info_vec.size() > index + 1) {
      absl::StrAppend(&generated, GenerateOpcodeSpec(range_info_vec, index + 1,
                                                     template_str));
    } else {
      absl::StrAppend(&generated, template_str);
    }
    // If there were no replacements, then the range variables weren't used,
    // and the template string won't change for any other values in the range.
    // This can happen if the range variables aren't referenced in the string.
    // Thus, break out of the loop.
    if (replace_count == 0) break;
  }
  return generated;
}

static absl::StatusOr<std::pair<std::string, std::string::size_type>> get_ident(
    std::string str, std::string::size_type pos) {
  // If the next character is not an alpha or '_' it's an error.
  if (!std::isalpha(str[pos]) && (str[pos] != '_')) {
    return absl::InternalError(
        absl::StrCat("Invalid character in operand name at position ", pos,
                     " in '", str, "'"));
  }
  std::string op_name;
  while (std::isalnum(str[pos]) || (str[pos] == '_')) {
    op_name.push_back(str[pos]);
    pos++;
    if (pos >= str.size()) {
      pos = std::string::npos;
      break;
    }
  }
  return std::make_pair(op_name, pos);
}
// This method parses the disasm format string.
absl::Status InstructionSetVisitor::ParseDisasmFormat(std::string format,
                                                      Instruction *inst) {
  std::string::size_type pos = 0;
  std::string::size_type prev = 0;
  std::string::size_type length = format.size();
  FormatInfo *format_info = nullptr;
  // Extract raw text without (between) the '%' specifiers.
  DisasmFormat *disasm_fmt = new DisasmFormat();
  while ((pos != std::string::npos) &&
         ((pos = format.find_first_of('%', pos)) != std::string::npos)) {
    std::string text = format.substr(prev, pos - prev);
    std::string new_text;
    for (auto &c : text) {
      if (c == '\\') continue;
      new_text.push_back(c);
    }
    disasm_fmt->format_fragment_vec.push_back(new_text);
    pos++;
    if (pos >= length) break;

    // See if it is a simple %opname specifier or an expression.
    if (format[pos] == '(') {  // This is an expression.
      pos++;
      if (pos >= length) break;

      // Find end of the expression.
      std::string::size_type end_pos = pos;
      int paren_count = 0;
      while (true) {
        if (end_pos >= length) break;
        if (format[end_pos] == ':') break;
        if (format[end_pos] == '(') paren_count++;
        if (format[end_pos] == ')') {
          if (paren_count == 0) break;
          paren_count--;
        }
        end_pos++;
      }

      if (end_pos >= length) break;

      auto res = ParseFormatExpression(format.substr(pos, end_pos - pos),
                                       inst->opcode());
      if (!res.ok()) {
        delete disasm_fmt;
        return res.status();
      }

      format_info = res.value();

      pos = end_pos;

      format_info->number_format = "%d";  // Default number format.

      if (format[pos] == ':') {
        pos++;
        if (pos >= length) break;

        end_pos = format.find_first_of(')', pos);
        if (end_pos == std::string::npos) break;
        auto res = ParseNumberFormat(format.substr(pos, end_pos - pos));
        if (!res.ok()) {
          delete format_info;
          delete disasm_fmt;
          return res.status();
        }
        format_info->number_format = res.value();
        pos = end_pos;
      }
      pos++;
      if (pos >= format.size()) {
        pos = std::string::npos;
      }
      format_info->is_formatted = true;
      disasm_fmt->format_info_vec.push_back(format_info);

    } else {  // Simple %opname specifier.
      auto res = get_ident(format, pos);
      if (!res.ok()) {
        delete disasm_fmt;
        return res.status();
      }
      auto [op_name, end_pos] = res.value();
      pos = end_pos;
      if (!inst->opcode()->op_locator_map().contains(op_name)) {
        delete disasm_fmt;
        return absl::InternalError(absl::StrCat(
            "Invalid operand '", op_name, "' used in format '", format, "'"));
      }
      auto *format_info = new FormatInfo();
      format_info->op_name = op_name;
      format_info->is_formatted = false;
      disasm_fmt->format_info_vec.push_back(format_info);
    }

    prev = pos;
  }
  if (pos != std::string::npos) {
    delete format_info;
    delete disasm_fmt;
    return absl::InternalError(
        absl::StrCat("Unexpected end of format string in '", format, "'"));
  }
  if (prev != std::string::npos) {
    std::string text = format.substr(prev);
    std::string new_text;
    for (auto &c : text) {
      if (c == '\\') continue;
      new_text.push_back(c);
    }
    disasm_fmt->format_fragment_vec.push_back(new_text);
  }
  std::string str;
  for (auto &s : disasm_fmt->format_fragment_vec) {
    absl::StrAppend(&str, s, ":");
  }
  int width = 0;
  auto count = inst->disasm_format_vec().size();
  if (count < disasm_field_widths_.size()) {
    auto result = disasm_field_widths_[count]->GetValue();
    if (result.ok()) {
      auto *value_ptr = std::get_if<int>(&result.value());
      width = *value_ptr;
    }
  }
  disasm_fmt->width = width;
  inst->AppendDisasmFormat(disasm_fmt);
  return absl::OkStatus();
}

static std::string::size_type skip_space(const std::string &str,
                                         std::string::size_type pos) {
  if (pos == std::string::npos) return pos;
  if (pos >= str.size()) {
    return std::string::npos;
  }
  while ((str[pos] == ' ') || (str[pos] == '\t')) {
    pos++;
    if (pos >= str.size()) return std::string::npos;
  }
  return pos;
}

absl::StatusOr<FormatInfo *> InstructionSetVisitor::ParseFormatExpression(
    std::string expr, Opcode *op) {
  // The format expression is very simple. It is of the form:
  // [@+/-] ident | '(' ident <</>> number ')'
  // where @ signifies the current instruction address.
  // In short, the value of the field can be shifted left or right, then added
  // to, or subtracted from, the instruction address.

  FormatInfo *format_info = new FormatInfo();

  std::string::size_type pos = 0;
  pos = skip_space(expr, pos);
  if (pos == std::string::npos) {
    delete format_info;
    return absl::InternalError("Empty format expression");
  }

  if (expr[pos] == '@') {
    pos++;
    format_info->use_address = true;
    pos = skip_space(expr, pos);
    if (pos == std::string::npos) {
      return format_info;
    }

    if (expr[pos] == '-') {
      format_info->operation = "-";
    } else if (expr[pos] == '+') {
      format_info->operation = "+";
    } else {
      delete format_info;
      return absl::InternalError(
          absl::StrCat("@ must be followed by a '+' or a '-' in '", expr, "'"));
    }
    pos++;
  }

  pos = skip_space(expr, pos);
  if (pos == std::string::npos) {
    delete format_info;
    return absl::InternalError(
        absl::StrCat("Malformed expression '", expr, "'"));
  }

  if (expr[pos] != '(') {  // No shift expression.
    // Get the field identifier.
    auto res = get_ident(expr, pos);
    if (!res.ok()) {
      delete format_info;
      return res.status();
    }
    auto [ident, new_pos] = res.value();
    if (!op->op_locator_map().contains(ident)) {
      delete format_info;
      return absl::InternalError(absl::StrCat("Invalid operand '", ident,
                                              "' used in format for opcode'",
                                              op->name(), "'"));
    }
    format_info->op_name = ident;
    // Verify that there are no more characters in the expression.
    pos = skip_space(expr, new_pos);
    if (pos != std::string::npos) {
      delete format_info;
      return absl::InternalError(
          absl::StrCat("Malformed expression '", expr, "'"));
    }
  } else {  // expr[pos] == '('
    pos++;
    pos = skip_space(expr, pos);
    // The input expression has balanced parens, so we don't have to check for
    // end of string.

    // Get the field identifier.
    auto res = get_ident(expr, pos);
    if (!res.ok()) {
      delete format_info;
      return res.status();
    }
    auto [ident, new_pos] = res.value();
    format_info->op_name = ident;

    pos = skip_space(expr, new_pos);

    // Get the shift direction.
    if (expr.substr(pos, 2) == "<<") {
      format_info->do_left_shift = true;
    } else if (expr.substr(pos, 2) != ">>") {
      delete format_info;
      return absl::InternalError(
          absl::StrCat("Missing shift in expression '", expr, "'"));
    }
    pos += 2;

    // Get the shift amount.
    pos = skip_space(expr, pos);

    std::string num;
    while (std::isdigit(expr[pos])) {
      num.push_back(expr[pos]);
      pos++;
    }
    if (num.empty()) {
      delete format_info;
      return absl::InternalError(
          absl::StrCat("Malformed expression '", expr, "'"));
    }
    format_info->shift_amount = std::stoi(num);

    // Verify close paren, and that there aren't any other characters after
    // that.
    pos = skip_space(expr, pos);
    if (expr[pos] != ')') {
      delete format_info;
      return absl::InternalError(
          absl::StrCat("Malformed expression '", expr, "'"));
    }
    pos = skip_space(expr, pos);
    if (pos != std::string::npos) {
      delete format_info;
      return absl::InternalError(
          absl::StrCat("Malformed expression '", expr, "'"));
    }
  }
  return format_info;
}

absl::StatusOr<std::string> InstructionSetVisitor::ParseNumberFormat(
    std::string format) {
  std::string::size_type pos = 0;
  std::string format_string = "%";
  bool leading_zero = false;
  if (format[pos] == '0') {
    leading_zero = true;
    format_string.push_back('0');
    pos++;
  }
  // If there's a leading zero, there has to be a width. Signal error
  // otherwise.
  if (leading_zero && !std::isdigit(format[pos])) {
    return absl::InternalError(
        absl::StrCat("Format width required when a leading 0 is specified - '",
                     format.substr(0, pos + 1), "'"));
  }
  // Read the format width. It's an error if it's three digits, otherwise,
  // just roll with it.
  if (std::isdigit(format[pos])) {
    std::string number = format.substr(pos++, 1);
    if (std::isdigit(format[pos])) {
      number.push_back(format[pos++]);
      if (std::isdigit(format[pos])) {
        return absl::InternalError(
            absl::StrCat("Format width > than 3 digits not allowed '",
                         format.substr(0, pos + 1), "'"));
      }
    }
    format_string.append(number);
  }
  // Read the number base.
  if ((format[pos] != 'o') && (format[pos] != 'd') && (format[pos] != 'x') &&
      (format[pos] != 'X')) {
    return absl::InternalError(
        absl::StrCat("Illegal format specifier '", std::string(1, format[pos]),
                     "' in '", format.substr(0, pos + 1), "'"));
  }
  format_string.push_back(format[pos++]);
  if (pos < format.size()) {
    return absl::InternalError(
        absl::StrCat("Too many characters in format specifier '", format, "'"));
  }
  return format_string;
}

// The following methods are used to generate the prologs and epilogs in the
// emitted files.
std::string InstructionSetVisitor::GenerateHdrFileProlog(
    absl::string_view file_name, absl::string_view opcode_file_name,
    absl::string_view guard_name, absl::string_view encoding_base_name,
    const std::vector<std::string> &namespaces) {
  std::string output;
  absl::StrAppend(&output, "#ifndef ", guard_name,
                  "\n"
                  "#define ",
                  guard_name,
                  "\n"
                  "\n"
                  "#include <functional>\n"
                  "#include <map>\n"
                  "#include <vector>\n"
                  "\n"
                  "#include \"mpact/sim/generic/arch_state.h\"\n"
                  "#include "
                  "\"mpact/sim/generic/instruction.h\"\n"
                  "#include \"",
                  opcode_file_name,
                  "\"\n"
                  "\n");

  for (const auto &namespace_name : namespaces) {
    absl::StrAppend(&output, "namespace ", namespace_name, " {\n");
  }
  absl::StrAppend(
      &output,
      "\n"
      "using ::mpact::sim::generic::Instruction;\n"
      "using SemFunc = "
      "::mpact::sim::generic::Instruction::SemanticFunction;\n"
      "using ::mpact::sim::generic::ArchState;\n"
      "using ::mpact::sim::generic::PredicateOperandInterface;\n"
      "using ::mpact::sim::generic::SourceOperandInterface;\n"
      "using ::mpact::sim::generic::DestinationOperandInterface;\n"
      "using ::mpact::sim::generic::ResourceOperandInterface;\n"
      "using SimpleResourceVector = std::vector<SimpleResourceEnum>;\n"
      "\n");
  // Emit encoding base class.
  absl::StrAppend(&output, "class ", encoding_base_name, " {\n public:\n");
  absl::StrAppend(&output, "  virtual ~", encoding_base_name,
                  "() = default;\n\n");
  // Get opcode method.
  absl::StrAppend(
      &output,
      "  virtual OpcodeEnum GetOpcode(SlotEnum slot, int entry) = 0;\n");
  // Get resource methods.
  absl::StrAppend(
      &output, "  virtual ResourceOperandInterface *GetSimpleResourceOperand",
      "(SlotEnum slot, int entry, OpcodeEnum opcode, SimpleResourceVector "
      "&resource_vec, int end) = 0;\n");
  absl::StrAppend(
      &output, "  virtual ResourceOperandInterface *GetComplexResourceOperand",
      "(SlotEnum slot, int entry, OpcodeEnum opcode, ComplexResourceEnum "
      "resource_op, int begin, int end) = 0;\n");
  // For each operand type, declare the pure virtual method that returns the
  // given operand.
  absl::StrAppend(&output,
                  "  virtual PredicateOperandInterface *GetPredicate"
                  "(SlotEnum slot, int entry, OpcodeEnum opcode, PredOpEnum "
                  "pred_op) = 0;\n");
  absl::StrAppend(&output,
                  "  virtual SourceOperandInterface *GetSource"
                  "(SlotEnum slot, int entry, OpcodeEnum opcode, SourceOpEnum "
                  "source_op, int source_no) = 0;\n");
  absl::StrAppend(&output,
                  "  virtual DestinationOperandInterface *GetDestination"
                  "(SlotEnum slot, int entry, OpcodeEnum opcode, "
                  "DestOpEnum dest_op, int dest_no, int latency)"
                  "= 0;\n");
  // Destination operand latency getter for destination operands with '*'
  // as latency.
  absl::StrAppend(
      &output,
      "  virtual int GetLatency(SlotEnum slot, int entry, OpcodeEnum "
      "opcode, DestOpEnum dest_op, int dest_no) = 0;\n");

  absl::StrAppend(&output, "};\n\n");
  absl::StrAppend(
      &output,
      "using OperandSetter = "
      "std::vector<std::function<void(Instruction *, ",
      encoding_base_name,
      "*, SlotEnum, int)>>;\n"
      "using DisassemblySetter = std::function<void(Instruction *)>;\n"
      "using ResourceSetter = std::function<void(Instruction *, ",
      encoding_base_name,
      "*, SlotEnum, int)>;\n"
      "using AttributeSetter = std::function<void(Instruction *)>;\n"
      "struct InstructionInfo {\n"
      "  OperandSetter operand_setter;\n"
      "  DisassemblySetter disassembly_setter;\n"
      "  ResourceSetter resource_setter;\n"
      "  AttributeSetter attribute_setter;\n"
      "  std::vector<SemFunc> semfunc;\n"
      "  int instruction_size;\n"
      "};\n"
      "using InstructionInfoMap = absl::flat_hash_map<int, "
      "InstructionInfo *>;\n"
      "\n");
  return output;
}

std::string InstructionSetVisitor::GenerateHdrFileEpilog(
    absl::string_view guard_name, const std::vector<std::string> &namespaces) {
  std::string output;
  absl::StrAppend(&output, GenerateNamespaceEpilog(namespaces));
  absl::StrAppend(&output, "\n#endif  // ", guard_name, "\n");
  return output;
}

std::string InstructionSetVisitor::GenerateCcFileProlog(
    absl::string_view hdr_file_name,
    const std::vector<std::string> &namespaces) {
  std::string output;
  // Include files.
  absl::StrAppend(&output, "#include \"", hdr_file_name, "\"\n");
  absl::StrAppend(&output,
                  "\n"
                  "#include \"absl/strings/str_format.h\"\n\n");

  for (auto &include_file : include_files_) {
    absl::StrAppend(&output, "#include ", include_file, "\n");
  }
  absl::StrAppend(&output, "\n");
  // Namespaces.
  for (const auto &namespace_name : namespaces) {
    absl::StrAppend(&output, "namespace ", namespace_name, " {\n");
  }
  absl::StrAppend(&output, "\n");
  return output;
}

std::string InstructionSetVisitor::GenerateSimpleHdrProlog(
    absl::string_view guard_name, const std::vector<std::string> &namespaces) {
  std::string output;
  absl::StrAppend(&output, "#ifndef ", guard_name, "\n#define ", guard_name,
                  "\n\n");

  for (const auto &namespace_name : namespaces) {
    absl::StrAppend(&output, "namespace ", namespace_name, " {\n");
  }
  absl::StrAppend(&output, "\n");
  return output;
}

std::string InstructionSetVisitor::GenerateNamespaceEpilog(
    const std::vector<std::string> &namespaces) {
  std::string output;
  // Close up namespaces.
  absl::StrAppend(&output, "\n");
  for (auto namespace_name = namespaces.crbegin();
       namespace_name != namespaces.crend(); ++namespace_name) {
    absl::StrAppend(&output, "}  // namespace ", *namespace_name, "\n");
  }
  return output;
}

absl::Status InstructionSetVisitor::AddConstant(absl::string_view name,
                                                absl::string_view,
                                                TemplateExpression *expr) {
  if (constant_map_.contains(name)) {
    return absl::AlreadyExistsError(
        absl::StrCat("Constant redefinition of '", name, "'"));
  }
  constant_map_.emplace(name, expr);
  return absl::OkStatus();
}

TemplateExpression *InstructionSetVisitor::GetConstExpression(
    absl::string_view name) const {
  auto iter = constant_map_.find(name);
  if (iter == constant_map_.end()) return nullptr;
  return iter->second;
}

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