[Lldb-commits] [lldb] [LLDB] Add framework for Data Inspection Language (DIL) work. (PR #115666)

via lldb-commits lldb-commits at lists.llvm.org
Sun Nov 10 10:17:16 PST 2024


https://github.com/cmtice created https://github.com/llvm/llvm-project/pull/115666

Add the framework code for hooking up and calling the Data Inspection Language (DIL) implementation, as an alternate implementation for the 'frame variable' command. For now, this is an opt-in option, via a target setting 'target.experimental.use-DIL'.  See
https://discourse.llvm.org/t/rfc-data-inspection-language/69893 for more information about this project.

This PR does not actually call any of the DIL code; instead the piece that will eventually call the DIL code (StackFrame::DILEvaluateVariableExpression) calls back into the original 'frame variable' implementation.

>From d757bf7ac49d504707e39fe6f3a0bc93da5aef30 Mon Sep 17 00:00:00 2001
From: Caroline Tice <cmtice at google.com>
Date: Sun, 10 Nov 2024 10:07:22 -0800
Subject: [PATCH] [LLDB] Add framework for Data Inspection Language (DIL) work.

Add the framework code for hooking up and calling the Data Inspection Language
(DIL) implementation, as an alternate implementation for the 'frame
variable' command. For now, this is an opt-in option, via a target setting
'target.experimental.use-DIL'.  See
https://discourse.llvm.org/t/rfc-data-inspection-language/69893 for more
information about this project.

This PR does not actually call any of the DIL code; instead the piece that will
eventually call the DIL code (StackFrame::DILEvaluateVariableExpression) calls
back into the original 'frame variable' implementation.
---
 lldb/include/lldb/Target/StackFrame.h         | 29 +++++++++++++++++++
 lldb/include/lldb/Target/Target.h             |  4 +++
 lldb/source/API/SBFrame.cpp                   | 22 ++++++++++----
 lldb/source/Commands/CommandObjectFrame.cpp   | 19 +++++++++---
 .../Commands/CommandObjectWatchpoint.cpp      | 14 +++++++--
 lldb/source/Expression/UserExpression.cpp     | 29 ++++++++++++++-----
 .../SymbolFile/DWARF/DWARFASTParser.cpp       | 15 ++++++++--
 lldb/source/Target/StackFrame.cpp             |  9 ++++++
 lldb/source/Target/Target.cpp                 | 21 ++++++++++++++
 lldb/source/Target/TargetProperties.td        |  3 ++
 10 files changed, 144 insertions(+), 21 deletions(-)

diff --git a/lldb/include/lldb/Target/StackFrame.h b/lldb/include/lldb/Target/StackFrame.h
index 3881137583b941..03128447b5d496 100644
--- a/lldb/include/lldb/Target/StackFrame.h
+++ b/lldb/include/lldb/Target/StackFrame.h
@@ -308,6 +308,35 @@ class StackFrame : public ExecutionContextScope,
       llvm::StringRef var_expr, lldb::DynamicValueType use_dynamic,
       uint32_t options, lldb::VariableSP &var_sp, Status &error);
 
+  /// Create a ValueObject for a variable name / pathname, possibly including
+  /// simple dereference/child selection syntax.
+  ///
+  /// \param[in] var_expr
+  ///     The string specifying a variable to base the VariableObject off
+  ///     of.
+  ///
+  /// \param[in] use_dynamic
+  ///     Whether the correct dynamic type of an object pointer should be
+  ///     determined before creating the object, or if the static type is
+  ///     sufficient.  One of the DynamicValueType enumerated values.
+  ///
+  /// \param[in] options
+  ///     An unsigned integer of flags, values from
+  ///     StackFrame::ExpressionPathOption
+  ///     enum.
+  /// \param[in] var_sp
+  ///     A VariableSP that will be set to the variable described in the
+  ///     var_expr path.
+  ///
+  /// \param[in] error
+  ///     Record any errors encountered while evaluating var_expr.
+  ///
+  /// \return
+  ///     A shared pointer to the ValueObject described by var_expr.
+  lldb::ValueObjectSP DILEvaluateVariableExpression(
+      llvm::StringRef var_expr, lldb::DynamicValueType use_dynamic,
+      uint32_t options, lldb::VariableSP &var_sp, Status &error);
+
   /// Determine whether this StackFrame has debug information available or not.
   ///
   /// \return
diff --git a/lldb/include/lldb/Target/Target.h b/lldb/include/lldb/Target/Target.h
index cab21c29a7486f..b5becfb0e4fe17 100644
--- a/lldb/include/lldb/Target/Target.h
+++ b/lldb/include/lldb/Target/Target.h
@@ -252,6 +252,10 @@ class TargetProperties : public Properties {
 
   bool GetInjectLocalVariables(ExecutionContext *exe_ctx) const;
 
+  bool GetUseDIL(ExecutionContext *exe_ctx) const;
+
+  void SetUseDIL(ExecutionContext *exe_ctx, bool b);
+
   void SetRequireHardwareBreakpoints(bool b);
 
   bool GetRequireHardwareBreakpoints() const;
diff --git a/lldb/source/API/SBFrame.cpp b/lldb/source/API/SBFrame.cpp
index dc41e80b457d7d..4e3e47b7a5f60b 100644
--- a/lldb/source/API/SBFrame.cpp
+++ b/lldb/source/API/SBFrame.cpp
@@ -472,6 +472,7 @@ lldb::SBValue SBFrame::GetValueForVariablePath(const char *var_path,
   StackFrame *frame = nullptr;
   Target *target = exe_ctx.GetTargetPtr();
   Process *process = exe_ctx.GetProcessPtr();
+  bool use_DIL = target->GetUseDIL(&exe_ctx);
   if (target && process) {
     Process::StopLocker stop_locker;
     if (stop_locker.TryLock(&process->GetRunLock())) {
@@ -479,11 +480,22 @@ lldb::SBValue SBFrame::GetValueForVariablePath(const char *var_path,
       if (frame) {
         VariableSP var_sp;
         Status error;
-        ValueObjectSP value_sp(frame->GetValueForVariableExpressionPath(
-            var_path, eNoDynamicValues,
-            StackFrame::eExpressionPathOptionCheckPtrVsMember |
-                StackFrame::eExpressionPathOptionsAllowDirectIVarAccess,
-            var_sp, error));
+        ValueObjectSP value_sp;
+        if (use_DIL) {
+          // Use DIL parser/evaluator.
+          value_sp = frame->DILEvaluateVariableExpression(
+              var_path, eNoDynamicValues,
+              StackFrame::eExpressionPathOptionCheckPtrVsMember |
+                  StackFrame::eExpressionPathOptionsAllowDirectIVarAccess,
+              var_sp, error);
+        } else {
+          // Use original frame function.
+          value_sp = frame->GetValueForVariableExpressionPath(
+              var_path, eNoDynamicValues,
+              StackFrame::eExpressionPathOptionCheckPtrVsMember |
+                  StackFrame::eExpressionPathOptionsAllowDirectIVarAccess,
+              var_sp, error);
+        }
         sb_value.SetSP(value_sp, use_dynamic);
       }
     }
diff --git a/lldb/source/Commands/CommandObjectFrame.cpp b/lldb/source/Commands/CommandObjectFrame.cpp
index a5709b36f52ee2..7e0651657482bb 100644
--- a/lldb/source/Commands/CommandObjectFrame.cpp
+++ b/lldb/source/Commands/CommandObjectFrame.cpp
@@ -517,7 +517,10 @@ may even involve JITing and running code in the target program.)");
       result.AppendError(error.AsCString());
 
     }
+    VariableSP var_sp;
     ValueObjectSP valobj_sp;
+    TargetSP target_sp = frame->CalculateTarget();
+    bool use_DIL = target_sp->GetUseDIL(&m_exe_ctx);
 
     TypeSummaryImplSP summary_format_sp;
     if (!m_option_variable.summary.IsCurrentValueEmpty())
@@ -600,9 +603,17 @@ may even involve JITing and running code in the target program.)");
                 StackFrame::eExpressionPathOptionsAllowDirectIVarAccess |
                 StackFrame::eExpressionPathOptionsInspectAnonymousUnions;
             lldb::VariableSP var_sp;
-            valobj_sp = frame->GetValueForVariableExpressionPath(
-                entry.ref(), m_varobj_options.use_dynamic, expr_path_options,
-                var_sp, error);
+            if (use_DIL) {
+              // Use the DIL parser/evaluator.
+              valobj_sp = frame->DILEvaluateVariableExpression(
+                  entry.ref(), m_varobj_options.use_dynamic, expr_path_options,
+                  var_sp, error);
+            } else {
+              // Original 'frame variable' execution path
+              valobj_sp = frame->GetValueForVariableExpressionPath(
+                  entry.ref(), m_varobj_options.use_dynamic, expr_path_options,
+                  var_sp, error);
+            }
             if (valobj_sp) {
               std::string scope_string;
               if (m_option_variable.show_scope)
@@ -641,7 +652,7 @@ may even involve JITing and running code in the target program.)");
         const size_t num_variables = variable_list->GetSize();
         if (num_variables > 0) {
           for (size_t i = 0; i < num_variables; i++) {
-            VariableSP var_sp = variable_list->GetVariableAtIndex(i);
+            var_sp = variable_list->GetVariableAtIndex(i);
             if (!ScopeRequested(var_sp->GetScope()))
                 continue;
             std::string scope_string;
diff --git a/lldb/source/Commands/CommandObjectWatchpoint.cpp b/lldb/source/Commands/CommandObjectWatchpoint.cpp
index 766d650a2ca070..6eaefcef4398f4 100644
--- a/lldb/source/Commands/CommandObjectWatchpoint.cpp
+++ b/lldb/source/Commands/CommandObjectWatchpoint.cpp
@@ -806,6 +806,7 @@ corresponding to the byte size of the data type.");
   void DoExecute(Args &command, CommandReturnObject &result) override {
     Target &target = GetTarget();
     StackFrame *frame = m_exe_ctx.GetFramePtr();
+    bool use_DIL = target.GetUseDIL(&m_exe_ctx);
 
     // If no argument is present, issue an error message.  There's no way to
     // set a watchpoint.
@@ -840,9 +841,16 @@ corresponding to the byte size of the data type.");
     uint32_t expr_path_options =
         StackFrame::eExpressionPathOptionCheckPtrVsMember |
         StackFrame::eExpressionPathOptionsAllowDirectIVarAccess;
-    valobj_sp = frame->GetValueForVariableExpressionPath(
-        command.GetArgumentAtIndex(0), eNoDynamicValues, expr_path_options,
-        var_sp, error);
+    if (use_DIL)
+      // Use the DIL parser/evaluator.
+      valobj_sp = frame->DILEvaluateVariableExpression(
+          command.GetArgumentAtIndex(0), eNoDynamicValues, expr_path_options,
+          var_sp, error);
+    else
+      // Use the original frame function.
+      valobj_sp = frame->GetValueForVariableExpressionPath(
+          command.GetArgumentAtIndex(0), eNoDynamicValues, expr_path_options,
+          var_sp, error);
 
     if (!valobj_sp) {
       // Not in the frame; let's check the globals.
diff --git a/lldb/source/Expression/UserExpression.cpp b/lldb/source/Expression/UserExpression.cpp
index ed3734cbb943f6..bcfc25ff40b537 100644
--- a/lldb/source/Expression/UserExpression.cpp
+++ b/lldb/source/Expression/UserExpression.cpp
@@ -110,13 +110,28 @@ lldb::ValueObjectSP UserExpression::GetObjectPointerValueObject(
   lldb::VariableSP var_sp;
   lldb::ValueObjectSP valobj_sp;
 
-  return frame_sp->GetValueForVariableExpressionPath(
-      object_name, lldb::eNoDynamicValues,
-      StackFrame::eExpressionPathOptionCheckPtrVsMember |
-          StackFrame::eExpressionPathOptionsNoFragileObjcIvar |
-          StackFrame::eExpressionPathOptionsNoSyntheticChildren |
-          StackFrame::eExpressionPathOptionsNoSyntheticArrayRange,
-      var_sp, err);
+  lldb::TargetSP target_sp = frame_sp->CalculateTarget();
+  ExecutionContext exe_ctx;
+  frame_sp->CalculateExecutionContext(exe_ctx);
+  bool use_DIL = target_sp->GetUseDIL(&exe_ctx);
+
+  if (use_DIL) {
+    return frame_sp->DILEvaluateVariableExpression(
+        object_name, lldb::eNoDynamicValues,
+        StackFrame::eExpressionPathOptionCheckPtrVsMember |
+            StackFrame::eExpressionPathOptionsNoFragileObjcIvar |
+            StackFrame::eExpressionPathOptionsNoSyntheticChildren |
+            StackFrame::eExpressionPathOptionsNoSyntheticArrayRange,
+        var_sp, err);
+  } else {
+    return frame_sp->GetValueForVariableExpressionPath(
+        object_name, lldb::eNoDynamicValues,
+        StackFrame::eExpressionPathOptionCheckPtrVsMember |
+            StackFrame::eExpressionPathOptionsNoFragileObjcIvar |
+            StackFrame::eExpressionPathOptionsNoSyntheticChildren |
+            StackFrame::eExpressionPathOptionsNoSyntheticArrayRange,
+        var_sp, err);
+  }
 }
 
 lldb::addr_t UserExpression::GetObjectPointer(lldb::StackFrameSP frame_sp,
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParser.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParser.cpp
index e53e930665a602..270aa1481994c8 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParser.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParser.cpp
@@ -56,8 +56,19 @@ DWARFASTParser::ParseChildArrayInfo(const DWARFDIE &parent_die,
                 if (auto frame = exe_ctx->GetFrameSP()) {
                   Status error;
                   lldb::VariableSP var_sp;
-                  auto valobj_sp = frame->GetValueForVariableExpressionPath(
-                      var_die.GetName(), eNoDynamicValues, 0, var_sp, error);
+                  lldb::TargetSP target_sp = frame->CalculateTarget();
+                  bool use_DIL = target_sp->GetUseDIL(
+                      (lldb_private::ExecutionContext *)exe_ctx);
+                  lldb::ValueObjectSP valobj_sp;
+                  if (use_DIL) {
+                    // Use the DIL parser/evaluator.
+                    valobj_sp = frame->DILEvaluateVariableExpression(
+                        var_die.GetName(), eNoDynamicValues, 0, var_sp, error);
+                  } else {
+                    // Use the original frame function.
+                    valobj_sp = frame->GetValueForVariableExpressionPath(
+                        var_die.GetName(), eNoDynamicValues, 0, var_sp, error);
+                  }
                   if (valobj_sp) {
                     num_elements = valobj_sp->GetValueAsUnsigned(0);
                     break;
diff --git a/lldb/source/Target/StackFrame.cpp b/lldb/source/Target/StackFrame.cpp
index 3761b867452c99..83d8cbb440ad9d 100644
--- a/lldb/source/Target/StackFrame.cpp
+++ b/lldb/source/Target/StackFrame.cpp
@@ -505,6 +505,15 @@ StackFrame::GetInScopeVariableList(bool get_file_globals,
   return var_list_sp;
 }
 
+ValueObjectSP StackFrame::DILEvaluateVariableExpression(
+    llvm::StringRef var_expr, lldb::DynamicValueType use_dynamic,
+    uint32_t options, lldb::VariableSP &var_sp, Status &error) {
+  // This is a place-holder for the calls into the DIL parser and
+  // evaluator.  For now, just call the "real" frame variable implementation.
+  return GetValueForVariableExpressionPath(var_expr, use_dynamic, options,
+                                           var_sp, error);
+}
+
 ValueObjectSP StackFrame::GetValueForVariableExpressionPath(
     llvm::StringRef var_expr, DynamicValueType use_dynamic, uint32_t options,
     VariableSP &var_sp, Status &error) {
diff --git a/lldb/source/Target/Target.cpp b/lldb/source/Target/Target.cpp
index 242d2eaec2a15a..57ecbbc29bce64 100644
--- a/lldb/source/Target/Target.cpp
+++ b/lldb/source/Target/Target.cpp
@@ -4385,6 +4385,27 @@ bool TargetProperties::GetInjectLocalVariables(
       .value_or(true);
 }
 
+bool TargetProperties::GetUseDIL(ExecutionContext *exe_ctx) const {
+  const Property *exp_property =
+      m_collection_sp->GetPropertyAtIndex(ePropertyExperimental, exe_ctx);
+  OptionValueProperties *exp_values =
+      exp_property->GetValue()->GetAsProperties();
+  if (exp_values)
+    return exp_values->GetPropertyAtIndexAs<bool>(ePropertyUseDIL, exe_ctx)
+        .value_or(false);
+  else
+    return true;
+}
+
+void TargetProperties::SetUseDIL(ExecutionContext *exe_ctx, bool b) {
+  const Property *exp_property =
+      m_collection_sp->GetPropertyAtIndex(ePropertyExperimental, exe_ctx);
+  OptionValueProperties *exp_values =
+      exp_property->GetValue()->GetAsProperties();
+  if (exp_values)
+    exp_values->SetPropertyAtIndex(ePropertyUseDIL, true, exe_ctx);
+}
+
 ArchSpec TargetProperties::GetDefaultArchitecture() const {
   const uint32_t idx = ePropertyDefaultArch;
   return GetPropertyAtIndexAs<ArchSpec>(idx, {});
diff --git a/lldb/source/Target/TargetProperties.td b/lldb/source/Target/TargetProperties.td
index 00ad8dd2a9f7f9..8978a4a143b6f7 100644
--- a/lldb/source/Target/TargetProperties.td
+++ b/lldb/source/Target/TargetProperties.td
@@ -4,6 +4,9 @@ let Definition = "target_experimental" in {
   def InjectLocalVars : Property<"inject-local-vars", "Boolean">,
     Global, DefaultTrue,
     Desc<"If true, inject local variables explicitly into the expression text. This will fix symbol resolution when there are name collisions between ivars and local variables. But it can make expressions run much more slowly.">;
+  def UseDIL : Property<"use-DIL", "Boolean">,
+    Global, DefaultFalse,
+    Desc<"If true, use the alternative DIL implementation for frame variable evaluation.">;
 }
 
 let Definition = "target" in {



More information about the lldb-commits mailing list