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

#include <algorithm>
#include <cstdint>
#include <string>
#include <utility>

#include "absl/numeric/bits.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/Token.h"
#include "mpact/sim/decoder/format_name.h"
#include "mpact/sim/decoder/overlay.h"

namespace mpact {
namespace sim {
namespace decoder {
namespace bin_format {

using ::mpact::sim::machine_description::instruction_set::ToSnakeCase;

FieldOrFormat::~FieldOrFormat() {
  if (is_field_) {
    delete field_;
  }
  field_ = nullptr;
  format_ = nullptr;
}

// The equality operator compares to verify that the field/format definitions
// are equivalent, i.e., refers to the same bits.
bool FieldOrFormat::operator==(const FieldOrFormat &rhs) const {
  if (is_field_ != rhs.is_field_) return false;
  if (is_field_) {
    if (high_ != rhs.high_) return false;
    if (size_ != rhs.size_) return false;
  } else {
    if (format_ != rhs.format_) return false;
  }
  return true;
}

bool FieldOrFormat::operator!=(const FieldOrFormat &rhs) const {
  return !(*this == rhs);
}

using ::mpact::sim::machine_description::instruction_set::ToPascalCase;

Format::Format(std::string name, int width, BinEncodingInfo *encoding_info)
    : Format(name, width, "", encoding_info) {}

Format::Format(std::string name, int width, std::string base_format_name,
               BinEncodingInfo *encoding_info)
    : name_(name),
      base_format_name_(base_format_name),
      declared_width_(width),
      encoding_info_(encoding_info) {}

Format::~Format() {
  // for (auto &[unused, field_ptr] : field_map_) {
  //   delete field_ptr;
  // }
  field_map_.clear();
  for (auto &[unused, overlay_ptr] : overlay_map_) {
    delete overlay_ptr;
  }
  overlay_map_.clear();
  for (auto *field : field_vec_) {
    delete field;
  }
  field_vec_.clear();
}

// Add a field to the current format with the given width and signed/unsigned
// attribute.
absl::Status Format::AddField(std::string name, bool is_signed, int width) {
  // Make sure that the name isn't used already in the format.
  if (field_map_.contains(name)) {
    return absl::InvalidArgumentError(
        absl::StrCat("Field '", name, "' already defined"));
  }
  auto field = new Field(name, is_signed, width, this);
  field_vec_.push_back(new FieldOrFormat(field));
  field_map_.insert(std::make_pair(name, field));
  return absl::OkStatus();
}

// Add a format reference field - name of another format - to the current
// format. This will be resolved once all the formats have been parsed.
void Format::AddFormatReferenceField(std::string format_alias,
                                     std::string format_name, int size,
                                     antlr4::Token *ctx) {
  field_vec_.push_back(new FieldOrFormat(format_alias, format_name, size, ctx));
}

// Add an overlay to the current format. An overlay is a named alias for a
// not necessarily contiguous nor in order collection of bits in the format.
absl::StatusOr<Overlay *> Format::AddFieldOverlay(std::string name,
                                                  bool is_signed, int width) {
  // Make sure that the name isn't used already in the format.
  if (overlay_map_.contains(name)) {
    return absl::InvalidArgumentError(
        absl::StrCat("Overlay '", name, "' already defined as an overlay"));
  }
  if (field_map_.contains(name)) {
    return absl::InvalidArgumentError(
        absl::StrCat("Overlay '", name, "' already defined as a field"));
  }
  auto overlay = new Overlay(name, is_signed, width, this);
  overlay_map_.insert(std::make_pair(name, overlay));
  return overlay;
}

// Return the named field if it exists, nullptr otherwise.
Field *Format::GetField(absl::string_view field_name) const {
  auto iter = field_map_.find(field_name);
  if (iter == field_map_.end()) return nullptr;
  return iter->second;
}

// Return the named field if it exists, nullptr otherwise.
Overlay *Format::GetOverlay(absl::string_view overlay_name) const {
  auto iter = overlay_map_.find(overlay_name);
  if (iter == overlay_map_.end()) return nullptr;
  return iter->second;
}

// Return the string containing the integer type used to contain the current
// format. If it is greater than 128 bits, will use a byte array (int8_t *).
// If it is 65 to 128 bits, will use absl::[u]int128.
std::string Format::GetUIntType(int bitwidth) const {
  if (bitwidth > 128) return "uint8_t *";
  if (bitwidth > 64) return "absl::uint128";
  return absl::StrCat("uint", GetIntTypeBitWidth(bitwidth), "_t");
}

std::string Format::GetIntType(int bitwidth) const {
  if (bitwidth > 128) return "int8_t *";
  if (bitwidth > 64) return "absl::int128";
  return absl::StrCat("int", GetIntTypeBitWidth(bitwidth), "_t");
}

// Return the int type byte width (1, 2, 4, 8, 16) or (-1 if it's bigger), of
// the integer type that would fit this format.
int Format::GetIntTypeBitWidth(int bitwidth) const {
  auto shift = absl::bit_width(static_cast<unsigned>(bitwidth)) - 1;
  if (absl::popcount(static_cast<unsigned>(bitwidth)) > 1) shift++;
  shift = std::max(shift, 3);
  if (shift > 7) return -1;
  return 1 << shift;
}

// Once all the formats have been read in, this method is called to check the
// format and update any widths that depended on other formats being read in.
absl::Status Format::ComputeAndCheckFormatWidth() {
  // If there is a base format name, look up that format, verify that the widths
  // are the same.
  if (!base_format_name_.empty()) {
    auto *base_format = encoding_info_->GetFormat(base_format_name_);
    if (base_format == nullptr) {
      return absl::InternalError(
          absl::StrCat("Format ", name(), " refers to undefined base format ",
                       base_format_name_));
    }
    if (base_format->declared_width() != declared_width_) {
      return absl::InternalError(absl::StrCat(
          "Format ", name_, " (", declared_width_,
          ") differs in width from base format ", base_format->name(), " (",
          base_format->declared_width(), ")"));
    }
    base_format_ = base_format;
    base_format_->derived_formats_.push_back(this);
  }
  if (computed_width_ == 0) {
    // Go through the list of fields/format references. Get the declared widths
    // of the formats and add to the computed width. Signal error if the
    // computed width differs from the declared width.
    for (auto *field_or_format : field_vec_) {
      // Field.
      if (field_or_format->is_field()) {
        auto *field = field_or_format->field();
        field->high = declared_width_ - computed_width_ - 1;
        field->low = field->high - field->width + 1;
        computed_width_ += field->width;
        extractors_.insert(std::make_pair(field->name, field_or_format));
        continue;
      }

      // Format;
      auto *format = field_or_format->format();
      if (format == nullptr) {
        std::string fmt_name = field_or_format->format_name();
        format = encoding_info_->GetFormat(fmt_name);
        if (format == nullptr) {
          return absl::InternalError(absl::StrCat(
              "Format '", name(), "' refers to undefined format ", fmt_name));
        }
        field_or_format->set_format(format);
      }
      field_or_format->set_high(declared_width_ - computed_width_ - 1);
      computed_width_ += format->declared_width() * field_or_format->size();
      extractors_.insert(
          std::make_pair(field_or_format->format_alias(), field_or_format));
    }
    if (computed_width_ != declared_width_) {
      return absl::InternalError(absl::StrCat(
          "Format '", name_, "' declared width (", declared_width_,
          ") differs from computed width (", computed_width_, ")"));
    }
  }
  for (auto &[name, overlay_ptr] : overlay_map_) {
    auto status = overlay_ptr->ComputeHighLow();
    if (!status.ok()) return status;
    overlay_extractors_.insert(std::make_pair(name, overlay_ptr));
  }
  // Set the type names.
  int_type_name_ = GetIntType(declared_width_);
  uint_type_name_ = absl::StrCat("u", int_type_name_);
  return absl::OkStatus();
}

// The extractor functions in the generated code are all generated within a
// namespace specific to the format they're associated with. However, extractors
// that don't conflict in the bits they select may be promoted to be generated
// in the base format namespace. This method is used to propagate such
// potential promotions upward in the inheritance tree.
void Format::PropagateExtractorsUp() {
  for (auto *fmt : derived_formats_) {
    fmt->PropagateExtractorsUp();
  }
  if (base_format_ != nullptr) {
    // Try to propagate extractors up the inheritance tree.
    for (auto const &[name, field_or_format_ptr] : extractors_) {
      // Ignore those that have a nullptr, they have already failed to be
      // promoted.
      if (field_or_format_ptr == nullptr) continue;
      auto iter = base_format_->extractors_.find(name);
      // If it isn't in the parent, add it.
      if (iter == base_format_->extractors_.end()) {
        base_format_->extractors_.insert(
            std::make_pair(name, field_or_format_ptr));
      } else if (iter->second == nullptr) {
        // Can't promote it, a previous attempt failed.
        continue;
      } else if (*field_or_format_ptr != *(iter->second)) {
        // If the base extractor refers to a different object, fail the
        // promotion.
        base_format_->extractors_[name] = nullptr;
      }
    }
    for (auto const &[name, overlay_ptr] : overlay_extractors_) {
      // Ignore those that have a nullptr, they have already failed to be
      // promoted.
      if (overlay_ptr == nullptr) continue;
      auto iter = base_format_->overlay_extractors_.find(name);
      // If it isn't in the parent, add it.
      if (iter == base_format_->overlay_extractors_.end()) {
        base_format_->overlay_extractors_.insert(
            std::make_pair(name, overlay_ptr));
      } else if (iter->second == nullptr) {
        // Previous attempt fail, don't promote.
        continue;
      } else if (*overlay_ptr != *(iter->second)) {
        // If the base format extractor refers to a different overlay type,
        // fail the promotion.
        base_format_->overlay_extractors_[name] = nullptr;
      }
    }
  }
}

// This is the counterpart to the previous method and cleans up extractors that
// were attempted to be promoted, but couldn't be due to conflicts with others,
// e.g., two fields were named the same in different formats but referred to
// different bits.
void Format::PropagateExtractorsDown() {
  // Remove the extractor entries with null ptrs and any extractors that
  // have been promoted.
  auto e_iter = extractors_.begin();
  while (e_iter != extractors_.end()) {
    auto cur = e_iter++;
    // Failed promotion from derived format extractors.
    if (cur->second == nullptr) {
      extractors_.erase(cur);
      continue;
    }
    // If the name exists in overlay extractors, erase both.
    if (overlay_extractors_.find(cur->first) != overlay_extractors_.end()) {
      overlay_extractors_.erase(cur->first);
      extractors_.erase(cur);
      continue;
    }
  }
  // Remove the overlay extractor entries with null ptrs.
  auto o_iter = overlay_extractors_.begin();
  while (o_iter != overlay_extractors_.end()) {
    auto cur = o_iter++;
    // Failed promotion from derived format extractors.
    if (cur->second == nullptr) {
      overlay_extractors_.erase(cur);
      continue;
    }
    // If the name exists in overlay extractors, erase both.
    if (extractors_.find(cur->first) != extractors_.end()) {
      extractors_.erase(cur->first);
      overlay_extractors_.erase(cur);
      continue;
    }
  }
  for (auto *fmt : derived_formats_) {
    fmt->PropagateExtractorsDown();
  }
}

// Returns true if the current format, or a base format, contains an
// extractor for field 'name'.
bool Format::HasExtract(const std::string &name) const {
  auto iter = extractors_.find(name);
  if ((iter != extractors_.end()) && (iter->second != nullptr)) return true;

  if (base_format_ != nullptr) return base_format_->HasExtract(name);

  return false;
}

// Returns true if the current format, or a base format, contains an
// extractor for overlay 'name'.
bool Format::HasOverlayExtract(const std::string &name) const {
  auto iter = overlay_extractors_.find(name);
  if ((iter != overlay_extractors_.end()) && (iter->second != nullptr)) {
    return true;
  }

  if (base_format_ != nullptr) return base_format_->HasOverlayExtract(name);

  return false;
}

std::string Format::GeneratePackedStructFieldExtractor(
    const Field *field) const {
  std::string h_output;
  int width = field->width;
  std::string return_type = GetUIntType(width);
  std::string signature = absl::StrCat("inline ", return_type, " Extract",
                                       ToPascalCase(field->name), "(");
  if (declared_width_ < 64) {
    absl::StrAppend(&signature, GetUIntType(declared_width_), " value) {\n");
  } else {
    absl::StrAppend(&signature, "const uint8_t *value) {\n");
  }
  absl::StrAppend(&h_output, signature);
  // Now start the body.
  std::string union_type = absl::StrCat("const ", ToSnakeCase(name()),
                                        "::Union", ToPascalCase(name()));
  absl::StrAppend(&h_output, "  ", union_type,
                  " *packed_union;\n"
                  "  packed_union = reinterpret_cast<",
                  union_type, "*>(",
                  declared_width_ > 64 ? "value);\n" : "&value);\n",
                  "  return packed_union->", ToSnakeCase(name()), ".",
                  field->name, ";\n}\n\n");
  return h_output;
}

// This method generates the C++ code for the field extractors for the current
// format.
std::string Format::GenerateFieldExtractor(const Field *field) const {
  std::string h_output;
  int return_width = GetIntTypeBitWidth(field->width);
  std::string result_type_name =
      field->is_signed ? GetIntType(return_width) : GetUIntType(return_width);
  std::string argument_type_name = GetUIntType(computed_width_);
  std::string signature = absl::StrCat(
      result_type_name, " Extract", ToPascalCase(field->name), "(",
      computed_width_ > 128 ? "const " : "", argument_type_name, " value)");

  absl::StrAppend(&h_output, "inline ", signature, " {\n");

  // Generate extraction function. For fields it's a simple shift and mask if
  // the source format width <= 64 bits. Slightly more involved with format
  // <= 128 bits. For larger formats use the templated extract helper function.
  std::string expr;
  if (declared_width_ <= 64) {
    uint64_t mask = (1ULL << field->width) - 1;
    if (field->low == 0) {
      expr = absl::StrCat("value & 0x", absl::Hex(mask));
    } else {
      expr = absl::StrCat(" (value >> ", field->low, ") & 0x", absl::Hex(mask));
    }
  } else if (declared_width_ <= 128) {
    absl::StrAppend(&h_output,
                    "  absl::uint128 mask = 1;\n"
                    "  mask = (mask << ",
                    field->width, ") - 1;\n");
    if (field->low == 0) {
      expr = absl::StrCat("value & mask");
    } else {
      expr = absl::StrCat(" (value >> ", field->low, ") & mask");
    }
  } else {
    // For format width > 128 bits, use the templated extract helper function.
    int byte_size = (declared_width_ + 7) / 8;
    expr = absl::StrCat("internal::ExtractBits<", result_type_name, ">(value, ",
                        byte_size, ", ", field->high, ", ", field->width, ")");
  }

  // Add sign-extension if the field is signed.
  std::string sign_extension;
  if (field->is_signed) {
    int shift = return_width - field->width;
    sign_extension =
        absl::StrCat("  ", result_type_name, " result = (", expr, ") << ",
                     shift, ";\n  result = result >> ", shift, ";\n");
    expr = "result";
  }
  if (declared_width_ <= 64) {
    absl::StrAppend(&h_output, sign_extension, "  return ", expr, ";\n}\n\n");
  } else if ((declared_width_ <= 128) && (return_width <= 64)) {
    absl::StrAppend(&h_output, sign_extension, "  return absl::Uint128Low64(",
                    expr, ");\n}\n\n");
  } else {
    absl::StrAppend(&h_output, sign_extension, "  return ", expr, ";\n}\n\n");
  }
  // If the parent format size is not a power of two, also create an extractor
  // that takes a uint8_t * parameter.
  if ((declared_width_ <= 128) &&
      (absl::popcount(static_cast<unsigned>(declared_width_)) > 1)) {
    absl::StrAppend(&h_output, "inline ", result_type_name, " Extract",
                    ToPascalCase(field->name), "(const uint8_t *value) {\n");
    int byte_size = (declared_width_ + 7) / 8;
    absl::StrAppend(&h_output, "  return internal::ExtractBits<",
                    result_type_name, ">(value, ", byte_size, ", ", field->high,
                    ", ", field->width, ");\n}\n\n");
  }
  return h_output;
}

std::string Format::GeneratePackedStructFieldInserter(
    const Field *field) const {
  std::string h_output;
  std::string field_type_name;
  std::string inst_word_type_name;
  if (computed_width_ <= 64) {
    inst_word_type_name = GetUIntType(computed_width_);
  } else {
    inst_word_type_name = "uint8_t *";
  }
  field_type_name = GetUIntType(field->width);
  std::string union_type =
      absl::StrCat(ToSnakeCase(name()), "::Union", ToPascalCase(name()));
  absl::StrAppend(&h_output, "static inline ", inst_word_type_name, " Insert",
                  ToPascalCase(field->name), "(", field_type_name, " value, ",
                  inst_word_type_name,
                  " inst_word) {\n"
                  "  ",
                  union_type,
                  " *packed_union;\n"
                  "  packed_union = reinterpret_cast<",
                  union_type, "*>(",
                  (computed_width_ <= 64 ? "&inst_word" : "inst_word"),
                  ");\n"
                  "  packed_union->",
                  ToSnakeCase(name()), ".", field->name,
                  " = value;\n"
                  "  return inst_word;\n"
                  "}\n\n");
  return h_output;
}

// This method generates the C++ code for field inserters for the current
// format. That is, the generated code will take the value of a field and
// insert it into the right place in the instruction word.
std::string Format::GenerateFieldInserter(const Field *field) const {
  std::string h_output;
  std::string field_type_name;
  std::string inst_word_type_name = GetUIntType(computed_width_);
  if (declared_width_ <= 128) {
    field_type_name = inst_word_type_name;
  } else {
    field_type_name = GetUIntType(field->width);
  }
  absl::StrAppend(&h_output, "static inline ", inst_word_type_name, " Insert",
                  ToPascalCase(field->name), "(", field_type_name, " value, ",
                  inst_word_type_name, " inst_word) {\n");
  if (declared_width_ <= 64) {
    uint64_t mask = ((1ULL << field->width) - 1) << field->low;
    std::string shift;
    if (field->low != 0) {
      shift = absl::StrCat(" << ", field->low);
    }
    absl::StrAppend(&h_output, "  inst_word = (inst_word & ~0x",
                    absl::Hex(mask), "ULL)", " | ((value", shift, ") & 0x",
                    absl::Hex(mask),
                    "ULL);\n"
                    "  return inst_word;\n"
                    "}\n");
  } else if (declared_width_ <= 128) {
    absl::StrAppend(&h_output,
                    "  absl::uint128 mask = 1;\n"
                    "  mask = (mask << ",
                    field->width, ") - 1;\n");
    if (field->low != 0) {
      absl::StrAppend(&h_output, "  mask = mask << ", field->low, ";\n");
    }
    absl::StrAppend(&h_output,
                    "  inst_word = (inst_word & ~mask) | (value & mask);\n"
                    "  return inst_word;\n"
                    "}\n");
  } else if (field->width <= 128) {
    int byte_size = (declared_width_ + 7) / 8;
    absl::StrAppend(&h_output, "  internal::InsertBits(inst_word, ", byte_size,
                    ", ", field->high, ", ", field->width,
                    ", value);\n"
                    "  return inst_word;\n"
                    "}\n");
  } else {
    absl::StrAppend(&h_output,
                    "  LOG(FATAL) << \" Support for fields > 128 bits not "
                    "implemented - "
                    "yet.\";\n"
                    "  return 0;\n}\n");
  }
  return h_output;
}

// This method generates the C++ code for overlay inserters for the current
// format. That is, the generated code will take the value of an overlay and
// insert its components into the right places in the instruction word.
std::string Format::GenerateOverlayInserter(Overlay *overlay) const {
  std::string h_output;
  std::string result_type_name = GetUIntType(computed_width_);
  std::string overlay_type_name;
  if (computed_width_ <= 128) {
    overlay_type_name = result_type_name;
  } else {
    overlay_type_name = GetUIntType(overlay->declared_width());
  }
  absl::StrAppend(&h_output, "static inline ", result_type_name, " Insert",
                  ToPascalCase(overlay->name()), "(", overlay_type_name,
                  " value, ", result_type_name, " inst_word) {\n");
  // Mark error if either the overlay or the format is > 64 bits.
  if (overlay->declared_width() > 128) {
    absl::StrAppend(&h_output,
                    "  LOG(FATAL) << \" Support for overlays > 128 bits "
                    "not implemented - "
                    "yet.\";\n"
                    "  return 0;\n}\n");
    return h_output;
  }
  bool use_mask_variable = false;
  int remaining = overlay->declared_width();
  int byte_size = (declared_width_ + 7) / 8;
  if (declared_width_ <= 128) {
    absl::StrAppend(&h_output, "  ", result_type_name, " tmp;\n");
    // Track the leftmost bit in the overlay.
    if (declared_width_ > 64) {
      absl::StrAppend(&h_output, "  absl::uint128 mask;\n");
      use_mask_variable = true;
    }
  } else {
    absl::StrAppend(&h_output, "  ", overlay_type_name, " tmp;\n");
    if (overlay->declared_width() > 64) {
      absl::StrAppend(&h_output, "  absl::uint128 mask;\n");
      use_mask_variable = true;
    }
  }
  for (auto &bits_or_field : overlay->component_vec()) {
    int width = bits_or_field->width();
    // Ignore the bit fields in the overlay.
    if (bits_or_field->high() < 0) {
      remaining -= width;
      continue;
    }
    std::string shift;
    if (remaining - width > 0) {
      shift = absl::StrCat(" >> ", remaining - width);
    }
    if (use_mask_variable) {
      absl::StrAppend(&h_output,
                      "  mask = 1;\n"
                      "  mask = (mask << ",
                      width, ") - 1;\n");
      absl::StrAppend(&h_output, "  tmp = (value ", shift, ") & mask;\n");
    } else {
      uint64_t mask = ((1ULL << width) - 1);
      // Extract the bits from the overlay value for the current component.
      absl::StrAppend(&h_output, "  tmp = (value ", shift, ") & 0x",
                      absl::Hex(mask), "ULL;\n");
    }
    shift.clear();
    if (bits_or_field->low() != 0) {
      shift = absl::StrCat(" << ", bits_or_field->low());
    }
    if (declared_width_ <= 128) {
      absl::StrAppend(&h_output, "  inst_word |= (tmp ", shift, ");\n");
    } else {
      absl::StrAppend(&h_output, "  internal::InsertBits(inst_word, ",
                      byte_size, ", ", bits_or_field->high(), ", ", width,
                      ",  tmp);\n");
    }

    remaining -= width;
  }
  absl::StrAppend(&h_output, "  return inst_word;\n}\n");
  return h_output;
}

std::string Format::GeneratePackedStructFormatInserter(
    std::string_view format_alias, const Format *format, int high,
    int size) const {
  std::string h_output;
  std::string inst_word_type_name;
  if (computed_width_ <= 64) {
    inst_word_type_name = GetUIntType(computed_width_);
  } else {
    inst_word_type_name = "uint8_t *";
  }
  std::string format_type_name = GetUIntType(format->declared_width());
  std::string union_type =
      absl::StrCat(ToSnakeCase(name()), "::Union", ToPascalCase(name()));
  absl::StrAppend(&h_output, "static inline ", inst_word_type_name, "Insert",
                  ToPascalCase(format_alias), "(", format_type_name, " value, ",
                  inst_word_type_name,
                  " inst_word) {\n"
                  "  ",
                  union_type,
                  " *packed_union;\n"
                  "  packed_union = reinterpret_cast<",
                  union_type, "*>(",
                  (computed_width_ <= 64 ? "&inst_word" : "inst_word"),
                  ");\n"
                  "  packed_union->",
                  ToSnakeCase(name()), ".", format_alias,
                  " = value;\n"
                  "  return inst_word;\n"
                  "}\n\n");
  return h_output;
}

// This method generates the C++ code for format inserters for the current
// format. That is, the generated code will take the value of a format and
// insert it into the right place in the instruction word.
std::string Format::GenerateFormatInserter(std::string_view format_alias,
                                           const Format *format, int high,
                                           int size) const {
  if (size > 1) {
    return GenerateReplicatedFormatInserter(format_alias, format, high, size);
  }
  return GenerateSingleFormatInserter(format_alias, format, high);
}

std::string Format::GenerateReplicatedFormatInserter(
    std::string_view format_alias, const Format *format, int high,
    int size) const {
  std::string h_output;
  std::string target_type_name = GetUIntType(declared_width_);
  std::string format_type_name;

  if (declared_width_ <= 128) {
    format_type_name = target_type_name;
  } else {
    format_type_name = GetUIntType(format->declared_width());
  }
  absl::StrAppend(&h_output, "static inline ", target_type_name, " Insert",
                  ToPascalCase(format_alias), "(", "int index, ",
                  format_type_name, " value, ", target_type_name,
                  " inst_word) {\n");
  if (format->declared_width() > 128) {
    absl::StrAppend(&h_output,
                    "  LOG(FATAL) << \" Support for formats > 128 bits not "
                    "implemented - "
                    "yet.\";\n"
                    "  return 0;\n}\n");
    return h_output;
  }
  int width = format->declared_width();
  int low = high - width + 1;
  if (declared_width_ <= 64) {
    uint64_t mask = (1ULL << width) - 1;
    absl::StrAppend(&h_output, "  int low = ", low, " - (index * ", width,
                    ");\n"
                    "  return (inst_word & (~0x",
                    absl::Hex(mask), "ULL << low))", " | ((value << low) & (0x",
                    absl::Hex(mask), "ULL << low));\n}\n");
  } else if (declared_width_ <= 128) {
    absl::StrAppend(
        &h_output, "  int low = ", low, " - (index * ", width,
        ");\n"
        "  absl::uint128 mask = 1;\n"
        "  mask = (mask << ",
        width,
        ") - 1;\n"
        "  mask <<= low;\n"
        "  return (inst_word & ~mask) | (value << low) & mask;\n}\n");
  } else {
    int byte_size = (declared_width_ + 7) / 8;
    absl::StrAppend(&h_output, "  internal::InsertBits(inst_word, ", byte_size,
                    ", ", high, " - (index * ", width, "), ", width,
                    ", value);\n"
                    "  return inst_word;\n}\n");
  }
  return h_output;
}

std::string Format::GenerateSingleFormatInserter(std::string_view format_alias,
                                                 const Format *format,
                                                 int high) const {
  std::string h_output;
  std::string target_type_name = GetUIntType(declared_width_);
  std::string format_type_name;
  if (declared_width_ <= 128) {
    format_type_name = target_type_name;
  } else {
    format_type_name = GetUIntType(format->declared_width());
  }

  absl::StrAppend(&h_output, "static inline ", target_type_name, " Insert",
                  ToPascalCase(format_alias), "(", format_type_name, " value, ",
                  target_type_name, " inst_word) {\n");
  if (format->declared_width() > 128) {
    absl::StrAppend(&h_output,
                    "  LOG(FATAL) << \" Support for formats > 128 bits not "
                    "implemented - "
                    "yet.\";\n"
                    "  return 0;\n}\n");
    return h_output;
  }
  int width = format->declared_width();
  int low = high - width + 1;
  std::string shift;
  if (low != 0) {
    shift = absl::StrCat(" << ", low);
  }
  if (declared_width_ <= 64) {
    uint64_t mask = ((1ULL << width) - 1) << low;
    absl::StrAppend(&h_output, "  return (inst_word & (~0x", absl::Hex(mask),
                    "ULL))", " | ((value ", shift, ") & 0x", absl::Hex(mask),
                    "ULL);\n}\n");
  } else if (declared_width_ <= 128) {
    absl::StrAppend(&h_output,
                    "  absl::uint128 mask = 1;\n"
                    "  mask = (mask << ",
                    width, ") - 1;\n");
    if (low > 0) {
      absl::StrAppend(&h_output, "  mask = mask << ", low, ";\n");
    }
    absl::StrAppend(&h_output, "  return (inst_word & ~mask) | (value ", shift,
                    ") & mask;\n}\n");
  } else {
    int byte_size = (declared_width_ + 7) / 8;
    absl::StrAppend(&h_output, "  internal::InsertBits(inst_word, ", byte_size,
                    ", ", high, ", ", width,
                    ", value);\n"
                    "  return inst_word;\n}\n");
  }
  return h_output;
}

std::string Format::GeneratePackedStructFormatExtractor(
    absl::string_view format_alias, const Format *format, int high,
    int size) const {
  std::string h_output;
  int width = format->declared_width();
  std::string return_type = GetUIntType(width);
  std::string signature = absl::StrCat("inline ", return_type, " Extract",
                                       ToPascalCase(format_alias), "(");
  if (declared_width_ < 64) {
    absl::StrAppend(&signature, GetUIntType(declared_width_), " value) {\n");
  } else {
    absl::StrAppend(&signature, "const uint8_t *value) {\n");
  }
  absl::StrAppend(&h_output, signature);
  // Now start the body.
  std::string union_type = absl::StrCat("const ", ToSnakeCase(name()),
                                        "::Union", ToPascalCase(name()));
  absl::StrAppend(&h_output, "  ", union_type,
                  " *packed_union;\n"
                  "  packed_union = reinterpret_cast<",
                  union_type, " *>(",
                  declared_width_ > 64 ? "value);\n" : "&value);\n",
                  "  return packed_union->", ToSnakeCase(name()), ".",
                  format_alias, ";\n}\n\n");
  return h_output;
}

// This method generates the format extractors for the current format (for
// when a format contains other formats).
std::string Format::GenerateFormatExtractor(absl::string_view format_alias,
                                            const Format *format, int high,
                                            int size) const {
  std::string h_output;  // For each format generate an extractor.
  int width = format->declared_width();
  // An extraction can only be for 128 bits or less.
  if (width > 128) {
    encoding_info_->error_listener()->semanticError(
        nullptr,
        absl::StrCat("Cannot generate a format extractor for format '",
                     format->name(), "': format is wider than 128 bits"));
    return "";
  }
  std::string return_type = GetUIntType(width);
  std::string signature = absl::StrCat("inline ", return_type, " Extract",
                                       ToPascalCase(format_alias), "(");
  if (declared_width_ <= 128) {
    // If the source format is <= 128 bits, then use an int type.
    std::string arg_type = GetUIntType(declared_width_);
    absl::StrAppend(&signature, arg_type, " value");
  } else {
    // Otherwise use a pointer to uint8_t type.
    absl::StrAppend(&signature, "const uint8_t *value");
  }
  // If the format has multiple instances add an index parameter.
  if (size > 1) {
    absl::StrAppend(&signature, ", int index");
  }
  absl::StrAppend(&signature, ")");
  // Now start the body.
  absl::StrAppend(&h_output, signature, " {\n");
  std::string expr;
  if (declared_width_ <= 128) {
    // If the source format can be stored in a uint128 or smaller.
    int low = high - width + 1;
    std::string shift;
    if (size > 1) {
      shift = absl::StrCat("(", low, " + (index - 1) * ", width, ")");
    } else {
      shift = absl::StrCat(low);
    }
    if (declared_width_ <= 64) {
      uint64_t mask = (1ULL << width) - 1;
      expr =
          absl::StrCat("(value >> ", shift, ") & 0x", absl::Hex(mask), ";\n");
      absl::StrAppend(&h_output, "  return ", expr, ";\n}\n\n");
    } else {
      absl::StrAppend(&h_output,
                      "  absl::uint128 mask = 1;\n"
                      "  mask = (mask << ",
                      width, ") - 1;\n");
      expr = absl::StrCat("(value >> ", shift, ") & mask");
      if (width <= 64) {
        absl::StrAppend(&h_output, "  return absl::Uint128Low64(", expr,
                        ");\n}\n\n");
      } else {
        absl::StrAppend(&h_output, "  return ", expr, ";\n}\n\n");
      }
    }
  } else {
    // If the source format is stored in uint8_t[].
    int byte_size = (declared_width_ + 7) / 8;
    expr = absl::StrCat("internal::ExtractBits<", return_type, ">(value, ",
                        byte_size, ", ", high);
    if (size > 1) {
      absl::StrAppend(&expr, " - (index * ", width, ")");
    }
    absl::StrAppend(&expr, ", ", width, ")");
    absl::StrAppend(&h_output, "  return ", expr, ";\n}\n\n");
  }
  // If the parent format size is not a power of two, also create an
  // extractor that takes a uint8_t * parameter.
  if ((declared_width_ <= 128) &&
      (absl::popcount(static_cast<unsigned>(declared_width_)) > 1)) {
    absl::StrAppend(&h_output, "inline ", return_type, " Extract",
                    ToPascalCase(format_alias), "(const uint8_t *value) {\n");
    int byte_size = (declared_width_ + 7) / 8;
    expr = absl::StrCat("internal::ExtractBits<", return_type, ">(value, ",
                        byte_size, ", ", high);
    if (size > 1) {
      absl::StrAppend(&expr, " - (index * ", width, ")");
    }
    absl::StrAppend(&expr, ", ", width, ")");
    absl::StrAppend(&h_output, "  return ", expr, ";\n}\n\n");
  }
  return h_output;
}

std::string Format::GeneratePackedStructOverlayExtractor(
    Overlay *overlay) const {
  std::string h_output;
  std::string arg_type;
  if (declared_width_ > 128) {
    arg_type = "const uint8_t *";
  } else {
    arg_type = GetUIntType(declared_width_);
  }
  std::string return_type = overlay->is_signed()
                                ? GetIntType(overlay->declared_width())
                                : GetUIntType(overlay->declared_width());
  std::string signature =
      absl::StrCat("inline ", return_type, " Extract",
                   ToPascalCase(overlay->name()), "(", arg_type, " value)");
  absl::StrAppend(&h_output, signature, " {\n  ", return_type, " result;\n",
                  overlay->WritePackedStructValueExtractor("value", "result"));
  if (overlay->is_signed()) {
    int shift = GetIntTypeBitWidth(overlay->declared_width()) -
                overlay->declared_width();
    absl::StrAppend(&h_output, "  result = result << ", shift,
                    ";\n"
                    "  result = result >> ",
                    shift, ";\n");
  }
  absl::StrAppend(&h_output,
                  "  return result;\n"
                  "}\n\n");
  return h_output;
}

// Generates the C++ code for the overlay extractors in the current format.
std::string Format::GenerateOverlayExtractor(Overlay *overlay) const {
  std::string h_output;

  std::string return_type = overlay->is_signed()
                                ? GetIntType(overlay->declared_width())
                                : GetUIntType(overlay->declared_width());

  std::string arg_type = GetUIntType(declared_width_);
  std::string signature =
      absl::StrCat("inline ", return_type, " Extract",
                   ToPascalCase(overlay->name()), "(", arg_type, " value)");

  // Generate definition.
  absl::StrAppend(&h_output, signature,
                  " {\n"
                  "  ",
                  return_type, " result;\n");
  if (declared_width_ <= 64) {
    absl::StrAppend(&h_output,
                    overlay->WriteSimpleValueExtractor("value", "result"));
  } else {
    absl::StrAppend(&h_output, overlay->WriteComplexValueExtractor(
                                   "value", "result", return_type));
  }
  if (overlay->is_signed()) {
    int shift = GetIntTypeBitWidth(overlay->declared_width()) -
                overlay->declared_width();
    absl::StrAppend(&h_output, "  result = result << ", shift,
                    ";\n"
                    "  result = result >> ",
                    shift, ";\n");
  }
  if ((declared_width_ > 64) && (overlay->declared_width() <= 64)) {
    absl::StrAppend(&h_output,
                    "  return UInt128Low64(result();\n"
                    "}\n\n");
  } else {
    absl::StrAppend(&h_output,
                    "  return result;\n"
                    "}\n\n");
  }
  return h_output;
}

// Top level function called to generate all the inserters for this format.
std::string Format::GenerateInserters() const {
  std::string class_output;
  std::string h_output;
  if (extractors_.empty() && overlay_extractors_.empty()) {
    return h_output;
  }
  absl::StrAppend(&h_output, "struct ", ToPascalCase(name()), " {\n\n");
  // First fields and formats.
  std::string inserter;
  for (auto &[unused, field_or_format_ptr] : extractors_) {
    if (field_or_format_ptr->is_field()) {
      if (layout() == Layout::kPackedStruct) {
        inserter =
            GeneratePackedStructFieldInserter(field_or_format_ptr->field());
      } else {
        inserter = GenerateFieldInserter(field_or_format_ptr->field());
      }
      absl::StrAppend(&h_output, inserter);
    } else {
      if (layout() == Layout::kPackedStruct) {
        inserter = GeneratePackedStructFormatInserter(
            field_or_format_ptr->format_alias(), field_or_format_ptr->format(),
            field_or_format_ptr->high(), field_or_format_ptr->size());
      } else {
        inserter = GenerateFormatInserter(
            field_or_format_ptr->format_alias(), field_or_format_ptr->format(),
            field_or_format_ptr->high(), field_or_format_ptr->size());
      }
      absl::StrAppend(&h_output, inserter);
    }
  }
  // Next the overlays.
  for (auto &[unused, overlay_ptr] : overlay_extractors_) {
    auto inserter = GenerateOverlayInserter(overlay_ptr);
    absl::StrAppend(&h_output, inserter);
  }
  absl::StrAppend(&h_output, "};  // struct ", ToPascalCase(name()), "\n\n");
  return h_output;
}

std::string Format::GeneratePackedStructTypes() const {
  std::string h_output;
  // First the struct.
  absl::StrAppend(&h_output, "struct Packed", ToPascalCase(name()), " {\n");
  for (auto it = field_vec_.rbegin(); it != field_vec_.rend(); ++it) {
    auto *component = *it;
    if (component->is_field()) {
      int width = component->field()->width;
      std::string field_type = component->field()->is_signed
                                   ? GetIntType(width)
                                   : GetUIntType(width);
      absl::StrAppend(&h_output, "  ", field_type, " ",
                      component->field()->name, " : ",
                      component->field()->width, ";\n");
    } else {
      absl::StrAppend(&h_output, "  ",
                      GetUIntType(component->format()->declared_width()), " ",
                      component->format_alias(), " : ",
                      component->format()->declared_width(), ";\n");
    }
  }
  absl::StrAppend(&h_output, "} ABSL_ATTRIBUTE_PACKED;\n\n");
  // Next the union.
  int num_bytes = (declared_width_ + 7) / 8;
  absl::StrAppend(&h_output, "union Union", ToPascalCase(name()),
                  " {\n"
                  "  Packed",
                  ToPascalCase(name()), " ", ToSnakeCase(name()),
                  ";\n"
                  "  uint8_t bytes[",
                  num_bytes, "];\n");
  // If it is 64 bits or less, add an unsigned integer value type.
  if (declared_width_ <= 64) {
    absl::StrAppend(&h_output, "  ", GetUIntType(declared_width_), " value;\n");
  }
  absl::StrAppend(&h_output, "};\n\n");
  return h_output;
}

// Top level function called to generate all the extractors for this format.
Extractors Format::GenerateExtractors() const {
  Extractors extractors;
  if (extractors_.empty() && overlay_extractors_.empty()) {
    return extractors;
  }

  extractors.class_output =
      absl::StrCat("class ", ToPascalCase(name()), " {\n public:\n", "  ",
                   ToPascalCase(name()), "() = default;\n\n");

  // Use a separate namespace for each format.
  extractors.h_output =
      absl::StrCat("namespace ", ToSnakeCase(name()), " {\n\n");
  extractors.types_output =
      absl::StrCat("namespace ", ToSnakeCase(name()), " {\n\n");

  std::string get_size = absl::StrCat("constexpr int k", ToPascalCase(name()),
                                      "Size = ", declared_width(), ";\n\n");
  absl::StrAppend(&extractors.h_output, get_size);
  absl::StrAppend(&extractors.class_output, "static ", get_size);

  // If this format has a packed struct layout, generate the types required.
  if (layout() == Layout::kPackedStruct) {
    absl::StrAppend(&extractors.types_output, GeneratePackedStructTypes());
  }

  // First fields and formats.
  for (auto &[unused, field_or_format_ptr] : extractors_) {
    if (field_or_format_ptr->is_field()) {
      std::string extractor;
      if (layout() == Layout::kPackedStruct) {
        extractor =
            GeneratePackedStructFieldExtractor(field_or_format_ptr->field());
      } else {
        extractor = GenerateFieldExtractor(field_or_format_ptr->field());
      }
      absl::StrAppend(&extractors.h_output, extractor);
      absl::StrAppend(&extractors.class_output, "static ", extractor);
    } else {
      std::string extractor;
      if (layout() == Layout::kPackedStruct) {
        extractor = GeneratePackedStructFormatExtractor(
            field_or_format_ptr->format_alias(), field_or_format_ptr->format(),
            field_or_format_ptr->high(), field_or_format_ptr->size());
      } else {
        extractor = GenerateFormatExtractor(
            field_or_format_ptr->format_alias(), field_or_format_ptr->format(),
            field_or_format_ptr->high(), field_or_format_ptr->size());
      }
      absl::StrAppend(&extractors.h_output, extractor);
      absl::StrAppend(&extractors.class_output, "static ", extractor);
    }
  }

  // Then the overlays.
  for (auto &[unused, overlay_ptr] : overlay_extractors_) {
    std::string extractor;
    if (layout() == Layout::kPackedStruct) {
      extractor = GeneratePackedStructOverlayExtractor(overlay_ptr);
    } else {
      extractor = GenerateOverlayExtractor(overlay_ptr);
    }
    absl::StrAppend(&extractors.h_output, extractor);
    absl::StrAppend(&extractors.class_output, "static ", extractor);
  }

  absl::StrAppend(&extractors.h_output, "}  // namespace ", ToSnakeCase(name()),
                  "\n\n");
  absl::StrAppend(&extractors.types_output, "}  // namespace ",
                  ToSnakeCase(name()), "\n\n");
  absl::StrAppend(&extractors.class_output, "};\n\n");
  return extractors;
}

bool Format::IsDerivedFrom(const Format *format) {
  if (format == this) return true;
  if (base_format_ == nullptr) return false;
  if (base_format_ == format) return true;
  return base_format_->IsDerivedFrom(format);
}

}  // namespace bin_format
}  // namespace decoder
}  // namespace sim
}  // namespace mpact
