[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