-
Notifications
You must be signed in to change notification settings - Fork 341
[lldb] Extract logic out of GetFunctionDisplayName into a helper function #10766
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
base: swift/release/6.2
Are you sure you want to change the base?
Changes from all commits
9ec61f0
06cefd5
e969b6c
1c2f362
c2178ee
34c2dd9
c6f292e
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -1704,30 +1704,16 @@ bool SwiftLanguage::GetFunctionDisplayName( | |
// No need to customize this. | ||
return false; | ||
case Language::FunctionNameRepresentation::eNameWithNoArgs: { | ||
if (!sc.function) | ||
return false; | ||
if (sc.function->GetLanguage() != eLanguageTypeSwift) | ||
return false; | ||
std::string display_name = SwiftLanguageRuntime::DemangleSymbolAsString( | ||
sc.function->GetMangled().GetMangledName().GetStringRef(), | ||
SwiftLanguageRuntime::eSimplified, &sc, exe_ctx); | ||
std::string display_name = GetFunctionName(sc, exe_ctx); | ||
if (display_name.empty()) | ||
return false; | ||
s << display_name; | ||
return true; | ||
} | ||
case Language::FunctionNameRepresentation::eNameWithArgs: { | ||
if (!sc.function) | ||
return false; | ||
if (sc.function->GetLanguage() != eLanguageTypeSwift) | ||
return false; | ||
std::string display_name = SwiftLanguageRuntime::DemangleSymbolAsString( | ||
sc.function->GetMangled().GetMangledName().GetStringRef(), | ||
SwiftLanguageRuntime::eSimplified, &sc, exe_ctx); | ||
std::string display_name = GetFunctionName(sc, exe_ctx); | ||
if (display_name.empty()) | ||
return false; | ||
ExecutionContextScope *exe_scope = | ||
exe_ctx ? exe_ctx->GetBestExecutionContextScope() : NULL; | ||
const InlineFunctionInfo *inline_info = NULL; | ||
VariableListSP variable_list_sp; | ||
bool get_function_vars = true; | ||
|
@@ -1747,109 +1733,137 @@ bool SwiftLanguage::GetFunctionDisplayName( | |
sc.function->GetBlock(true).GetBlockVariableList(true); | ||
} | ||
|
||
if (inline_info) { | ||
s << display_name; | ||
s.PutCString(" [inlined] "); | ||
display_name = inline_info->GetName().GetString(); | ||
} | ||
|
||
VariableList args; | ||
if (variable_list_sp) | ||
variable_list_sp->AppendVariablesWithScope(eValueTypeVariableArgument, | ||
args); | ||
if (args.GetSize() == 0) { | ||
s << display_name; | ||
return true; | ||
|
||
s << display_name; | ||
if (inline_info) { | ||
s.PutCString(" [inlined] "); | ||
} | ||
const char *cstr = display_name.data(); | ||
const char *open_paren = strchr(cstr, '('); | ||
const char *close_paren = nullptr; | ||
const char *generic = strchr(cstr, '<'); | ||
// If before the arguments list begins there is a template sign | ||
// then scan to the end of the generic args before you try to find | ||
// the arguments list. | ||
if (generic && open_paren && generic < open_paren) { | ||
int generic_depth = 1; | ||
++generic; | ||
for (; *generic && generic_depth > 0; generic++) { | ||
if (*generic == '<') | ||
generic_depth++; | ||
if (*generic == '>') | ||
generic_depth--; | ||
} | ||
if (*generic) | ||
open_paren = strchr(generic, '('); | ||
else | ||
open_paren = nullptr; | ||
s << GetFunctionDisplayArgs(sc, args, exe_ctx); | ||
return true; | ||
} | ||
if (open_paren) { | ||
close_paren = strchr(open_paren, ')'); | ||
} | ||
return false; | ||
} | ||
|
||
if (open_paren) | ||
s.Write(cstr, open_paren - cstr + 1); | ||
else { | ||
s << display_name; | ||
s.PutChar('('); | ||
std::string SwiftLanguage::GetFunctionName(const SymbolContext &sc, | ||
const ExecutionContext *exe_ctx) { | ||
if (!sc.function) | ||
return {}; | ||
if (sc.function->GetLanguage() != eLanguageTypeSwift) | ||
return {}; | ||
std::string name = SwiftLanguageRuntime::DemangleSymbolAsString( | ||
sc.function->GetMangled().GetMangledName().GetStringRef(), | ||
SwiftLanguageRuntime::eSimplified, &sc, exe_ctx); | ||
if (name.empty()) | ||
return {}; | ||
const char *cstr = name.data(); | ||
const char *open_paren = strchr(cstr, '('); | ||
const char *generic = strchr(cstr, '<'); | ||
if (open_paren && generic && generic < open_paren) | ||
return std::string(cstr, generic); | ||
if (open_paren) | ||
return std::string(cstr, open_paren); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hmmm why is this new logic needed? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We didn't previously do this in the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I am a bit confused by the original implementation of the This additional logic is due to me splitting the the logic into 2 helper functions. Say we have Hence: no, we didn't previously do this in the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Oh I see. In that case, if |
||
return name; | ||
} | ||
|
||
std::string SwiftLanguage::GetFunctionDisplayArgs( | ||
const SymbolContext &sc, VariableList &args, | ||
const lldb_private::ExecutionContext *exe_ctx) { | ||
ExecutionContextScope *exe_scope = | ||
exe_ctx ? exe_ctx->GetBestExecutionContextScope() : NULL; | ||
std::string name = SwiftLanguageRuntime::DemangleSymbolAsString( | ||
sc.function->GetMangled().GetMangledName().GetStringRef(), | ||
SwiftLanguageRuntime::eSimplified, &sc, exe_ctx); | ||
lldb_private::StreamString s; | ||
const char *cstr = name.data(); | ||
const char *open_paren = strchr(cstr, '('); | ||
const char *close_paren = nullptr; | ||
const char *generic = strchr(cstr, '<'); | ||
// If before the arguments list begins there is a template sign | ||
// then scan to the end of the generic args before you try to find | ||
// the arguments list. | ||
const char *generic_start = generic; | ||
if (generic && open_paren && generic < open_paren) { | ||
int generic_depth = 1; | ||
++generic; | ||
for (; *generic && generic_depth > 0; generic++) { | ||
if (*generic == '<') | ||
generic_depth++; | ||
if (*generic == '>') | ||
generic_depth--; | ||
} | ||
const size_t num_args = args.GetSize(); | ||
for (size_t arg_idx = 0; arg_idx < num_args; ++arg_idx) { | ||
std::string buffer; | ||
|
||
VariableSP var_sp(args.GetVariableAtIndex(arg_idx)); | ||
ValueObjectSP var_value_sp( | ||
ValueObjectVariable::Create(exe_scope, var_sp)); | ||
if (!var_sp || !var_value_sp || var_sp->IsArtificial()) | ||
continue; | ||
StreamString ss; | ||
const char *var_representation = nullptr; | ||
const char *var_name = var_value_sp->GetName().GetCString(); | ||
if (var_value_sp->GetCompilerType().IsValid()) { | ||
if (var_value_sp && exe_scope->CalculateTarget()) | ||
var_value_sp = var_value_sp->GetQualifiedRepresentationIfAvailable( | ||
exe_scope->CalculateTarget() | ||
->TargetProperties::GetPreferDynamicValue(), | ||
exe_scope->CalculateTarget() | ||
->TargetProperties::GetEnableSyntheticValue()); | ||
if (var_value_sp->GetCompilerType().IsAggregateType() && | ||
DataVisualization::ShouldPrintAsOneLiner(*var_value_sp.get())) { | ||
static StringSummaryFormat format(TypeSummaryImpl::Flags() | ||
.SetHideItemNames(false) | ||
.SetShowMembersOneLiner(true), | ||
""); | ||
format.FormatObject(var_value_sp.get(), buffer, TypeSummaryOptions()); | ||
var_representation = buffer.c_str(); | ||
} else | ||
var_value_sp->DumpPrintableRepresentation( | ||
ss, | ||
ValueObject::ValueObjectRepresentationStyle:: | ||
eValueObjectRepresentationStyleSummary, | ||
eFormatDefault, | ||
ValueObject::PrintableRepresentationSpecialCases::eAllow, false); | ||
} | ||
if (ss.GetData() && ss.GetSize()) | ||
var_representation = ss.GetData(); | ||
if (arg_idx > 0) | ||
s.PutCString(", "); | ||
if (var_value_sp->GetError().Success()) { | ||
if (var_representation) | ||
s.Printf("%s=%s", var_name, var_representation); | ||
else | ||
s.Printf("%s=%s at %s", var_name, | ||
var_value_sp->GetTypeName().GetCString(), | ||
var_value_sp->GetLocationAsCString()); | ||
if (*generic) | ||
open_paren = strchr(generic, '('); | ||
else | ||
open_paren = nullptr; | ||
} | ||
if (open_paren) { | ||
close_paren = strchr(open_paren, ')'); | ||
} | ||
|
||
if (generic_start && generic_start < open_paren) | ||
s.Write(generic_start, open_paren - generic_start); | ||
s.PutChar('('); | ||
|
||
const size_t num_args = args.GetSize(); | ||
for (size_t arg_idx = 0; arg_idx < num_args; ++arg_idx) { | ||
std::string buffer; | ||
|
||
VariableSP var_sp(args.GetVariableAtIndex(arg_idx)); | ||
ValueObjectSP var_value_sp(ValueObjectVariable::Create(exe_scope, var_sp)); | ||
if (!var_sp || !var_value_sp || var_sp->IsArtificial()) | ||
continue; | ||
StreamString ss; | ||
const char *var_representation = nullptr; | ||
const char *var_name = var_value_sp->GetName().GetCString(); | ||
if (var_value_sp->GetCompilerType().IsValid()) { | ||
if (var_value_sp && exe_scope->CalculateTarget()) | ||
var_value_sp = var_value_sp->GetQualifiedRepresentationIfAvailable( | ||
exe_scope->CalculateTarget() | ||
->TargetProperties::GetPreferDynamicValue(), | ||
exe_scope->CalculateTarget() | ||
->TargetProperties::GetEnableSyntheticValue()); | ||
if (var_value_sp->GetCompilerType().IsAggregateType() && | ||
DataVisualization::ShouldPrintAsOneLiner(*var_value_sp.get())) { | ||
static StringSummaryFormat format(TypeSummaryImpl::Flags() | ||
.SetHideItemNames(false) | ||
.SetShowMembersOneLiner(true), | ||
""); | ||
format.FormatObject(var_value_sp.get(), buffer, TypeSummaryOptions()); | ||
var_representation = buffer.c_str(); | ||
} else | ||
s.Printf("%s=<unavailable>", var_name); | ||
var_value_sp->DumpPrintableRepresentation( | ||
ss, | ||
ValueObject::ValueObjectRepresentationStyle:: | ||
eValueObjectRepresentationStyleSummary, | ||
eFormatDefault, | ||
ValueObject::PrintableRepresentationSpecialCases::eAllow, false); | ||
} | ||
|
||
if (close_paren) | ||
s.PutCString(close_paren); | ||
else | ||
s.PutChar(')'); | ||
} | ||
return true; | ||
if (ss.GetData() && ss.GetSize()) | ||
var_representation = ss.GetData(); | ||
if (arg_idx > 0) | ||
s.PutCString(", "); | ||
if (var_value_sp->GetError().Success()) { | ||
if (var_representation) | ||
s.Printf("%s=%s", var_name, var_representation); | ||
else | ||
s.Printf("%s=%s at %s", var_name, | ||
var_value_sp->GetTypeName().GetCString(), | ||
var_value_sp->GetLocationAsCString()); | ||
} else | ||
s.Printf("%s=<unavailable>", var_name); | ||
} | ||
return false; | ||
|
||
if (close_paren) | ||
s.PutCString(close_paren); | ||
else | ||
s.PutChar(')'); | ||
|
||
return s.GetString().str(); | ||
} | ||
|
||
void SwiftLanguage::GetExceptionResolverDescription(bool catch_on, | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
# XFAIL: target-windows | ||
Michael137 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
# Test Swift function name printing in backtraces. | ||
|
||
# RUN: split-file %s %t | ||
# RUN: %target-swiftc -g %t/main.swift -o %t.out | ||
# RUN: %lldb -x -b -s %t/commands.input %t.out -o exit 2>&1 \ | ||
# RUN: | FileCheck %s | ||
|
||
#--- main.swift | ||
func foo() async -> Int { | ||
return await try! bar(a: 1, b: 1) | ||
} | ||
|
||
var res = { | ||
(index: Int) -> Int in | ||
return index + 10 | ||
}(1) | ||
|
||
fileprivate func bar(a: Int, b: Int) async throws -> Int { | ||
var baz = Baz(baz: 1) | ||
return res + a + b + Foo.foo_(a: baz) | ||
} | ||
|
||
struct Foo { | ||
let foo: Int | ||
static func foo_<T>(a: T) -> Int { | ||
var a_ = a as! Baz | ||
return a_.qux(a: 1) | ||
} | ||
} | ||
|
||
struct Baz { | ||
var baz: Int | ||
mutating func qux<T>(a: T) -> Int { | ||
baz += 1 | ||
return baz | ||
} | ||
} | ||
|
||
await foo() | ||
|
||
#--- commands.input | ||
b qux | ||
|
||
run | ||
bt | ||
|
||
# CHECK: `Baz.qux<Int>(a=1) | ||
# CHECK: `static Foo.foo_<main.Baz>(a=(baz = 1)) | ||
# CHECK: `bar(a=1, b=1) | ||
# CHECK: `foo() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In llvm#135343 I added a
SymbolContext::GetPossiblyInlinedFunctionName
. We decided the[inlined]
format was a bit too noisy.Could we clean up the Swift plugin to use that functionality?