https://github.com/hawkinsw updated https://github.com/llvm/llvm-project/pull/215706
>From 22fc78067e2ae82e8991ff3b9e5a877bf8fb9f35 Mon Sep 17 00:00:00 2001 From: Will Hawkins <[email protected]> Date: Tue, 11 Aug 2026 21:46:30 -0400 Subject: [PATCH] [lldb] Support Persistent Variables as DIL Identifiers When a persistent variable is used in a DIL expression, look it up as if it were any other identifier in the global scope. Signed-off-by: Will Hawkins <[email protected]> --- lldb/include/lldb/ValueObject/DILEval.h | 7 ++++ .../Commands/CommandObjectDWIMPrint.cpp | 3 ++ lldb/source/ValueObject/DILEval.cpp | 37 ++++++++++++++++++ .../PersistentResultVariableLookup/Makefile | 3 ++ .../TestFrameVarDILGlobalVariableLookup.py | 39 +++++++++++++++++++ .../PersistentResultVariableLookup/main.cpp | 4 ++ .../Shell/Commands/command-dwim-print.test | 7 ++++ 7 files changed, 100 insertions(+) create mode 100644 lldb/test/API/commands/frame/var-dil/basics/PersistentResultVariableLookup/Makefile create mode 100644 lldb/test/API/commands/frame/var-dil/basics/PersistentResultVariableLookup/TestFrameVarDILGlobalVariableLookup.py create mode 100644 lldb/test/API/commands/frame/var-dil/basics/PersistentResultVariableLookup/main.cpp diff --git a/lldb/include/lldb/ValueObject/DILEval.h b/lldb/include/lldb/ValueObject/DILEval.h index 489dc801b20db..3a873063adda1 100644 --- a/lldb/include/lldb/ValueObject/DILEval.h +++ b/lldb/include/lldb/ValueObject/DILEval.h @@ -18,6 +18,13 @@ namespace lldb_private::dil { +/// Given the name of a persistent identifier (i.e., one that starts with a $), +/// find the ValueObject for that name (if it exists). +lldb::ValueObjectSP LookupPersistentIdentifier(llvm::StringRef name_ref, + StackFrame &stack_frame, + lldb::TargetSP target_sp, + lldb::LanguageType language); + /// Given the name of an identifier (variable name, member name, type name, /// etc.), find the ValueObject for that name (if it exists), excluding global /// variables, and create and return an IdentifierInfo object containing all diff --git a/lldb/source/Commands/CommandObjectDWIMPrint.cpp b/lldb/source/Commands/CommandObjectDWIMPrint.cpp index 1b0b4c7881cfc..6332fbf2b291c 100644 --- a/lldb/source/Commands/CommandObjectDWIMPrint.cpp +++ b/lldb/source/Commands/CommandObjectDWIMPrint.cpp @@ -191,6 +191,7 @@ void CommandObjectDWIMPrint::DoExecute(StringRef command, } } + #if 0 // Second, try `expr` as a persistent variable. if (expr.starts_with("$")) if (auto *state = target.GetPersistentExpressionStateForLanguage( @@ -201,6 +202,8 @@ void CommandObjectDWIMPrint::DoExecute(StringRef command, return; } + #endif + // Third, and lastly, try `expr` as a source expression to evaluate. { auto *exe_scope = m_exe_ctx.GetBestExecutionContextScope(); diff --git a/lldb/source/ValueObject/DILEval.cpp b/lldb/source/ValueObject/DILEval.cpp index 0ef4e244410a4..da7c7eaac16ac 100644 --- a/lldb/source/ValueObject/DILEval.cpp +++ b/lldb/source/ValueObject/DILEval.cpp @@ -8,16 +8,20 @@ #include "lldb/ValueObject/DILEval.h" #include "lldb/Core/Module.h" +#include "lldb/Expression/ExpressionVariable.h" #include "lldb/Symbol/CompileUnit.h" #include "lldb/Symbol/TypeSystem.h" #include "lldb/Symbol/VariableList.h" #include "lldb/Target/RegisterContext.h" +#include "lldb/Target/Target.h" #include "lldb/Utility/LLDBLog.h" #include "lldb/ValueObject/DILAST.h" #include "lldb/ValueObject/DILParser.h" #include "lldb/ValueObject/ValueObject.h" #include "lldb/ValueObject/ValueObjectRegister.h" #include "lldb/ValueObject/ValueObjectVariable.h" +#include "lldb/lldb-enumerations.h" +#include "lldb/lldb-private-types.h" #include "llvm/Support/ErrorExtras.h" #include "llvm/Support/FormatAdapters.h" #include <memory> @@ -44,6 +48,17 @@ static lldb::ValueObjectSP ArrayToPointerConversion(ValueObject &valobj, /* do_deref */ false); } +static llvm::Expected<lldb::LanguageType> +GetSourceLanguageFromCU(StackFrame &ctx) { + SymbolContext symbol_context = + ctx.GetSymbolContext(lldb::eSymbolContextCompUnit); + if (!symbol_context.comp_unit) + return llvm::createStringErrorV("no compile unit for frame: {}", + ctx.GetFunctionName()); + + return symbol_context.comp_unit->GetLanguage(); +} + static llvm::Expected<lldb::TypeSystemSP> GetTypeSystemFromCU(StackFrame &ctx) { SymbolContext symbol_context = ctx.GetSymbolContext(lldb::eSymbolContextCompUnit); @@ -323,6 +338,20 @@ lldb::ValueObjectSP LookupGlobalIdentifier(llvm::StringRef name_ref, return nullptr; } +lldb::ValueObjectSP LookupPersistentIdentifier(llvm::StringRef name_ref, + StackFrame &stack_frame, + lldb::TargetSP target_sp, + lldb::LanguageType language) { + if (name_ref.starts_with("$")) { + if (auto *state = + target_sp->GetPersistentExpressionStateForLanguage(language)) + if (auto var_sp = state->GetVariable(name_ref)) + if (auto valobj_sp = var_sp->GetValueObject()) + return valobj_sp; + } + return nullptr; +} + lldb::ValueObjectSP LookupIdentifier(llvm::StringRef name_ref, StackFrame &stack_frame, lldb::DynamicValueType use_dynamic) { @@ -459,6 +488,14 @@ Interpreter::Visit(const IdentifierNode &node) { if (!identifier) identifier = LookupEnumValue(node.GetName(), m_stack_frame); + if (!identifier && node.GetName()[0] == '$') { + auto language = GetSourceLanguageFromCU(m_stack_frame); + if (!language) + return language.takeError(); + identifier = LookupPersistentIdentifier(node.GetName(), m_stack_frame, + m_target, language.get()); + } + if (!identifier && node.GetName() == "nullptr") { // If we got a "nullptr" identifier, and there is no defined variable with // this name, resolve it as a null pointer. diff --git a/lldb/test/API/commands/frame/var-dil/basics/PersistentResultVariableLookup/Makefile b/lldb/test/API/commands/frame/var-dil/basics/PersistentResultVariableLookup/Makefile new file mode 100644 index 0000000000000..99998b20bcb05 --- /dev/null +++ b/lldb/test/API/commands/frame/var-dil/basics/PersistentResultVariableLookup/Makefile @@ -0,0 +1,3 @@ +CXX_SOURCES := main.cpp + +include Makefile.rules diff --git a/lldb/test/API/commands/frame/var-dil/basics/PersistentResultVariableLookup/TestFrameVarDILGlobalVariableLookup.py b/lldb/test/API/commands/frame/var-dil/basics/PersistentResultVariableLookup/TestFrameVarDILGlobalVariableLookup.py new file mode 100644 index 0000000000000..a3d3825532ccc --- /dev/null +++ b/lldb/test/API/commands/frame/var-dil/basics/PersistentResultVariableLookup/TestFrameVarDILGlobalVariableLookup.py @@ -0,0 +1,39 @@ +""" +Make sure 'frame var' using DIL parser/evaluator works for persistent/result variables. +""" + +import lldb +from lldbsuite.test.lldbtest import * +from lldbsuite.test.decorators import * +from lldbsuite.test import lldbutil + +import os +import shutil +import time + + +class TestFrameVarDILGlobalVariableLookup(TestBase): + # If your test case doesn't stress debug info, then + # set this to true. That way it won't be run once for + # each debug info format. + NO_DEBUG_INFO_TESTCASE = True + + @skipIf(macos_version=["<", "15.0"], archs=["arm64", "arm64e"]) + @skipIf( + dwarf_version=["<", "5"], + oslist=[lldbplatformutil.getDarwinOSTriples()], + ) + @expectedFailureAll( + compiler="clang", + compiler_version=["<", "19.0"], + oslist=[lldbplatformutil.getDarwinOSTriples()], + ) + def test_frame_var(self): + self.build() + lldbutil.run_to_source_breakpoint( + self, "Set a breakpoint here", lldb.SBFileSpec("main.cpp") + ) + + self.runCmd("settings set target.experimental.use-DIL true") + self.expect("dwim-print --persistent-result true -- foo + 5", startstr="(int) $0 = ") + self.expect_var_path("$0", type="int", value="6") diff --git a/lldb/test/API/commands/frame/var-dil/basics/PersistentResultVariableLookup/main.cpp b/lldb/test/API/commands/frame/var-dil/basics/PersistentResultVariableLookup/main.cpp new file mode 100644 index 0000000000000..fd23884132e8d --- /dev/null +++ b/lldb/test/API/commands/frame/var-dil/basics/PersistentResultVariableLookup/main.cpp @@ -0,0 +1,4 @@ +int main(int argc, char **argv) { + int foo = 1; + return 0; // Set a breakpoint here +} diff --git a/lldb/test/Shell/Commands/command-dwim-print.test b/lldb/test/Shell/Commands/command-dwim-print.test index 8c2697d8ebf8c..26662ea822648 100644 --- a/lldb/test/Shell/Commands/command-dwim-print.test +++ b/lldb/test/Shell/Commands/command-dwim-print.test @@ -14,3 +14,10 @@ # RUN: echo quit | %lldb -o "settings set show-inline-diagnostics false" \ # RUN: -o "dwim-print a" 2>&1 | FileCheck %s --check-prefix=CHECK4 # CHECK4: error: <user expression 0>:1:1: use of undeclared identifier +# RUN: %clang_host -g %S/Inputs/main.c -o %t +# RUN: echo quit | %lldb %t -o "b main" -o "r" -o \ +# RUN: "dwim-print --persistent-result true -- foo" -o \ +# RUN: "settings set dwim-print-verbosity full" -o \ +# RUN: "dwim-print -- $0" | FileCheck %s --check-prefix=CHECK5 +# (lldb) dwim-print -- $0 +# CHECK5:note: ran `frame variable $0` \ No newline at end of file _______________________________________________ lldb-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
