Skip to content

Commit dfa7c1b

Browse files
Merge pull request #11916 from swiftlang/dl/lldb-Adopt-new-pointer-and-mangled-typename-based-stringForPrintObject
[lldb] Adopt new pointer and mangled typename based stringForPrintObject
2 parents ea6cf24 + 6f0d8fd commit dfa7c1b

File tree

10 files changed

+381
-26
lines changed

10 files changed

+381
-26
lines changed

lldb/include/lldb/Target/Target.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,8 @@ class TargetProperties : public Properties {
216216

217217
bool GetSwiftAutoImportFrameworks() const;
218218

219+
bool GetSwiftUseContextFreePrintObject() const;
220+
219221
bool GetEnableAutoImportClangModules() const;
220222

221223
bool GetUseAllCompilerFlags() const;
@@ -567,6 +569,14 @@ class EvaluateExpressionOptions {
567569

568570
bool GetPreparePlaygroundStubFunctions() const { return m_prepare_playground_stub_functions; }
569571

572+
void SetUseContextFreeSwiftPrintObject(bool enable = true) {
573+
m_use_context_free_swift_print_object = enable;
574+
}
575+
576+
bool GetUseContextFreeSwiftPrintObject() const {
577+
return m_use_context_free_swift_print_object;
578+
}
579+
570580
private:
571581
ExecutionPolicy m_execution_policy = default_execution_policy;
572582
SourceLanguage m_language;
@@ -608,6 +618,11 @@ class EvaluateExpressionOptions {
608618
mutable uint32_t m_pound_line_line = 0;
609619
bool m_prepare_playground_stub_functions = true;
610620

621+
/// An evaluation mode that for swift. Has the following effects:
622+
/// 1. Disables implicit module loading
623+
/// 2. Disables compiler availability checking
624+
bool m_use_context_free_swift_print_object = false;
625+
611626
/// During expression evaluation, any SymbolContext in this list will be
612627
/// used for symbol/function lookup before any other context (except for
613628
/// the module corresponding to the current frame).

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

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1317,13 +1317,14 @@ SwiftExpressionParser::ParseAndImport(
13171317
if (lldb::StackFrameSP this_frame_sp = m_stack_frame_wp.lock())
13181318
process_sp = this_frame_sp->CalculateProcess();
13191319
m_swift_ast_ctx.LoadImplicitModules(m_sc.target_sp, process_sp, *m_exe_scope);
1320-
if (!m_swift_ast_ctx.GetImplicitImports(m_sc, process_sp, additional_imports,
1321-
implicit_import_error)) {
1322-
const char *msg = implicit_import_error.AsCString();
1323-
if (!msg)
1324-
msg = "error status positive, but import still failed";
1325-
return make_error<ModuleImportError>(msg);
1326-
}
1320+
if (!m_options.GetUseContextFreeSwiftPrintObject())
1321+
if (!m_swift_ast_ctx.GetImplicitImports(
1322+
m_sc, process_sp, additional_imports, implicit_import_error)) {
1323+
const char *msg = implicit_import_error.AsCString();
1324+
if (!msg)
1325+
msg = "error status positive, but import still failed";
1326+
return make_error<ModuleImportError>(msg);
1327+
}
13271328

13281329
swift::ImplicitImportInfo importInfo;
13291330
importInfo.StdlibKind = swift::ImplicitStdlibKind::Stdlib;

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

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -640,15 +640,22 @@ 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.GetUseContextFreeSwiftPrintObject()) {
644+
// Disable availability by setting the OS version to 9999. This
645+
// placeholder OS version used for future OS versions when building
646+
// the Swift standard library locally.
647+
os_vers << "9999";
649648
} else {
650-
llvm::VersionTuple version = process_sp->GetHostOSVersion();
651-
os_vers << version.getAsString();
649+
auto platform = target->GetPlatform();
650+
bool is_simulator = platform->GetPluginName().ends_with("-simulator");
651+
if (is_simulator) {
652+
// The simulators look like the host OS to Process, but Platform
653+
// can get the version out of an environment variable.
654+
os_vers << platform->GetOSVersion(process_sp.get()).getAsString();
655+
} else {
656+
llvm::VersionTuple version = process_sp->GetHostOSVersion();
657+
os_vers << version.getAsString();
658+
}
652659
}
653660
}
654661
}

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

Lines changed: 95 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 context_free = 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 (context_free)
927+
eval_options.SetUseContextFreeSwiftPrintObject();
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,17 @@ 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+
Log *log(GetLog(LLDBLog::DataFormatters | LLDBLog::Expressions));
955963
formatters::StringPrinter::ReadStringAndDumpToStreamOptions dump_options;
956964
dump_options.SetEscapeNonPrintables(false);
957965
dump_options.SetQuote('\0');
958966
dump_options.SetPrefixToken(nullptr);
959967
if (formatters::swift::String_SummaryProvider(
960-
*result_sp.get(), result,
968+
*result_sp, strm,
961969
TypeSummaryOptions()
962970
.SetLanguage(lldb::eLanguageTypeSwift)
963971
.SetCapping(eTypeSummaryUncapped),
@@ -973,6 +981,15 @@ llvm::Error SwiftLanguageRuntime::RunObjectDescriptionExpr(
973981
return llvm::createStringError("expression produced unprintable string");
974982
}
975983

984+
llvm::Error SwiftLanguageRuntime::RunObjectDescriptionExpr(
985+
ValueObject &object, std::string &expr_string, Stream &strm) {
986+
auto result_or_err = RunObjectDescription(object, expr_string, GetProcess());
987+
if (!result_or_err)
988+
return result_or_err.takeError();
989+
990+
return DumpString(*result_or_err, strm);
991+
}
992+
976993
static bool IsVariable(ValueObject &object) {
977994
if (object.IsSynthetic())
978995
return IsVariable(*object.GetNonSyntheticValue());
@@ -1002,11 +1019,80 @@ static bool IsSwiftReferenceType(ValueObject &object) {
10021019
return false;
10031020
}
10041021

1022+
static llvm::Error PrintObjectViaPointer(Stream &strm, ValueObject &object,
1023+
Process &process) {
1024+
Flags flags(object.GetCompilerType().GetTypeInfo());
1025+
addr_t addr = LLDB_INVALID_ADDRESS;
1026+
if (flags.Test(eTypeInstanceIsPointer)) {
1027+
// Objects are pointers.
1028+
addr = object.GetValueAsUnsigned(LLDB_INVALID_ADDRESS);
1029+
addr = process.FixDataAddress(addr);
1030+
} else {
1031+
// Get the address of non-object values (structs, enums).
1032+
auto addr_and_type = object.GetAddressOf(false);
1033+
if (addr_and_type.type != eAddressTypeLoad) {
1034+
return llvm::createStringError("address-of value object failed");
1035+
}
1036+
addr = addr_and_type.address;
1037+
}
1038+
1039+
if (addr == 0 || addr == LLDB_INVALID_ADDRESS)
1040+
return llvm::createStringError("invalid address 0x%x", addr);
1041+
1042+
StringRef mangled_type_name = object.GetMangledTypeName();
1043+
// Swift APIs that receive mangled names require the prefix removed.
1044+
mangled_type_name.consume_front("$s");
1045+
mangled_type_name.consume_front("$e"); // Embedded Swift prefix
1046+
1047+
std::string expr_string =
1048+
llvm::formatv(
1049+
"Swift._DebuggerSupport.stringForPrintObject(UnsafeRawPointer("
1050+
"bitPattern: {0}), mangledTypeName: \"{1}\")",
1051+
addr, mangled_type_name)
1052+
.str();
1053+
1054+
auto result_or_err = RunObjectDescription(object, expr_string, process, true);
1055+
if (!result_or_err)
1056+
return result_or_err.takeError();
1057+
1058+
// A `(Bool, String)` tuple, where the bool indicates success/failure.
1059+
auto result_sp = *result_or_err;
1060+
auto success_sp = result_sp->GetChildAtIndex(0);
1061+
auto description_sp = result_sp->GetChildAtIndex(1);
1062+
1063+
StreamString string_result;
1064+
auto err = DumpString(description_sp, string_result);
1065+
if (err) {
1066+
return llvm::joinErrors(
1067+
std::move(err),
1068+
llvm::createStringError("decoding of description String failed"));
1069+
}
1070+
1071+
Status status;
1072+
if (!success_sp->IsLogicalTrue(status))
1073+
// The Bool is false, which means the String is an error message.
1074+
return llvm::createStringError(string_result.GetData());
1075+
1076+
strm.PutCString(string_result.GetString());
1077+
return llvm::Error::success();
1078+
}
1079+
10051080
llvm::Error SwiftLanguageRuntime::GetObjectDescription(Stream &str,
10061081
ValueObject &object) {
10071082
if (object.IsUninitializedReference())
10081083
return llvm::createStringError("<uninitialized>");
10091084

1085+
Log *log = GetLog(LLDBLog::DataFormatters | LLDBLog::Expressions);
1086+
if (GetProcess().GetTarget().GetSwiftUseContextFreePrintObject()) {
1087+
if (auto err = PrintObjectViaPointer(str, object, GetProcess())) {
1088+
LLDB_LOG_ERROR(log, std::move(err),
1089+
"stringForPrintObject(_:mangledTypeName) failed: {0}");
1090+
} else {
1091+
LLDB_LOG(log, "stringForPrintObject(_:mangledTypeName:) succeeded");
1092+
return llvm::Error::success();
1093+
}
1094+
}
1095+
10101096
std::string expr_string;
10111097

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

lldb/source/Target/Target.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4760,6 +4760,18 @@ bool TargetProperties::GetSwiftAutoImportFrameworks() const {
47604760
idx, g_target_properties[idx].default_uint_value != 0);
47614761
}
47624762

4763+
bool TargetProperties::GetSwiftUseContextFreePrintObject() const {
4764+
const Property *exp_property =
4765+
m_collection_sp->GetPropertyAtIndex(ePropertyExperimental);
4766+
OptionValueProperties *exp_values =
4767+
exp_property->GetValue()->GetAsProperties();
4768+
if (exp_values)
4769+
return exp_values
4770+
->GetPropertyAtIndexAs<bool>(ePropertySwiftUseContextFreePrintObject)
4771+
.value_or(false);
4772+
return false;
4773+
}
4774+
47634775
void TargetProperties::SetUseDIL(ExecutionContext *exe_ctx, bool b) {
47644776
const Property *exp_property =
47654777
m_collection_sp->GetPropertyAtIndex(ePropertyExperimental, exe_ctx);

lldb/source/Target/TargetProperties.td

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,9 @@ let Definition = "target_experimental" in {
3737
def SwiftCacheTaskPointerLocation: Property<"swift-cache-task-pointer-location", "Boolean">,
3838
DefaultTrue,
3939
Desc<"Enables caching of task pointers inside the swift tasks plugin">;
40+
def SwiftUseContextFreePrintObject: Property<"swift-use-context-free-po", "Boolean">,
41+
DefaultFalse,
42+
Desc<"If true, use the context-free po implementation for Swift.">;
4043
def UseDIL : Property<"use-DIL", "Boolean">,
4144
Global, DefaultTrue,
4245
Desc<"If true, use the DIL implementation for frame variable evaluation.">;

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

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,8 @@ def test_missing_type(self):
6868
target, process, thread, bkpt = lldbutil.run_to_source_breakpoint(
6969
self, 'break here', lldb.SBFileSpec('main.swift'))
7070

71+
self.runCmd("settings set target.experimental.swift-use-context-free-po true")
72+
7173
options = lldb.SBExpressionOptions()
7274
value = self.frame().EvaluateExpression("strct", options)
7375
def check(value):
@@ -81,12 +83,14 @@ def check(value):
8183

8284
check(value)
8385

86+
# This succeeds using stringForPrintObject(_:mangledTypeName:), which
87+
# doesn't require the type to be available.
88+
# Note: (?s)^(?!.*<pattern>) checks that the pattern is not found.
8489
self.expect(
8590
"dwim-print -O -- strct",
86-
substrs=["error: Missing type", "properties = true"],
91+
patterns=["(?s)^(?!.*error: Missing type)", "properties : true"],
8792
)
8893

8994
process.Continue()
9095
self.expect('expression -O -- number', error=True,
9196
substrs=['self', 'not', 'found'])
92-
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
SWIFT_SOURCES := main.swift
2+
SWIFTFLAGS_EXTRAS := -parse-as-library
3+
include Makefile.rules

0 commit comments

Comments
 (0)