Index: lldb/include/lldb/Target/DynamicRegisterInfo.h =================================================================== --- lldb/include/lldb/Target/DynamicRegisterInfo.h +++ lldb/include/lldb/Target/DynamicRegisterInfo.h @@ -40,11 +40,6 @@ 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; Index: lldb/include/lldb/Target/RemoteRegisterInfo.h =================================================================== --- lldb/include/lldb/Target/RemoteRegisterInfo.h +++ lldb/include/lldb/Target/RemoteRegisterInfo.h @@ -32,6 +32,11 @@ std::vector invalidate_regs; }; +// Add a new register and cross-link it via invalidate_regs with other +// registers sharing its value_regs. +void addSupplementaryRegister(std::vector ®s, + RemoteRegisterInfo reg_info); + } // namespace lldb_private #endif // LLDB_TARGET_REMOTEREGISTERINFO_H Index: lldb/source/Target/CMakeLists.txt =================================================================== --- lldb/source/Target/CMakeLists.txt +++ lldb/source/Target/CMakeLists.txt @@ -33,6 +33,7 @@ RegisterContextUnwind.cpp RegisterNumber.cpp RemoteAwarePlatform.cpp + RemoteRegisterInfo.cpp SectionLoadHistory.cpp SectionLoadList.cpp StackFrame.cpp Index: lldb/source/Target/DynamicRegisterInfo.cpp =================================================================== --- lldb/source/Target/DynamicRegisterInfo.cpp +++ lldb/source/Target/DynamicRegisterInfo.cpp @@ -408,29 +408,6 @@ 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; Index: lldb/source/Target/RemoteRegisterInfo.cpp =================================================================== --- /dev/null +++ lldb/source/Target/RemoteRegisterInfo.cpp @@ -0,0 +1,38 @@ +//===-- RemoteRegisterInfo.cpp --------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "lldb/Target/RemoteRegisterInfo.h" + +#include + +using namespace lldb; +using namespace lldb_private; + +void lldb_private::addSupplementaryRegister( + std::vector ®s, RemoteRegisterInfo new_reg_info) { + assert(!new_reg_info.value_regs.empty()); + const uint32_t reg_num = regs.size(); + regs.push_back(new_reg_info); + + std::map> new_invalidates; + for (uint32_t value_reg : new_reg_info.value_regs) { + // 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], + regs[value_reg].invalidate_regs); + + // add reverse invalidate entries + for (uint32_t x : new_invalidates[reg_num]) + new_invalidates[x].push_back(reg_num); + } + + for (const auto &x : new_invalidates) + llvm::append_range(regs[x.first].invalidate_regs, x.second); +} Index: lldb/unittests/Target/CMakeLists.txt =================================================================== --- lldb/unittests/Target/CMakeLists.txt +++ lldb/unittests/Target/CMakeLists.txt @@ -6,6 +6,7 @@ ModuleCacheTest.cpp PathMappingListTest.cpp RemoteAwarePlatformTest.cpp + RemoteRegisterInfoTest.cpp StackFrameRecognizerTest.cpp LINK_LIBS Index: lldb/unittests/Target/DynamicRegisterInfoTest.cpp =================================================================== --- lldb/unittests/Target/DynamicRegisterInfoTest.cpp +++ lldb/unittests/Target/DynamicRegisterInfoTest.cpp @@ -123,47 +123,3 @@ 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 - }; - 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 - }; - 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 - }; - 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}); -} Index: lldb/unittests/Target/RemoteRegisterInfoTest.cpp =================================================================== --- /dev/null +++ lldb/unittests/Target/RemoteRegisterInfoTest.cpp @@ -0,0 +1,79 @@ +//===-- RemoteRegisterInfoTest.cpp ----------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "gmock/gmock.h" +#include "gtest/gtest.h" + +#include "lldb/Target/RemoteRegisterInfo.h" + +#include + +using namespace lldb; +using namespace lldb_private; + +class RemoteRegisterInfoTest : public ::testing::Test { +protected: + std::vector regs; + + uint32_t + AddTestRegister(const char *name, const char *group, uint32_t byte_size, + std::function adder, + std::vector value_regs = {}, + std::vector invalidate_regs = {}) { + RemoteRegisterInfo new_reg{ConstString(name), ConstString(), + ConstString(group), byte_size, + LLDB_INVALID_INDEX32, lldb::eEncodingUint, + lldb::eFormatUnsigned, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, value_regs, + invalidate_regs}; + adder(new_reg); + return regs.size() - 1; + } + + void AssertRegisterInfo(uint32_t reg_num, const char *reg_name, + std::vector value_regs = {}, + std::vector invalidate_regs = {}) { + EXPECT_GT(regs.size(), reg_num); + if (regs.size() <= reg_num) + return; + + const RemoteRegisterInfo ® = regs[reg_num]; + ConstString expected_reg_name{reg_name}; + EXPECT_EQ(reg.name, expected_reg_name); + EXPECT_EQ(reg.value_regs, value_regs); + EXPECT_EQ(reg.invalidate_regs, invalidate_regs); + } +}; + +#define ASSERT_REG(reg, ...) \ + { \ + SCOPED_TRACE("at register " #reg); \ + AssertRegisterInfo(reg, #reg, __VA_ARGS__); \ + } + +TEST_F(RemoteRegisterInfoTest, addSupplementaryRegister) { + // Add a base register + uint32_t rax = + AddTestRegister("rax", "group", 8, [this](const RemoteRegisterInfo &r) { + regs.push_back(r); + }); + + // Add supplementary registers + auto suppl_adder = [this](const RemoteRegisterInfo &r) { + addSupplementaryRegister(regs, r); + }; + uint32_t eax = AddTestRegister("eax", "supplementary", 4, suppl_adder, {rax}); + uint32_t ax = AddTestRegister("ax", "supplementary", 2, suppl_adder, {rax}); + uint32_t al = AddTestRegister("al", "supplementary", 1, suppl_adder, {rax}); + + ASSERT_REG(rax, {}, {eax, ax, al}); + ASSERT_REG(eax, {rax}, {rax, ax, al}); + ASSERT_REG(ax, {rax}, {rax, eax, al}); + ASSERT_REG(al, {rax}, {rax, eax, ax}); +}