// 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>
#include <fstream>
#include <iostream>
#include <istream>
#include <memory>
#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)) {
    disasm_fmt->format_fragment_vec.push_back(format.substr(prev, pos - prev));
    std::string text = format.substr(prev, pos - prev);
    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) {
    disasm_fmt->format_fragment_vec.push_back(format.substr(prev));
  }
  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
