Skip to content

Commit 7b1bb14

Browse files
committed
[lldb] Run generic expression evaluator first
The generic expression evaluator can be significantly faster than the regular one since it only needs to import information about the module the debugger is stopped at to evaluate the expression. This patch swaps the order of the expression evaluators so that the generic expression evaluator is tried first. rdar://139239935
1 parent 77c0016 commit 7b1bb14

File tree

7 files changed

+82
-48
lines changed

7 files changed

+82
-48
lines changed

lldb/include/lldb/Interpreter/CommandOptionArgumentTable.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -160,8 +160,9 @@ static constexpr OptionEnumValueElement g_bind_gen_type_params[] = {
160160
{
161161
lldb::eBindAuto,
162162
"auto",
163-
"Attempt to run the expression with bound generic parameters first, "
164-
"fallback to unbound generic parameters if binding the type parameters "
163+
"Attempt to run the expression with unbound generic parameters first, "
164+
"fallback to binding the generic parameters if the expression with "
165+
"unbound generic type parameters "
165166
"fails",
166167
},
167168
{lldb::eBind, "true", "Bind generic type parameters."},

lldb/source/Plugins/ExpressionParser/Swift/SwiftASTManipulator.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -878,7 +878,7 @@ swift::FuncDecl *SwiftASTManipulator::GetFunctionToInjectVariableInto(
878878
// When not binding generic type parameters, we want to inject the metadata
879879
// pointers in the wrapper, so we can pass them as opaque pointers in the
880880
// trampoline function later on.
881-
if (m_bind_generic_types == lldb::eDontBind &&
881+
if (!ShouldBindGenericTypes(m_bind_generic_types) &&
882882
(variable.IsMetadataPointer() || variable.IsPackCount() ||
883883
variable.IsUnboundPack()))
884884
return m_entrypoint_decl;
@@ -896,7 +896,8 @@ llvm::Expected<swift::Type> SwiftASTManipulator::GetSwiftTypeForVariable(
896896

897897
// When injecting a value pack or pack count into the outer
898898
// lldb_expr function, treat it as an opaque raw pointer.
899-
if (m_bind_generic_types == lldb::eDontBind && variable.IsUnboundPack()) {
899+
if (!ShouldBindGenericTypes(m_bind_generic_types) &&
900+
variable.IsUnboundPack()) {
900901
auto swift_ast_ctx = type_system_swift->GetSwiftASTContext(m_sc);
901902
if (!swift_ast_ctx)
902903
return llvm::createStringError("no typesystem for variable " +

lldb/source/Plugins/ExpressionParser/Swift/SwiftASTManipulator.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -284,6 +284,12 @@ class SwiftASTManipulator : public SwiftASTManipulatorBase {
284284
const EvaluateExpressionOptions &options,
285285
std::string &expr_source_path);
286286

287+
// By default expression evaluation should not try to bind the generic types.
288+
static bool
289+
ShouldBindGenericTypes(lldb::BindGenericTypes bind_generic_types) {
290+
return bind_generic_types == lldb::eBind;
291+
}
292+
287293
swift::FuncDecl *GetEntrypointDecl() const {
288294
return m_entrypoint_decl;
289295
}

lldb/source/Plugins/ExpressionParser/Swift/SwiftExpressionParser.cpp

Lines changed: 27 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -448,7 +448,7 @@ static CompilerType GetSwiftTypeForVariableValueObject(
448448
CompilerType result = valobj_sp->GetCompilerType();
449449
if (!result)
450450
return {};
451-
if (bind_generic_types != lldb::eDontBind)
451+
if (SwiftASTManipulator::ShouldBindGenericTypes(bind_generic_types))
452452
result = runtime->BindGenericTypeParameters(*stack_frame_sp, result);
453453
if (!result)
454454
return {};
@@ -489,7 +489,8 @@ CompilerType SwiftExpressionParser::ResolveVariable(
489489
// though, as we don't bind the generic parameters in that case.
490490
if (swift_type_system->IsMeaninglessWithoutDynamicResolution(
491491
var_type.GetOpaqueQualType()) &&
492-
bind_generic_types != lldb::eDontBind && use_dynamic_value) {
492+
SwiftASTManipulator::ShouldBindGenericTypes(bind_generic_types) &&
493+
use_dynamic_value) {
493494
var_type = GetSwiftTypeForVariableValueObject(
494495
valobj_sp->GetDynamicValue(use_dynamic), stack_frame_sp, runtime,
495496
bind_generic_types);
@@ -583,7 +584,7 @@ AddRequiredAliases(Block *block, lldb::StackFrameSP &stack_frame_sp,
583584
"self type from an import isn't valid.");
584585

585586
auto *stack_frame = stack_frame_sp.get();
586-
if (bind_generic_types != lldb::eDontBind) {
587+
if (SwiftASTManipulator::ShouldBindGenericTypes(bind_generic_types)) {
587588
imported_self_type = swift_runtime->BindGenericTypeParameters(
588589
*stack_frame, imported_self_type);
589590
if (!imported_self_type)
@@ -1710,6 +1711,11 @@ SwiftExpressionParser::Parse(DiagnosticManager &diagnostic_manager,
17101711
auto expr_diagnostics = m_swift_ast_ctx.getScopedDiagnosticConsumer();
17111712
m_swift_ast_ctx.GetDiagnosticEngine().resetHadAnyError();
17121713

1714+
// The result in case parsing the expression fails. If the option is auto
1715+
// expression evaluation should retry by binding the generic types.
1716+
auto parse_result_failure = m_options.GetBindGenericTypes() == lldb::eBindAuto
1717+
? ParseResult::retry_bind_generic_params
1718+
: ParseResult::unrecoverable_error;
17131719
// Helper function to diagnose errors in m_swift_scratch_context.
17141720
unsigned buffer_id = UINT32_MAX;
17151721
auto DiagnoseSwiftASTContextError = [&]() {
@@ -1726,7 +1732,7 @@ SwiftExpressionParser::Parse(DiagnosticManager &diagnostic_manager,
17261732
const bool playground = m_options.GetPlaygroundTransformEnabled();
17271733

17281734
if (!m_exe_scope)
1729-
return ParseResult::unrecoverable_error;
1735+
return parse_result_failure;
17301736

17311737
// Parse the expression and import all nececssary swift modules.
17321738
auto parsed_expr = ParseAndImport(*expr_diagnostics, variable_map, buffer_id,
@@ -1767,7 +1773,7 @@ SwiftExpressionParser::Parse(DiagnosticManager &diagnostic_manager,
17671773
return ParseResult::retry_fresh_context;
17681774

17691775
// Unrecoverable error.
1770-
return ParseResult::unrecoverable_error;
1776+
return parse_result_failure;
17711777
}
17721778

17731779
// If any generics are present, this expression is not parseable.
@@ -1809,11 +1815,11 @@ SwiftExpressionParser::Parse(DiagnosticManager &diagnostic_manager,
18091815
"Missing type debug information for variable \"%s\": %s",
18101816
var.GetName().str().str().c_str(),
18111817
llvm::toString(std::move(error)).c_str());
1812-
return ParseResult::unrecoverable_error;
1818+
return parse_result_failure;
18131819
}
18141820
// Otherwise print the diagnostics from the Swift compiler.
18151821
DiagnoseSwiftASTContextError();
1816-
return ParseResult::unrecoverable_error;
1822+
return parse_result_failure;
18171823
}
18181824

18191825
if (repl)
@@ -1826,7 +1832,7 @@ SwiftExpressionParser::Parse(DiagnosticManager &diagnostic_manager,
18261832
if (error) {
18271833
diagnostic_manager.PutString(eSeverityError,
18281834
llvm::toString(std::move(error)));
1829-
return ParseResult::unrecoverable_error;
1835+
return parse_result_failure;
18301836
}
18311837
} else {
18321838
swift::performPlaygroundTransform(
@@ -1842,7 +1848,7 @@ SwiftExpressionParser::Parse(DiagnosticManager &diagnostic_manager,
18421848
diagnostic_manager.PutString(
18431849
eSeverityError,
18441850
"Cannot evaluate an expression that results in a ~Copyable type");
1845-
return ParseResult::unrecoverable_error;
1851+
return parse_result_failure;
18461852
}
18471853

18481854
// FIXME: We now should have to do the name binding and type
@@ -1965,10 +1971,9 @@ SwiftExpressionParser::Parse(DiagnosticManager &diagnostic_manager,
19651971
if (!var_info) {
19661972
auto error_string = llvm::toString(var_info.takeError());
19671973
LLDB_LOG(log, "Variable info failzed to materialize with error: {0}",
1968-
error_string);
1969-
1974+
error_string);
19701975

1971-
return ParseResult::unrecoverable_error;
1976+
return parse_result_failure;
19721977
}
19731978

19741979
const char *name = ConstString(variable.GetName().get()).GetCString();
@@ -2001,7 +2006,7 @@ SwiftExpressionParser::Parse(DiagnosticManager &diagnostic_manager,
20012006

20022007
if (expr_diagnostics->HasErrors()) {
20032008
DiagnoseSwiftASTContextError();
2004-
return ParseResult::unrecoverable_error;
2009+
return parse_result_failure;
20052010
}
20062011

20072012
if (log) {
@@ -2025,7 +2030,7 @@ SwiftExpressionParser::Parse(DiagnosticManager &diagnostic_manager,
20252030

20262031
if (expr_diagnostics->HasErrors()) {
20272032
DiagnoseSwiftASTContextError();
2028-
return ParseResult::unrecoverable_error;
2033+
return parse_result_failure;
20292034
}
20302035

20312036
{
@@ -2063,14 +2068,14 @@ SwiftExpressionParser::Parse(DiagnosticManager &diagnostic_manager,
20632068
diagnostic_manager.PutString(
20642069
eSeverityInfo, "couldn't IRGen expression: Clang importer error");
20652070
DiagnoseSwiftASTContextError();
2066-
return ParseResult::unrecoverable_error;
2071+
return parse_result_failure;
20672072
}
20682073

20692074
if (error_kind == ErrorKind::swift) {
20702075
diagnostic_manager.PutString(eSeverityInfo,
20712076
"couldn't IRGen expression: Swift error");
20722077
DiagnoseSwiftASTContextError();
2073-
return ParseResult::unrecoverable_error;
2078+
return parse_result_failure;
20742079
}
20752080

20762081
if (!m_module) {
@@ -2079,7 +2084,7 @@ SwiftExpressionParser::Parse(DiagnosticManager &diagnostic_manager,
20792084
"couldn't IRGen expression. Please enable the expression log by "
20802085
"running \"log enable lldb expr\", then run the failing expression "
20812086
"again, and file a bug report with the log output.");
2082-
return ParseResult::unrecoverable_error;
2087+
return parse_result_failure;
20832088
}
20842089

20852090
if (log) {
@@ -2091,7 +2096,8 @@ SwiftExpressionParser::Parse(DiagnosticManager &diagnostic_manager,
20912096
}
20922097

20932098
if (ThreadSafeASTContext ast_ctx = m_swift_ast_ctx.GetASTContext()) {
2094-
if (m_options.GetBindGenericTypes() == lldb::eDontBind &&
2099+
if (!SwiftASTManipulator::ShouldBindGenericTypes(
2100+
m_options.GetBindGenericTypes()) &&
20952101
!RedirectCallFromSinkToTrampolineFunction(
20962102
*m_module.get(), *parsed_expr->code_manipulator.get(), **ast_ctx)) {
20972103
diagnostic_manager.Printf(
@@ -2100,7 +2106,7 @@ SwiftExpressionParser::Parse(DiagnosticManager &diagnostic_manager,
21002106
"expression log by running \"log enable lldb "
21012107
"expr\", then run the failing expression again, and file a "
21022108
"bugreport with the log output.");
2103-
return ParseResult::unrecoverable_error;
2109+
return parse_result_failure;
21042110
}
21052111
}
21062112

@@ -2120,14 +2126,14 @@ SwiftExpressionParser::Parse(DiagnosticManager &diagnostic_manager,
21202126
LLVMReturnStatusAction, nullptr);
21212127
if (has_errors) {
21222128
diagnostic_manager.PutString(eSeverityInfo, "LLVM verification error");
2123-
return ParseResult::unrecoverable_error;
2129+
return parse_result_failure;
21242130
}
21252131
}
21262132

21272133
if (expr_diagnostics->HasErrors()) {
21282134
diagnostic_manager.PutString(eSeverityInfo, "post-IRGen error");
21292135
DiagnoseSwiftASTContextError();
2130-
return ParseResult::unrecoverable_error;
2136+
return parse_result_failure;
21312137
}
21322138

21332139
// The Parse succeeded! Now put this module into the context's list

lldb/source/Plugins/ExpressionParser/Swift/SwiftExpressionParser.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,10 @@ class SwiftExpressionParser : public ExpressionParser {
5151
enum class ParseResult {
5252
success,
5353
retry_fresh_context,
54-
retry_no_bind_generic_params,
54+
retry_bind_generic_params,
55+
// Retry by binding the generic parameters because the generic expression
56+
// evaluator does not support running this expression.
57+
retry_bind_generic_params_not_supported,
5558
unrecoverable_error
5659
};
5760
//------------------------------------------------------------------

lldb/source/Plugins/ExpressionParser/Swift/SwiftExpressionSourceCode.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -408,7 +408,8 @@ do {
408408
weak_self ? "Swift.Optional where Wrapped == " : "";
409409

410410
// The expression text is inserted into the body of $__lldb_user_expr_%u.
411-
if (options.GetBindGenericTypes() == lldb::eDontBind) {
411+
if (!SwiftASTManipulator::ShouldBindGenericTypes(
412+
options.GetBindGenericTypes())) {
412413
// A Swift program can't have types with non-bound generic type parameters
413414
// inside a non generic function. For example, the following program would
414415
// not compile as T is not part of foo's signature.
@@ -511,7 +512,8 @@ func $__lldb_expr(_ $__lldb_arg : UnsafeMutablePointer<Any>) {
511512
wrapped_expr_text.GetData(), availability.c_str(),
512513
current_counter);
513514
}
514-
} else if (options.GetBindGenericTypes() == lldb::eDontBind) {
515+
} else if (!SwiftASTManipulator::ShouldBindGenericTypes(
516+
options.GetBindGenericTypes())) {
515517
auto c = MakeGenericSignaturesAndCalls(local_variables, generic_sig,
516518
needs_object_ptr);
517519
if (!c) {

lldb/source/Plugins/ExpressionParser/Swift/SwiftUserExpression.cpp

Lines changed: 35 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -322,16 +322,18 @@ static llvm::Error AddVariableInfo(
322322
return llvm::Error::success();
323323

324324
CompilerType target_type;
325+
bool should_not_bind_generic_types =
326+
!SwiftASTManipulator::ShouldBindGenericTypes(bind_generic_types);
325327
bool is_unbound_pack =
326-
bind_generic_types == lldb::eDontBind &&
328+
should_not_bind_generic_types &&
327329
(variable_sp->GetType()->GetForwardCompilerType().GetTypeInfo() &
328330
lldb::eTypeIsPack);
329331

330332
// If we're not binding the generic types, we need to set the self type as an
331333
// opaque pointer type. This is necessary because we don't bind the generic
332334
// parameters, and we can't have a type with unbound generics in a non-generic
333335
// function.
334-
if (bind_generic_types == lldb::eDontBind && is_self)
336+
if (should_not_bind_generic_types && is_self)
335337
target_type = ast_context.GetBuiltinRawPointerType();
336338
else if (is_unbound_pack)
337339
target_type = variable_sp->GetType()->GetForwardCompilerType();
@@ -623,7 +625,7 @@ SwiftUserExpression::GetTextAndSetExpressionParser(
623625
lldb::eSeverityError,
624626
"Couldn't realize Swift AST type of self. Hint: using `v` to "
625627
"directly inspect variables and fields may still work.");
626-
return ParseResult::retry_no_bind_generic_params;
628+
return ParseResult::retry_bind_generic_params;
627629
}
628630

629631
auto ts = m_swift_ast_ctx->GetTypeSystemSwiftTypeRef();
@@ -636,14 +638,15 @@ SwiftUserExpression::GetTextAndSetExpressionParser(
636638
func_name.GetStringRef(), *ts);
637639
}
638640

639-
if (m_options.GetBindGenericTypes() == lldb::eDontBind &&
641+
if (!SwiftASTManipulator::ShouldBindGenericTypes(
642+
m_options.GetBindGenericTypes()) &&
640643
!CanEvaluateExpressionWithoutBindingGenericParams(
641644
local_variables, m_generic_signature, *m_swift_ast_ctx, sc.block,
642645
*stack_frame.get())) {
643646
diagnostic_manager.PutString(
644647
lldb::eSeverityError,
645648
"Could not evaluate the expression without binding generic types.");
646-
return ParseResult::unrecoverable_error;
649+
return ParseResult::retry_bind_generic_params_not_supported;
647650
}
648651

649652
uint32_t first_body_line = 0;
@@ -807,44 +810,56 @@ bool SwiftUserExpression::Parse(DiagnosticManager &diagnostic_manager,
807810
DiagnosticManager second_try_diagnostic_manager;
808811

809812
bool retry = false;
813+
bool first_expression_not_supported = false;
810814
while (true) {
811815
SwiftExpressionParser::ParseResult parse_result;
812816
if (!retry) {
813817
parse_result = GetTextAndSetExpressionParser(
814818
first_try_diagnostic_manager, source_code, exe_ctx, exe_scope);
815-
if (parse_result != SwiftExpressionParser::ParseResult::
816-
retry_no_bind_generic_params ||
819+
if ((parse_result !=
820+
SwiftExpressionParser::ParseResult::retry_bind_generic_params &&
821+
parse_result != SwiftExpressionParser::ParseResult::
822+
retry_bind_generic_params_not_supported) ||
817823
m_options.GetBindGenericTypes() != lldb::eBindAuto)
818824
// If we're not retrying, just copy the diagnostics over.
819825
diagnostic_manager.Consume(std::move(first_try_diagnostic_manager));
820826
} else {
821827
parse_result = GetTextAndSetExpressionParser(
822828
second_try_diagnostic_manager, source_code, exe_ctx, exe_scope);
823-
if (parse_result == SwiftExpressionParser::ParseResult::success)
824-
// If we succeeded the second time around, copy any diagnostics we
825-
// produced in the success case over, and ignore the first attempt's
826-
// failures.
829+
827830
diagnostic_manager.Consume(std::move(second_try_diagnostic_manager));
828-
else
829-
// If we failed though, copy the diagnostics of the first attempt, and
830-
// silently ignore any errors produced by the retry, as the retry was
831-
// not what the user asked, and any diagnostics produced by it will
832-
// most likely confuse the user.
833-
diagnostic_manager.Consume(std::move(first_try_diagnostic_manager));
831+
if (parse_result == SwiftExpressionParser::ParseResult::success ||
832+
first_expression_not_supported)
833+
// If we succeeded the second time around, copy any diagnostics we
834+
// produced in the success case over, and ignore the first attempt's
835+
// failures.
836+
// If the generic expression evaluator failed because it doesn't
837+
// support the expression the error message won't be very useful, so
838+
// print the regular expression evaluator's error instead.
839+
diagnostic_manager.Consume(std::move(second_try_diagnostic_manager));
840+
else
841+
// If we failed though, copy the diagnostics of the first attempt, and
842+
// silently ignore any errors produced by the retry, as the retry was
843+
// not what the user asked, and any diagnostics produced by it will
844+
// most likely confuse the user.
845+
diagnostic_manager.Consume(std::move(first_try_diagnostic_manager));
834846
}
835847

836848
if (parse_result == SwiftExpressionParser::ParseResult::success)
837849
break;
838850

839851
switch (parse_result) {
840-
case ParseResult::retry_no_bind_generic_params:
852+
case ParseResult::retry_bind_generic_params_not_supported:
853+
first_expression_not_supported = true;
854+
LLVM_FALLTHROUGH;
855+
case ParseResult::retry_bind_generic_params:
841856
// Retry running the expression without binding the generic types if
842857
// BindGenericTypes was in the auto setting, give up otherwise.
843858
if (m_options.GetBindGenericTypes() != lldb::eBindAuto)
844859
return false;
845-
// Retry without binding generic parameters, this is the only
860+
// Retry binding generic parameters, this is the only
846861
// case that will loop.
847-
m_options.SetBindGenericTypes(lldb::eDontBind);
862+
m_options.SetBindGenericTypes(lldb::eBind);
848863
retry = true;
849864
break;
850865

0 commit comments

Comments
 (0)