Skip to content

Revert "[SwiftLanguageRuntime] Simplify GetObjectDescription()." #79

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Nov 1, 2019
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
258 changes: 258 additions & 0 deletions lldb/source/Target/SwiftLanguageRuntime.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -274,6 +274,215 @@ void SwiftLanguageRuntime::ModulesDidLoad(const ModuleList &module_list) {
});
}

static bool GetObjectDescription_ResultVariable(Process *process, Stream &str,
ValueObject &object) {
Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_DATAFORMATTERS));

StreamString expr_string;
expr_string.Printf("Swift._DebuggerSupport.stringForPrintObject(%s)",
object.GetName().GetCString());

if (log)
log->Printf("[GetObjectDescription_ResultVariable] expression: %s",
expr_string.GetData());

ValueObjectSP result_sp;
EvaluateExpressionOptions eval_options;
eval_options.SetLanguage(lldb::eLanguageTypeSwift);
eval_options.SetResultIsInternal(true);
eval_options.SetGenerateDebugInfo(true);
eval_options.SetTimeout(g_po_function_timeout);
auto eval_result = process->GetTarget().EvaluateExpression(
expr_string.GetData(),
process->GetThreadList().GetSelectedThread()->GetSelectedFrame().get(),
result_sp, eval_options);

if (log) {
switch (eval_result) {
case eExpressionCompleted:
log->Printf("[GetObjectDescription_ResultVariable] eExpressionCompleted");
break;
case eExpressionSetupError:
log->Printf(
"[GetObjectDescription_ResultVariable] eExpressionSetupError");
break;
case eExpressionParseError:
log->Printf(
"[GetObjectDescription_ResultVariable] eExpressionParseError");
break;
case eExpressionDiscarded:
log->Printf("[GetObjectDescription_ResultVariable] eExpressionDiscarded");
break;
case eExpressionInterrupted:
log->Printf(
"[GetObjectDescription_ResultVariable] eExpressionInterrupted");
break;
case eExpressionHitBreakpoint:
log->Printf(
"[GetObjectDescription_ResultVariable] eExpressionHitBreakpoint");
break;
case eExpressionTimedOut:
log->Printf("[GetObjectDescription_ResultVariable] eExpressionTimedOut");
break;
case eExpressionResultUnavailable:
log->Printf(
"[GetObjectDescription_ResultVariable] eExpressionResultUnavailable");
break;
case eExpressionStoppedForDebug:
log->Printf(
"[GetObjectDescription_ResultVariable] eExpressionStoppedForDebug");
break;
}
}

// sanitize the result of the expression before moving forward
if (!result_sp) {
if (log)
log->Printf("[GetObjectDescription_ResultVariable] expression generated "
"no result");
return false;
}
if (result_sp->GetError().Fail()) {
if (log)
log->Printf("[GetObjectDescription_ResultVariable] expression generated "
"error: %s",
result_sp->GetError().AsCString());
return false;
}
if (false == result_sp->GetCompilerType().IsValid()) {
if (log)
log->Printf("[GetObjectDescription_ResultVariable] expression generated "
"invalid type");
return false;
}

lldb_private::formatters::StringPrinter::ReadStringAndDumpToStreamOptions
dump_options;
dump_options.SetEscapeNonPrintables(false).SetQuote('\0').SetPrefixToken(
nullptr);
if (lldb_private::formatters::swift::String_SummaryProvider(
*result_sp.get(), str, TypeSummaryOptions()
.SetLanguage(lldb::eLanguageTypeSwift)
.SetCapping(eTypeSummaryUncapped),
dump_options)) {
if (log)
log->Printf("[GetObjectDescription_ResultVariable] expression completed "
"successfully");
return true;
} else {
if (log)
log->Printf("[GetObjectDescription_ResultVariable] expression generated "
"invalid string data");
return false;
}
}

static bool GetObjectDescription_ObjectReference(Process *process, Stream &str,
ValueObject &object) {
Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_DATAFORMATTERS));

StreamString expr_string;
expr_string.Printf("Swift._DebuggerSupport.stringForPrintObject(Swift."
"unsafeBitCast(0x%" PRIx64 ", to: AnyObject.self))",
object.GetValueAsUnsigned(0));

if (log)
log->Printf("[GetObjectDescription_ObjectReference] expression: %s",
expr_string.GetData());

ValueObjectSP result_sp;
EvaluateExpressionOptions eval_options;
eval_options.SetLanguage(lldb::eLanguageTypeSwift);
eval_options.SetResultIsInternal(true);
eval_options.SetGenerateDebugInfo(true);
eval_options.SetTimeout(g_po_function_timeout);
auto eval_result = process->GetTarget().EvaluateExpression(
expr_string.GetData(),
process->GetThreadList().GetSelectedThread()->GetSelectedFrame().get(),
result_sp, eval_options);

if (log) {
switch (eval_result) {
case eExpressionCompleted:
log->Printf(
"[GetObjectDescription_ObjectReference] eExpressionCompleted");
break;
case eExpressionSetupError:
log->Printf(
"[GetObjectDescription_ObjectReference] eExpressionSetupError");
break;
case eExpressionParseError:
log->Printf(
"[GetObjectDescription_ObjectReference] eExpressionParseError");
break;
case eExpressionDiscarded:
log->Printf(
"[GetObjectDescription_ObjectReference] eExpressionDiscarded");
break;
case eExpressionInterrupted:
log->Printf(
"[GetObjectDescription_ObjectReference] eExpressionInterrupted");
break;
case eExpressionHitBreakpoint:
log->Printf(
"[GetObjectDescription_ObjectReference] eExpressionHitBreakpoint");
break;
case eExpressionTimedOut:
log->Printf("[GetObjectDescription_ObjectReference] eExpressionTimedOut");
break;
case eExpressionResultUnavailable:
log->Printf("[GetObjectDescription_ObjectReference] "
"eExpressionResultUnavailable");
break;
case eExpressionStoppedForDebug:
log->Printf(
"[GetObjectDescription_ObjectReference] eExpressionStoppedForDebug");
break;
}
}

// sanitize the result of the expression before moving forward
if (!result_sp) {
if (log)
log->Printf("[GetObjectDescription_ObjectReference] expression generated "
"no result");
return false;
}
if (result_sp->GetError().Fail()) {
if (log)
log->Printf("[GetObjectDescription_ObjectReference] expression generated "
"error: %s",
result_sp->GetError().AsCString());
return false;
}
if (false == result_sp->GetCompilerType().IsValid()) {
if (log)
log->Printf("[GetObjectDescription_ObjectReference] expression generated "
"invalid type");
return false;
}

lldb_private::formatters::StringPrinter::ReadStringAndDumpToStreamOptions
dump_options;
dump_options.SetEscapeNonPrintables(false).SetQuote('\0').SetPrefixToken(
nullptr);
if (lldb_private::formatters::swift::String_SummaryProvider(
*result_sp.get(), str, TypeSummaryOptions()
.SetLanguage(lldb::eLanguageTypeSwift)
.SetCapping(eTypeSummaryUncapped),
dump_options)) {
if (log)
log->Printf("[GetObjectDescription_ObjectReference] expression completed "
"successfully");
return true;
} else {
if (log)
log->Printf("[GetObjectDescription_ObjectReference] expression generated "
"invalid string data");
return false;
}
}

static const ExecutionContextRef *GetSwiftExeCtx(ValueObject &valobj) {
return (valobj.GetPreferredDisplayLanguage() == eLanguageTypeSwift)
? &valobj.GetExecutionContextRef()
Expand Down Expand Up @@ -440,12 +649,61 @@ static bool GetObjectDescription_ObjectCopy(SwiftLanguageRuntime *runtime,
return true;
}

static bool IsSwiftResultVariable(ConstString name) {
if (name) {
llvm::StringRef name_sr(name.GetStringRef());
if (name_sr.size() > 2 &&
(name_sr.startswith("$R") || name_sr.startswith("$E")) &&
::isdigit(name_sr[2]))
return true;
}
return false;
}

static bool IsSwiftReferenceType(ValueObject &object) {
CompilerType object_type(object.GetCompilerType());
if (llvm::dyn_cast_or_null<SwiftASTContext>(object_type.GetTypeSystem())) {
Flags type_flags(object_type.GetTypeInfo());
if (type_flags.AllSet(eTypeIsClass | eTypeHasValue |
eTypeInstanceIsPointer))
return true;
}
return false;
}

bool SwiftLanguageRuntime::GetObjectDescription(Stream &str,
ValueObject &object) {
if (object.IsUninitializedReference()) {
str.Printf("<uninitialized>");
return true;
}

if (::IsSwiftResultVariable(object.GetName())) {
// if this thing is a Swift expression result variable, it has two
// properties:
// a) its name is something we can refer to in expressions for free
// b) its type may be something we can't actually talk about in expressions
// so, just use the result variable's name in the expression and be done
// with it
StreamString probe_stream;
if (GetObjectDescription_ResultVariable(m_process, probe_stream, object)) {
str.Printf("%s", probe_stream.GetData());
return true;
}
} else if (::IsSwiftReferenceType(object)) {
// if this is a Swift class, it has two properties:
// a) we do not need its type name, AnyObject is just as good
// b) its value is something we can directly use to refer to it
// so, just use the ValueObject's pointer-value and be done with it
StreamString probe_stream;
if (GetObjectDescription_ObjectReference(m_process, probe_stream, object)) {
str.Printf("%s", probe_stream.GetData());
return true;
}
}

// in general, don't try to use the name of the ValueObject as it might end up
// referring to the wrong thing
return GetObjectDescription_ObjectCopy(this, m_process, str, object);
}

Expand Down