This is an archive of the discontinued LLVM Phabricator instance.

[lldb] Delay removal of persistent results
ClosedPublic

Authored by kastiglione on May 15 2023, 3:11 PM.

Details

Summary

Follow up to "Suppress persistent result when running po" (D144044).

This change delays removal of the persistent result until after Dump has been called.
In doing so, the persistent result is available for the purpose of getting its object
description.

In the original change, the persistent result removal happens indirectly, by setting
EvaluateExpressionOptions::SetSuppressPersistentResult. In practice this has worked,
however this exposed a latent bug in swift-lldb. The subtlety, and the bug, depend on
when the persisteted result variable is removed.

When the result is removed via SetSuppressPersistentResult, it happens within the call
to Target::EvaluateExpression. That is, by the time the call returns, the persistent
result is already removed.

The issue occurs shortly thereafter, when ValueObject::Dump is called, it cannot make
use of the persistent result variable (instead it uses the ValueObjectConstResult). In
swift-lldb, this causes an additional expression evaluation to happen. It first tries an
expression that reference $R0 etc, but that always fails because $R0 is removed. The
fallback to this failure does work most of the time, but there's at least one bug
involving imported Clang types.

rdar://108656999

Diff Detail

Event Timeline

kastiglione created this revision.May 15 2023, 3:11 PM
Herald added a project: Restricted Project. · View Herald TranscriptMay 15 2023, 3:11 PM
kastiglione requested review of this revision.May 15 2023, 3:11 PM
Herald added a project: Restricted Project. · View Herald TranscriptMay 15 2023, 3:11 PM

This change is tested using the original tests from D144044.

check frame pointer before calling GuessLanguage

s/frame pointer/pointer to StackFrame/

This seems fine in general, with one quibble:

IIUC, the "indirect" removal of persistent results which you are trying to avoid happens here:

lldb::ExpressionResults
UserExpression::Execute(DiagnosticManager &diagnostic_manager,
                        ExecutionContext &exe_ctx,
                        const EvaluateExpressionOptions &options,
                        lldb::UserExpressionSP &shared_ptr_to_me,
                        lldb::ExpressionVariableSP &result_var) {
  lldb::ExpressionResults expr_result = DoExecute(
      diagnostic_manager, exe_ctx, options, shared_ptr_to_me, result_var);
  Target *target = exe_ctx.GetTargetPtr();
  if (options.GetSuppressPersistentResult() && result_var && target) {
    if (auto *persistent_state =
            target->GetPersistentExpressionStateForLanguage(m_language))
      persistent_state->RemovePersistentVariable(result_var);
  }
  return expr_result;
}

So to succeed in preserving the persistent result, your patch relies on SuppressPersistentResult being false in the EvaluateExpressionOptions you pass to the expression. However, you derive the expression options from the command options, for instance in:

const EvaluateExpressionOptions eval_options =
    m_command_options.GetEvaluateExpressionOptions(target, m_varobj_options);

so you don't actually know what the value of the SuppressPersistentResults is going to be. Since you rely on this having a particular value regardless of the user's intentions, you should do SetSuppressPersistentResults explicitly (with an appropriate comment) after you've fetch the eval_options in the dwim-print and expr commands.

A much smaller quibble is that it seems a little weird to ask the expression options or the frame which language in the PersistentExpressionResultsForLanguage map the result variable was stuffed into when you have the Result ValueObject on hand. That seems like something the ValueObject should tell you. When we Persist ValueObjects we use ValueObject::GetPreferredDisplayLanguage. That seems more trustworthy - if it isn't we should make it so...

  • Explicitly control expression evaluation options for suppressing persistent result
  • Use the ValueObject's display language instead of the CU or frame's language

thank you @jingham, that is great feedback!

kastiglione edited the summary of this revision. (Show Details)May 17 2023, 1:34 PM
This revision was not accepted when it landed; it landed in state Needs Review.May 18 2023, 9:44 AM
This revision was automatically updated to reflect the committed changes.