llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-lldb Author: David Spickett (DavidSpickett) <details> <summary>Changes</summary> This function encodes relations between sets so that you don't have to remember all the dependencies. There are some places where we do: if some condition: Invalidate(some set); I've chosen not to put that logic in this new function so that it can be a simple switch case. The few places we need extra state to make the decision are also all SVE/SME related. This code will likely remain bespoke anyway. Whereas the simple paths will all get collapsed into a generic handler later. I have kept Invalidate() variadic as there might be some situations where explicitly invalidating many things helps readers understand the code. --- Full diff: https://github.com/llvm/llvm-project/pull/212476.diff 2 Files Affected: - (modified) lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp (+40-22) - (modified) lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.h (+11-1) ``````````diff diff --git a/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp b/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp index 82d6f8658c30b..4d317bd794079 100644 --- a/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp +++ b/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp @@ -59,6 +59,36 @@ using namespace lldb; using namespace lldb_private; using namespace lldb_private::process_linux; +NativeRegisterContextLinux_arm64::RegisterSetType +NativeRegisterContextLinux_arm64::GetInvalidationMask( + const RegisterSetType set) const { + switch (set) { + case RegisterSetType::FPMR: + case RegisterSetType::GPR: + case RegisterSetType::GCS: + case RegisterSetType::MTE: + case RegisterSetType::PAC: + case RegisterSetType::POE: + case RegisterSetType::TLS: + return set; + case RegisterSetType::SVE_HEADER: + case RegisterSetType::SVE: + case RegisterSetType::FPR: + return RegisterSetType::SVE_HEADER | RegisterSetType::SVE | + // SVE registers overlap FP registers in hardware. + RegisterSetType::FPR; + case RegisterSetType::ZA_HEADER: + case RegisterSetType::ZA: + case RegisterSetType::ZT: + // In the Linux ptrace ABI, writes that enable ZA or ZT result in + // both ZA and ZT being enabled. + return RegisterSetType::ZA_HEADER | RegisterSetType::ZA | + RegisterSetType::ZT; + default: + llvm_unreachable("Unhandled register set"); + } +} + // A NativeRegisterContext is constructed per thread, but all threads' registers // will contain the same fields. Therefore this mutex prevents each instance // competing with the other, and subsequent instances from having to detect the @@ -1082,7 +1112,7 @@ Status NativeRegisterContextLinux_arm64::WriteAllRegisterValues( std::bind(&NativeRegisterContextLinux_arm64::WriteAllSVE, this)); break; case RegisterSetType::FPR: { - Invalidate(RegisterSetType::SVE_HEADER, RegisterSetType::SVE); + Invalidate(RegisterSetType::SVE_HEADER); m_sve_state = SVEState::Unknown; ConfigureRegisterContext(); @@ -1132,10 +1162,7 @@ Status NativeRegisterContextLinux_arm64::WriteAllRegisterValues( src += GetFPRSize(); if (error.Success()) { - // Wrote FPU, and SVE overlaps FPU. - Invalidate(RegisterSetType::FPR, RegisterSetType::SVE_HEADER, - RegisterSetType::SVE); - + Invalidate(RegisterSetType::FPR); m_sve_state = SVEState::Unknown; ConfigureRegisterContext(); } @@ -1327,9 +1354,7 @@ Status NativeRegisterContextLinux_arm64::WriteFPR() { ioVec.iov_base = GetFPRBuffer(); ioVec.iov_len = GetFPRSize(); - // SVE Z registers overlap the FP registers. - Invalidate(RegisterSetType::FPR, RegisterSetType::SVE_HEADER, - RegisterSetType::SVE); + Invalidate(RegisterSetType::FPR); return WriteRegisterSet(&ioVec, GetFPRSize(), llvm::ELF::NT_FPREGSET); } @@ -1398,8 +1423,7 @@ Status NativeRegisterContextLinux_arm64::WriteSVEHeader() { ioVec.iov_base = GetSVEHeader(); ioVec.iov_len = GetSVEHeaderSize(); - Invalidate(RegisterSetType::FPR, RegisterSetType::SVE_HEADER, - RegisterSetType::SVE); + Invalidate(RegisterSetType::SVE_HEADER); return WriteRegisterSet(&ioVec, GetSVEHeaderSize(), GetSVERegSet()); } @@ -1433,8 +1457,7 @@ Status NativeRegisterContextLinux_arm64::WriteAllSVE() { ioVec.iov_base = GetSVEBuffer(); ioVec.iov_len = GetSVEBufferSize(); - Invalidate(RegisterSetType::FPR, RegisterSetType::SVE_HEADER, - RegisterSetType::SVE); + Invalidate(RegisterSetType::SVE); return WriteRegisterSet(&ioVec, GetSVEBufferSize(), GetSVERegSet()); } @@ -1611,9 +1634,7 @@ 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); return WriteRegisterSet(&ioVec, GetZABufferSize(), llvm::ELF::NT_ARM_ZA); } @@ -1646,10 +1667,7 @@ Status NativeRegisterContextLinux_arm64::WriteZT() { ioVec.iov_base = GetZTBuffer(); 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); + Invalidate(RegisterSetType::ZT); return WriteRegisterSet(&ioVec, GetZTBufferSize(), llvm::ELF::NT_ARM_ZT); } @@ -1735,7 +1753,7 @@ void NativeRegisterContextLinux_arm64::ConfigureRegisterContext() { // only the active mode will return valid register data. // Check for SME. - Invalidate(RegisterSetType::SVE_HEADER, RegisterSetType::SVE); + Invalidate(RegisterSetType::SVE_HEADER); m_sve_state = SVEState::Streaming; Status error = ReadSVEHeader(); @@ -1745,7 +1763,7 @@ void NativeRegisterContextLinux_arm64::ConfigureRegisterContext() { ((m_sve_header.flags & sve::ptrace_regs_mask) == sve::ptrace_regs_sve); // Check for SVE. - Invalidate(RegisterSetType::SVE_HEADER, RegisterSetType::SVE); + Invalidate(RegisterSetType::SVE_HEADER); m_sve_state = SVEState::Full; error = ReadSVEHeader(); @@ -1774,7 +1792,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) { - Invalidate(RegisterSetType::SVE_HEADER, RegisterSetType::SVE); + Invalidate(RegisterSetType::SVE_HEADER); error = ReadSVEHeader(); // On every stop we configure SVE vector length by calling diff --git a/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.h b/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.h index 0414e5b6e612d..a9f34399f2a34 100644 --- a/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.h +++ b/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.h @@ -123,9 +123,19 @@ class NativeRegisterContextLinux_arm64 return any(m_validity & set); } + /// Returns the mask of sets that would be invalidated if the given set was + /// invalidated. That is, the set itself and any sets that depend on it. + /// + /// If you need anything more complex such as only invalidating during certain + /// modes, put that logic in the function that calls Invalidate(). + RegisterSetType GetInvalidationMask(const RegisterSetType set) const; + + /// Invalidate our saved copies of the given register sets and any sets that + /// depend on those sets. template <typename... Ts> void Invalidate(RegisterSetType first, Ts... rest) { static_assert((std::is_same_v<Ts, RegisterSetType> && ...)); - m_validity &= ~(first | ... | rest); + m_validity &= + ~(GetInvalidationMask(first) | ... | GetInvalidationMask(rest)); } Status RestoreRegisters(void *buffer, const uint8_t **src, size_t len, `````````` </details> https://github.com/llvm/llvm-project/pull/212476 _______________________________________________ lldb-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
