omjavaid updated this revision to Diff 329232.
omjavaid added a comment.

This update fixes review comments highlighted by @rovka


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D96458/new/

https://reviews.llvm.org/D96458

Files:
  lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp
  lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_arm64.cpp
  lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_arm64.cpp
  lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_arm64.h
  lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm64.cpp

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
@@ -57,6 +57,7 @@
 }
 
 void RegisterContextCorePOSIX_arm64::ConfigureRegisterContext() {
+  Flags opt_regsets = RegisterInfoPOSIX_arm64::eRegsetMaskDefault;
   if (m_sveregset.GetByteSize() > sizeof(sve::user_sve_header)) {
     uint64_t sve_header_field_offset = 8;
     m_sve_vector_length = m_sveregset.GetU16(&sve_header_field_offset);
@@ -70,15 +71,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;
     }
+    opt_regsets.Set(RegisterInfoPOSIX_arm64::eRegsetMaskSVE);
   } else
     m_sve_state = SVEState::Disabled;
+
+  m_register_info_up->ConfigureRegisterInfos(opt_regsets);
+  if (m_sve_state != SVEState::Disabled)
+    m_register_info_up->ConfigureVectorLength(
+        sve::vq_from_vl(m_sve_vector_length));
 }
 
 uint32_t RegisterContextCorePOSIX_arm64::CalculateSVEOffset(
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
@@ -19,7 +19,14 @@
 class RegisterInfoPOSIX_arm64
     : public lldb_private::RegisterInfoAndSetInterface {
 public:
-  enum { GPRegSet = 0, FPRegSet, SVERegSet };
+  enum { GPRegSet = 0, FPRegSet };
+
+  // AArch64 register set mask value
+  enum {
+    eRegsetMaskDefault = 0,
+    eRegsetMaskSVE = (1 << 0),
+    eRegsetMaskDynamic = (~0u << 2),
+  };
 
   // AArch64 Register set FP/SIMD feature configuration
   enum {
@@ -85,7 +92,9 @@
 
   size_t GetRegisterSetFromRegisterIndex(uint32_t reg_index) const override;
 
-  uint32_t ConfigureVectorRegisterInfos(uint32_t sve_vq);
+  void ConfigureRegisterInfos(lldb_private::Flags &opt_regsets);
+
+  uint32_t ConfigureVectorLength(uint32_t sve_vq);
 
   bool VectorSizeIsValid(uint32_t vq) {
     if (vq >= eVectorQuadwordAArch64 && vq <= eVectorQuadwordAArch64SVEMax)
@@ -95,6 +104,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 +125,18 @@
 
   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;
+
+  // Contains pair of [start, end] register numbers of a register set with start
+  // and end included.
+  std::map<uint32_t, std::pair<uint32_t, uint32_t>> m_per_regset_regnum_range;
+
+  bool m_reg_infos_is_dynamic = false;
+
+  std::vector<lldb_private::RegisterInfo> m_dynamic_reg_infos;
+  std::vector<lldb_private::RegisterSet> 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
@@ -10,6 +10,7 @@
 #include <stddef.h>
 #include <vector>
 
+#include "lldb/Utility/Flags.h"
 #include "lldb/lldb-defines.h"
 #include "llvm/Support/Compiler.h"
 
@@ -203,10 +204,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 +235,73 @@
 }
 
 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 &regset_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(
+    lldb_private::Flags &opt_regsets) {
+  // Configures register sets supported by current target. If we have a dynamic
+  // register set like MTE, Pointer Authentication regset then we need to
+  // create a dynamic register infos and regset array. Push back all optional
+  // register infos and regset and calculate register offsets accordingly.
+  if (opt_regsets.AnySet(eRegsetMaskDynamic)) {
+    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.AllSet(eRegsetMaskSVE)) {
+      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.AllSet(eRegsetMaskSVE)) {
+      m_register_info_p = g_register_infos_arm64_sve_le;
+      m_register_info_count =
+          static_cast<uint32_t>(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 +316,15 @@
 
   m_vector_reg_vq = sve_vq;
 
-  if (sve_vq == eVectorQuadwordAArch64) {
-    m_register_info_count =
-        static_cast<uint32_t>(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<uint32_t>(sizeof(g_register_infos_arm64_sve_le) /
-                            sizeof(g_register_infos_arm64_sve_le[0]));
-
   std::vector<lldb_private::RegisterInfo> &reg_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 +353,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/Utility/RegisterContextPOSIX_arm64.cpp
===================================================================
--- lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_arm64.cpp
+++ lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_arm64.cpp
@@ -40,10 +40,7 @@
 }
 
 bool RegisterContextPOSIX_arm64::IsSVE(unsigned reg) const {
-  if (m_register_info_up->GetRegisterSetFromRegisterIndex(reg) ==
-      RegisterInfoPOSIX_arm64::SVERegSet)
-    return true;
-  return false;
+  return m_register_info_up->IsSVEReg(reg);
 }
 
 RegisterContextPOSIX_arm64::RegisterContextPOSIX_arm64(
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
@@ -75,8 +75,22 @@
   m_sve_buffer_is_valid = false;
   m_sve_header_is_valid = false;
 
-  // SVE is not enabled until we query user_sve_header
-  m_sve_state = SVEState::Unknown;
+  // At this stage we configure register sets supported by this AArch64 target.
+  // ReadSVEHeader is called to check for SVE support.
+  Flags opt_regsets;
+  Status error = ReadSVEHeader();
+  if (error.Success()) {
+    // SVE is supported, enable its register set.
+    // Setting m_sve_state to SVEState::Unknown it will be updated by
+    // ConfigureRegisterContext.
+    m_sve_state = SVEState::Unknown;
+    opt_regsets.Set(RegisterInfoPOSIX_arm64::eRegsetMaskSVE);
+    GetRegisterInfo().ConfigureRegisterInfos(opt_regsets);
+  } else {
+    // SVE is not supported by this target.
+    m_sve_state = SVEState::Disabled;
+    GetRegisterInfo().ConfigureRegisterInfos(opt_regsets);
+  }
 }
 
 RegisterInfoPOSIX_arm64 &
@@ -451,10 +465,7 @@
 }
 
 bool NativeRegisterContextLinux_arm64::IsSVE(unsigned reg) const {
-  if (GetRegisterInfo().GetRegisterSetFromRegisterIndex(reg) ==
-      RegisterInfoPOSIX_arm64::SVERegSet)
-    return true;
-  return false;
+  return GetRegisterInfo().IsSVEReg(reg);
 }
 
 uint32_t NativeRegisterContextLinux_arm64::NumSupportedHardwareBreakpoints() {
@@ -1092,23 +1103,27 @@
 }
 
 void NativeRegisterContextLinux_arm64::ConfigureRegisterContext() {
-  // Read SVE configuration data and configure register infos.
+  // ConfigureRegisterContext gets called from InvalidateAllRegisters
+  // on every stop and configures SVE vector length.
+  // If m_sve_state is set to SVEState::Disabled on first stop, code below will
+  // be deemed non operational for the lifetime of current process.
   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 {
+    if (error.Success()) {
+      // If SVE is enabled thread can switch between SVEState::FPSIMD and
+      // SVEState::Full on every stop.
       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)
         m_sve_state = SVEState::Full;
 
+      // On every stop we configure SVE vector length by calling
+      // ConfigureVectorLength regardless of current SVEState of this thread.
       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));
     }
   }
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to