https://github.com/DavidSpickett updated 
https://github.com/llvm/llvm-project/pull/197113

>From 192b4c1dd55cf3691d906f0423f20f37a0748643 Mon Sep 17 00:00:00 2001
From: David Spickett <[email protected]>
Date: Thu, 2 Apr 2026 13:19:01 +0000
Subject: [PATCH 01/10] [lldb][AArch64][Linux] Track all register cache
 validity in one place

In this change I've expanded the existing RegisterSetType enum
to be used as part of a singular cache tracking object which replaces
all the separate booleans. These booleans were hard to track and
set/reset in the right places.

This new validity object can be reset by default constructing,
and uses a member initialiser so everything starts out as invalid.

RegisterSetType is now a bitmask enum for easier storage.
It's 32-bit now which is enough for now. Just in case we expand it.
(and I previously updated all sizeof calls to use RegisterSetType
instead of the raw type)

Over time, RegisterSetType will become the key for all the
operations in the register context. You can see a preview of
that "vision" in #193174.

For instance getting the buffer location and size, looking up
the ptrace set number, finding out what a set write invalidates,
and so on.
---
 .../NativeRegisterContextLinux_arm64.cpp      | 212 ++++++++----------
 .../Linux/NativeRegisterContextLinux_arm64.h  |  75 ++++---
 2 files changed, 146 insertions(+), 141 deletions(-)

diff --git 
a/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp 
b/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp
index 3377c8d018629..bf602bc8bf504 100644
--- a/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp
+++ b/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp
@@ -180,17 +180,7 @@ 
NativeRegisterContextLinux_arm64::NativeRegisterContextLinux_arm64(
   m_max_hwp_supported = 16;
   m_max_hbp_supported = 16;
 
-  m_gpr_is_valid = false;
-  m_fpu_is_valid = false;
-  m_sve_buffer_is_valid = false;
-  m_sve_header_is_valid = false;
-  m_pac_mask_is_valid = false;
-  m_mte_ctrl_is_valid = false;
-  m_tls_is_valid = false;
-  m_zt_buffer_is_valid = false;
-  m_fpmr_is_valid = false;
-  m_gcs_is_valid = false;
-  m_poe_is_valid = false;
+  m_refresh_hwdebug_info = true;
 
   // SME adds the tpidr2 register
   m_tls_size = GetRegisterInfo().IsSSVEPresent() ? sizeof(m_tls_regs)
@@ -623,7 +613,8 @@ Status NativeRegisterContextLinux_arm64::WriteRegister(
         uint64_t vg_value = reg_value.GetAsUInt64();
 
         if (sve::vl_valid(vg_value * 8)) {
-          if (m_sve_header_is_valid && vg_value == GetSVERegVG())
+          if (m_validity.IsValid(RegisterSetType::SVE_HEADER) &&
+              vg_value == GetSVERegVG())
             return error;
 
           SetSVERegVG(vg_value);
@@ -632,11 +623,12 @@ Status NativeRegisterContextLinux_arm64::WriteRegister(
           if (error.Success()) {
             // Changing VG during streaming mode also changes the size of ZA.
             if (m_sve_state == SVEState::Streaming)
-              m_za_header_is_valid = false;
+              m_validity.Invalidate(RegisterSetType::ZA_HEADER);
             ConfigureRegisterContext();
           }
 
-          if (m_sve_header_is_valid && vg_value == GetSVERegVG())
+          if (m_validity.IsValid(RegisterSetType::SVE_HEADER) &&
+              vg_value == GetSVERegVG())
             return error;
         }
 
@@ -785,7 +777,9 @@ static uint8_t *AddSavedRegistersData(uint8_t *dst, void 
*src, size_t size) {
 }
 
 uint8_t *NativeRegisterContextLinux_arm64::AddSavedRegisters(
-    uint8_t *dst, RegisterSetType register_set_type, void *src, size_t size) {
+    uint8_t *dst,
+    NativeRegisterContextLinux_arm64::RegisterSetType register_set_type,
+    void *src, size_t size) {
   dst = AddRegisterSetType(dst, register_set_type);
   return AddSavedRegistersData(dst, src, size);
 }
@@ -809,7 +803,7 @@ 
NativeRegisterContextLinux_arm64::CacheAllRegisters(uint32_t &cached_size) {
     cached_size += sizeof(RegisterSetType) + m_za_header.size;
     // For the same reason, we need to force it to be re-read so that it will
     // always contain the real header.
-    m_za_buffer_is_valid = false;
+    m_validity.Invalidate(RegisterSetType::ZA);
     error = ReadZA();
     if (error.Fail())
       return error;
@@ -939,7 +933,7 @@ Status 
NativeRegisterContextLinux_arm64::ReadAllRegisterValues(
     // Use the header size not the buffer size, as we may be using the buffer
     // for fake data, which we do not want to write out.
     assert(m_za_header.size <= GetZABufferSize());
-    dst = AddSavedRegisters(dst, RegisterSetType::SME, GetZABuffer(),
+    dst = AddSavedRegisters(dst, RegisterSetType::ZA, GetZABuffer(),
                             m_za_header.size);
   }
 
@@ -956,7 +950,7 @@ Status 
NativeRegisterContextLinux_arm64::ReadAllRegisterValues(
 
   if ((m_sve_state == SVEState::Streaming) && GetRegisterInfo().IsZAPresent()) 
{
     assert(m_za_header.size <= GetZABufferSize());
-    dst = AddSavedRegisters(dst, RegisterSetType::SME, GetZABuffer(),
+    dst = AddSavedRegisters(dst, RegisterSetType::ZA, GetZABuffer(),
                             m_za_header.size);
   }
 
@@ -970,7 +964,7 @@ Status 
NativeRegisterContextLinux_arm64::ReadAllRegisterValues(
       GetRegisterInfo().IsZTPresent() &&
       // And ZA is enabled.
       m_za_header.size > sizeof(m_za_header))
-    dst = AddSavedRegisters(dst, RegisterSetType::SME2, GetZTBuffer(),
+    dst = AddSavedRegisters(dst, RegisterSetType::ZT, GetZTBuffer(),
                             GetZTBufferSize());
 
   if (GetRegisterInfo().IsMTEPresent()) {
@@ -999,10 +993,12 @@ Status 
NativeRegisterContextLinux_arm64::ReadAllRegisterValues(
   return error;
 }
 
-static Status RestoreRegisters(void *buffer, const uint8_t **src, size_t len,
-                               bool &is_valid, std::function<Status()> writer) 
{
+Status NativeRegisterContextLinux_arm64::RestoreRegisters(
+    void *buffer, const uint8_t **src, size_t len,
+    const NativeRegisterContextLinux_arm64::RegisterSetType set,
+    std::function<Status()> writer) {
   ::memcpy(buffer, *src, len);
-  is_valid = true;
+  m_validity.MakeValid(set);
   *src += len;
   return writer();
 }
@@ -1057,7 +1053,7 @@ Status 
NativeRegisterContextLinux_arm64::WriteAllRegisterValues(
     switch (kind) {
     case RegisterSetType::GPR:
       error = RestoreRegisters(
-          GetGPRBuffer(), &src, GetGPRBufferSize(), m_gpr_is_valid,
+          GetGPRBuffer(), &src, GetGPRBufferSize(), kind,
           std::bind(&NativeRegisterContextLinux_arm64::WriteGPR, this));
       break;
     case RegisterSetType::SVE:
@@ -1069,14 +1065,14 @@ Status 
NativeRegisterContextLinux_arm64::WriteAllRegisterValues(
       // not want src to be modified yet.
       ::memcpy(GetSVEHeader(), src, GetSVEHeaderSize());
       if (!sve::vl_valid(m_sve_header.vl)) {
-        m_sve_header_is_valid = false;
+        m_validity.Invalidate(RegisterSetType::SVE_HEADER);
         error = Status::FromErrorStringWithFormat(
             "NativeRegisterContextLinux_arm64::%s "
             "Invalid SVE header in data_sp",
             __FUNCTION__);
         return error;
       }
-      m_sve_header_is_valid = true;
+      m_validity.MakeValid(RegisterSetType::SVE_HEADER);
       error = WriteSVEHeader();
       if (error.Fail())
         return error;
@@ -1088,12 +1084,11 @@ Status 
NativeRegisterContextLinux_arm64::WriteAllRegisterValues(
 
       // Write header and register data, incrementing src this time.
       error = RestoreRegisters(
-          GetSVEBuffer(), &src, GetSVEBufferSize(), m_sve_buffer_is_valid,
+          GetSVEBuffer(), &src, GetSVEBufferSize(), kind,
           std::bind(&NativeRegisterContextLinux_arm64::WriteAllSVE, this));
       break;
     case RegisterSetType::FPR: {
-      m_sve_buffer_is_valid = false;
-      m_sve_header_is_valid = false;
+      m_validity.Invalidate(RegisterSetType::SVE_HEADER, RegisterSetType::SVE);
       m_sve_state = SVEState::Unknown;
       ConfigureRegisterContext();
 
@@ -1144,9 +1139,9 @@ Status 
NativeRegisterContextLinux_arm64::WriteAllRegisterValues(
 
         if (error.Success()) {
           // Wrote FPU, and SVE overlaps FPU.
-          m_fpu_is_valid = false;
-          m_sve_buffer_is_valid = false;
-          m_sve_header_is_valid = false;
+          m_validity.Invalidate(RegisterSetType::FPR,
+                                RegisterSetType::SVE_HEADER,
+                                RegisterSetType::SVE);
 
           m_sve_state = SVEState::Unknown;
           ConfigureRegisterContext();
@@ -1155,22 +1150,22 @@ Status 
NativeRegisterContextLinux_arm64::WriteAllRegisterValues(
         // the others.
       } else {
         error = RestoreRegisters(
-            GetFPRBuffer(), &src, GetFPRSize(), m_fpu_is_valid,
+            GetFPRBuffer(), &src, GetFPRSize(), kind,
             std::bind(&NativeRegisterContextLinux_arm64::WriteFPR, this));
       }
       break;
     }
     case RegisterSetType::MTE:
       error = RestoreRegisters(
-          GetMTEControl(), &src, GetMTEControlSize(), m_mte_ctrl_is_valid,
+          GetMTEControl(), &src, GetMTEControlSize(), kind,
           std::bind(&NativeRegisterContextLinux_arm64::WriteMTEControl, this));
       break;
     case RegisterSetType::TLS:
       error = RestoreRegisters(
-          GetTLSBuffer(), &src, GetTLSBufferSize(), m_tls_is_valid,
+          GetTLSBuffer(), &src, GetTLSBufferSize(), kind,
           std::bind(&NativeRegisterContextLinux_arm64::WriteTLS, this));
       break;
-    case RegisterSetType::SME:
+    case RegisterSetType::ZA:
       // To enable or disable ZA you write the regset with or without register
       // data. The kernel detects this by looking at the ioVec's length, not 
the
       // ZA header size you pass in. Therefore we must write header and 
register
@@ -1182,7 +1177,7 @@ Status 
NativeRegisterContextLinux_arm64::WriteAllRegisterValues(
       // this so WriteZA uses the correct size.
       m_za_ptrace_payload.resize(m_za_header.size);
       ::memcpy(GetZABuffer(), src, GetZABufferSize());
-      m_za_buffer_is_valid = true;
+      m_validity.MakeValid(RegisterSetType::ZA);
 
       error = WriteZA();
       if (error.Fail())
@@ -1197,17 +1192,17 @@ Status 
NativeRegisterContextLinux_arm64::WriteAllRegisterValues(
       error = ReadZA();
       src += GetZABufferSize();
       break;
-    case RegisterSetType::SME2:
+    case RegisterSetType::ZT:
       // Doing this would activate an inactive ZA, however we will only get 
here
       // if the state we are restoring had an active ZA. Restoring ZT0 will
       // always come after restoring ZA.
       error = RestoreRegisters(
-          GetZTBuffer(), &src, GetZTBufferSize(), m_zt_buffer_is_valid,
+          GetZTBuffer(), &src, GetZTBufferSize(), kind,
           std::bind(&NativeRegisterContextLinux_arm64::WriteZT, this));
       break;
     case RegisterSetType::FPMR:
       error = RestoreRegisters(
-          GetFPMRBuffer(), &src, GetFPMRBufferSize(), m_fpmr_is_valid,
+          GetFPMRBuffer(), &src, GetFPMRBufferSize(), kind,
           std::bind(&NativeRegisterContextLinux_arm64::WriteFPMR, this));
       break;
     case RegisterSetType::GCS: {
@@ -1215,7 +1210,7 @@ Status 
NativeRegisterContextLinux_arm64::WriteAllRegisterValues(
       // to keep things simple we will not revert any change to the
       // PR_SHADOW_STACK_ENABLE bit. Instead patch in the current enable bit
       // into the registers we are about to restore.
-      m_gcs_is_valid = false;
+      m_validity.Invalidate(RegisterSetType::GCS);
       error = ReadGCS();
       if (error.Fail())
         return error;
@@ -1229,7 +1224,7 @@ Status 
NativeRegisterContextLinux_arm64::WriteAllRegisterValues(
       const uint8_t *new_gcs_src =
           reinterpret_cast<const uint8_t *>(&new_gcs_regs);
       error = RestoreRegisters(
-          GetGCSBuffer(), &new_gcs_src, GetGCSBufferSize(), m_gcs_is_valid,
+          GetGCSBuffer(), &new_gcs_src, GetGCSBufferSize(), kind,
           std::bind(&NativeRegisterContextLinux_arm64::WriteGCS, this));
       src += GetGCSBufferSize();
 
@@ -1237,9 +1232,14 @@ Status 
NativeRegisterContextLinux_arm64::WriteAllRegisterValues(
     }
     case RegisterSetType::POE:
       error = RestoreRegisters(
-          GetPOEBuffer(), &src, GetPOEBufferSize(), m_poe_is_valid,
+          GetPOEBuffer(), &src, GetPOEBufferSize(), kind,
           std::bind(&NativeRegisterContextLinux_arm64::WritePOE, this));
       break;
+    case RegisterSetType::PAC:
+    case RegisterSetType::SVE_HEADER:
+    case RegisterSetType::ZA_HEADER:
+      // These are not saved or restored.
+      break;
     }
 
     if (error.Fail())
@@ -1279,7 +1279,7 @@ 
NativeRegisterContextLinux_arm64::WriteHardwareDebugRegs(DREGType hwbType) {
 Status NativeRegisterContextLinux_arm64::ReadGPR() {
   Status error;
 
-  if (m_gpr_is_valid)
+  if (m_validity.IsValid(RegisterSetType::GPR))
     return error;
 
   struct iovec ioVec;
@@ -1289,7 +1289,7 @@ Status NativeRegisterContextLinux_arm64::ReadGPR() {
   error = ReadRegisterSet(&ioVec, GetGPRBufferSize(), llvm::ELF::NT_PRSTATUS);
 
   if (error.Success())
-    m_gpr_is_valid = true;
+    m_validity.MakeValid(RegisterSetType::GPR);
 
   return error;
 }
@@ -1303,7 +1303,7 @@ Status NativeRegisterContextLinux_arm64::WriteGPR() {
   ioVec.iov_base = GetGPRBuffer();
   ioVec.iov_len = GetGPRBufferSize();
 
-  m_gpr_is_valid = false;
+  m_validity.Invalidate(RegisterSetType::GPR);
 
   return WriteRegisterSet(&ioVec, GetGPRBufferSize(), llvm::ELF::NT_PRSTATUS);
 }
@@ -1311,7 +1311,7 @@ Status NativeRegisterContextLinux_arm64::WriteGPR() {
 Status NativeRegisterContextLinux_arm64::ReadFPR() {
   Status error;
 
-  if (m_fpu_is_valid)
+  if (m_validity.IsValid(RegisterSetType::FPR))
     return error;
 
   struct iovec ioVec;
@@ -1320,7 +1320,7 @@ Status NativeRegisterContextLinux_arm64::ReadFPR() {
 
   error = ReadRegisterSet(&ioVec, GetFPRSize(), llvm::ELF::NT_FPREGSET);
   if (error.Success())
-    m_fpu_is_valid = true;
+    m_validity.MakeValid(RegisterSetType::FPR);
 
   return error;
 }
@@ -1334,28 +1334,15 @@ Status NativeRegisterContextLinux_arm64::WriteFPR() {
   ioVec.iov_base = GetFPRBuffer();
   ioVec.iov_len = GetFPRSize();
 
-  m_fpu_is_valid = false;
   // SVE Z registers overlap the FP registers.
-  m_sve_buffer_is_valid = false;
-  m_sve_header_is_valid = false;
+  m_validity.Invalidate(RegisterSetType::FPR, RegisterSetType::SVE_HEADER,
+                        RegisterSetType::SVE);
 
   return WriteRegisterSet(&ioVec, GetFPRSize(), llvm::ELF::NT_FPREGSET);
 }
 
 void NativeRegisterContextLinux_arm64::InvalidateAllRegisters() {
-  m_gpr_is_valid = false;
-  m_fpu_is_valid = false;
-  m_sve_buffer_is_valid = false;
-  m_sve_header_is_valid = false;
-  m_za_buffer_is_valid = false;
-  m_za_header_is_valid = false;
-  m_pac_mask_is_valid = false;
-  m_mte_ctrl_is_valid = false;
-  m_tls_is_valid = false;
-  m_zt_buffer_is_valid = false;
-  m_fpmr_is_valid = false;
-  m_gcs_is_valid = false;
-  m_poe_is_valid = false;
+  m_validity = CacheValidity();
 
   // Update SVE and ZA registers in case there is change in configuration.
   ConfigureRegisterContext();
@@ -1374,7 +1361,7 @@ unsigned NativeRegisterContextLinux_arm64::GetSVERegSet() 
{
 Status NativeRegisterContextLinux_arm64::ReadSVEHeader() {
   Status error;
 
-  if (m_sve_header_is_valid)
+  if (m_validity.IsValid(RegisterSetType::SVE_HEADER))
     return error;
 
   struct iovec ioVec;
@@ -1384,7 +1371,7 @@ Status NativeRegisterContextLinux_arm64::ReadSVEHeader() {
   error = ReadRegisterSet(&ioVec, GetSVEHeaderSize(), GetSVERegSet());
 
   if (error.Success())
-    m_sve_header_is_valid = true;
+    m_validity.MakeValid(RegisterSetType::SVE_HEADER);
 
   return error;
 }
@@ -1392,7 +1379,7 @@ Status NativeRegisterContextLinux_arm64::ReadSVEHeader() {
 Status NativeRegisterContextLinux_arm64::ReadPAuthMask() {
   Status error;
 
-  if (m_pac_mask_is_valid)
+  if (m_validity.IsValid(RegisterSetType::PAC))
     return error;
 
   struct iovec ioVec;
@@ -1402,7 +1389,7 @@ Status NativeRegisterContextLinux_arm64::ReadPAuthMask() {
   error = ReadRegisterSet(&ioVec, GetPACMaskSize(), 
llvm::ELF::NT_ARM_PAC_MASK);
 
   if (error.Success())
-    m_pac_mask_is_valid = true;
+    m_validity.MakeValid(RegisterSetType::PAC);
 
   return error;
 }
@@ -1418,16 +1405,15 @@ Status 
NativeRegisterContextLinux_arm64::WriteSVEHeader() {
   ioVec.iov_base = GetSVEHeader();
   ioVec.iov_len = GetSVEHeaderSize();
 
-  m_sve_buffer_is_valid = false;
-  m_sve_header_is_valid = false;
-  m_fpu_is_valid = false;
+  m_validity.Invalidate(RegisterSetType::FPR, RegisterSetType::SVE_HEADER,
+                        RegisterSetType::SVE);
 
   return WriteRegisterSet(&ioVec, GetSVEHeaderSize(), GetSVERegSet());
 }
 
 Status NativeRegisterContextLinux_arm64::ReadAllSVE() {
   Status error;
-  if (m_sve_buffer_is_valid)
+  if (m_validity.IsValid(RegisterSetType::SVE))
     return error;
 
   struct iovec ioVec;
@@ -1437,7 +1423,7 @@ Status NativeRegisterContextLinux_arm64::ReadAllSVE() {
   error = ReadRegisterSet(&ioVec, GetSVEBufferSize(), GetSVERegSet());
 
   if (error.Success())
-    m_sve_buffer_is_valid = true;
+    m_validity.MakeValid(RegisterSetType::SVE);
 
   return error;
 }
@@ -1454,9 +1440,8 @@ Status NativeRegisterContextLinux_arm64::WriteAllSVE() {
   ioVec.iov_base = GetSVEBuffer();
   ioVec.iov_len = GetSVEBufferSize();
 
-  m_sve_buffer_is_valid = false;
-  m_sve_header_is_valid = false;
-  m_fpu_is_valid = false;
+  m_validity.Invalidate(RegisterSetType::FPR, RegisterSetType::SVE_HEADER,
+                        RegisterSetType::SVE);
 
   return WriteRegisterSet(&ioVec, GetSVEBufferSize(), GetSVERegSet());
 }
@@ -1482,7 +1467,7 @@ Status NativeRegisterContextLinux_arm64::ReadSMEControl() 
{
 Status NativeRegisterContextLinux_arm64::ReadMTEControl() {
   Status error;
 
-  if (m_mte_ctrl_is_valid)
+  if (m_validity.IsValid(RegisterSetType::MTE))
     return error;
 
   struct iovec ioVec;
@@ -1493,7 +1478,7 @@ Status NativeRegisterContextLinux_arm64::ReadMTEControl() 
{
                           llvm::ELF::NT_ARM_TAGGED_ADDR_CTRL);
 
   if (error.Success())
-    m_mte_ctrl_is_valid = true;
+    m_validity.MakeValid(RegisterSetType::MTE);
 
   return error;
 }
@@ -1509,7 +1494,7 @@ Status 
NativeRegisterContextLinux_arm64::WriteMTEControl() {
   ioVec.iov_base = GetMTEControl();
   ioVec.iov_len = GetMTEControlSize();
 
-  m_mte_ctrl_is_valid = false;
+  m_validity.Invalidate(RegisterSetType::MTE);
 
   return WriteRegisterSet(&ioVec, GetMTEControlSize(),
                           llvm::ELF::NT_ARM_TAGGED_ADDR_CTRL);
@@ -1518,7 +1503,7 @@ Status 
NativeRegisterContextLinux_arm64::WriteMTEControl() {
 Status NativeRegisterContextLinux_arm64::ReadTLS() {
   Status error;
 
-  if (m_tls_is_valid)
+  if (m_validity.IsValid(RegisterSetType::TLS))
     return error;
 
   struct iovec ioVec;
@@ -1528,7 +1513,7 @@ Status NativeRegisterContextLinux_arm64::ReadTLS() {
   error = ReadRegisterSet(&ioVec, GetTLSBufferSize(), llvm::ELF::NT_ARM_TLS);
 
   if (error.Success())
-    m_tls_is_valid = true;
+    m_validity.MakeValid(RegisterSetType::TLS);
 
   return error;
 }
@@ -1544,7 +1529,7 @@ Status NativeRegisterContextLinux_arm64::WriteTLS() {
   ioVec.iov_base = GetTLSBuffer();
   ioVec.iov_len = GetTLSBufferSize();
 
-  m_tls_is_valid = false;
+  m_validity.Invalidate(RegisterSetType::TLS);
 
   return WriteRegisterSet(&ioVec, GetTLSBufferSize(), llvm::ELF::NT_ARM_TLS);
 }
@@ -1552,7 +1537,7 @@ Status NativeRegisterContextLinux_arm64::WriteTLS() {
 Status NativeRegisterContextLinux_arm64::ReadGCS() {
   Status error;
 
-  if (m_gcs_is_valid)
+  if (m_validity.IsValid(RegisterSetType::GCS))
     return error;
 
   struct iovec ioVec;
@@ -1562,7 +1547,7 @@ Status NativeRegisterContextLinux_arm64::ReadGCS() {
   error = ReadRegisterSet(&ioVec, GetGCSBufferSize(), llvm::ELF::NT_ARM_GCS);
 
   if (error.Success())
-    m_gcs_is_valid = true;
+    m_validity.MakeValid(RegisterSetType::GCS);
 
   return error;
 }
@@ -1578,7 +1563,7 @@ Status NativeRegisterContextLinux_arm64::WriteGCS() {
   ioVec.iov_base = GetGCSBuffer();
   ioVec.iov_len = GetGCSBufferSize();
 
-  m_gcs_is_valid = false;
+  m_validity.Invalidate(RegisterSetType::GCS);
 
   return WriteRegisterSet(&ioVec, GetGCSBufferSize(), llvm::ELF::NT_ARM_GCS);
 }
@@ -1586,7 +1571,7 @@ Status NativeRegisterContextLinux_arm64::WriteGCS() {
 Status NativeRegisterContextLinux_arm64::ReadZAHeader() {
   Status error;
 
-  if (m_za_header_is_valid)
+  if (m_validity.IsValid(RegisterSetType::ZA_HEADER))
     return error;
 
   struct iovec ioVec;
@@ -1596,7 +1581,7 @@ Status NativeRegisterContextLinux_arm64::ReadZAHeader() {
   error = ReadRegisterSet(&ioVec, GetZAHeaderSize(), llvm::ELF::NT_ARM_ZA);
 
   if (error.Success())
-    m_za_header_is_valid = true;
+    m_validity.MakeValid(RegisterSetType::ZA_HEADER);
 
   return error;
 }
@@ -1604,7 +1589,7 @@ Status NativeRegisterContextLinux_arm64::ReadZAHeader() {
 Status NativeRegisterContextLinux_arm64::ReadZA() {
   Status error;
 
-  if (m_za_buffer_is_valid)
+  if (m_validity.IsValid(RegisterSetType::ZA))
     return error;
 
   struct iovec ioVec;
@@ -1614,7 +1599,7 @@ Status NativeRegisterContextLinux_arm64::ReadZA() {
   error = ReadRegisterSet(&ioVec, GetZABufferSize(), llvm::ELF::NT_ARM_ZA);
 
   if (error.Success())
-    m_za_buffer_is_valid = true;
+    m_validity.MakeValid(RegisterSetType::ZA);
 
   return error;
 }
@@ -1633,10 +1618,10 @@ Status NativeRegisterContextLinux_arm64::WriteZA() {
   ioVec.iov_base = GetZABuffer();
   ioVec.iov_len = GetZABufferSize();
 
-  m_za_buffer_is_valid = false;
-  m_za_header_is_valid = false;
-  // Writing to ZA may enable ZA, which means ZT0 may change too.
-  m_zt_buffer_is_valid = false;
+  m_validity.Invalidate(
+      RegisterSetType::ZA_HEADER, RegisterSetType::ZA,
+      // Writing to ZA may enable ZA, which means ZT0 may change too.
+      RegisterSetType::ZT);
 
   return WriteRegisterSet(&ioVec, GetZABufferSize(), llvm::ELF::NT_ARM_ZA);
 }
@@ -1644,7 +1629,7 @@ Status NativeRegisterContextLinux_arm64::WriteZA() {
 Status NativeRegisterContextLinux_arm64::ReadZT() {
   Status error;
 
-  if (m_zt_buffer_is_valid)
+  if (m_validity.IsValid(RegisterSetType::ZT))
     return error;
 
   struct iovec ioVec;
@@ -1652,7 +1637,8 @@ Status NativeRegisterContextLinux_arm64::ReadZT() {
   ioVec.iov_len = GetZTBufferSize();
 
   error = ReadRegisterSet(&ioVec, GetZTBufferSize(), llvm::ELF::NT_ARM_ZT);
-  m_zt_buffer_is_valid = error.Success();
+  if (error.Success())
+    m_validity.MakeValid(RegisterSetType::ZT);
 
   return error;
 }
@@ -1668,11 +1654,10 @@ Status NativeRegisterContextLinux_arm64::WriteZT() {
   ioVec.iov_base = GetZTBuffer();
   ioVec.iov_len = GetZTBufferSize();
 
-  m_zt_buffer_is_valid = false;
-  // Writing to an inactive ZT0 will enable ZA as well, which invalidates our
-  // current copy of it.
-  m_za_buffer_is_valid = false;
-  m_za_header_is_valid = false;
+  m_validity.Invalidate(RegisterSetType::ZT,
+                        // Writing to an inactive ZT0 will enable ZA as well,
+                        // which invalidates our current copy of it.
+                        RegisterSetType::ZA_HEADER, RegisterSetType::ZA);
 
   return WriteRegisterSet(&ioVec, GetZTBufferSize(), llvm::ELF::NT_ARM_ZT);
 }
@@ -1680,7 +1665,7 @@ Status NativeRegisterContextLinux_arm64::WriteZT() {
 Status NativeRegisterContextLinux_arm64::ReadFPMR() {
   Status error;
 
-  if (m_fpmr_is_valid)
+  if (m_validity.IsValid(RegisterSetType::FPMR))
     return error;
 
   struct iovec ioVec;
@@ -1690,7 +1675,7 @@ Status NativeRegisterContextLinux_arm64::ReadFPMR() {
   error = ReadRegisterSet(&ioVec, GetFPMRBufferSize(), llvm::ELF::NT_ARM_FPMR);
 
   if (error.Success())
-    m_fpmr_is_valid = true;
+    m_validity.MakeValid(RegisterSetType::FPMR);
 
   return error;
 }
@@ -1706,7 +1691,7 @@ Status NativeRegisterContextLinux_arm64::WriteFPMR() {
   ioVec.iov_base = GetFPMRBuffer();
   ioVec.iov_len = GetFPMRBufferSize();
 
-  m_fpmr_is_valid = false;
+  m_validity.Invalidate(RegisterSetType::FPMR);
 
   return WriteRegisterSet(&ioVec, GetFPMRBufferSize(), llvm::ELF::NT_ARM_FPMR);
 }
@@ -1714,7 +1699,7 @@ Status NativeRegisterContextLinux_arm64::WriteFPMR() {
 Status NativeRegisterContextLinux_arm64::ReadPOE() {
   Status error;
 
-  if (m_poe_is_valid)
+  if (m_validity.IsValid(RegisterSetType::POE))
     return error;
 
   struct iovec ioVec;
@@ -1724,7 +1709,7 @@ Status NativeRegisterContextLinux_arm64::ReadPOE() {
   error = ReadRegisterSet(&ioVec, GetPOEBufferSize(), llvm::ELF::NT_ARM_POE);
 
   if (error.Success())
-    m_poe_is_valid = true;
+    m_validity.MakeValid(RegisterSetType::POE);
 
   return error;
 }
@@ -1740,7 +1725,7 @@ Status NativeRegisterContextLinux_arm64::WritePOE() {
   ioVec.iov_base = GetPOEBuffer();
   ioVec.iov_len = GetPOEBufferSize();
 
-  m_poe_is_valid = false;
+  m_validity.Invalidate(RegisterSetType::POE);
 
   return WriteRegisterSet(&ioVec, GetPOEBufferSize(), llvm::ELF::NT_ARM_POE);
 }
@@ -1751,14 +1736,14 @@ void 
NativeRegisterContextLinux_arm64::ConfigureRegisterContext() {
   // streaming SVE mode.
   // 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) {
+  if (!m_validity.IsValid(RegisterSetType::SVE_HEADER) &&
+      m_sve_state != SVEState::Disabled) {
     // Systems may have SVE and/or SME. If they are SME only, the SVE regset
     // cannot be read from but the SME one can. If they have both SVE and SME,
     // only the active mode will return valid register data.
 
     // Check for SME.
-    m_sve_header_is_valid = false;
-    m_sve_buffer_is_valid = false;
+    m_validity.Invalidate(RegisterSetType::SVE_HEADER, RegisterSetType::SVE);
     m_sve_state = SVEState::Streaming;
     Status error = ReadSVEHeader();
 
@@ -1768,8 +1753,7 @@ void 
NativeRegisterContextLinux_arm64::ConfigureRegisterContext() {
         ((m_sve_header.flags & sve::ptrace_regs_mask) == sve::ptrace_regs_sve);
 
     // Check for SVE.
-    m_sve_header_is_valid = false;
-    m_sve_buffer_is_valid = false;
+    m_validity.Invalidate(RegisterSetType::SVE_HEADER, RegisterSetType::SVE);
     m_sve_state = SVEState::Full;
     error = ReadSVEHeader();
 
@@ -1798,9 +1782,7 @@ void 
NativeRegisterContextLinux_arm64::ConfigureRegisterContext() {
     if (m_sve_state == SVEState::Full || m_sve_state == SVEState::FPSIMD ||
         m_sve_state == SVEState::Streaming ||
         m_sve_state == SVEState::StreamingFPSIMD) {
-
-      m_sve_header_is_valid = false;
-      m_sve_buffer_is_valid = false;
+      m_validity.Invalidate(RegisterSetType::SVE_HEADER, RegisterSetType::SVE);
       error = ReadSVEHeader();
 
       // On every stop we configure SVE vector length by calling
@@ -1814,7 +1796,7 @@ void 
NativeRegisterContextLinux_arm64::ConfigureRegisterContext() {
     }
   }
 
-  if (!m_za_header_is_valid) {
+  if (!m_validity.IsValid(RegisterSetType::ZA_HEADER)) {
     Status error = ReadZAHeader();
     if (error.Success()) {
       uint32_t vq = RegisterInfoPOSIX_arm64::eVectorQuadwordAArch64SVE;
@@ -1823,7 +1805,7 @@ void 
NativeRegisterContextLinux_arm64::ConfigureRegisterContext() {
 
       GetRegisterInfo().ConfigureVectorLengthZA(vq);
       m_za_ptrace_payload.resize(m_za_header.size);
-      m_za_buffer_is_valid = false;
+      m_validity.Invalidate(RegisterSetType::ZA);
     }
   }
 }
diff --git 
a/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.h 
b/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.h
index 41266f7082880..89923ad0e3bb2 100644
--- a/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.h
+++ b/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.h
@@ -79,36 +79,59 @@ class NativeRegisterContextLinux_arm64
   lldb::addr_t FixWatchpointHitAddress(lldb::addr_t hit_addr) override;
 
 private:
+  // Bit mask enum used to refer to the types of registers we support. 
Currently
+  // used for tracking cache validity and ReadAll/WriteAllRegister data. Will
+  // be used for much more in future.
   enum RegisterSetType : uint32_t {
-    GPR, // General purpose registers.
-    SVE, // Used for SVE registers in streaming or non-streaming mode.
-    FPR, // When there is no SVE, or SVE in FPSIMD mode, or streaming only SVE
-         // that is in non-streaming mode.
-    // Pointer authentication registers are read only, so not included here.
-    MTE,  // Memory tagging control registers.
-    TLS,  // Thread local storage registers.
-    SME,  // ZA only, because SVCR and SVG are pseudo registers.
-    SME2, // ZT only.
-    FPMR, // Floating point mode control registers.
-    GCS,  // Guarded Control Stack registers.
-    POE,  // Permission Overlay registers.
+    GPR = 1 << 0, // General purpose registers.
+    FPR = 1 << 1, // When there is no SVE, or SVE in FPSIMD mode, or streaming
+                  // only SVE that is in non-streaming mode.
+    SVE = 1 << 2, // Used for SVE registers in streaming or non-streaming mode.
+    SVE_HEADER = 1 << 3, // Only the ptrace header for SVE.
+    PAC = 1 << 4,        // Pointer authentication mask registers.
+    MTE = 1 << 5,        // Memory tagging control registers.
+    TLS = 1 << 6,        // Thread local storage registers.
+    ZA = 1 << 7,         // ZA only, because SVCR and SVG are pseudo registers.
+    ZA_HEADER = 1 << 8,  // Only the ptrace header for ZA.
+    ZT = 1 << 9,         // ZT only.
+    FPMR = 1 << 10,      // Floating point mode control registers.
+    GCS = 1 << 11,       // Guarded Control Stack registers.
+    POE = 1 << 12,       // Permission Overlay registers.
   };
 
-  bool m_gpr_is_valid;
-  bool m_fpu_is_valid;
-  bool m_sve_buffer_is_valid;
-  bool m_mte_ctrl_is_valid;
-  bool m_zt_buffer_is_valid;
-  bool m_fpmr_is_valid;
-
-  bool m_sve_header_is_valid;
-  bool m_za_buffer_is_valid;
-  bool m_za_header_is_valid;
-  bool m_pac_mask_is_valid;
-  bool m_tls_is_valid;
+  // This single object manages all tracking of whether register value caches
+  // are valid. Having a single object makes it easy to reset without missing
+  // anything.
+  class CacheValidity {
+  private:
+    using Storage = std::underlying_type_t<RegisterSetType>;
+    Storage m_valid_flags = 0;
+
+  public:
+    void Invalidate(RegisterSetType set) {
+      m_valid_flags &= ~static_cast<Storage>(set);
+    }
+
+    template <typename... Ts>
+    void Invalidate(RegisterSetType first, Ts... rest) {
+      static_assert((std::is_same_v<Ts, RegisterSetType> && ...));
+      Invalidate(first);
+      (Invalidate(rest), ...);
+    }
+
+    void MakeValid(RegisterSetType set) {
+      m_valid_flags |= static_cast<Storage>(set);
+    }
+    bool IsValid(RegisterSetType set) {
+      return (m_valid_flags & static_cast<Storage>(set)) != 0;
+    }
+  } m_validity;
+
+  Status RestoreRegisters(void *buffer, const uint8_t **src, size_t len,
+                          const RegisterSetType set,
+                          std::function<Status()> writer);
+
   size_t m_tls_size = 0;
-  bool m_gcs_is_valid;
-  bool m_poe_is_valid;
 
   /// 64-bit general purpose registers.
   struct user_pt_regs m_gpr_arm64{};

>From 0ffe5263070adef8e48451de1fa26b8a821c5b2b Mon Sep 17 00:00:00 2001
From: David Spickett <[email protected]>
Date: Mon, 20 Jul 2026 10:08:17 +0000
Subject: [PATCH 02/10] Reduce the noise

---
 .../NativeRegisterContextLinux_arm64.cpp      | 108 +++++++++---------
 .../Linux/NativeRegisterContextLinux_arm64.h  |  34 +++---
 2 files changed, 73 insertions(+), 69 deletions(-)

diff --git 
a/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp 
b/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp
index bf602bc8bf504..0caafc3ace8ef 100644
--- a/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp
+++ b/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp
@@ -613,7 +613,7 @@ Status NativeRegisterContextLinux_arm64::WriteRegister(
         uint64_t vg_value = reg_value.GetAsUInt64();
 
         if (sve::vl_valid(vg_value * 8)) {
-          if (m_validity.IsValid(RegisterSetType::SVE_HEADER) &&
+          if (IsValid(RegisterSetType::SVE_HEADER) &&
               vg_value == GetSVERegVG())
             return error;
 
@@ -623,11 +623,11 @@ Status NativeRegisterContextLinux_arm64::WriteRegister(
           if (error.Success()) {
             // Changing VG during streaming mode also changes the size of ZA.
             if (m_sve_state == SVEState::Streaming)
-              m_validity.Invalidate(RegisterSetType::ZA_HEADER);
+              Invalidate(RegisterSetType::ZA_HEADER);
             ConfigureRegisterContext();
           }
 
-          if (m_validity.IsValid(RegisterSetType::SVE_HEADER) &&
+          if (IsValid(RegisterSetType::SVE_HEADER) &&
               vg_value == GetSVERegVG())
             return error;
         }
@@ -803,7 +803,7 @@ 
NativeRegisterContextLinux_arm64::CacheAllRegisters(uint32_t &cached_size) {
     cached_size += sizeof(RegisterSetType) + m_za_header.size;
     // For the same reason, we need to force it to be re-read so that it will
     // always contain the real header.
-    m_validity.Invalidate(RegisterSetType::ZA);
+    Invalidate(RegisterSetType::ZA);
     error = ReadZA();
     if (error.Fail())
       return error;
@@ -998,7 +998,7 @@ Status NativeRegisterContextLinux_arm64::RestoreRegisters(
     const NativeRegisterContextLinux_arm64::RegisterSetType set,
     std::function<Status()> writer) {
   ::memcpy(buffer, *src, len);
-  m_validity.MakeValid(set);
+  MakeValid(set);
   *src += len;
   return writer();
 }
@@ -1065,14 +1065,14 @@ Status 
NativeRegisterContextLinux_arm64::WriteAllRegisterValues(
       // not want src to be modified yet.
       ::memcpy(GetSVEHeader(), src, GetSVEHeaderSize());
       if (!sve::vl_valid(m_sve_header.vl)) {
-        m_validity.Invalidate(RegisterSetType::SVE_HEADER);
+        Invalidate(RegisterSetType::SVE_HEADER);
         error = Status::FromErrorStringWithFormat(
             "NativeRegisterContextLinux_arm64::%s "
             "Invalid SVE header in data_sp",
             __FUNCTION__);
         return error;
       }
-      m_validity.MakeValid(RegisterSetType::SVE_HEADER);
+      MakeValid(RegisterSetType::SVE_HEADER);
       error = WriteSVEHeader();
       if (error.Fail())
         return error;
@@ -1088,7 +1088,7 @@ Status 
NativeRegisterContextLinux_arm64::WriteAllRegisterValues(
           std::bind(&NativeRegisterContextLinux_arm64::WriteAllSVE, this));
       break;
     case RegisterSetType::FPR: {
-      m_validity.Invalidate(RegisterSetType::SVE_HEADER, RegisterSetType::SVE);
+      Invalidate(RegisterSetType::SVE_HEADER, RegisterSetType::SVE);
       m_sve_state = SVEState::Unknown;
       ConfigureRegisterContext();
 
@@ -1139,7 +1139,7 @@ Status 
NativeRegisterContextLinux_arm64::WriteAllRegisterValues(
 
         if (error.Success()) {
           // Wrote FPU, and SVE overlaps FPU.
-          m_validity.Invalidate(RegisterSetType::FPR,
+          Invalidate(RegisterSetType::FPR,
                                 RegisterSetType::SVE_HEADER,
                                 RegisterSetType::SVE);
 
@@ -1177,7 +1177,7 @@ Status 
NativeRegisterContextLinux_arm64::WriteAllRegisterValues(
       // this so WriteZA uses the correct size.
       m_za_ptrace_payload.resize(m_za_header.size);
       ::memcpy(GetZABuffer(), src, GetZABufferSize());
-      m_validity.MakeValid(RegisterSetType::ZA);
+      MakeValid(RegisterSetType::ZA);
 
       error = WriteZA();
       if (error.Fail())
@@ -1210,7 +1210,7 @@ Status 
NativeRegisterContextLinux_arm64::WriteAllRegisterValues(
       // to keep things simple we will not revert any change to the
       // PR_SHADOW_STACK_ENABLE bit. Instead patch in the current enable bit
       // into the registers we are about to restore.
-      m_validity.Invalidate(RegisterSetType::GCS);
+      Invalidate(RegisterSetType::GCS);
       error = ReadGCS();
       if (error.Fail())
         return error;
@@ -1279,7 +1279,7 @@ 
NativeRegisterContextLinux_arm64::WriteHardwareDebugRegs(DREGType hwbType) {
 Status NativeRegisterContextLinux_arm64::ReadGPR() {
   Status error;
 
-  if (m_validity.IsValid(RegisterSetType::GPR))
+  if (IsValid(RegisterSetType::GPR))
     return error;
 
   struct iovec ioVec;
@@ -1289,7 +1289,7 @@ Status NativeRegisterContextLinux_arm64::ReadGPR() {
   error = ReadRegisterSet(&ioVec, GetGPRBufferSize(), llvm::ELF::NT_PRSTATUS);
 
   if (error.Success())
-    m_validity.MakeValid(RegisterSetType::GPR);
+    MakeValid(RegisterSetType::GPR);
 
   return error;
 }
@@ -1303,7 +1303,7 @@ Status NativeRegisterContextLinux_arm64::WriteGPR() {
   ioVec.iov_base = GetGPRBuffer();
   ioVec.iov_len = GetGPRBufferSize();
 
-  m_validity.Invalidate(RegisterSetType::GPR);
+  Invalidate(RegisterSetType::GPR);
 
   return WriteRegisterSet(&ioVec, GetGPRBufferSize(), llvm::ELF::NT_PRSTATUS);
 }
@@ -1311,7 +1311,7 @@ Status NativeRegisterContextLinux_arm64::WriteGPR() {
 Status NativeRegisterContextLinux_arm64::ReadFPR() {
   Status error;
 
-  if (m_validity.IsValid(RegisterSetType::FPR))
+  if (IsValid(RegisterSetType::FPR))
     return error;
 
   struct iovec ioVec;
@@ -1320,7 +1320,7 @@ Status NativeRegisterContextLinux_arm64::ReadFPR() {
 
   error = ReadRegisterSet(&ioVec, GetFPRSize(), llvm::ELF::NT_FPREGSET);
   if (error.Success())
-    m_validity.MakeValid(RegisterSetType::FPR);
+    MakeValid(RegisterSetType::FPR);
 
   return error;
 }
@@ -1335,7 +1335,7 @@ Status NativeRegisterContextLinux_arm64::WriteFPR() {
   ioVec.iov_len = GetFPRSize();
 
   // SVE Z registers overlap the FP registers.
-  m_validity.Invalidate(RegisterSetType::FPR, RegisterSetType::SVE_HEADER,
+  Invalidate(RegisterSetType::FPR, RegisterSetType::SVE_HEADER,
                         RegisterSetType::SVE);
 
   return WriteRegisterSet(&ioVec, GetFPRSize(), llvm::ELF::NT_FPREGSET);
@@ -1361,7 +1361,7 @@ unsigned NativeRegisterContextLinux_arm64::GetSVERegSet() 
{
 Status NativeRegisterContextLinux_arm64::ReadSVEHeader() {
   Status error;
 
-  if (m_validity.IsValid(RegisterSetType::SVE_HEADER))
+  if (IsValid(RegisterSetType::SVE_HEADER))
     return error;
 
   struct iovec ioVec;
@@ -1371,7 +1371,7 @@ Status NativeRegisterContextLinux_arm64::ReadSVEHeader() {
   error = ReadRegisterSet(&ioVec, GetSVEHeaderSize(), GetSVERegSet());
 
   if (error.Success())
-    m_validity.MakeValid(RegisterSetType::SVE_HEADER);
+    MakeValid(RegisterSetType::SVE_HEADER);
 
   return error;
 }
@@ -1379,7 +1379,7 @@ Status NativeRegisterContextLinux_arm64::ReadSVEHeader() {
 Status NativeRegisterContextLinux_arm64::ReadPAuthMask() {
   Status error;
 
-  if (m_validity.IsValid(RegisterSetType::PAC))
+  if (IsValid(RegisterSetType::PAC))
     return error;
 
   struct iovec ioVec;
@@ -1389,7 +1389,7 @@ Status NativeRegisterContextLinux_arm64::ReadPAuthMask() {
   error = ReadRegisterSet(&ioVec, GetPACMaskSize(), 
llvm::ELF::NT_ARM_PAC_MASK);
 
   if (error.Success())
-    m_validity.MakeValid(RegisterSetType::PAC);
+    MakeValid(RegisterSetType::PAC);
 
   return error;
 }
@@ -1405,7 +1405,7 @@ Status NativeRegisterContextLinux_arm64::WriteSVEHeader() 
{
   ioVec.iov_base = GetSVEHeader();
   ioVec.iov_len = GetSVEHeaderSize();
 
-  m_validity.Invalidate(RegisterSetType::FPR, RegisterSetType::SVE_HEADER,
+  Invalidate(RegisterSetType::FPR, RegisterSetType::SVE_HEADER,
                         RegisterSetType::SVE);
 
   return WriteRegisterSet(&ioVec, GetSVEHeaderSize(), GetSVERegSet());
@@ -1413,7 +1413,7 @@ Status NativeRegisterContextLinux_arm64::WriteSVEHeader() 
{
 
 Status NativeRegisterContextLinux_arm64::ReadAllSVE() {
   Status error;
-  if (m_validity.IsValid(RegisterSetType::SVE))
+  if (IsValid(RegisterSetType::SVE))
     return error;
 
   struct iovec ioVec;
@@ -1423,7 +1423,7 @@ Status NativeRegisterContextLinux_arm64::ReadAllSVE() {
   error = ReadRegisterSet(&ioVec, GetSVEBufferSize(), GetSVERegSet());
 
   if (error.Success())
-    m_validity.MakeValid(RegisterSetType::SVE);
+    MakeValid(RegisterSetType::SVE);
 
   return error;
 }
@@ -1440,7 +1440,7 @@ Status NativeRegisterContextLinux_arm64::WriteAllSVE() {
   ioVec.iov_base = GetSVEBuffer();
   ioVec.iov_len = GetSVEBufferSize();
 
-  m_validity.Invalidate(RegisterSetType::FPR, RegisterSetType::SVE_HEADER,
+  Invalidate(RegisterSetType::FPR, RegisterSetType::SVE_HEADER,
                         RegisterSetType::SVE);
 
   return WriteRegisterSet(&ioVec, GetSVEBufferSize(), GetSVERegSet());
@@ -1467,7 +1467,7 @@ Status NativeRegisterContextLinux_arm64::ReadSMEControl() 
{
 Status NativeRegisterContextLinux_arm64::ReadMTEControl() {
   Status error;
 
-  if (m_validity.IsValid(RegisterSetType::MTE))
+  if (IsValid(RegisterSetType::MTE))
     return error;
 
   struct iovec ioVec;
@@ -1478,7 +1478,7 @@ Status NativeRegisterContextLinux_arm64::ReadMTEControl() 
{
                           llvm::ELF::NT_ARM_TAGGED_ADDR_CTRL);
 
   if (error.Success())
-    m_validity.MakeValid(RegisterSetType::MTE);
+    MakeValid(RegisterSetType::MTE);
 
   return error;
 }
@@ -1494,7 +1494,7 @@ Status 
NativeRegisterContextLinux_arm64::WriteMTEControl() {
   ioVec.iov_base = GetMTEControl();
   ioVec.iov_len = GetMTEControlSize();
 
-  m_validity.Invalidate(RegisterSetType::MTE);
+  Invalidate(RegisterSetType::MTE);
 
   return WriteRegisterSet(&ioVec, GetMTEControlSize(),
                           llvm::ELF::NT_ARM_TAGGED_ADDR_CTRL);
@@ -1503,7 +1503,7 @@ Status 
NativeRegisterContextLinux_arm64::WriteMTEControl() {
 Status NativeRegisterContextLinux_arm64::ReadTLS() {
   Status error;
 
-  if (m_validity.IsValid(RegisterSetType::TLS))
+  if (IsValid(RegisterSetType::TLS))
     return error;
 
   struct iovec ioVec;
@@ -1513,7 +1513,7 @@ Status NativeRegisterContextLinux_arm64::ReadTLS() {
   error = ReadRegisterSet(&ioVec, GetTLSBufferSize(), llvm::ELF::NT_ARM_TLS);
 
   if (error.Success())
-    m_validity.MakeValid(RegisterSetType::TLS);
+    MakeValid(RegisterSetType::TLS);
 
   return error;
 }
@@ -1529,7 +1529,7 @@ Status NativeRegisterContextLinux_arm64::WriteTLS() {
   ioVec.iov_base = GetTLSBuffer();
   ioVec.iov_len = GetTLSBufferSize();
 
-  m_validity.Invalidate(RegisterSetType::TLS);
+  Invalidate(RegisterSetType::TLS);
 
   return WriteRegisterSet(&ioVec, GetTLSBufferSize(), llvm::ELF::NT_ARM_TLS);
 }
@@ -1537,7 +1537,7 @@ Status NativeRegisterContextLinux_arm64::WriteTLS() {
 Status NativeRegisterContextLinux_arm64::ReadGCS() {
   Status error;
 
-  if (m_validity.IsValid(RegisterSetType::GCS))
+  if (IsValid(RegisterSetType::GCS))
     return error;
 
   struct iovec ioVec;
@@ -1547,7 +1547,7 @@ Status NativeRegisterContextLinux_arm64::ReadGCS() {
   error = ReadRegisterSet(&ioVec, GetGCSBufferSize(), llvm::ELF::NT_ARM_GCS);
 
   if (error.Success())
-    m_validity.MakeValid(RegisterSetType::GCS);
+    MakeValid(RegisterSetType::GCS);
 
   return error;
 }
@@ -1563,7 +1563,7 @@ Status NativeRegisterContextLinux_arm64::WriteGCS() {
   ioVec.iov_base = GetGCSBuffer();
   ioVec.iov_len = GetGCSBufferSize();
 
-  m_validity.Invalidate(RegisterSetType::GCS);
+  Invalidate(RegisterSetType::GCS);
 
   return WriteRegisterSet(&ioVec, GetGCSBufferSize(), llvm::ELF::NT_ARM_GCS);
 }
@@ -1571,7 +1571,7 @@ Status NativeRegisterContextLinux_arm64::WriteGCS() {
 Status NativeRegisterContextLinux_arm64::ReadZAHeader() {
   Status error;
 
-  if (m_validity.IsValid(RegisterSetType::ZA_HEADER))
+  if (IsValid(RegisterSetType::ZA_HEADER))
     return error;
 
   struct iovec ioVec;
@@ -1581,7 +1581,7 @@ Status NativeRegisterContextLinux_arm64::ReadZAHeader() {
   error = ReadRegisterSet(&ioVec, GetZAHeaderSize(), llvm::ELF::NT_ARM_ZA);
 
   if (error.Success())
-    m_validity.MakeValid(RegisterSetType::ZA_HEADER);
+    MakeValid(RegisterSetType::ZA_HEADER);
 
   return error;
 }
@@ -1589,7 +1589,7 @@ Status NativeRegisterContextLinux_arm64::ReadZAHeader() {
 Status NativeRegisterContextLinux_arm64::ReadZA() {
   Status error;
 
-  if (m_validity.IsValid(RegisterSetType::ZA))
+  if (IsValid(RegisterSetType::ZA))
     return error;
 
   struct iovec ioVec;
@@ -1599,7 +1599,7 @@ Status NativeRegisterContextLinux_arm64::ReadZA() {
   error = ReadRegisterSet(&ioVec, GetZABufferSize(), llvm::ELF::NT_ARM_ZA);
 
   if (error.Success())
-    m_validity.MakeValid(RegisterSetType::ZA);
+    MakeValid(RegisterSetType::ZA);
 
   return error;
 }
@@ -1618,7 +1618,7 @@ Status NativeRegisterContextLinux_arm64::WriteZA() {
   ioVec.iov_base = GetZABuffer();
   ioVec.iov_len = GetZABufferSize();
 
-  m_validity.Invalidate(
+  Invalidate(
       RegisterSetType::ZA_HEADER, RegisterSetType::ZA,
       // Writing to ZA may enable ZA, which means ZT0 may change too.
       RegisterSetType::ZT);
@@ -1629,7 +1629,7 @@ Status NativeRegisterContextLinux_arm64::WriteZA() {
 Status NativeRegisterContextLinux_arm64::ReadZT() {
   Status error;
 
-  if (m_validity.IsValid(RegisterSetType::ZT))
+  if (IsValid(RegisterSetType::ZT))
     return error;
 
   struct iovec ioVec;
@@ -1638,7 +1638,7 @@ Status NativeRegisterContextLinux_arm64::ReadZT() {
 
   error = ReadRegisterSet(&ioVec, GetZTBufferSize(), llvm::ELF::NT_ARM_ZT);
   if (error.Success())
-    m_validity.MakeValid(RegisterSetType::ZT);
+    MakeValid(RegisterSetType::ZT);
 
   return error;
 }
@@ -1654,7 +1654,7 @@ Status NativeRegisterContextLinux_arm64::WriteZT() {
   ioVec.iov_base = GetZTBuffer();
   ioVec.iov_len = GetZTBufferSize();
 
-  m_validity.Invalidate(RegisterSetType::ZT,
+  Invalidate(RegisterSetType::ZT,
                         // Writing to an inactive ZT0 will enable ZA as well,
                         // which invalidates our current copy of it.
                         RegisterSetType::ZA_HEADER, RegisterSetType::ZA);
@@ -1665,7 +1665,7 @@ Status NativeRegisterContextLinux_arm64::WriteZT() {
 Status NativeRegisterContextLinux_arm64::ReadFPMR() {
   Status error;
 
-  if (m_validity.IsValid(RegisterSetType::FPMR))
+  if (IsValid(RegisterSetType::FPMR))
     return error;
 
   struct iovec ioVec;
@@ -1675,7 +1675,7 @@ Status NativeRegisterContextLinux_arm64::ReadFPMR() {
   error = ReadRegisterSet(&ioVec, GetFPMRBufferSize(), llvm::ELF::NT_ARM_FPMR);
 
   if (error.Success())
-    m_validity.MakeValid(RegisterSetType::FPMR);
+    MakeValid(RegisterSetType::FPMR);
 
   return error;
 }
@@ -1691,7 +1691,7 @@ Status NativeRegisterContextLinux_arm64::WriteFPMR() {
   ioVec.iov_base = GetFPMRBuffer();
   ioVec.iov_len = GetFPMRBufferSize();
 
-  m_validity.Invalidate(RegisterSetType::FPMR);
+  Invalidate(RegisterSetType::FPMR);
 
   return WriteRegisterSet(&ioVec, GetFPMRBufferSize(), llvm::ELF::NT_ARM_FPMR);
 }
@@ -1699,7 +1699,7 @@ Status NativeRegisterContextLinux_arm64::WriteFPMR() {
 Status NativeRegisterContextLinux_arm64::ReadPOE() {
   Status error;
 
-  if (m_validity.IsValid(RegisterSetType::POE))
+  if (IsValid(RegisterSetType::POE))
     return error;
 
   struct iovec ioVec;
@@ -1709,7 +1709,7 @@ Status NativeRegisterContextLinux_arm64::ReadPOE() {
   error = ReadRegisterSet(&ioVec, GetPOEBufferSize(), llvm::ELF::NT_ARM_POE);
 
   if (error.Success())
-    m_validity.MakeValid(RegisterSetType::POE);
+    MakeValid(RegisterSetType::POE);
 
   return error;
 }
@@ -1725,7 +1725,7 @@ Status NativeRegisterContextLinux_arm64::WritePOE() {
   ioVec.iov_base = GetPOEBuffer();
   ioVec.iov_len = GetPOEBufferSize();
 
-  m_validity.Invalidate(RegisterSetType::POE);
+  Invalidate(RegisterSetType::POE);
 
   return WriteRegisterSet(&ioVec, GetPOEBufferSize(), llvm::ELF::NT_ARM_POE);
 }
@@ -1736,14 +1736,14 @@ void 
NativeRegisterContextLinux_arm64::ConfigureRegisterContext() {
   // streaming SVE mode.
   // 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_validity.IsValid(RegisterSetType::SVE_HEADER) &&
+  if (!IsValid(RegisterSetType::SVE_HEADER) &&
       m_sve_state != SVEState::Disabled) {
     // Systems may have SVE and/or SME. If they are SME only, the SVE regset
     // cannot be read from but the SME one can. If they have both SVE and SME,
     // only the active mode will return valid register data.
 
     // Check for SME.
-    m_validity.Invalidate(RegisterSetType::SVE_HEADER, RegisterSetType::SVE);
+    Invalidate(RegisterSetType::SVE_HEADER, RegisterSetType::SVE);
     m_sve_state = SVEState::Streaming;
     Status error = ReadSVEHeader();
 
@@ -1753,7 +1753,7 @@ void 
NativeRegisterContextLinux_arm64::ConfigureRegisterContext() {
         ((m_sve_header.flags & sve::ptrace_regs_mask) == sve::ptrace_regs_sve);
 
     // Check for SVE.
-    m_validity.Invalidate(RegisterSetType::SVE_HEADER, RegisterSetType::SVE);
+    Invalidate(RegisterSetType::SVE_HEADER, RegisterSetType::SVE);
     m_sve_state = SVEState::Full;
     error = ReadSVEHeader();
 
@@ -1782,7 +1782,7 @@ void 
NativeRegisterContextLinux_arm64::ConfigureRegisterContext() {
     if (m_sve_state == SVEState::Full || m_sve_state == SVEState::FPSIMD ||
         m_sve_state == SVEState::Streaming ||
         m_sve_state == SVEState::StreamingFPSIMD) {
-      m_validity.Invalidate(RegisterSetType::SVE_HEADER, RegisterSetType::SVE);
+      Invalidate(RegisterSetType::SVE_HEADER, RegisterSetType::SVE);
       error = ReadSVEHeader();
 
       // On every stop we configure SVE vector length by calling
@@ -1796,7 +1796,7 @@ void 
NativeRegisterContextLinux_arm64::ConfigureRegisterContext() {
     }
   }
 
-  if (!m_validity.IsValid(RegisterSetType::ZA_HEADER)) {
+  if (!IsValid(RegisterSetType::ZA_HEADER)) {
     Status error = ReadZAHeader();
     if (error.Success()) {
       uint32_t vq = RegisterInfoPOSIX_arm64::eVectorQuadwordAArch64SVE;
@@ -1805,7 +1805,7 @@ void 
NativeRegisterContextLinux_arm64::ConfigureRegisterContext() {
 
       GetRegisterInfo().ConfigureVectorLengthZA(vq);
       m_za_ptrace_payload.resize(m_za_header.size);
-      m_validity.Invalidate(RegisterSetType::ZA);
+      Invalidate(RegisterSetType::ZA);
     }
   }
 }
diff --git 
a/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.h 
b/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.h
index 89923ad0e3bb2..edc9af56868dc 100644
--- a/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.h
+++ b/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.h
@@ -99,32 +99,36 @@ class NativeRegisterContextLinux_arm64
     POE = 1 << 12,       // Permission Overlay registers.
   };
 
+  void MakeValid(RegisterSetType set) {
+    m_validity.m_valid_flags |= static_cast<CacheValidity::Storage>(set);
+  }
+
+  bool IsValid(RegisterSetType set) {
+    return (m_validity.m_valid_flags & 
static_cast<CacheValidity::Storage>(set)) != 0;
+  }
+
+  template <typename... Ts>
+  void Invalidate(RegisterSetType first, Ts... rest) {
+    static_assert((std::is_same_v<Ts, RegisterSetType> && ...));
+    m_validity.Invalidate(first);
+    (Invalidate(rest), ...);
+  }
+
   // This single object manages all tracking of whether register value caches
   // are valid. Having a single object makes it easy to reset without missing
   // anything.
   class CacheValidity {
-  private:
     using Storage = std::underlying_type_t<RegisterSetType>;
+  private:
     Storage m_valid_flags = 0;
 
-  public:
+    friend void NativeRegisterContextLinux_arm64::MakeValid(RegisterSetType 
set);
+    friend bool NativeRegisterContextLinux_arm64::IsValid(RegisterSetType set);
+  public: 
     void Invalidate(RegisterSetType set) {
       m_valid_flags &= ~static_cast<Storage>(set);
     }
 
-    template <typename... Ts>
-    void Invalidate(RegisterSetType first, Ts... rest) {
-      static_assert((std::is_same_v<Ts, RegisterSetType> && ...));
-      Invalidate(first);
-      (Invalidate(rest), ...);
-    }
-
-    void MakeValid(RegisterSetType set) {
-      m_valid_flags |= static_cast<Storage>(set);
-    }
-    bool IsValid(RegisterSetType set) {
-      return (m_valid_flags & static_cast<Storage>(set)) != 0;
-    }
   } m_validity;
 
   Status RestoreRegisters(void *buffer, const uint8_t **src, size_t len,

>From e81214fe9ff4317e3a1245116f914e615e1d10b6 Mon Sep 17 00:00:00 2001
From: David Spickett <[email protected]>
Date: Mon, 20 Jul 2026 10:12:58 +0000
Subject: [PATCH 03/10] formatting

---
 .../NativeRegisterContextLinux_arm64.cpp      | 30 ++++++++-----------
 .../Linux/NativeRegisterContextLinux_arm64.h  | 13 ++++----
 2 files changed, 21 insertions(+), 22 deletions(-)

diff --git 
a/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp 
b/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp
index 0caafc3ace8ef..85a3ad6d041ca 100644
--- a/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp
+++ b/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp
@@ -613,8 +613,7 @@ Status NativeRegisterContextLinux_arm64::WriteRegister(
         uint64_t vg_value = reg_value.GetAsUInt64();
 
         if (sve::vl_valid(vg_value * 8)) {
-          if (IsValid(RegisterSetType::SVE_HEADER) &&
-              vg_value == GetSVERegVG())
+          if (IsValid(RegisterSetType::SVE_HEADER) && vg_value == 
GetSVERegVG())
             return error;
 
           SetSVERegVG(vg_value);
@@ -627,8 +626,7 @@ Status NativeRegisterContextLinux_arm64::WriteRegister(
             ConfigureRegisterContext();
           }
 
-          if (IsValid(RegisterSetType::SVE_HEADER) &&
-              vg_value == GetSVERegVG())
+          if (IsValid(RegisterSetType::SVE_HEADER) && vg_value == 
GetSVERegVG())
             return error;
         }
 
@@ -1139,9 +1137,8 @@ Status 
NativeRegisterContextLinux_arm64::WriteAllRegisterValues(
 
         if (error.Success()) {
           // Wrote FPU, and SVE overlaps FPU.
-          Invalidate(RegisterSetType::FPR,
-                                RegisterSetType::SVE_HEADER,
-                                RegisterSetType::SVE);
+          Invalidate(RegisterSetType::FPR, RegisterSetType::SVE_HEADER,
+                     RegisterSetType::SVE);
 
           m_sve_state = SVEState::Unknown;
           ConfigureRegisterContext();
@@ -1336,7 +1333,7 @@ Status NativeRegisterContextLinux_arm64::WriteFPR() {
 
   // SVE Z registers overlap the FP registers.
   Invalidate(RegisterSetType::FPR, RegisterSetType::SVE_HEADER,
-                        RegisterSetType::SVE);
+             RegisterSetType::SVE);
 
   return WriteRegisterSet(&ioVec, GetFPRSize(), llvm::ELF::NT_FPREGSET);
 }
@@ -1406,7 +1403,7 @@ Status NativeRegisterContextLinux_arm64::WriteSVEHeader() 
{
   ioVec.iov_len = GetSVEHeaderSize();
 
   Invalidate(RegisterSetType::FPR, RegisterSetType::SVE_HEADER,
-                        RegisterSetType::SVE);
+             RegisterSetType::SVE);
 
   return WriteRegisterSet(&ioVec, GetSVEHeaderSize(), GetSVERegSet());
 }
@@ -1441,7 +1438,7 @@ Status NativeRegisterContextLinux_arm64::WriteAllSVE() {
   ioVec.iov_len = GetSVEBufferSize();
 
   Invalidate(RegisterSetType::FPR, RegisterSetType::SVE_HEADER,
-                        RegisterSetType::SVE);
+             RegisterSetType::SVE);
 
   return WriteRegisterSet(&ioVec, GetSVEBufferSize(), GetSVERegSet());
 }
@@ -1618,10 +1615,9 @@ Status NativeRegisterContextLinux_arm64::WriteZA() {
   ioVec.iov_base = GetZABuffer();
   ioVec.iov_len = GetZABufferSize();
 
-  Invalidate(
-      RegisterSetType::ZA_HEADER, RegisterSetType::ZA,
-      // Writing to ZA may enable ZA, which means ZT0 may change too.
-      RegisterSetType::ZT);
+  Invalidate(RegisterSetType::ZA_HEADER, RegisterSetType::ZA,
+             // Writing to ZA may enable ZA, which means ZT0 may change too.
+             RegisterSetType::ZT);
 
   return WriteRegisterSet(&ioVec, GetZABufferSize(), llvm::ELF::NT_ARM_ZA);
 }
@@ -1655,9 +1651,9 @@ Status NativeRegisterContextLinux_arm64::WriteZT() {
   ioVec.iov_len = GetZTBufferSize();
 
   Invalidate(RegisterSetType::ZT,
-                        // Writing to an inactive ZT0 will enable ZA as well,
-                        // which invalidates our current copy of it.
-                        RegisterSetType::ZA_HEADER, RegisterSetType::ZA);
+             // Writing to an inactive ZT0 will enable ZA as well,
+             // which invalidates our current copy of it.
+             RegisterSetType::ZA_HEADER, RegisterSetType::ZA);
 
   return WriteRegisterSet(&ioVec, GetZTBufferSize(), llvm::ELF::NT_ARM_ZT);
 }
diff --git 
a/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.h 
b/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.h
index edc9af56868dc..e205546b454f2 100644
--- a/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.h
+++ b/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.h
@@ -104,11 +104,11 @@ class NativeRegisterContextLinux_arm64
   }
 
   bool IsValid(RegisterSetType set) {
-    return (m_validity.m_valid_flags & 
static_cast<CacheValidity::Storage>(set)) != 0;
+    return (m_validity.m_valid_flags &
+            static_cast<CacheValidity::Storage>(set)) != 0;
   }
 
-  template <typename... Ts>
-  void Invalidate(RegisterSetType first, Ts... rest) {
+  template <typename... Ts> void Invalidate(RegisterSetType first, Ts... rest) 
{
     static_assert((std::is_same_v<Ts, RegisterSetType> && ...));
     m_validity.Invalidate(first);
     (Invalidate(rest), ...);
@@ -119,12 +119,15 @@ class NativeRegisterContextLinux_arm64
   // anything.
   class CacheValidity {
     using Storage = std::underlying_type_t<RegisterSetType>;
+
   private:
     Storage m_valid_flags = 0;
 
-    friend void NativeRegisterContextLinux_arm64::MakeValid(RegisterSetType 
set);
+    friend void
+    NativeRegisterContextLinux_arm64::MakeValid(RegisterSetType set);
     friend bool NativeRegisterContextLinux_arm64::IsValid(RegisterSetType set);
-  public: 
+
+  public:
     void Invalidate(RegisterSetType set) {
       m_valid_flags &= ~static_cast<Storage>(set);
     }

>From 9fe398d2668f706e4a7cb2bffdba4ddc37cb49ac Mon Sep 17 00:00:00 2001
From: David Spickett <[email protected]>
Date: Mon, 20 Jul 2026 11:45:44 +0000
Subject: [PATCH 04/10] remove unnecessary changes

---
 .../Process/Linux/NativeRegisterContextLinux_arm64.cpp        | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git 
a/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp 
b/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp
index 85a3ad6d041ca..bb03b93e1f513 100644
--- a/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp
+++ b/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp
@@ -775,9 +775,7 @@ static uint8_t *AddSavedRegistersData(uint8_t *dst, void 
*src, size_t size) {
 }
 
 uint8_t *NativeRegisterContextLinux_arm64::AddSavedRegisters(
-    uint8_t *dst,
-    NativeRegisterContextLinux_arm64::RegisterSetType register_set_type,
-    void *src, size_t size) {
+    uint8_t *dst, RegisterSetType register_set_type, void *src, size_t size) {
   dst = AddRegisterSetType(dst, register_set_type);
   return AddSavedRegistersData(dst, src, size);
 }

>From 73cd25bf3a2b4dd5baaee2eb91efe4166b6975f2 Mon Sep 17 00:00:00 2001
From: David Spickett <[email protected]>
Date: Mon, 20 Jul 2026 11:52:05 +0000
Subject: [PATCH 05/10] comment

---
 .../Plugins/Process/Linux/NativeRegisterContextLinux_arm64.h  | 4 ++++
 1 file changed, 4 insertions(+)

diff --git 
a/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.h 
b/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.h
index e205546b454f2..50d0ec5f473c5 100644
--- a/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.h
+++ b/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.h
@@ -99,6 +99,10 @@ class NativeRegisterContextLinux_arm64
     POE = 1 << 12,       // Permission Overlay registers.
   };
 
+  // Validity management functions are class members who are friends of
+  // CacheValidity. This means we don't have to write "m_validity." every time
+  // we do an update.
+
   void MakeValid(RegisterSetType set) {
     m_validity.m_valid_flags |= static_cast<CacheValidity::Storage>(set);
   }

>From 5e653eaa5ceea48e26fbcec7e78bd15f52ff1d31 Mon Sep 17 00:00:00 2001
From: David Spickett <[email protected]>
Date: Mon, 20 Jul 2026 11:57:29 +0000
Subject: [PATCH 06/10] Simplify the validity object

---
 .../NativeRegisterContextLinux_arm64.cpp      |  2 +-
 .../Linux/NativeRegisterContextLinux_arm64.h  | 41 ++++---------------
 2 files changed, 10 insertions(+), 33 deletions(-)

diff --git 
a/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp 
b/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp
index bb03b93e1f513..629eca7949b0d 100644
--- a/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp
+++ b/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp
@@ -1337,7 +1337,7 @@ Status NativeRegisterContextLinux_arm64::WriteFPR() {
 }
 
 void NativeRegisterContextLinux_arm64::InvalidateAllRegisters() {
-  m_validity = CacheValidity();
+  m_validity = static_cast<RegisterSetType>(0);
 
   // Update SVE and ZA registers in case there is change in configuration.
   ConfigureRegisterContext();
diff --git 
a/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.h 
b/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.h
index 50d0ec5f473c5..a5b611e6587db 100644
--- a/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.h
+++ b/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.h
@@ -16,6 +16,8 @@
 #include "Plugins/Process/Utility/NativeRegisterContextDBReg_arm64.h"
 #include "Plugins/Process/Utility/RegisterInfoPOSIX_arm64.h"
 
+#include "llvm/ADT/BitmaskEnum.h"
+
 #include <asm/ptrace.h>
 
 namespace lldb_private {
@@ -82,7 +84,7 @@ class NativeRegisterContextLinux_arm64
   // Bit mask enum used to refer to the types of registers we support. 
Currently
   // used for tracking cache validity and ReadAll/WriteAllRegister data. Will
   // be used for much more in future.
-  enum RegisterSetType : uint32_t {
+  enum class RegisterSetType : uint32_t {
     GPR = 1 << 0, // General purpose registers.
     FPR = 1 << 1, // When there is no SVE, or SVE in FPSIMD mode, or streaming
                   // only SVE that is in non-streaming mode.
@@ -97,47 +99,22 @@ class NativeRegisterContextLinux_arm64
     FPMR = 1 << 10,      // Floating point mode control registers.
     GCS = 1 << 11,       // Guarded Control Stack registers.
     POE = 1 << 12,       // Permission Overlay registers.
+    LLVM_MARK_AS_BITMASK_ENUM(POE),
   };
 
-  // Validity management functions are class members who are friends of
-  // CacheValidity. This means we don't have to write "m_validity." every time
-  // we do an update.
+  RegisterSetType m_validity = static_cast<RegisterSetType>(0);
 
-  void MakeValid(RegisterSetType set) {
-    m_validity.m_valid_flags |= static_cast<CacheValidity::Storage>(set);
-  }
+  void MakeValid(RegisterSetType set) { m_validity |= set; }
 
-  bool IsValid(RegisterSetType set) {
-    return (m_validity.m_valid_flags &
-            static_cast<CacheValidity::Storage>(set)) != 0;
+  [[nodsicard]] bool IsValid(RegisterSetType set) {
+    return any(m_validity & set);
   }
 
   template <typename... Ts> void Invalidate(RegisterSetType first, Ts... rest) 
{
     static_assert((std::is_same_v<Ts, RegisterSetType> && ...));
-    m_validity.Invalidate(first);
-    (Invalidate(rest), ...);
+    m_validity &= ~(first | ... | rest);
   }
 
-  // This single object manages all tracking of whether register value caches
-  // are valid. Having a single object makes it easy to reset without missing
-  // anything.
-  class CacheValidity {
-    using Storage = std::underlying_type_t<RegisterSetType>;
-
-  private:
-    Storage m_valid_flags = 0;
-
-    friend void
-    NativeRegisterContextLinux_arm64::MakeValid(RegisterSetType set);
-    friend bool NativeRegisterContextLinux_arm64::IsValid(RegisterSetType set);
-
-  public:
-    void Invalidate(RegisterSetType set) {
-      m_valid_flags &= ~static_cast<Storage>(set);
-    }
-
-  } m_validity;
-
   Status RestoreRegisters(void *buffer, const uint8_t **src, size_t len,
                           const RegisterSetType set,
                           std::function<Status()> writer);

>From 5eae5c7cf45f38fc98a812cd28ed987d3917195e Mon Sep 17 00:00:00 2001
From: David Spickett <[email protected]>
Date: Mon, 20 Jul 2026 12:24:20 +0000
Subject: [PATCH 07/10] correct attribute

---
 .../Plugins/Process/Linux/NativeRegisterContextLinux_arm64.h    | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git 
a/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.h 
b/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.h
index a5b611e6587db..82a4636ef5df8 100644
--- a/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.h
+++ b/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.h
@@ -106,7 +106,7 @@ class NativeRegisterContextLinux_arm64
 
   void MakeValid(RegisterSetType set) { m_validity |= set; }
 
-  [[nodsicard]] bool IsValid(RegisterSetType set) {
+  [[nodiscard]] bool IsValid(RegisterSetType set) {
     return any(m_validity & set);
   }
 

>From b89b2cc2ba4d3eda635412a2931cc33595217bf9 Mon Sep 17 00:00:00 2001
From: David Spickett <[email protected]>
Date: Mon, 20 Jul 2026 13:08:05 +0000
Subject: [PATCH 08/10] this is init at the class member already

---
 .../Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp  | 2 --
 1 file changed, 2 deletions(-)

diff --git 
a/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp 
b/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp
index 629eca7949b0d..82d6f8658c30b 100644
--- a/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp
+++ b/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp
@@ -180,8 +180,6 @@ 
NativeRegisterContextLinux_arm64::NativeRegisterContextLinux_arm64(
   m_max_hwp_supported = 16;
   m_max_hbp_supported = 16;
 
-  m_refresh_hwdebug_info = true;
-
   // SME adds the tpidr2 register
   m_tls_size = GetRegisterInfo().IsSSVEPresent() ? sizeof(m_tls_regs)
                                                  : 
sizeof(m_tls_regs.tpidr_reg);

>From 55f2f6ce7bbcfb4eacfa36d7fc82019f4bbd7aa3 Mon Sep 17 00:00:00 2001
From: David Spickett <[email protected]>
Date: Tue, 21 Jul 2026 10:35:08 +0000
Subject: [PATCH 09/10] move comments

---
 .../Linux/NativeRegisterContextLinux_arm64.h  | 41 ++++++++++++-------
 1 file changed, 27 insertions(+), 14 deletions(-)

diff --git 
a/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.h 
b/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.h
index 82a4636ef5df8..ff957f11c8753 100644
--- a/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.h
+++ b/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.h
@@ -85,20 +85,33 @@ class NativeRegisterContextLinux_arm64
   // used for tracking cache validity and ReadAll/WriteAllRegister data. Will
   // be used for much more in future.
   enum class RegisterSetType : uint32_t {
-    GPR = 1 << 0, // General purpose registers.
-    FPR = 1 << 1, // When there is no SVE, or SVE in FPSIMD mode, or streaming
-                  // only SVE that is in non-streaming mode.
-    SVE = 1 << 2, // Used for SVE registers in streaming or non-streaming mode.
-    SVE_HEADER = 1 << 3, // Only the ptrace header for SVE.
-    PAC = 1 << 4,        // Pointer authentication mask registers.
-    MTE = 1 << 5,        // Memory tagging control registers.
-    TLS = 1 << 6,        // Thread local storage registers.
-    ZA = 1 << 7,         // ZA only, because SVCR and SVG are pseudo registers.
-    ZA_HEADER = 1 << 8,  // Only the ptrace header for ZA.
-    ZT = 1 << 9,         // ZT only.
-    FPMR = 1 << 10,      // Floating point mode control registers.
-    GCS = 1 << 11,       // Guarded Control Stack registers.
-    POE = 1 << 12,       // Permission Overlay registers.
+    // General purpose registers.
+    GPR = 1 << 0,
+    // When there is no SVE, or SVE in FPSIMD mode, or streaming only SVE that
+    // is in non-streaming mode.
+    FPR = 1 << 1,
+    // Used for SVE registers in streaming or non-streaming mode.
+    SVE = 1 << 2,
+    // Only the ptrace header for SVE.
+    SVE_HEADER = 1 << 3,
+    // Pointer authentication mask registers.
+    PAC = 1 << 4,
+    // Memory tagging control registers.
+    MTE = 1 << 5,
+    // Thread local storage registers.
+    TLS = 1 << 6,
+    // ZA only, because SVCR and SVG are pseudo registers.
+    ZA = 1 << 7,
+    // Only the ptrace header for ZA.
+    ZA_HEADER = 1 << 8,
+    // ZT only.
+    ZT = 1 << 9,
+    // Floating point mode control registers.
+    FPMR = 1 << 10,
+    // Guarded Control Stack registers.
+    GCS = 1 << 11,
+    // Permission Overlay registers.
+    POE = 1 << 12,
     LLVM_MARK_AS_BITMASK_ENUM(POE),
   };
 

>From c6afda1c74d14fec92f387ff17c8335489b29431 Mon Sep 17 00:00:00 2001
From: David Spickett <[email protected]>
Date: Tue, 21 Jul 2026 10:37:45 +0000
Subject: [PATCH 10/10] const

---
 .../Plugins/Process/Linux/NativeRegisterContextLinux_arm64.h    | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git 
a/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.h 
b/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.h
index ff957f11c8753..0414e5b6e612d 100644
--- a/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.h
+++ b/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.h
@@ -119,7 +119,7 @@ class NativeRegisterContextLinux_arm64
 
   void MakeValid(RegisterSetType set) { m_validity |= set; }
 
-  [[nodiscard]] bool IsValid(RegisterSetType set) {
+  [[nodiscard]] bool IsValid(RegisterSetType set) const {
     return any(m_validity & set);
   }
 

_______________________________________________
lldb-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to