Index: lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp =================================================================== --- lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp +++ lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp @@ -451,8 +451,7 @@ } bool NativeRegisterContextLinux_arm64::IsSVE(unsigned reg) const { - if (GetRegisterInfo().GetRegisterSetFromRegisterIndex(reg) == - RegisterInfoPOSIX_arm64::SVERegSet) + if (GetRegisterInfo().IsSVEReg(reg)) return true; return false; } @@ -1095,11 +1094,19 @@ // Read SVE configuration data and configure register infos. if (!m_sve_header_is_valid && m_sve_state != SVEState::Disabled) { Status error = ReadSVEHeader(); - if (!error.Success() && m_sve_state == SVEState::Unknown) { - m_sve_state = SVEState::Disabled; - GetRegisterInfo().ConfigureVectorRegisterInfos( - RegisterInfoPOSIX_arm64::eVectorQuadwordAArch64); - } else { + uint32_t opt_regset = ARM64_REGS_CONFIG_DEFAULT; + if (m_sve_state == SVEState::Unknown) { + if (error.Success()) { + opt_regset |= ARM64_REGS_CONFIG_SVE; + GetRegisterInfo().ConfigureRegisterInfos(opt_regset); + } else { + m_sve_state = SVEState::Disabled; + GetRegisterInfo().ConfigureRegisterInfos(opt_regset); + return; + } + } + + if (error.Success()) { if ((m_sve_header.flags & SVE_PT_REGS_MASK) == SVE_PT_REGS_FPSIMD) m_sve_state = SVEState::FPSIMD; else if ((m_sve_header.flags & SVE_PT_REGS_MASK) == SVE_PT_REGS_SVE) @@ -1108,7 +1115,8 @@ uint32_t vq = RegisterInfoPOSIX_arm64::eVectorQuadwordAArch64SVE; if (sve_vl_valid(m_sve_header.vl)) vq = sve_vq_from_vl(m_sve_header.vl); - GetRegisterInfo().ConfigureVectorRegisterInfos(vq); + + GetRegisterInfo().ConfigureVectorLength(vq); m_sve_ptrace_payload.resize(SVE_PT_SIZE(vq, SVE_PT_REGS_SVE)); } } Index: lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_arm64.cpp =================================================================== --- lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_arm64.cpp +++ lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_arm64.cpp @@ -40,8 +40,7 @@ } bool RegisterContextPOSIX_arm64::IsSVE(unsigned reg) const { - if (m_register_info_up->GetRegisterSetFromRegisterIndex(reg) == - RegisterInfoPOSIX_arm64::SVERegSet) + if (m_register_info_up->IsSVEReg(reg)) return true; return false; } Index: lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_arm64.h =================================================================== --- lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_arm64.h +++ lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_arm64.h @@ -14,6 +14,9 @@ #include "lldb/lldb-private.h" #include +#define ARM64_REGS_CONFIG_DEFAULT 0x00 +#define ARM64_REGS_CONFIG_SVE 0x01 + enum class SVEState { Unknown, Disabled, FPSIMD, Full }; class RegisterInfoPOSIX_arm64 @@ -85,7 +88,9 @@ size_t GetRegisterSetFromRegisterIndex(uint32_t reg_index) const override; - uint32_t ConfigureVectorRegisterInfos(uint32_t sve_vq); + void ConfigureRegisterInfos(uint32_t opt_regsets); + + uint32_t ConfigureVectorLength(uint32_t mode); bool VectorSizeIsValid(uint32_t vq) { if (vq >= eVectorQuadwordAArch64 && vq <= eVectorQuadwordAArch64SVEMax) @@ -95,6 +100,7 @@ bool IsSVEEnabled() const { return m_vector_reg_vq > eVectorQuadwordAArch64; } + bool IsSVEReg(unsigned reg) const; bool IsSVEZReg(unsigned reg) const; bool IsSVEPReg(unsigned reg) const; bool IsSVERegVG(unsigned reg) const; @@ -115,6 +121,16 @@ const lldb_private::RegisterInfo *m_register_info_p; uint32_t m_register_info_count; + + const lldb_private::RegisterSet *m_register_set_p; + uint32_t m_register_set_count; + + std::map> m_per_regset_regnum_range; + + bool m_reg_infos_is_dynamic = false; + + std::vector m_dynamic_reg_infos; + std::vector m_dynamic_reg_sets; }; #endif Index: lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_arm64.cpp =================================================================== --- lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_arm64.cpp +++ lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_arm64.cpp @@ -203,10 +203,17 @@ const lldb_private::ArchSpec &target_arch) : lldb_private::RegisterInfoAndSetInterface(target_arch), m_register_info_p(GetRegisterInfoPtr(target_arch)), - m_register_info_count(GetRegisterInfoCount(target_arch)) { + m_register_info_count(GetRegisterInfoCount(target_arch)), + m_register_set_p(g_reg_sets_arm64), + m_register_set_count(k_num_register_sets - 1) { + m_per_regset_regnum_range[GPRegSet] = std::make_pair(gpr_x0, gpr_w28); + m_per_regset_regnum_range[FPRegSet] = std::make_pair(fpu_v0, fpu_fpcr); } uint32_t RegisterInfoPOSIX_arm64::GetRegisterCount() const { + if (m_reg_infos_is_dynamic) + return m_register_info_count; + if (IsSVEEnabled()) return k_num_gpr_registers + k_num_fpr_registers + k_num_sve_registers; @@ -227,31 +234,69 @@ } size_t RegisterInfoPOSIX_arm64::GetRegisterSetCount() const { - if (IsSVEEnabled()) - return k_num_register_sets; - return k_num_register_sets - 1; + return m_register_set_count; } size_t RegisterInfoPOSIX_arm64::GetRegisterSetFromRegisterIndex( uint32_t reg_index) const { - if (reg_index <= gpr_w28) - return GPRegSet; - if (reg_index <= fpu_fpcr) - return FPRegSet; - if (reg_index <= sve_ffr) - return SVERegSet; + for (const auto ®set_range : m_per_regset_regnum_range) { + if (reg_index >= regset_range.second.first && + reg_index <= regset_range.second.second) + return regset_range.first; + } return LLDB_INVALID_REGNUM; } const lldb_private::RegisterSet * RegisterInfoPOSIX_arm64::GetRegisterSet(size_t set_index) const { if (set_index < GetRegisterSetCount()) - return &g_reg_sets_arm64[set_index]; + return &m_register_set_p[set_index]; return nullptr; } -uint32_t -RegisterInfoPOSIX_arm64::ConfigureVectorRegisterInfos(uint32_t sve_vq) { +void RegisterInfoPOSIX_arm64::ConfigureRegisterInfos(uint32_t opt_regsets) { + // TODO: Comment Here + if (opt_regsets > ARM64_REGS_CONFIG_SVE) { + m_reg_infos_is_dynamic = true; + } + + if (m_reg_infos_is_dynamic) { + const lldb_private::RegisterInfo *reginfo_start, *reginfo_end; + const lldb_private::RegisterSet *regset_start = g_reg_sets_arm64; + if (opt_regsets & ARM64_REGS_CONFIG_SVE) { + reginfo_start = g_register_infos_arm64_sve_le; + reginfo_end = g_register_infos_arm64_sve_le + sve_ffr + 1; + m_per_regset_regnum_range[m_register_set_count] = + std::make_pair(sve_vg, sve_ffr); + m_register_set_count++; + } else { + reginfo_start = g_register_infos_arm64_le; + reginfo_end = g_register_infos_arm64_le + fpu_fpcr + 1; + } + + std::copy(reginfo_start, reginfo_end, + std::back_inserter(m_dynamic_reg_infos)); + std::copy(regset_start, regset_start + m_register_set_count, + std::back_inserter(m_dynamic_reg_sets)); + + m_register_info_count = m_dynamic_reg_infos.size(); + m_register_info_p = m_dynamic_reg_infos.data(); + m_register_set_p = m_dynamic_reg_sets.data(); + m_register_set_count = m_dynamic_reg_sets.size(); + } else { + if (opt_regsets & ARM64_REGS_CONFIG_SVE) { + m_register_info_p = g_register_infos_arm64_sve_le; + m_register_info_count = + static_cast(sizeof(g_register_infos_arm64_sve_le) / + sizeof(g_register_infos_arm64_sve_le[0])); + m_per_regset_regnum_range[m_register_set_count] = + std::make_pair(sve_vg, sve_ffr); + m_register_set_count++; + } + } +} + +uint32_t RegisterInfoPOSIX_arm64::ConfigureVectorLength(uint32_t sve_vq) { // sve_vq contains SVE Quad vector length in context of AArch64 SVE. // SVE register infos if enabled cannot be disabled by selecting sve_vq = 0. // Also if an invalid or previously set vector length is passed to this @@ -266,28 +311,15 @@ m_vector_reg_vq = sve_vq; - if (sve_vq == eVectorQuadwordAArch64) { - m_register_info_count = - static_cast(sizeof(g_register_infos_arm64_le) / - sizeof(g_register_infos_arm64_le[0])); - m_register_info_p = g_register_infos_arm64_le; - + if (sve_vq == eVectorQuadwordAArch64) return m_vector_reg_vq; - } - - m_register_info_count = - static_cast(sizeof(g_register_infos_arm64_sve_le) / - sizeof(g_register_infos_arm64_sve_le[0])); - std::vector ®_info_ref = m_per_vq_reg_infos[sve_vq]; if (reg_info_ref.empty()) { - reg_info_ref = llvm::makeArrayRef(g_register_infos_arm64_sve_le, - m_register_info_count); + reg_info_ref = llvm::makeArrayRef(m_register_info_p, m_register_info_count); uint32_t offset = SVE_REGS_DEFAULT_OFFSET_LINUX; - reg_info_ref[fpu_fpsr].byte_offset = offset; reg_info_ref[fpu_fpcr].byte_offset = offset + 4; reg_info_ref[sve_vg].byte_offset = offset + 8; @@ -316,13 +348,25 @@ offset += reg_info_ref[it].byte_size; } + for (uint32_t it = sve_ffr + 1; it < m_register_info_count; it++) { + reg_info_ref[it].byte_offset = offset; + offset += reg_info_ref[it].byte_size; + } + m_per_vq_reg_infos[sve_vq] = reg_info_ref; } - m_register_info_p = reg_info_ref.data(); + m_register_info_p = m_per_vq_reg_infos[sve_vq].data(); return m_vector_reg_vq; } +bool RegisterInfoPOSIX_arm64::IsSVEReg(unsigned reg) const { + if (m_vector_reg_vq > eVectorQuadwordAArch64) + return (sve_vg <= reg && reg <= sve_ffr); + else + return false; +} + bool RegisterInfoPOSIX_arm64::IsSVEZReg(unsigned reg) const { return (sve_z0 <= reg && reg <= sve_z31); } Index: lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm64.cpp =================================================================== --- lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm64.cpp +++ lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm64.cpp @@ -70,15 +70,18 @@ sve::ptrace_regs_sve) m_sve_state = SVEState::Full; - if (sve::vl_valid(m_sve_vector_length)) - m_register_info_up->ConfigureVectorRegisterInfos( - sve::vq_from_vl(m_sve_vector_length)); - else { + if (!sve::vl_valid(m_sve_vector_length)) { m_sve_state = SVEState::Disabled; m_sve_vector_length = 0; } } else m_sve_state = SVEState::Disabled; + + if (m_sve_state != SVEState::Disabled) { + m_register_info_up->ConfigureRegisterInfos(ARM64_REGS_CONFIG_SVE); + m_register_info_up->ConfigureVectorLength( + sve::vq_from_vl(m_sve_vector_length)); + } } uint32_t RegisterContextCorePOSIX_arm64::CalculateSVEOffset(