diff --git a/lldb/source/Plugins/Process/Utility/DynamicRegisterInfo.h b/lldb/source/Plugins/Process/Utility/DynamicRegisterInfo.h --- a/lldb/source/Plugins/Process/Utility/DynamicRegisterInfo.h +++ b/lldb/source/Plugins/Process/Utility/DynamicRegisterInfo.h @@ -38,6 +38,11 @@ void AddRegister(lldb_private::RegisterInfo reg_info, lldb_private::ConstString &set_name); + // Add a new register and cross-link it via invalidate_regs with other + // registers sharing its value_regs. + void AddSupplementaryRegister(lldb_private::RegisterInfo reg_info, + lldb_private::ConstString &set_name); + void Finalize(const lldb_private::ArchSpec &arch); size_t GetNumRegisters() const; diff --git a/lldb/source/Plugins/Process/Utility/DynamicRegisterInfo.cpp b/lldb/source/Plugins/Process/Utility/DynamicRegisterInfo.cpp --- a/lldb/source/Plugins/Process/Utility/DynamicRegisterInfo.cpp +++ b/lldb/source/Plugins/Process/Utility/DynamicRegisterInfo.cpp @@ -430,6 +430,29 @@ m_set_reg_nums[set].push_back(reg_num); } +void DynamicRegisterInfo::AddSupplementaryRegister(RegisterInfo new_reg_info, + ConstString &set_name) { + assert(new_reg_info.value_regs != nullptr); + const uint32_t reg_num = m_regs.size(); + AddRegister(new_reg_info, set_name); + + reg_to_regs_map new_invalidates; + for (uint32_t value_reg : m_value_regs_map[reg_num]) { + // copy value_regs to invalidate_regs + new_invalidates[reg_num].push_back(value_reg); + + // copy invalidate_regs from the parent register + llvm::append_range(new_invalidates[reg_num], m_invalidate_regs_map[value_reg]); + + // add reverse invalidate entries + for (uint32_t x : new_invalidates[reg_num]) + new_invalidates[x].push_back(new_reg_info.kinds[eRegisterKindLLDB]); + } + + for (const auto &x : new_invalidates) + llvm::append_range(m_invalidate_regs_map[x.first], x.second); +} + void DynamicRegisterInfo::Finalize(const ArchSpec &arch) { if (m_finalized) return; diff --git a/lldb/unittests/Process/Utility/DynamicRegisterInfoTest.cpp b/lldb/unittests/Process/Utility/DynamicRegisterInfoTest.cpp --- a/lldb/unittests/Process/Utility/DynamicRegisterInfoTest.cpp +++ b/lldb/unittests/Process/Utility/DynamicRegisterInfoTest.cpp @@ -124,3 +124,47 @@ ASSERT_REG(i1, LLDB_INVALID_INDEX32); ASSERT_REG(i2, LLDB_INVALID_INDEX32); } + +TEST_F(DynamicRegisterInfoTest, add_supplementary_register) { + // Add a base register + uint32_t rax = AddTestRegister("rax", 8); + + // Register numbers + uint32_t eax = 1; + uint32_t ax = 2; + uint32_t al = 3; + + ConstString group{"supplementary registers"}; + uint32_t value_regs[2] = {rax, LLDB_INVALID_REGNUM}; + struct RegisterInfo eax_reg { + "eax", nullptr, 4, LLDB_INVALID_INDEX32, lldb::eEncodingUint, + lldb::eFormatUnsigned, + {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, eax, + eax}, + value_regs, nullptr, nullptr, 0 + }; + info.AddSupplementaryRegister(eax_reg, group); + + struct RegisterInfo ax_reg { + "ax", nullptr, 2, LLDB_INVALID_INDEX32, lldb::eEncodingUint, + lldb::eFormatUnsigned, + {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, ax, ax}, + value_regs, nullptr, nullptr, 0 + }; + info.AddSupplementaryRegister(ax_reg, group); + + struct RegisterInfo al_reg { + "al", nullptr, 1, LLDB_INVALID_INDEX32, lldb::eEncodingUint, + lldb::eFormatUnsigned, + {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, al, al}, + value_regs, nullptr, nullptr, 0 + }; + info.AddSupplementaryRegister(al_reg, group); + + info.Finalize(lldb_private::ArchSpec()); + + ASSERT_REG(rax, 0, {}, {eax, ax, al}); + ASSERT_REG(eax, 0, {rax}, {rax, ax, al}); + ASSERT_REG(ax, 0, {rax}, {rax, eax, al}); + ASSERT_REG(al, 0, {rax}, {rax, eax, ax}); +}