[Lldb-commits] [lldb] a14f4a7 - tab completion for register read/write

Raphael Isemann via lldb-commits lldb-commits at lists.llvm.org
Thu May 7 09:14:45 PDT 2020


Author: Gongyu Deng
Date: 2020-05-07T18:14:27+02:00
New Revision: a14f4a7531f083a4820b5452808a1d003f1e88cc

URL: https://github.com/llvm/llvm-project/commit/a14f4a7531f083a4820b5452808a1d003f1e88cc
DIFF: https://github.com/llvm/llvm-project/commit/a14f4a7531f083a4820b5452808a1d003f1e88cc.diff

LOG: tab completion for register read/write

Summary:
1. Created a new common completion for the registers of the current context;
2. Apply this new common completion to the commands register read/write;
3. Unit test.

Reviewers: teemperor, JDevlieghere

Reviewed By: teemperor

Tags: #lldb

Differential Revision: https://reviews.llvm.org/D79490

Added: 
    

Modified: 
    lldb/include/lldb/Interpreter/CommandCompletions.h
    lldb/source/Commands/CommandCompletions.cpp
    lldb/source/Commands/CommandObjectRegister.cpp
    lldb/test/API/functionalities/completion/TestCompletion.py

Removed: 
    


################################################################################
diff  --git a/lldb/include/lldb/Interpreter/CommandCompletions.h b/lldb/include/lldb/Interpreter/CommandCompletions.h
index 51f5a2e5705e..a6e025e72baf 100644
--- a/lldb/include/lldb/Interpreter/CommandCompletions.h
+++ b/lldb/include/lldb/Interpreter/CommandCompletions.h
@@ -34,10 +34,11 @@ class CommandCompletions {
     ePlatformPluginCompletion = (1u << 6),
     eArchitectureCompletion = (1u << 7),
     eVariablePathCompletion = (1u << 8),
+    eRegisterCompletion = (1u << 9),
     // This item serves two purposes.  It is the last element in the enum, so
     // you can add custom enums starting from here in your Option class. Also
     // if you & in this bit the base code will not process the option.
-    eCustomCompletion = (1u << 9)
+    eCustomCompletion = (1u << 10)
   };
 
   static bool InvokeCommonCompletionCallbacks(
@@ -81,6 +82,9 @@ class CommandCompletions {
 
   static void VariablePath(CommandInterpreter &interpreter,
                            CompletionRequest &request, SearchFilter *searcher);
+
+  static void Registers(CommandInterpreter &interpreter,
+                        CompletionRequest &request, SearchFilter *searcher);
 };
 
 } // namespace lldb_private

diff  --git a/lldb/source/Commands/CommandCompletions.cpp b/lldb/source/Commands/CommandCompletions.cpp
index bc3a2ec4bd9e..1e903157c511 100644
--- a/lldb/source/Commands/CommandCompletions.cpp
+++ b/lldb/source/Commands/CommandCompletions.cpp
@@ -18,6 +18,7 @@
 #include "lldb/Interpreter/OptionValueProperties.h"
 #include "lldb/Symbol/CompileUnit.h"
 #include "lldb/Symbol/Variable.h"
+#include "lldb/Target/RegisterContext.h"
 #include "lldb/Utility/FileSpec.h"
 #include "lldb/Utility/StreamString.h"
 #include "lldb/Utility/TildeExpressionResolver.h"
@@ -55,6 +56,7 @@ bool CommandCompletions::InvokeCommonCompletionCallbacks(
       {ePlatformPluginCompletion, CommandCompletions::PlatformPluginNames},
       {eArchitectureCompletion, CommandCompletions::ArchitectureNames},
       {eVariablePathCompletion, CommandCompletions::VariablePath},
+      {eRegisterCompletion, CommandCompletions::Registers},
       {eNoCompletion, nullptr} // This one has to be last in the list.
   };
 
@@ -531,3 +533,20 @@ void CommandCompletions::VariablePath(CommandInterpreter &interpreter,
                                       SearchFilter *searcher) {
   Variable::AutoComplete(interpreter.GetExecutionContext(), request);
 }
+
+void CommandCompletions::Registers(CommandInterpreter &interpreter,
+                                   CompletionRequest &request,
+                                   SearchFilter *searcher) {
+  std::string reg_prefix = "";
+  if (request.GetCursorArgumentPrefix().startswith("$"))
+    reg_prefix = "$";
+
+  RegisterContext *reg_ctx =
+      interpreter.GetExecutionContext().GetRegisterContext();
+  const size_t reg_num = reg_ctx->GetRegisterCount();
+  for (size_t reg_idx = 0; reg_idx < reg_num; ++reg_idx) {
+    const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoAtIndex(reg_idx);
+    request.TryCompleteCurrentArg(reg_prefix + reg_info->name,
+                                  reg_info->alt_name);
+  }
+}
\ No newline at end of file

diff  --git a/lldb/source/Commands/CommandObjectRegister.cpp b/lldb/source/Commands/CommandObjectRegister.cpp
index 2c5457396eca..56e8c3fb4b84 100644
--- a/lldb/source/Commands/CommandObjectRegister.cpp
+++ b/lldb/source/Commands/CommandObjectRegister.cpp
@@ -70,6 +70,17 @@ class CommandObjectRegisterRead : public CommandObjectParsed {
 
   ~CommandObjectRegisterRead() override = default;
 
+  void
+  HandleArgumentCompletion(CompletionRequest &request,
+                           OptionElementVector &opt_element_vector) override {
+    if (!m_exe_ctx.HasProcessScope())
+      return;
+
+    CommandCompletions::InvokeCommonCompletionCallbacks(
+        GetCommandInterpreter(), CommandCompletions::eRegisterCompletion,
+        request, nullptr);
+  }
+
   Options *GetOptions() override { return &m_option_group; }
 
   bool DumpRegister(const ExecutionContext &exe_ctx, Stream &strm,
@@ -323,6 +334,17 @@ class CommandObjectRegisterWrite : public CommandObjectParsed {
 
   ~CommandObjectRegisterWrite() override = default;
 
+  void
+  HandleArgumentCompletion(CompletionRequest &request,
+                           OptionElementVector &opt_element_vector) override {
+    if (!m_exe_ctx.HasProcessScope() || request.GetCursorIndex() != 0)
+      return;
+
+    CommandCompletions::InvokeCommonCompletionCallbacks(
+        GetCommandInterpreter(), CommandCompletions::eRegisterCompletion,
+        request, nullptr);
+  }
+
 protected:
   bool DoExecute(Args &command, CommandReturnObject &result) override {
     DataExtractor reg_data;

diff  --git a/lldb/test/API/functionalities/completion/TestCompletion.py b/lldb/test/API/functionalities/completion/TestCompletion.py
index c2d3b919f1de..5e8f79934345 100644
--- a/lldb/test/API/functionalities/completion/TestCompletion.py
+++ b/lldb/test/API/functionalities/completion/TestCompletion.py
@@ -414,3 +414,66 @@ def test_symbol_name(self):
         # No completion for Qu because the candidate is
         # (anonymous namespace)::Quux().
         self.complete_from_to('breakpoint set -n Qu', '')
+
+    @skipIf(archs=no_match(['x86_64']))
+    def test_register_read_and_write_on_x86(self):
+        """Test the completion of the commands register read and write on x86"""
+
+        # The tab completion for "register read/write"  won't work without a running process.
+        self.complete_from_to('register read ',
+                              'register read ')
+        self.complete_from_to('register write ',
+                              'register write ')
+
+        self.build()
+        self.main_source_spec = lldb.SBFileSpec("main.cpp")
+        lldbutil.run_to_source_breakpoint(self, '// Break here', self.main_source_spec)
+
+        # test cases for register read
+        self.complete_from_to('register read ',
+                              ['rax',
+                               'rbx',
+                               'rcx'])
+        self.complete_from_to('register read r',
+                              ['rax',
+                               'rbx',
+                               'rcx'])
+        self.complete_from_to('register read ra',
+                              'register read rax')
+        # register read can take multiple register names as arguments
+        self.complete_from_to('register read rax ',
+                              ['rax',
+                               'rbx',
+                               'rcx'])
+        # complete with prefix '$'
+        self.completions_match('register read $rb',
+                              ['$rbx',
+                               '$rbp'])
+        self.completions_match('register read $ra',
+                              ['$rax'])
+        self.complete_from_to('register read rax $',
+                              ['\$rax',
+                               '\$rbx',
+                               '\$rcx'])
+        self.complete_from_to('register read $rax ',
+                              ['rax',
+                               'rbx',
+                               'rcx'])
+
+        # test cases for register write
+        self.complete_from_to('register write ',
+                              ['rax',
+                               'rbx',
+                               'rcx'])
+        self.complete_from_to('register write r',
+                              ['rax',
+                               'rbx',
+                               'rcx'])
+        self.complete_from_to('register write ra',
+                              'register write rax')
+        self.complete_from_to('register write rb',
+                              ['rbx',
+                               'rbp'])
+        # register write can only take exact one register name as argument
+        self.complete_from_to('register write rbx ',
+                              [])


        


More information about the lldb-commits mailing list