mgorny created this revision.
mgorny added reviewers: labath, krytarowski, emaste.
mgorny requested review of this revision.

Add a convenience method to add supplementary registers that takes care
of adding invalidate_regs to all (potentially) overlapping registers.


https://reviews.llvm.org/D110023

Files:
  lldb/source/Plugins/Process/Utility/DynamicRegisterInfo.cpp
  lldb/source/Plugins/Process/Utility/DynamicRegisterInfo.h
  lldb/unittests/Process/Utility/DynamicRegisterInfoTest.cpp

Index: lldb/unittests/Process/Utility/DynamicRegisterInfoTest.cpp
===================================================================
--- lldb/unittests/Process/Utility/DynamicRegisterInfoTest.cpp
+++ lldb/unittests/Process/Utility/DynamicRegisterInfoTest.cpp
@@ -134,3 +134,104 @@
   EXPECT_EQ(added_reg->invalidate_regs[1], i1);
   EXPECT_EQ(added_reg->invalidate_regs[2], LLDB_INVALID_REGNUM);
 }
+
+TEST(DynamicRegisterInfoTest, add_supplementary_register) {
+  DynamicRegisterInfo info;
+
+  // Add a base register
+  uint32_t rax = AddRegister(info, "rax", 8);
+
+  // Register numbers
+  uint32_t eax = 1;
+  uint32_t ax = 2;
+  uint32_t ah = 3;
+  uint32_t al = 4;
+
+  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 ah_reg {
+    "ah", nullptr, 1, LLDB_INVALID_INDEX32, lldb::eEncodingUint,
+        lldb::eFormatUnsigned,
+        {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, ah, ah},
+        value_regs, nullptr, nullptr, 0
+  };
+  info.AddSupplementaryRegister(ah_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);
+
+  const RegisterInfo *added_reg = info.GetRegisterInfoAtIndex(0);
+  ASSERT_NE(added_reg, nullptr);
+  ASSERT_NE(added_reg->invalidate_regs, nullptr);
+  EXPECT_EQ(added_reg->invalidate_regs[0], eax);
+  EXPECT_EQ(added_reg->invalidate_regs[1], ax);
+  EXPECT_EQ(added_reg->invalidate_regs[2], ah);
+  EXPECT_EQ(added_reg->invalidate_regs[3], al);
+  EXPECT_EQ(added_reg->invalidate_regs[4], LLDB_INVALID_REGNUM);
+
+  added_reg = info.GetRegisterInfoAtIndex(1);
+  ASSERT_NE(added_reg, nullptr);
+  EXPECT_EQ(added_reg->value_regs[0], rax);
+  EXPECT_EQ(added_reg->value_regs[1], LLDB_INVALID_REGNUM);
+  ASSERT_NE(added_reg->invalidate_regs, nullptr);
+  EXPECT_EQ(added_reg->invalidate_regs[0], rax);
+  EXPECT_EQ(added_reg->invalidate_regs[1], ax);
+  EXPECT_EQ(added_reg->invalidate_regs[2], ah);
+  EXPECT_EQ(added_reg->invalidate_regs[3], al);
+  EXPECT_EQ(added_reg->invalidate_regs[4], LLDB_INVALID_REGNUM);
+
+  added_reg = info.GetRegisterInfoAtIndex(2);
+  ASSERT_NE(added_reg, nullptr);
+  EXPECT_EQ(added_reg->value_regs[0], rax);
+  EXPECT_EQ(added_reg->value_regs[1], LLDB_INVALID_REGNUM);
+  ASSERT_NE(added_reg->invalidate_regs, nullptr);
+  EXPECT_EQ(added_reg->invalidate_regs[0], rax);
+  EXPECT_EQ(added_reg->invalidate_regs[1], eax);
+  EXPECT_EQ(added_reg->invalidate_regs[2], ah);
+  EXPECT_EQ(added_reg->invalidate_regs[3], al);
+  EXPECT_EQ(added_reg->invalidate_regs[4], LLDB_INVALID_REGNUM);
+
+  added_reg = info.GetRegisterInfoAtIndex(3);
+  ASSERT_NE(added_reg, nullptr);
+  EXPECT_EQ(added_reg->value_regs[0], rax);
+  EXPECT_EQ(added_reg->value_regs[1], LLDB_INVALID_REGNUM);
+  ASSERT_NE(added_reg->invalidate_regs, nullptr);
+  EXPECT_EQ(added_reg->invalidate_regs[0], rax);
+  EXPECT_EQ(added_reg->invalidate_regs[1], eax);
+  EXPECT_EQ(added_reg->invalidate_regs[2], ax);
+  EXPECT_EQ(added_reg->invalidate_regs[3], al);
+  EXPECT_EQ(added_reg->invalidate_regs[4], LLDB_INVALID_REGNUM);
+
+  added_reg = info.GetRegisterInfoAtIndex(4);
+  ASSERT_NE(added_reg, nullptr);
+  EXPECT_EQ(added_reg->value_regs[0], rax);
+  EXPECT_EQ(added_reg->value_regs[1], LLDB_INVALID_REGNUM);
+  ASSERT_NE(added_reg->invalidate_regs, nullptr);
+  EXPECT_EQ(added_reg->invalidate_regs[0], rax);
+  EXPECT_EQ(added_reg->invalidate_regs[1], eax);
+  EXPECT_EQ(added_reg->invalidate_regs[2], ax);
+  EXPECT_EQ(added_reg->invalidate_regs[3], ah);
+  EXPECT_EQ(added_reg->invalidate_regs[4], LLDB_INVALID_REGNUM);
+}
Index: lldb/source/Plugins/Process/Utility/DynamicRegisterInfo.h
===================================================================
--- lldb/source/Plugins/Process/Utility/DynamicRegisterInfo.h
+++ 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;
Index: lldb/source/Plugins/Process/Utility/DynamicRegisterInfo.cpp
===================================================================
--- lldb/source/Plugins/Process/Utility/DynamicRegisterInfo.cpp
+++ lldb/source/Plugins/Process/Utility/DynamicRegisterInfo.cpp
@@ -464,6 +464,59 @@
   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);
+
+  // [lldb] -> [process plugin] number
+  reg_to_regs_map to_add;
+  for (uint32_t value_reg : m_value_regs_map[reg_num]) {
+    if (value_reg == LLDB_INVALID_REGNUM)
+      break;
+
+    // copy value_regs to invalidate_regs
+    to_add[reg_num].push_back(value_reg);
+
+    // copy invalidate_regs from the parent register
+    uint32_t value_reg_lldb = ConvertRegisterKindToRegisterNumber(eRegisterKindProcessPlugin,
+        value_reg);
+    assert(value_reg_lldb != LLDB_INVALID_REGNUM);
+    llvm::append_range(to_add[reg_num], m_invalidate_regs_map[value_reg_lldb]);
+
+    // add reverse invalidate entries
+    for (uint32_t x : to_add[reg_num]) {
+      if (x == LLDB_INVALID_REGNUM)
+        continue;
+      uint32_t x_lldb = ConvertRegisterKindToRegisterNumber(eRegisterKindProcessPlugin, x);
+      assert(x_lldb != LLDB_INVALID_REGNUM);
+      to_add[x_lldb].push_back(new_reg_info.kinds[eRegisterKindProcessPlugin]);
+    }
+  }
+
+  for (reg_to_regs_map::value_type &x : to_add) {
+    reg_num_collection &regnums = m_invalidate_regs_map[x.first];
+    // if the list is empty, add the terminator; otherwise, it's already there
+    if (regnums.empty())
+      regnums.push_back(LLDB_INVALID_REGNUM);
+    assert(regnums.back() == LLDB_INVALID_REGNUM);
+
+    // insert the requested elements sorted, if they're not there yet
+    for (uint32_t new_reg : x.second) {
+      // the new regnums can copy terminators from other invalidate_regs
+      if (new_reg == LLDB_INVALID_REGNUM)
+        continue;
+      reg_num_collection::iterator it = llvm::lower_bound(regnums, new_reg);
+      if (it != regnums.end() && *it != new_reg)
+        regnums.insert(it, new_reg);
+    }
+
+    // update the pointer
+    m_regs[x.first].invalidate_regs = regnums.data();
+  }
+}
+
 void DynamicRegisterInfo::Finalize(const ArchSpec &arch) {
   if (m_finalized)
     return;
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to