Skip to content

Commit 38f5709

Browse files
committed
[lldb] Adopt new pointer and mangled typename based stringForPrintObject
Adopt `stringForPrintObject(_:mangledTypeName:)`, an overload added in swiftlang/swift#84742. This new overload allows lldb to call `stringForPrintObject` using only a pointer referencing the value, and the mangled typename corresponding to the value. The resulting expression does not reference the concrete type. By not referencing a value's type, `po` can be performed on variables (and their nested stored properties) without loading the modules corresponding to the value's type. This will improve performance and reliability of `po`.
1 parent 03bec58 commit 38f5709

File tree

4 files changed

+125
-18
lines changed

4 files changed

+125
-18
lines changed

lldb/include/lldb/Target/Target.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -566,6 +566,10 @@ class EvaluateExpressionOptions {
566566

567567
bool GetPreparePlaygroundStubFunctions() const { return m_prepare_playground_stub_functions; }
568568

569+
void SetDisableAvailability() { m_disable_availability = true; }
570+
571+
bool GetDisableAvailability() const { return m_disable_availability; }
572+
569573
private:
570574
ExecutionPolicy m_execution_policy = default_execution_policy;
571575
SourceLanguage m_language;
@@ -607,6 +611,9 @@ class EvaluateExpressionOptions {
607611
mutable uint32_t m_pound_line_line = 0;
608612
bool m_prepare_playground_stub_functions = true;
609613

614+
/// Disable compiler availability checking.
615+
bool m_disable_availability = false;
616+
610617
/// During expression evaluation, any SymbolContext in this list will be
611618
/// used for symbol/function lookup before any other context (except for
612619
/// the module corresponding to the current frame).

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

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -640,15 +640,21 @@ Status SwiftExpressionSourceCode::GetText(
640640
if (triple.isOSDarwin()) {
641641
if (auto process_sp = exe_ctx.GetProcessSP()) {
642642
os_vers << getAvailabilityName(triple) << " ";
643-
auto platform = target->GetPlatform();
644-
bool is_simulator = platform->GetPluginName().ends_with("-simulator");
645-
if (is_simulator) {
646-
// The simulators look like the host OS to Process, but Platform
647-
// can the version out of an environment variable.
648-
os_vers << platform->GetOSVersion(process_sp.get()).getAsString();
643+
if (options.GetDisableAvailability()) {
644+
// Disable availability by setting the OS version to 9999, the
645+
// placeholder number used for future OS versions.
646+
os_vers << "9999";
649647
} else {
650-
llvm::VersionTuple version = process_sp->GetHostOSVersion();
651-
os_vers << version.getAsString();
648+
auto platform = target->GetPlatform();
649+
bool is_simulator = platform->GetPluginName().ends_with("-simulator");
650+
if (is_simulator) {
651+
// The simulators look like the host OS to Process, but Platform
652+
// can the version out of an environment variable.
653+
os_vers << platform->GetOSVersion(process_sp.get()).getAsString();
654+
} else {
655+
llvm::VersionTuple version = process_sp->GetHostOSVersion();
656+
os_vers << version.getAsString();
657+
}
652658
}
653659
}
654660
}

lldb/source/Plugins/LanguageRuntime/Swift/SwiftLanguageRuntime.cpp

Lines changed: 99 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@
4848
#include "lldb/Utility/Log.h"
4949
#include "lldb/Utility/OptionParsing.h"
5050
#include "lldb/Utility/Status.h"
51+
#include "lldb/Utility/StreamString.h"
5152
#include "lldb/Utility/StructuredData.h"
5253
#include "lldb/Utility/Timer.h"
5354
#include "lldb/ValueObject/ValueObject.h"
@@ -835,7 +836,7 @@ SwiftLanguageRuntime::GetObjectDescriptionExpr_Ref(ValueObject &object) {
835836
object.GetValueAsUnsigned(0)).str();
836837

837838
if (log)
838-
log->Printf("[GetObjectDescriptionExpr_Result] expression: %s",
839+
log->Printf("[GetObjectDescriptionExpr_Ref] expression: %s",
839840
expr_string.GetData());
840841
return expr_str;
841842
}
@@ -911,25 +912,27 @@ std::string SwiftLanguageRuntime::GetObjectDescriptionExpr_Copy(
911912
return expr_string;
912913
}
913914

914-
llvm::Error SwiftLanguageRuntime::RunObjectDescriptionExpr(
915-
ValueObject &object, std::string &expr_string, Stream &result) {
915+
static llvm::Expected<ValueObjectSP>
916+
runObjectDescription(ValueObject &object, std::string &expr_string,
917+
Process &process, bool disable_availability = false) {
916918
Log *log(GetLog(LLDBLog::DataFormatters | LLDBLog::Expressions));
917919
ValueObjectSP result_sp;
918920
EvaluateExpressionOptions eval_options;
919921
eval_options.SetUnwindOnError(true);
920922
eval_options.SetLanguage(lldb::eLanguageTypeSwift);
921923
eval_options.SetSuppressPersistentResult(true);
922924
eval_options.SetIgnoreBreakpoints(true);
923-
eval_options.SetTimeout(GetProcess().GetUtilityExpressionTimeout());
925+
eval_options.SetTimeout(process.GetUtilityExpressionTimeout());
926+
if (disable_availability)
927+
eval_options.SetDisableAvailability();
924928

925929
StackFrameSP frame_sp = object.GetFrameSP();
926930
if (!frame_sp)
927-
frame_sp =
928-
GetProcess().GetThreadList().GetSelectedThread()->GetSelectedFrame(
929-
DoNoSelectMostRelevantFrame);
931+
frame_sp = process.GetThreadList().GetSelectedThread()->GetSelectedFrame(
932+
DoNoSelectMostRelevantFrame);
930933
if (!frame_sp)
931934
return llvm::createStringError("no execution context to run expression in");
932-
auto eval_result = GetProcess().GetTarget().EvaluateExpression(
935+
auto eval_result = process.GetTarget().EvaluateExpression(
933936
expr_string, frame_sp.get(), result_sp, eval_options);
934937

935938
LLDB_LOG(log, "[RunObjectDescriptionExpr] {0}", toString(eval_result));
@@ -952,12 +955,28 @@ llvm::Error SwiftLanguageRuntime::RunObjectDescriptionExpr(
952955
return llvm::createStringError("expression produced invalid result type");
953956
}
954957

958+
return result_sp;
959+
}
960+
961+
static llvm::Error dumpString(ValueObjectSP result_sp, Stream &strm);
962+
963+
llvm::Error SwiftLanguageRuntime::RunObjectDescriptionExpr(
964+
ValueObject &object, std::string &expr_string, Stream &strm) {
965+
auto result_or_err = runObjectDescription(object, expr_string, GetProcess());
966+
if (!result_or_err)
967+
return result_or_err.takeError();
968+
969+
return dumpString(*result_or_err, strm);
970+
}
971+
972+
static llvm::Error dumpString(ValueObjectSP result_sp, Stream &strm) {
973+
Log *log(GetLog(LLDBLog::DataFormatters | LLDBLog::Expressions));
955974
formatters::StringPrinter::ReadStringAndDumpToStreamOptions dump_options;
956975
dump_options.SetEscapeNonPrintables(false);
957976
dump_options.SetQuote('\0');
958977
dump_options.SetPrefixToken(nullptr);
959978
if (formatters::swift::String_SummaryProvider(
960-
*result_sp.get(), result,
979+
*result_sp, strm,
961980
TypeSummaryOptions()
962981
.SetLanguage(lldb::eLanguageTypeSwift)
963982
.SetCapping(eTypeSummaryUncapped),
@@ -1002,11 +1021,82 @@ static bool IsSwiftReferenceType(ValueObject &object) {
10021021
return false;
10031022
}
10041023

1024+
static bool printObjectViaPointer(Stream &strm, ValueObject &object,
1025+
Process &process) {
1026+
Log *log = GetLog(LLDBLog::DataFormatters | LLDBLog::Expressions);
1027+
1028+
Flags flags(object.GetCompilerType().GetTypeInfo());
1029+
addr_t addr = LLDB_INVALID_ADDRESS;
1030+
if (flags.Test(eTypeInstanceIsPointer)) {
1031+
// Objects are pointers.
1032+
addr = object.GetValueAsUnsigned(LLDB_INVALID_ADDRESS);
1033+
} else {
1034+
// Get the address of non-object values (structs, enums).
1035+
auto addr_and_type = object.GetAddressOf(false);
1036+
if (addr_and_type.type != eAddressTypeLoad) {
1037+
LLDB_LOG(log, "address-of value object failed, preventing use of "
1038+
"stringForPrintObject(_:mangledTypeName:)");
1039+
return false;
1040+
}
1041+
addr = addr_and_type.address;
1042+
}
1043+
1044+
if (addr == 0 || addr == LLDB_INVALID_ADDRESS)
1045+
return false;
1046+
1047+
StringRef mangled_type_name = object.GetMangledTypeName();
1048+
// Swift's APIs that accept mangled names require the "$s" prefix removed.
1049+
mangled_type_name.consume_front("$s");
1050+
1051+
std::string expr_string =
1052+
llvm::formatv(
1053+
"Swift._DebuggerSupport.stringForPrintObject(UnsafeRawPointer("
1054+
"bitPattern: {0}), mangledTypeName: \"{1}\")",
1055+
addr, mangled_type_name)
1056+
.str();
1057+
1058+
auto result_or_err = runObjectDescription(object, expr_string, process, true);
1059+
if (!result_or_err) {
1060+
LLDB_LOG_ERROR(log, result_or_err.takeError(),
1061+
"stringForPrintObject(_:mangledTypeName:) failed: {0}");
1062+
return false;
1063+
}
1064+
1065+
// A `(Bool, String)` tuple, where the bool indicates success/failure.
1066+
auto result_sp = *result_or_err;
1067+
auto success_sp = result_sp->GetChildAtIndex(0);
1068+
auto description_sp = result_sp->GetChildAtIndex(1);
1069+
1070+
StreamString dump_stream;
1071+
auto err = dumpString(description_sp, dump_stream);
1072+
if (err) {
1073+
LLDB_LOG_ERROR(log, std::move(err),
1074+
"decoding result of "
1075+
"stringForPrintObject(_:mangledTypeName:) failed: {0}");
1076+
return false;
1077+
}
1078+
1079+
Status status;
1080+
if (!success_sp->IsLogicalTrue(status)) {
1081+
LLDB_LOGF(log,
1082+
"stringForPrintObject(_:mangledTypeName:) produced error: %s",
1083+
dump_stream.GetData());
1084+
return false;
1085+
}
1086+
1087+
LLDB_LOG(log, "stringForPrintObject(_:mangledTypeName:) succeeded");
1088+
strm.PutCString(dump_stream.GetString());
1089+
return true;
1090+
}
1091+
10051092
llvm::Error SwiftLanguageRuntime::GetObjectDescription(Stream &str,
10061093
ValueObject &object) {
10071094
if (object.IsUninitializedReference())
10081095
return llvm::createStringError("<uninitialized>");
10091096

1097+
if (tryPointerPrintObject(str, object, GetProcess()))
1098+
return llvm::Error::success();
1099+
10101100
std::string expr_string;
10111101

10121102
if (::IsVariable(object) || ::IsSwiftResultVariable(object.GetName())) {

lldb/test/API/lang/swift/expression/error_reporting/TestSwiftExpressionErrorReporting.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,9 +81,13 @@ def check(value):
8181

8282
check(value)
8383

84+
# This succeeds using stringForPrintObject(_:mangledTypeName:), which
85+
# doesn't require the type to be available.
86+
# Note: (?s)^(?!.*<pattern>) checks that the pattern is not found.
87+
# self.runCmd("log enable lldb formatters")
8488
self.expect(
8589
"dwim-print -O -- strct",
86-
substrs=["error: Missing type", "properties = true"],
90+
patterns=["(?s)^(?!.*error: Missing type)", "properties : true"],
8791
)
8892

8993
process.Continue()

0 commit comments

Comments
 (0)