mgorny updated this revision to Diff 379652.
mgorny added a comment.

Use `ArchSpec` instead of passing hardcoded 64bit. Abort the whole process if 
at least one subreg is present, eliminating all the `have*` bools.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D108831/new/

https://reviews.llvm.org/D108831

Files:
  lldb/source/Plugins/ABI/X86/ABIX86.cpp
  lldb/source/Plugins/ABI/X86/ABIX86.h
  lldb/test/API/functionalities/gdb_remote_client/TestGDBServerTargetXML.py

Index: lldb/test/API/functionalities/gdb_remote_client/TestGDBServerTargetXML.py
===================================================================
--- lldb/test/API/functionalities/gdb_remote_client/TestGDBServerTargetXML.py
+++ lldb/test/API/functionalities/gdb_remote_client/TestGDBServerTargetXML.py
@@ -163,6 +163,67 @@
                    ["xmm1 = {0x91 0x92 0x93 0x94 0x95 0x96 0x97 0x98 "
                     "0x99 0x9a 0x9b 0x9c 0x9d 0x9e 0x9f 0xa0}"])
 
+        # test pseudo-registers
+        self.match("register read ecx",
+                   ["ecx = 0x04030201"])
+        self.match("register read cx",
+                   ["cx = 0x0201"])
+        self.match("register read ch",
+                   ["ch = 0x02"])
+        self.match("register read cl",
+                   ["cl = 0x01"])
+        self.match("register read r8d",
+                   ["r8d = 0x64636261"])
+        self.match("register read r8w",
+                   ["r8w = 0x6261"])
+        self.match("register read r8l",
+                   ["r8l = 0x61"])
+        self.match("register read mm0",
+                   ["mm0 = 0x0807060504030201"])
+        self.match("register read mm1",
+                   ["mm1 = 0x1817161514131211"])
+
+        # test writing into pseudo-registers
+        self.runCmd("register write ecx 0xfffefdfc")
+        reg_data[0] = "fcfdfeff05060708"
+        self.assertPacketLogContains(["G" + "".join(reg_data)])
+        self.match("register read rcx",
+                   ["rcx = 0x08070605fffefdfc"])
+
+        self.runCmd("register write cx 0xfbfa")
+        reg_data[0] = "fafbfeff05060708"
+        self.assertPacketLogContains(["G" + "".join(reg_data)])
+        self.match("register read ecx",
+                   ["ecx = 0xfffefbfa"])
+        self.match("register read rcx",
+                   ["rcx = 0x08070605fffefbfa"])
+
+        self.runCmd("register write ch 0xf9")
+        reg_data[0] = "faf9feff05060708"
+        self.assertPacketLogContains(["G" + "".join(reg_data)])
+        self.match("register read cx",
+                   ["cx = 0xf9fa"])
+        self.match("register read ecx",
+                   ["ecx = 0xfffef9fa"])
+        self.match("register read rcx",
+                   ["rcx = 0x08070605fffef9fa"])
+
+        self.runCmd("register write cl 0xf8")
+        reg_data[0] = "f8f9feff05060708"
+        self.assertPacketLogContains(["G" + "".join(reg_data)])
+        self.match("register read cx",
+                   ["cx = 0xf9f8"])
+        self.match("register read ecx",
+                   ["ecx = 0xfffef9f8"])
+        self.match("register read rcx",
+                   ["rcx = 0x08070605fffef9f8"])
+
+        self.runCmd("register write mm0 0xfffefdfcfbfaf9f8")
+        reg_data[10] = "f8f9fafbfcfdfeff090a"
+        self.assertPacketLogContains(["G" + "".join(reg_data)])
+        self.match("register read st0",
+                   ["st0 = {0xf8 0xf9 0xfa 0xfb 0xfc 0xfd 0xfe 0xff 0x09 0x0a}"])
+
     @skipIfXmlSupportMissing
     @skipIfRemote
     @skipIfLLVMTargetMissing("X86")
@@ -272,11 +333,25 @@
         # test generic aliases
         self.match("register read fp",
                    ["ebp = 0x54535251"])
+        self.match("register read sp",
+                   ["esp = 0x44434241"])
         self.match("register read pc",
                    ["eip = 0x84838281"])
         self.match("register read flags",
                    ["eflags = 0x94939291"])
 
+        # test pseudo-registers
+        self.match("register read cx",
+                   ["cx = 0x1211"])
+        self.match("register read ch",
+                   ["ch = 0x12"])
+        self.match("register read cl",
+                   ["cl = 0x11"])
+        self.match("register read mm0",
+                   ["mm0 = 0x0807060504030201"])
+        self.match("register read mm1",
+                   ["mm1 = 0x1817161514131211"])
+
         # both stX and xmmX should be displayed as vectors
         self.match("register read st0",
                    ["st0 = {0x01 0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x09 0x0a}"])
@@ -289,6 +364,35 @@
                    ["xmm1 = {0x91 0x92 0x93 0x94 0x95 0x96 0x97 0x98 "
                     "0x99 0x9a 0x9b 0x9c 0x9d 0x9e 0x9f 0xa0}"])
 
+        # test writing into pseudo-registers
+        self.runCmd("register write cx 0xfbfa")
+        reg_data[1] = "fafb1314"
+        self.assertPacketLogContains(["G" + "".join(reg_data)])
+        self.match("register read ecx",
+                   ["ecx = 0x1413fbfa"])
+
+        self.runCmd("register write ch 0xf9")
+        reg_data[1] = "faf91314"
+        self.assertPacketLogContains(["G" + "".join(reg_data)])
+        self.match("register read cx",
+                   ["cx = 0xf9fa"])
+        self.match("register read ecx",
+                   ["ecx = 0x1413f9fa"])
+
+        self.runCmd("register write cl 0xf8")
+        reg_data[1] = "f8f91314"
+        self.assertPacketLogContains(["G" + "".join(reg_data)])
+        self.match("register read cx",
+                   ["cx = 0xf9f8"])
+        self.match("register read ecx",
+                   ["ecx = 0x1413f9f8"])
+
+        self.runCmd("register write mm0 0xfffefdfcfbfaf9f8")
+        reg_data[10] = "f8f9fafbfcfdfeff090a"
+        self.assertPacketLogContains(["G" + "".join(reg_data)])
+        self.match("register read st0",
+                   ["st0 = {0xf8 0xf9 0xfa 0xfb 0xfc 0xfd 0xfe 0xff 0x09 0x0a}"])
+
     @skipIfXmlSupportMissing
     @skipIfRemote
     @skipIfLLVMTargetMissing("AArch64")
Index: lldb/source/Plugins/ABI/X86/ABIX86.h
===================================================================
--- lldb/source/Plugins/ABI/X86/ABIX86.h
+++ lldb/source/Plugins/ABI/X86/ABIX86.h
@@ -17,6 +17,10 @@
   static void Initialize();
   static void Terminate();
 
+protected:
+  void AugmentRegisterInfo(
+      std::vector<lldb_private::DynamicRegisterInfo::Register> &regs) override;
+
 private:
   using lldb_private::MCBasedABI::MCBasedABI;
 };
Index: lldb/source/Plugins/ABI/X86/ABIX86.cpp
===================================================================
--- lldb/source/Plugins/ABI/X86/ABIX86.cpp
+++ lldb/source/Plugins/ABI/X86/ABIX86.cpp
@@ -6,12 +6,18 @@
 //
 //===----------------------------------------------------------------------===//
 
-#include "ABIX86.h"
 #include "ABIMacOSX_i386.h"
 #include "ABISysV_i386.h"
 #include "ABISysV_x86_64.h"
 #include "ABIWindows_x86_64.h"
+#include "ABIX86.h"
 #include "lldb/Core/PluginManager.h"
+#include "lldb/Target/Process.h"
+
+#include <unordered_set>
+
+using namespace lldb;
+using namespace lldb_private;
 
 LLDB_PLUGIN_DEFINE(ABIX86)
 
@@ -28,3 +34,236 @@
   ABISysV_x86_64::Terminate();
   ABIWindows_x86_64::Terminate();
 }
+
+static void addPartialRegister(std::vector<DynamicRegisterInfo::Register> &regs,
+                               uint32_t full_reg_index, uint32_t full_reg_size,
+                               const std::string &partial_reg_name,
+                               uint32_t partial_reg_size,
+                               uint32_t offset = 0,
+    lldb::Encoding encoding = eEncodingInvalid, lldb::Format format = eFormatInvalid) {
+  DynamicRegisterInfo::Register &full_reg = regs[full_reg_index];
+  if (full_reg.byte_size != full_reg_size)
+    return;
+
+  lldb_private::DynamicRegisterInfo::Register partial_reg{
+      lldb_private::ConstString(partial_reg_name),
+      lldb_private::ConstString(),
+      lldb_private::ConstString("supplementary registers"),
+      partial_reg_size,
+      LLDB_INVALID_INDEX32,
+      encoding != eEncodingInvalid ? encoding : full_reg.encoding,
+      format != eFormatInvalid ? format : full_reg.format,
+      LLDB_INVALID_REGNUM,
+      LLDB_INVALID_REGNUM,
+      LLDB_INVALID_REGNUM,
+      LLDB_INVALID_REGNUM,
+      {full_reg_index},
+      {},
+      offset};
+
+  addSupplementaryRegister(regs, partial_reg);
+}
+
+struct GPRReg {
+  uint32_t base_index = LLDB_INVALID_REGNUM;
+  std::string name32;
+  std::string name16;
+  std::string name8h;
+  std::string name8;
+};
+
+struct STReg {
+  uint32_t base_index = LLDB_INVALID_REGNUM;
+  std::string name_mm;
+};
+
+void ABIX86::AugmentRegisterInfo(
+    std::vector<DynamicRegisterInfo::Register> &regs) {
+  MCBasedABI::AugmentRegisterInfo(regs);
+
+  ProcessSP process_sp = GetProcessSP();
+  if (!process_sp)
+    return;
+
+  ArchSpec arch = process_sp->GetTarget().GetArchitecture();
+  bool is64bit;
+  switch (arch.GetMachine()) {
+  case llvm::Triple::x86:
+    is64bit = false;
+    break;
+  case llvm::Triple::x86_64:
+    is64bit = true;
+    break;
+  default:
+    llvm_unreachable("unexpected arch");
+  }
+
+  std::unordered_set<std::string> gpr_basenames{
+      {"ax", "bx", "cx", "dx", "si", "di", "bp", "sp"}};
+  char gpr_base_reg_prefix = is64bit ? 'r' : 'e';
+  uint32_t gpr_base_size = is64bit ? 8 : 4;
+  // regs from gpr_basenames, in list order
+  std::array<GPRReg, 8> gpr_base_reg_indices;
+  assert(gpr_base_reg_indices.size() == gpr_basenames.size());
+  // r8..r15, sorted
+  std::array<GPRReg, 8> gpr_extra_reg_indices;
+  // st0..st7, sorted
+  std::array<STReg, 8> st_reg_indices;
+  // map used for fast register lookups
+  std::unordered_set<std::string> subreg_name_set;
+
+  // find base registers and store their indices
+  // (note that with incorrect input we could get less than 8 regs)
+  size_t new_index = 0;
+  for (const auto &x : llvm::enumerate(regs)) {
+    const char *reg_name = x.value().name.AsCString();
+    if (reg_name[0] == gpr_base_reg_prefix) {
+      // handle regs from gpr_basenames
+      auto in_basenames = gpr_basenames.find(reg_name + 1);
+      if (in_basenames != gpr_basenames.end() &&
+          new_index < gpr_base_reg_indices.size()) {
+        GPRReg &reg_rec = gpr_base_reg_indices[new_index++];
+        reg_rec.base_index = x.index();
+
+        // construct derived register names
+        std::string new_regname{reg_name};
+        if (is64bit) {
+          // 32-bit e* registers
+          new_regname[0] = 'e';
+          reg_rec.name32 = new_regname;
+          subreg_name_set.insert(new_regname);
+        }
+
+        // 16-bit * registers
+        new_regname.erase(new_regname.begin());
+        reg_rec.name16 = new_regname;
+        subreg_name_set.insert(new_regname);
+
+        if (new_regname[1] == 'x') {
+          // 8-bit [a-d]h registers
+          new_regname[1] = 'h';
+          reg_rec.name8h = new_regname;
+          subreg_name_set.insert(new_regname);
+
+          // 8-bit [a-d]l registers
+          new_regname[1] = 'l';
+          reg_rec.name8 = new_regname;
+          subreg_name_set.insert(new_regname);
+        } else {
+          // 8-bit sil/dil/spl/bpl registers
+          new_regname += 'l';
+          reg_rec.name8 = new_regname;
+          subreg_name_set.insert(new_regname);
+        }
+
+        continue;
+      }
+
+      // handle r8..r15 regs
+      unsigned int suffix;
+      if (is64bit && llvm::to_integer(reg_name + 1, suffix, 10) &&
+          suffix >= 8 && suffix < 16) {
+        GPRReg &reg_rec = gpr_extra_reg_indices[suffix - 8];
+        reg_rec.base_index = x.index();
+
+        // construct derived register names
+        std::string new_regname{reg_name};
+        // 32-bit r*d registers
+        new_regname += 'd';
+        reg_rec.name32 = new_regname;
+        subreg_name_set.insert(new_regname);
+
+        // 16-bit r*w registers
+        new_regname.back() = 'w';
+        reg_rec.name16 = new_regname;
+        subreg_name_set.insert(new_regname);
+
+        // 8-bit r*l registers
+        new_regname.back() = 'l';
+        reg_rec.name8 = new_regname;
+        subreg_name_set.insert(new_regname);
+
+        continue;
+      }
+    }
+
+    // st0..st7 regs
+    if (llvm::StringRef(reg_name).startswith("st")) {
+      unsigned int suffix;
+      if (llvm::to_integer(reg_name + 2, suffix, 10) && suffix < 8) {
+        STReg &reg_rec = st_reg_indices[suffix];
+        reg_rec.base_index = x.index();
+
+        std::string new_regname{"mm"};
+        new_regname += llvm::utostr(suffix);
+        reg_rec.name_mm = new_regname;
+        subreg_name_set.insert(new_regname);
+
+        continue;
+      }
+    }
+  }
+
+  // abort if we have at least one existing subregister
+  for (const DynamicRegisterInfo::Register &x : regs) {
+    const char *reg_name = x.name.AsCString();
+    auto found = subreg_name_set.find(reg_name);
+    if (found != subreg_name_set.end())
+      return;
+  }
+
+  if (is64bit) {
+    // on amd64, add 32-bit e* registers
+    for (const GPRReg &reg : gpr_base_reg_indices) {
+      if (reg.base_index != LLDB_INVALID_REGNUM)
+        addPartialRegister(regs, reg.base_index, gpr_base_size, reg.name32, 4);
+    }
+
+    // add 32-bit r*d registers
+    for (const GPRReg &reg : gpr_extra_reg_indices) {
+      if (reg.base_index != LLDB_INVALID_REGNUM)
+        addPartialRegister(regs, reg.base_index, gpr_base_size, reg.name32, 4);
+    }
+  }
+
+  // add 16-bit * registers
+  for (const GPRReg &reg : gpr_base_reg_indices) {
+    if (reg.base_index != LLDB_INVALID_REGNUM)
+      addPartialRegister(regs, reg.base_index, gpr_base_size, reg.name16, 2);
+  }
+
+  if (is64bit) {
+    // add 16-bit r*w registers
+    for (const GPRReg &reg : gpr_extra_reg_indices) {
+      if (reg.base_index != LLDB_INVALID_REGNUM)
+        addPartialRegister(regs, reg.base_index, gpr_base_size, reg.name16, 2);
+    }
+  }
+
+  // add 8-bit *h registers
+  for (const GPRReg &reg : gpr_base_reg_indices) {
+    if (reg.base_index != LLDB_INVALID_REGNUM && !reg.name8h.empty())
+      addPartialRegister(regs, reg.base_index, gpr_base_size, reg.name8h, 1, 1);
+  }
+
+  // add 8-bit *l registers
+  for (const GPRReg &reg : gpr_base_reg_indices) {
+    if (reg.base_index != LLDB_INVALID_REGNUM)
+      addPartialRegister(regs, reg.base_index, gpr_base_size, reg.name8, 1);
+  }
+
+  if (is64bit) {
+    // add 8-bit r*l registers
+    for (const GPRReg &reg : gpr_extra_reg_indices) {
+      if (reg.base_index != LLDB_INVALID_REGNUM)
+        addPartialRegister(regs, reg.base_index, gpr_base_size, reg.name8, 1);
+    }
+  }
+
+  // add mm registers
+  for (const STReg &reg : st_reg_indices) {
+    if (reg.base_index != LLDB_INVALID_REGNUM)
+      addPartialRegister(regs, reg.base_index, 10, reg.name_mm, 8, 0,
+                         eEncodingUint, eFormatHex);
+  }
+}
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to