//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#include "RegisterInfoPOSIXDynamic_riscv32.h"

#include "lldb-riscv-register-enums.h"
#include "lldb/lldb-defines.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/Support/Compiler.h"

#include <stddef.h>

#define GPR_OFFSET(idx) ((idx) * sizeof(uint32_t))
#define FPR_OFFSET(idx) ((idx) * sizeof(uint32_t))

#define DECLARE_REGISTER_INFOS_RISCV32_STRUCT
#include "Plugins/Process/Utility/RegisterInfos_riscv32.h"
#undef DECLARE_REGISTER_INFOS_RISCV32_STRUCT

RegisterInfoPOSIXDynamic_riscv32::RegisterInfoPOSIXDynamic_riscv32(
    const lldb_private::ArchSpec &target_arch)
    : lldb_private::RegisterInfoAndSetInterface(target_arch),
      m_target_arch(target_arch) {}

uint32_t RegisterInfoPOSIXDynamic_riscv32::GetRegisterCount() const {
  return m_dyn_reg_infos.GetNumRegisters();
}

size_t RegisterInfoPOSIXDynamic_riscv32::GetGPRSize() const {
  for (uint32_t set_idx = 0; set_idx < GetRegisterSetCount(); ++set_idx) {
    const lldb_private::RegisterSet *set =
        m_dyn_reg_infos.GetRegisterSet(set_idx);
    if (strcmp(set->name, "GPR") == 0)
      return set->num_registers;
  }
  return 0;
}

size_t RegisterInfoPOSIXDynamic_riscv32::GetFPRSize() const {
  for (uint32_t set_idx = 0; set_idx < GetRegisterSetCount(); ++set_idx) {
    const lldb_private::RegisterSet *set =
        m_dyn_reg_infos.GetRegisterSet(set_idx);
    if (strcmp(set->name, "FPR") == 0)
      return set->num_registers;
  }
  return 0;
}

const lldb_private::RegisterInfo *
RegisterInfoPOSIXDynamic_riscv32::GetRegisterInfo() const {
  return &*m_dyn_reg_infos
               .registers<lldb_private::DynamicRegisterInfo::
                              reg_collection_const_range>()
               .begin();
}

size_t RegisterInfoPOSIXDynamic_riscv32::GetRegisterSetCount() const {
  return m_dyn_reg_infos.GetNumRegisterSets();
}

size_t RegisterInfoPOSIXDynamic_riscv32::GetRegisterSetFromRegisterIndex(
    uint32_t reg_index) const {
  for (size_t set_index = 0; set_index < m_dyn_reg_infos.GetNumRegisterSets();
       ++set_index) {
    const lldb_private::RegisterSet *reg_set =
        m_dyn_reg_infos.GetRegisterSet(set_index);
    for (uint32_t idx = 0; idx < reg_set->num_registers; ++idx)
      if (reg_set->registers[idx] == reg_index)
        return set_index;
  }
  return LLDB_INVALID_REGNUM;
}

const lldb_private::RegisterSet *
RegisterInfoPOSIXDynamic_riscv32::GetRegisterSet(size_t set_index) const {
  if (set_index < GetRegisterSetCount())
    return m_dyn_reg_infos.GetRegisterSet(set_index);
  return nullptr;
}

size_t RegisterInfoPOSIXDynamic_riscv32::SetRegisterInfo(
    std::vector<lldb_private::DynamicRegisterInfo::Register> regs) {
  return m_dyn_reg_infos.SetRegisterInfo(std::move(regs), m_target_arch);
}

const lldb_private::RegisterInfo *
RegisterInfoPOSIXDynamic_riscv32::GetRegisterInfo(
    llvm::StringRef reg_name) const {
  return m_dyn_reg_infos.GetRegisterInfo(reg_name);
}

void RegisterInfoPOSIXDynamic_riscv32::BuildCSRegInfos(
    llvm::ArrayRef<std::string> features,
    llvm::SmallVectorImpl<lldb_private::RegisterInfo> &cs_reg_infos) {
  cs_reg_infos.clear();

  // Sort and deduplicate to make the list independent of caller ordering.
  llvm::SmallVector<llvm::StringRef> normalized_features(features.begin(),
                                                         features.end());
  llvm::sort(normalized_features);
  normalized_features.erase(llvm::unique(normalized_features),
                            normalized_features.end());

  const uint32_t k_num_csr_registers = csr_last_riscv - csr_first_riscv + 1;
  cs_reg_infos.reserve(k_num_csr_registers);

  // Construct default CS register information. CS register information entries
  // are stored in CSR-address order.
  for (uint32_t reg = 0; reg < k_num_csr_registers; ++reg) {
    lldb_private::RegisterInfo csr{};
    for (auto &kind : csr.kinds)
      kind = LLDB_INVALID_REGNUM;

    lldb_private::ConstString name(llvm::formatv("csr_{0:x}", reg).str());
    csr.name = name.GetCString();
    csr.alt_name = csr.name;
    csr.byte_size = 4;
    csr.byte_offset = 0;
    csr.encoding = lldb::eEncodingUint;
    csr.format = lldb::eFormatHex;
    csr.kinds[lldb::eRegisterKindEHFrame] = riscv_dwarf::dwarf_first_csr + reg;
    csr.kinds[lldb::eRegisterKindDWARF] = riscv_dwarf::dwarf_first_csr + reg;
    csr.kinds[lldb::eRegisterKindGeneric] = LLDB_INVALID_REGNUM;
    csr.kinds[lldb::eRegisterKindProcessPlugin] = LLDB_INVALID_REGNUM;
    csr.kinds[lldb::eRegisterKindLLDB] = csr_first_riscv + reg;
    csr.value_regs = nullptr;
    csr.invalidate_regs = nullptr;
    csr.register_type = nullptr;

    cs_reg_infos.push_back(csr);
  }

  // Patch application is order-dependent; later patches override earlier ones
  // for the same CSR address.
  ConfigureCSRegInfos("default", cs_reg_infos);

  for (const auto &feature : normalized_features)
    ConfigureCSRegInfos(feature, cs_reg_infos);
}

void RegisterInfoPOSIXDynamic_riscv32::ConfigureCSRegInfos(
    llvm::StringRef feature,
    llvm::SmallVectorImpl<lldb_private::RegisterInfo> &cs_reg_infos) {
  // Initialized on first use so that the patch set does not depend on the
  // initialization order of globals in other translation units.
  static const llvm::StringMap<llvm::ArrayRef<lldb_private::RegisterInfo>>
      g_register_infos_riscv32_csr_patches = {
          {"default", llvm::ArrayRef(g_register_infos_riscv32_csr_patch)}};

  auto it = g_register_infos_riscv32_csr_patches.find(feature);
  if (it == g_register_infos_riscv32_csr_patches.end())
    return;

  for (const auto &csr : it->second) {
    const uint32_t lldb_reg = csr.kinds[lldb::eRegisterKindLLDB];
    if (lldb_reg < csr_first_riscv || lldb_reg > csr_last_riscv)
      continue;
    uint32_t idx = lldb_reg - csr_first_riscv;
    if (idx < cs_reg_infos.size())
      cs_reg_infos[idx] = csr;
  }
}
