//===-- DynamicRegisterInfo.cpp -------------------------------------------===//
//
// 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 "DynamicRegisterInfo.h"

#include "lldb/Core/StreamFile.h"
#include "lldb/DataFormatters/FormatManager.h"
#include "lldb/Host/StringConvert.h"
#include "lldb/Interpreter/OptionArgParser.h"
#include "lldb/Utility/ArchSpec.h"
#include "lldb/Utility/RegularExpression.h"
#include "lldb/Utility/StringExtractor.h"
#include "lldb/Utility/StructuredData.h"

using namespace lldb;
using namespace lldb_private;

DynamicRegisterInfo::DynamicRegisterInfo(
    const lldb_private::StructuredData::Dictionary &dict,
    const lldb_private::ArchSpec &arch) {
  SetRegisterInfo(dict, arch);
}

DynamicRegisterInfo::DynamicRegisterInfo(DynamicRegisterInfo &&info) {
  MoveFrom(std::move(info));
}

DynamicRegisterInfo &
DynamicRegisterInfo::operator=(DynamicRegisterInfo &&info) {
  MoveFrom(std::move(info));
  return *this;
}

void DynamicRegisterInfo::MoveFrom(DynamicRegisterInfo &&info) {
  m_regs = std::move(info.m_regs);
  m_sets = std::move(info.m_sets);
  m_set_reg_nums = std::move(info.m_set_reg_nums);
  m_set_names = std::move(info.m_set_names);
  m_value_regs_map = std::move(info.m_value_regs_map);
  m_invalidate_regs_map = std::move(info.m_invalidate_regs_map);
  m_dynamic_reg_size_map = std::move(info.m_dynamic_reg_size_map);

  m_reg_data_byte_size = info.m_reg_data_byte_size;
  m_finalized = info.m_finalized;

  if (m_finalized) {
    const size_t num_sets = m_sets.size();
    for (size_t set = 0; set < num_sets; ++set)
      m_sets[set].registers = m_set_reg_nums[set].data();
  }

  info.Clear();
}

size_t
DynamicRegisterInfo::SetRegisterInfo(const StructuredData::Dictionary &dict,
                                     const ArchSpec &arch) {
  assert(!m_finalized);
  StructuredData::Array *sets = nullptr;
  if (dict.GetValueForKeyAsArray("sets", sets)) {
    const uint32_t num_sets = sets->GetSize();
    for (uint32_t i = 0; i < num_sets; ++i) {
      ConstString set_name;
      if (sets->GetItemAtIndexAsString(i, set_name) && !set_name.IsEmpty()) {
        m_sets.push_back({set_name.AsCString(), nullptr, 0, nullptr});
      } else {
        Clear();
        printf("error: register sets must have valid names\n");
        return 0;
      }
    }
    m_set_reg_nums.resize(m_sets.size());
  }

  StructuredData::Array *regs = nullptr;
  if (!dict.GetValueForKeyAsArray("registers", regs))
    return 0;

  const uint32_t num_regs = regs->GetSize();
  //        typedef std::map<std::string, std::vector<std::string> >
  //        InvalidateNameMap;
  //        InvalidateNameMap invalidate_map;
  for (uint32_t i = 0; i < num_regs; ++i) {
    StructuredData::Dictionary *reg_info_dict = nullptr;
    if (!regs->GetItemAtIndexAsDictionary(i, reg_info_dict)) {
      Clear();
      printf("error: items in the 'registers' array must be dictionaries\n");
      regs->DumpToStdout();
      return 0;
    }

    // { 'name':'rcx'       , 'bitsize' :  64, 'offset' :  16,
    // 'encoding':'uint' , 'format':'hex'         , 'set': 0, 'ehframe' : 2,
    // 'dwarf' : 2, 'generic':'arg4', 'alt-name':'arg4', },
    RegisterInfo reg_info;
    std::vector<uint32_t> value_regs;
    std::vector<uint32_t> invalidate_regs;
    memset(&reg_info, 0, sizeof(reg_info));

    ConstString name_val;
    ConstString alt_name_val;
    if (!reg_info_dict->GetValueForKeyAsString("name", name_val, nullptr)) {
      Clear();
      printf("error: registers must have valid names and offsets\n");
      reg_info_dict->DumpToStdout();
      return 0;
    }
    reg_info.name = name_val.GetCString();
    reg_info_dict->GetValueForKeyAsString("alt-name", alt_name_val, nullptr);
    reg_info.alt_name = alt_name_val.GetCString();

    reg_info_dict->GetValueForKeyAsInteger("offset", reg_info.byte_offset,
                                           UINT32_MAX);

    const ByteOrder byte_order = arch.GetByteOrder();

    if (reg_info.byte_offset == UINT32_MAX) {
      // No offset for this register, see if the register has a value
      // expression which indicates this register is part of another register.
      // Value expressions are things like "rax[31:0]" which state that the
      // current register's value is in a concrete register "rax" in bits 31:0.
      // If there is a value expression we can calculate the offset
      bool success = false;
      llvm::StringRef slice_str;
      if (reg_info_dict->GetValueForKeyAsString("slice", slice_str, nullptr)) {
        // Slices use the following format:
        //  REGNAME[MSBIT:LSBIT]
        // REGNAME - name of the register to grab a slice of
        // MSBIT - the most significant bit at which the current register value
        // starts at
        // LSBIT - the least significant bit at which the current register value
        // ends at
        static RegularExpression g_bitfield_regex(
            llvm::StringRef("([A-Za-z_][A-Za-z0-9_]*)\\[([0-9]+):([0-9]+)\\]"));
        llvm::SmallVector<llvm::StringRef, 4> matches;
        if (g_bitfield_regex.Execute(slice_str, &matches)) {
          std::string reg_name_str = matches[1].str();
          std::string msbit_str = matches[2].str();
          std::string lsbit_str = matches[3].str();
          const uint32_t msbit =
              StringConvert::ToUInt32(msbit_str.c_str(), UINT32_MAX);
          const uint32_t lsbit =
              StringConvert::ToUInt32(lsbit_str.c_str(), UINT32_MAX);
          if (msbit != UINT32_MAX && lsbit != UINT32_MAX) {
            if (msbit > lsbit) {
              const uint32_t msbyte = msbit / 8;
              const uint32_t lsbyte = lsbit / 8;

              const RegisterInfo *containing_reg_info =
                  GetRegisterInfo(reg_name_str);
              if (containing_reg_info) {
                const uint32_t max_bit = containing_reg_info->byte_size * 8;
                if (msbit < max_bit && lsbit < max_bit) {
                  m_invalidate_regs_map[containing_reg_info
                                            ->kinds[eRegisterKindLLDB]]
                      .push_back(i);
                  m_value_regs_map[i].push_back(
                      containing_reg_info->kinds[eRegisterKindLLDB]);
                  m_invalidate_regs_map[i].push_back(
                      containing_reg_info->kinds[eRegisterKindLLDB]);

                  if (byte_order == eByteOrderLittle) {
                    success = true;
                    reg_info.byte_offset =
                        containing_reg_info->byte_offset + lsbyte;
                  } else if (byte_order == eByteOrderBig) {
                    success = true;
                    reg_info.byte_offset =
                        containing_reg_info->byte_offset + msbyte;
                  } else {
                    llvm_unreachable("Invalid byte order");
                  }
                } else {
                  if (msbit > max_bit)
                    printf("error: msbit (%u) must be less than the bitsize "
                           "of the register (%u)\n",
                           msbit, max_bit);
                  else
                    printf("error: lsbit (%u) must be less than the bitsize "
                           "of the register (%u)\n",
                           lsbit, max_bit);
                }
              } else {
                printf("error: invalid concrete register \"%s\"\n",
                       reg_name_str.c_str());
              }
            } else {
              printf("error: msbit (%u) must be greater than lsbit (%u)\n",
                     msbit, lsbit);
            }
          } else {
            printf("error: msbit (%u) and lsbit (%u) must be valid\n", msbit,
                   lsbit);
          }
        } else {
          // TODO: print error invalid slice string that doesn't follow the
          // format
          printf("error: failed to match against register bitfield regex\n");
        }
      } else {
        StructuredData::Array *composite_reg_list = nullptr;
        if (reg_info_dict->GetValueForKeyAsArray("composite",
                                                 composite_reg_list)) {
          const size_t num_composite_regs = composite_reg_list->GetSize();
          if (num_composite_regs > 0) {
            uint32_t composite_offset = UINT32_MAX;
            for (uint32_t composite_idx = 0; composite_idx < num_composite_regs;
                 ++composite_idx) {
              ConstString composite_reg_name;
              if (composite_reg_list->GetItemAtIndexAsString(
                      composite_idx, composite_reg_name, nullptr)) {
                const RegisterInfo *composite_reg_info =
                    GetRegisterInfo(composite_reg_name.GetStringRef());
                if (composite_reg_info) {
                  composite_offset = std::min(composite_offset,
                                              composite_reg_info->byte_offset);
                  m_value_regs_map[i].push_back(
                      composite_reg_info->kinds[eRegisterKindLLDB]);
                  m_invalidate_regs_map[composite_reg_info
                                            ->kinds[eRegisterKindLLDB]]
                      .push_back(i);
                  m_invalidate_regs_map[i].push_back(
                      composite_reg_info->kinds[eRegisterKindLLDB]);
                } else {
                  // TODO: print error invalid slice string that doesn't follow
                  // the format
                  printf("error: failed to find composite register by name: "
                         "\"%s\"\n",
                         composite_reg_name.GetCString());
                }
              } else {
                printf(
                    "error: 'composite' list value wasn't a python string\n");
              }
            }
            if (composite_offset != UINT32_MAX) {
              reg_info.byte_offset = composite_offset;
              success = m_value_regs_map.find(i) != m_value_regs_map.end();
            } else {
              printf("error: 'composite' registers must specify at least one "
                     "real register\n");
            }
          } else {
            printf("error: 'composite' list was empty\n");
          }
        }
      }

      if (!success) {
        Clear();
        reg_info_dict->DumpToStdout();
        return 0;
      }
    }

    int64_t bitsize = 0;
    if (!reg_info_dict->GetValueForKeyAsInteger("bitsize", bitsize)) {
      Clear();
      printf("error: invalid or missing 'bitsize' key/value pair in register "
             "dictionary\n");
      reg_info_dict->DumpToStdout();
      return 0;
    }

    reg_info.byte_size = bitsize / 8;

    llvm::StringRef dwarf_opcode_string;
    if (reg_info_dict->GetValueForKeyAsString("dynamic_size_dwarf_expr_bytes",
                                              dwarf_opcode_string)) {
      reg_info.dynamic_size_dwarf_len = dwarf_opcode_string.size() / 2;
      assert(reg_info.dynamic_size_dwarf_len > 0);

      std::vector<uint8_t> dwarf_opcode_bytes(reg_info.dynamic_size_dwarf_len);
      uint32_t j;
      StringExtractor opcode_extractor(dwarf_opcode_string);
      uint32_t ret_val = opcode_extractor.GetHexBytesAvail(dwarf_opcode_bytes);
      UNUSED_IF_ASSERT_DISABLED(ret_val);
      assert(ret_val == reg_info.dynamic_size_dwarf_len);

      for (j = 0; j < reg_info.dynamic_size_dwarf_len; ++j)
        m_dynamic_reg_size_map[i].push_back(dwarf_opcode_bytes[j]);

      reg_info.dynamic_size_dwarf_expr_bytes = m_dynamic_reg_size_map[i].data();
    }

    llvm::StringRef format_str;
    if (reg_info_dict->GetValueForKeyAsString("format", format_str, nullptr)) {
      if (OptionArgParser::ToFormat(format_str.str().c_str(), reg_info.format,
                                    nullptr)
              .Fail()) {
        Clear();
        printf("error: invalid 'format' value in register dictionary\n");
        reg_info_dict->DumpToStdout();
        return 0;
      }
    } else {
      reg_info_dict->GetValueForKeyAsInteger("format", reg_info.format,
                                             eFormatHex);
    }

    llvm::StringRef encoding_str;
    if (reg_info_dict->GetValueForKeyAsString("encoding", encoding_str))
      reg_info.encoding = Args::StringToEncoding(encoding_str, eEncodingUint);
    else
      reg_info_dict->GetValueForKeyAsInteger("encoding", reg_info.encoding,
                                             eEncodingUint);

    size_t set = 0;
    if (!reg_info_dict->GetValueForKeyAsInteger<size_t>("set", set, -1) ||
        set >= m_sets.size()) {
      Clear();
      printf("error: invalid 'set' value in register dictionary, valid values "
             "are 0 - %i\n",
             (int)set);
      reg_info_dict->DumpToStdout();
      return 0;
    }

    // Fill in the register numbers
    reg_info.kinds[lldb::eRegisterKindLLDB] = i;
    reg_info.kinds[lldb::eRegisterKindProcessPlugin] = i;
    uint32_t eh_frame_regno = LLDB_INVALID_REGNUM;
    reg_info_dict->GetValueForKeyAsInteger("gcc", eh_frame_regno,
                                           LLDB_INVALID_REGNUM);
    if (eh_frame_regno == LLDB_INVALID_REGNUM)
      reg_info_dict->GetValueForKeyAsInteger("ehframe", eh_frame_regno,
                                             LLDB_INVALID_REGNUM);
    reg_info.kinds[lldb::eRegisterKindEHFrame] = eh_frame_regno;
    reg_info_dict->GetValueForKeyAsInteger(
        "dwarf", reg_info.kinds[lldb::eRegisterKindDWARF], LLDB_INVALID_REGNUM);
    llvm::StringRef generic_str;
    if (reg_info_dict->GetValueForKeyAsString("generic", generic_str))
      reg_info.kinds[lldb::eRegisterKindGeneric] =
          Args::StringToGenericRegister(generic_str);
    else
      reg_info_dict->GetValueForKeyAsInteger(
          "generic", reg_info.kinds[lldb::eRegisterKindGeneric],
          LLDB_INVALID_REGNUM);

    // Check if this register invalidates any other register values when it is
    // modified
    StructuredData::Array *invalidate_reg_list = nullptr;
    if (reg_info_dict->GetValueForKeyAsArray("invalidate-regs",
                                             invalidate_reg_list)) {
      const size_t num_regs = invalidate_reg_list->GetSize();
      if (num_regs > 0) {
        for (uint32_t idx = 0; idx < num_regs; ++idx) {
          ConstString invalidate_reg_name;
          uint64_t invalidate_reg_num;
          if (invalidate_reg_list->GetItemAtIndexAsString(
                  idx, invalidate_reg_name)) {
            const RegisterInfo *invalidate_reg_info =
                GetRegisterInfo(invalidate_reg_name.GetStringRef());
            if (invalidate_reg_info) {
              m_invalidate_regs_map[i].push_back(
                  invalidate_reg_info->kinds[eRegisterKindLLDB]);
            } else {
              // TODO: print error invalid slice string that doesn't follow the
              // format
              printf("error: failed to find a 'invalidate-regs' register for "
                     "\"%s\" while parsing register \"%s\"\n",
                     invalidate_reg_name.GetCString(), reg_info.name);
            }
          } else if (invalidate_reg_list->GetItemAtIndexAsInteger(
                         idx, invalidate_reg_num)) {
            if (invalidate_reg_num != UINT64_MAX)
              m_invalidate_regs_map[i].push_back(invalidate_reg_num);
            else
              printf("error: 'invalidate-regs' list value wasn't a valid "
                     "integer\n");
          } else {
            printf("error: 'invalidate-regs' list value wasn't a python string "
                   "or integer\n");
          }
        }
      } else {
        printf("error: 'invalidate-regs' contained an empty list\n");
      }
    }

    // Calculate the register offset
    const size_t end_reg_offset = reg_info.byte_offset + reg_info.byte_size;
    if (m_reg_data_byte_size < end_reg_offset)
      m_reg_data_byte_size = end_reg_offset;

    m_regs.push_back(reg_info);
    m_set_reg_nums[set].push_back(i);
  }
  Finalize(arch);
  return m_regs.size();
}

void DynamicRegisterInfo::AddRegister(RegisterInfo &reg_info,
                                      ConstString &reg_name,
                                      ConstString &reg_alt_name,
                                      ConstString &set_name) {
  assert(!m_finalized);
  const uint32_t reg_num = m_regs.size();
  reg_info.name = reg_name.AsCString();
  assert(reg_info.name);
  reg_info.alt_name = reg_alt_name.AsCString(nullptr);
  uint32_t i;
  if (reg_info.value_regs) {
    for (i = 0; reg_info.value_regs[i] != LLDB_INVALID_REGNUM; ++i)
      m_value_regs_map[reg_num].push_back(reg_info.value_regs[i]);
  }
  if (reg_info.invalidate_regs) {
    for (i = 0; reg_info.invalidate_regs[i] != LLDB_INVALID_REGNUM; ++i)
      m_invalidate_regs_map[reg_num].push_back(reg_info.invalidate_regs[i]);
  }
  if (reg_info.dynamic_size_dwarf_expr_bytes) {
    for (i = 0; i < reg_info.dynamic_size_dwarf_len; ++i)
      m_dynamic_reg_size_map[reg_num].push_back(
          reg_info.dynamic_size_dwarf_expr_bytes[i]);

    reg_info.dynamic_size_dwarf_expr_bytes =
        m_dynamic_reg_size_map[reg_num].data();
  }

  m_regs.push_back(reg_info);
  uint32_t set = GetRegisterSetIndexByName(set_name, true);
  assert(set < m_sets.size());
  assert(set < m_set_reg_nums.size());
  assert(set < m_set_names.size());
  m_set_reg_nums[set].push_back(reg_num);
}

void DynamicRegisterInfo::Finalize(const ArchSpec &arch) {
  if (m_finalized)
    return;

  m_finalized = true;
  const size_t num_sets = m_sets.size();
  for (size_t set = 0; set < num_sets; ++set) {
    assert(m_sets.size() == m_set_reg_nums.size());
    m_sets[set].num_registers = m_set_reg_nums[set].size();
    m_sets[set].registers = m_set_reg_nums[set].data();
  }

  // sort and unique all value registers and make sure each is terminated with
  // LLDB_INVALID_REGNUM

  for (reg_to_regs_map::iterator pos = m_value_regs_map.begin(),
                                 end = m_value_regs_map.end();
       pos != end; ++pos) {
    if (pos->second.size() > 1) {
      llvm::sort(pos->second.begin(), pos->second.end());
      reg_num_collection::iterator unique_end =
          std::unique(pos->second.begin(), pos->second.end());
      if (unique_end != pos->second.end())
        pos->second.erase(unique_end, pos->second.end());
    }
    assert(!pos->second.empty());
    if (pos->second.back() != LLDB_INVALID_REGNUM)
      pos->second.push_back(LLDB_INVALID_REGNUM);
  }

  // Now update all value_regs with each register info as needed
  const size_t num_regs = m_regs.size();
  for (size_t i = 0; i < num_regs; ++i) {
    if (m_value_regs_map.find(i) != m_value_regs_map.end())
      m_regs[i].value_regs = m_value_regs_map[i].data();
    else
      m_regs[i].value_regs = nullptr;
  }

  // Expand all invalidation dependencies
  for (reg_to_regs_map::iterator pos = m_invalidate_regs_map.begin(),
                                 end = m_invalidate_regs_map.end();
       pos != end; ++pos) {
    const uint32_t reg_num = pos->first;

    if (m_regs[reg_num].value_regs) {
      reg_num_collection extra_invalid_regs;
      for (const uint32_t invalidate_reg_num : pos->second) {
        reg_to_regs_map::iterator invalidate_pos =
            m_invalidate_regs_map.find(invalidate_reg_num);
        if (invalidate_pos != m_invalidate_regs_map.end()) {
          for (const uint32_t concrete_invalidate_reg_num :
               invalidate_pos->second) {
            if (concrete_invalidate_reg_num != reg_num)
              extra_invalid_regs.push_back(concrete_invalidate_reg_num);
          }
        }
      }
      pos->second.insert(pos->second.end(), extra_invalid_regs.begin(),
                         extra_invalid_regs.end());
    }
  }

  // sort and unique all invalidate registers and make sure each is terminated
  // with LLDB_INVALID_REGNUM
  for (reg_to_regs_map::iterator pos = m_invalidate_regs_map.begin(),
                                 end = m_invalidate_regs_map.end();
       pos != end; ++pos) {
    if (pos->second.size() > 1) {
      llvm::sort(pos->second.begin(), pos->second.end());
      reg_num_collection::iterator unique_end =
          std::unique(pos->second.begin(), pos->second.end());
      if (unique_end != pos->second.end())
        pos->second.erase(unique_end, pos->second.end());
    }
    assert(!pos->second.empty());
    if (pos->second.back() != LLDB_INVALID_REGNUM)
      pos->second.push_back(LLDB_INVALID_REGNUM);
  }

  // Now update all invalidate_regs with each register info as needed
  for (size_t i = 0; i < num_regs; ++i) {
    if (m_invalidate_regs_map.find(i) != m_invalidate_regs_map.end())
      m_regs[i].invalidate_regs = m_invalidate_regs_map[i].data();
    else
      m_regs[i].invalidate_regs = nullptr;
  }

  // Check if we need to automatically set the generic registers in case they
  // weren't set
  bool generic_regs_specified = false;
  for (const auto &reg : m_regs) {
    if (reg.kinds[eRegisterKindGeneric] != LLDB_INVALID_REGNUM) {
      generic_regs_specified = true;
      break;
    }
  }

  if (!generic_regs_specified) {
    switch (arch.GetMachine()) {
    case llvm::Triple::aarch64:
    case llvm::Triple::aarch64_32:
    case llvm::Triple::aarch64_be:
      for (auto &reg : m_regs) {
        if (strcmp(reg.name, "pc") == 0)
          reg.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_PC;
        else if ((strcmp(reg.name, "fp") == 0) ||
                 (strcmp(reg.name, "x29") == 0))
          reg.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_FP;
        else if ((strcmp(reg.name, "lr") == 0) ||
                 (strcmp(reg.name, "x30") == 0))
          reg.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_RA;
        else if ((strcmp(reg.name, "sp") == 0) ||
                 (strcmp(reg.name, "x31") == 0))
          reg.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_SP;
        else if (strcmp(reg.name, "cpsr") == 0)
          reg.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_FLAGS;
      }
      break;

    case llvm::Triple::arm:
    case llvm::Triple::armeb:
    case llvm::Triple::thumb:
    case llvm::Triple::thumbeb:
      for (auto &reg : m_regs) {
        if ((strcmp(reg.name, "pc") == 0) || (strcmp(reg.name, "r15") == 0))
          reg.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_PC;
        else if ((strcmp(reg.name, "sp") == 0) ||
                 (strcmp(reg.name, "r13") == 0))
          reg.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_SP;
        else if ((strcmp(reg.name, "lr") == 0) ||
                 (strcmp(reg.name, "r14") == 0))
          reg.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_RA;
        else if ((strcmp(reg.name, "r7") == 0) &&
                 arch.GetTriple().getVendor() == llvm::Triple::Apple)
          reg.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_FP;
        else if ((strcmp(reg.name, "r11") == 0) &&
                 arch.GetTriple().getVendor() != llvm::Triple::Apple)
          reg.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_FP;
        else if (strcmp(reg.name, "fp") == 0)
          reg.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_FP;
        else if (strcmp(reg.name, "cpsr") == 0)
          reg.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_FLAGS;
      }
      break;

    case llvm::Triple::x86:
      for (auto &reg : m_regs) {
        if ((strcmp(reg.name, "eip") == 0) || (strcmp(reg.name, "pc") == 0))
          reg.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_PC;
        else if ((strcmp(reg.name, "esp") == 0) ||
                 (strcmp(reg.name, "sp") == 0))
          reg.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_SP;
        else if ((strcmp(reg.name, "ebp") == 0) ||
                 (strcmp(reg.name, "fp") == 0))
          reg.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_FP;
        else if ((strcmp(reg.name, "eflags") == 0) ||
                 (strcmp(reg.name, "flags") == 0))
          reg.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_FLAGS;
      }
      break;

    case llvm::Triple::x86_64:
      for (auto &reg : m_regs) {
        if ((strcmp(reg.name, "rip") == 0) || (strcmp(reg.name, "pc") == 0))
          reg.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_PC;
        else if ((strcmp(reg.name, "rsp") == 0) ||
                 (strcmp(reg.name, "sp") == 0))
          reg.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_SP;
        else if ((strcmp(reg.name, "rbp") == 0) ||
                 (strcmp(reg.name, "fp") == 0))
          reg.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_FP;
        else if ((strcmp(reg.name, "rflags") == 0) ||
                 (strcmp(reg.name, "flags") == 0))
          reg.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_FLAGS;
      }
      break;

    default:
      break;
    }
  }

  // At this stage call ConfigureOffsets to calculate register offsets for
  // targets supporting dynamic offset calculation. It also calculates
  // total byte size of register data.
  ConfigureOffsets();

  // Check if register info is reconfigurable
  // AArch64 SVE register set has configurable register sizes
  if (arch.GetTriple().isAArch64()) {
    for (const auto &reg : m_regs) {
      if (strcmp(reg.name, "vg") == 0) {
        m_is_reconfigurable = true;
        break;
      }
    }
  }
}

void DynamicRegisterInfo::ConfigureOffsets() {
  // We are going to create a map between remote (eRegisterKindProcessPlugin)
  // and local (eRegisterKindLLDB) register numbers. This map will give us
  // remote register numbers in increasing order for offset calculation.
  std::map<uint32_t, uint32_t> remote_to_local_regnum_map;
  for (const auto &reg : m_regs)
    remote_to_local_regnum_map[reg.kinds[eRegisterKindProcessPlugin]] =
        reg.kinds[eRegisterKindLLDB];

  // At this stage we manually calculate g/G packet offsets of all primary
  // registers, only if target XML or qRegisterInfo packet did not send
  // an offset explicitly.
  uint32_t reg_offset = 0;
  for (auto const &regnum_pair : remote_to_local_regnum_map) {
    if (m_regs[regnum_pair.second].byte_offset == LLDB_INVALID_INDEX32 &&
        m_regs[regnum_pair.second].value_regs == nullptr) {
      m_regs[regnum_pair.second].byte_offset = reg_offset;

      reg_offset = m_regs[regnum_pair.second].byte_offset +
                   m_regs[regnum_pair.second].byte_size;
    }
  }

  // Now update all value_regs with each register info as needed
  for (auto &reg : m_regs) {
    if (reg.value_regs != nullptr) {
      // Assign a valid offset to all pseudo registers if not assigned by stub.
      // Pseudo registers with value_regs list populated will share same offset
      // as that of their corresponding primary register in value_regs list.
      if (reg.byte_offset == LLDB_INVALID_INDEX32) {
        uint32_t value_regnum = reg.value_regs[0];
        if (value_regnum != LLDB_INVALID_INDEX32)
          reg.byte_offset =
              GetRegisterInfoAtIndex(remote_to_local_regnum_map[value_regnum])
                  ->byte_offset;
      }
    }

    reg_offset = reg.byte_offset + reg.byte_size;
    if (m_reg_data_byte_size < reg_offset)
      m_reg_data_byte_size = reg_offset;
  }
}

bool DynamicRegisterInfo::IsReconfigurable() { return m_is_reconfigurable; }

size_t DynamicRegisterInfo::GetNumRegisters() const { return m_regs.size(); }

size_t DynamicRegisterInfo::GetNumRegisterSets() const { return m_sets.size(); }

size_t DynamicRegisterInfo::GetRegisterDataByteSize() const {
  return m_reg_data_byte_size;
}

const RegisterInfo *
DynamicRegisterInfo::GetRegisterInfoAtIndex(uint32_t i) const {
  if (i < m_regs.size())
    return &m_regs[i];
  return nullptr;
}

RegisterInfo *DynamicRegisterInfo::GetRegisterInfoAtIndex(uint32_t i) {
  if (i < m_regs.size())
    return &m_regs[i];
  return nullptr;
}

const RegisterInfo *DynamicRegisterInfo::GetRegisterInfo(uint32_t kind,
                                                         uint32_t num) const {
  uint32_t reg_index = ConvertRegisterKindToRegisterNumber(kind, num);
  if (reg_index != LLDB_INVALID_REGNUM)
    return &m_regs[reg_index];
  return nullptr;
}

const RegisterSet *DynamicRegisterInfo::GetRegisterSet(uint32_t i) const {
  if (i < m_sets.size())
    return &m_sets[i];
  return nullptr;
}

uint32_t DynamicRegisterInfo::GetRegisterSetIndexByName(ConstString &set_name,
                                                        bool can_create) {
  name_collection::iterator pos, end = m_set_names.end();
  for (pos = m_set_names.begin(); pos != end; ++pos) {
    if (*pos == set_name)
      return std::distance(m_set_names.begin(), pos);
  }

  m_set_names.push_back(set_name);
  m_set_reg_nums.resize(m_set_reg_nums.size() + 1);
  RegisterSet new_set = {set_name.AsCString(), nullptr, 0, nullptr};
  m_sets.push_back(new_set);
  return m_sets.size() - 1;
}

uint32_t
DynamicRegisterInfo::ConvertRegisterKindToRegisterNumber(uint32_t kind,
                                                         uint32_t num) const {
  reg_collection::const_iterator pos, end = m_regs.end();
  for (pos = m_regs.begin(); pos != end; ++pos) {
    if (pos->kinds[kind] == num)
      return std::distance(m_regs.begin(), pos);
  }

  return LLDB_INVALID_REGNUM;
}

void DynamicRegisterInfo::Clear() {
  m_regs.clear();
  m_sets.clear();
  m_set_reg_nums.clear();
  m_set_names.clear();
  m_value_regs_map.clear();
  m_invalidate_regs_map.clear();
  m_dynamic_reg_size_map.clear();
  m_reg_data_byte_size = 0;
  m_finalized = false;
}

void DynamicRegisterInfo::Dump() const {
  StreamFile s(stdout, false);
  const size_t num_regs = m_regs.size();
  s.Printf("%p: DynamicRegisterInfo contains %" PRIu64 " registers:\n",
           static_cast<const void *>(this), static_cast<uint64_t>(num_regs));
  for (size_t i = 0; i < num_regs; ++i) {
    s.Printf("[%3" PRIu64 "] name = %-10s", (uint64_t)i, m_regs[i].name);
    s.Printf(", size = %2u, offset = %4u, encoding = %u, format = %-10s",
             m_regs[i].byte_size, m_regs[i].byte_offset, m_regs[i].encoding,
             FormatManager::GetFormatAsCString(m_regs[i].format));
    if (m_regs[i].kinds[eRegisterKindProcessPlugin] != LLDB_INVALID_REGNUM)
      s.Printf(", process plugin = %3u",
               m_regs[i].kinds[eRegisterKindProcessPlugin]);
    if (m_regs[i].kinds[eRegisterKindDWARF] != LLDB_INVALID_REGNUM)
      s.Printf(", dwarf = %3u", m_regs[i].kinds[eRegisterKindDWARF]);
    if (m_regs[i].kinds[eRegisterKindEHFrame] != LLDB_INVALID_REGNUM)
      s.Printf(", ehframe = %3u", m_regs[i].kinds[eRegisterKindEHFrame]);
    if (m_regs[i].kinds[eRegisterKindGeneric] != LLDB_INVALID_REGNUM)
      s.Printf(", generic = %3u", m_regs[i].kinds[eRegisterKindGeneric]);
    if (m_regs[i].alt_name)
      s.Printf(", alt-name = %s", m_regs[i].alt_name);
    if (m_regs[i].value_regs) {
      s.Printf(", value_regs = [ ");
      for (size_t j = 0; m_regs[i].value_regs[j] != LLDB_INVALID_REGNUM; ++j) {
        s.Printf("%s ", m_regs[m_regs[i].value_regs[j]].name);
      }
      s.Printf("]");
    }
    if (m_regs[i].invalidate_regs) {
      s.Printf(", invalidate_regs = [ ");
      for (size_t j = 0; m_regs[i].invalidate_regs[j] != LLDB_INVALID_REGNUM;
           ++j) {
        s.Printf("%s ", m_regs[m_regs[i].invalidate_regs[j]].name);
      }
      s.Printf("]");
    }
    s.EOL();
  }

  const size_t num_sets = m_sets.size();
  s.Printf("%p: DynamicRegisterInfo contains %" PRIu64 " register sets:\n",
           static_cast<const void *>(this), static_cast<uint64_t>(num_sets));
  for (size_t i = 0; i < num_sets; ++i) {
    s.Printf("set[%" PRIu64 "] name = %s, regs = [", (uint64_t)i,
             m_sets[i].name);
    for (size_t idx = 0; idx < m_sets[i].num_registers; ++idx) {
      s.Printf("%s ", m_regs[m_sets[i].registers[idx]].name);
    }
    s.Printf("]\n");
  }
}

const lldb_private::RegisterInfo *
DynamicRegisterInfo::GetRegisterInfo(llvm::StringRef reg_name) const {
  for (auto &reg_info : m_regs)
    if (reg_info.name == reg_name)
      return &reg_info;
  return nullptr;
}
