Skip to content

Commit d0fbe03

Browse files
committed
Display generic function type parameters in backtraces.
This patch changes the behavior of SwiftLanguage::GetFunctionDisplayName() so it now: - (if exe_ctx && sc available) does generic parameter binding - (if only sc availble) shows the archetype name - the letter τ will now only appear if neither no context whatsover is available - (drive by) omits self rdar://126883922
1 parent e4cf944 commit d0fbe03

File tree

10 files changed

+118
-56
lines changed

10 files changed

+118
-56
lines changed

lldb/include/lldb/Symbol/Function.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -537,7 +537,7 @@ class Function : public UserID, public SymbolContextScope {
537537

538538
ConstString GetNameNoArguments(const SymbolContext *sc = nullptr) const;
539539

540-
ConstString GetDisplayName(const SymbolContext *sc = nullptr) const;
540+
ConstString GetDisplayName() const;
541541

542542
const Mangled &GetMangled() const { return m_mangled; }
543543

lldb/source/Plugins/Language/Swift/SwiftLanguage.cpp

Lines changed: 20 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1207,7 +1207,8 @@ bool SwiftLanguage::IsSourceFile(llvm::StringRef file_path) const {
12071207
return file_path.endswith(".swift");
12081208
}
12091209

1210-
std::vector<FormattersMatchCandidate> SwiftLanguage::GetPossibleFormattersMatches(
1210+
std::vector<FormattersMatchCandidate>
1211+
SwiftLanguage::GetPossibleFormattersMatches(
12111212
ValueObject &valobj, lldb::DynamicValueType use_dynamic) {
12121213
std::vector<FormattersMatchCandidate> result;
12131214

@@ -1643,21 +1644,24 @@ bool SwiftLanguage::GetFunctionDisplayName(
16431644
return false;
16441645
if (sc->function->GetLanguage() != eLanguageTypeSwift)
16451646
return false;
1646-
ConstString cs = sc->function->GetDisplayName(sc);
1647-
if (!cs)
1647+
std::string display_name = SwiftLanguageRuntime::DemangleSymbolAsString(
1648+
sc->function->GetMangled().GetMangledName().GetStringRef(),
1649+
SwiftLanguageRuntime::eSimplified, sc, exe_ctx);
1650+
if (display_name.empty())
16481651
return false;
1649-
s.Printf("%s", cs.AsCString());
1652+
s << display_name;
16501653
return true;
16511654
}
16521655
case Language::FunctionNameRepresentation::eNameWithArgs: {
16531656
if (!sc->function)
16541657
return false;
16551658
if (sc->function->GetLanguage() != eLanguageTypeSwift)
16561659
return false;
1657-
ConstString cs = sc->function->GetDisplayName(sc);
1658-
if (!cs)
1660+
std::string display_name = SwiftLanguageRuntime::DemangleSymbolAsString(
1661+
sc->function->GetMangled().GetMangledName().GetStringRef(),
1662+
SwiftLanguageRuntime::eSimplified, sc, exe_ctx);
1663+
if (display_name.empty())
16591664
return false;
1660-
const char *cstr = cs.AsCString();
16611665
ExecutionContextScope *exe_scope =
16621666
exe_ctx ? exe_ctx->GetBestExecutionContextScope() : NULL;
16631667
const InlineFunctionInfo *inline_info = NULL;
@@ -1680,25 +1684,26 @@ bool SwiftLanguage::GetFunctionDisplayName(
16801684
}
16811685

16821686
if (inline_info) {
1683-
s.PutCString(cstr);
1687+
s << display_name;
16841688
s.PutCString(" [inlined] ");
1685-
cstr = inline_info->GetName().GetCString();
1689+
display_name = inline_info->GetName();
16861690
}
16871691

16881692
VariableList args;
16891693
if (variable_list_sp)
16901694
variable_list_sp->AppendVariablesWithScope(eValueTypeVariableArgument,
16911695
args);
16921696
if (args.GetSize() == 0) {
1693-
s.PutCString(cstr);
1697+
s << display_name;
16941698
return true;
16951699
}
1700+
const char *cstr = display_name.data();
16961701
const char *open_paren = strchr(cstr, '(');
16971702
const char *close_paren = nullptr;
16981703
const char *generic = strchr(cstr, '<');
1699-
// if before the arguments list begins there is a template sign
1704+
// If before the arguments list begins there is a template sign
17001705
// then scan to the end of the generic args before you try to find
1701-
// the arguments list
1706+
// the arguments list.
17021707
if (generic && open_paren && generic < open_paren) {
17031708
int generic_depth = 1;
17041709
++generic;
@@ -1720,7 +1725,7 @@ bool SwiftLanguage::GetFunctionDisplayName(
17201725
if (open_paren)
17211726
s.Write(cstr, open_paren - cstr + 1);
17221727
else {
1723-
s.PutCString(cstr);
1728+
s << display_name;
17241729
s.PutChar('(');
17251730
}
17261731
const size_t num_args = args.GetSize();
@@ -1730,6 +1735,8 @@ bool SwiftLanguage::GetFunctionDisplayName(
17301735
VariableSP var_sp(args.GetVariableAtIndex(arg_idx));
17311736
ValueObjectSP var_value_sp(
17321737
ValueObjectVariable::Create(exe_scope, var_sp));
1738+
if (!var_sp || !var_value_sp || var_sp->IsArtificial())
1739+
continue;
17331740
StreamString ss;
17341741
const char *var_representation = nullptr;
17351742
const char *var_name = var_value_sp->GetName().GetCString();

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

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -141,9 +141,10 @@ class SwiftLanguageRuntime : public LanguageRuntime {
141141
IsSwiftAsyncAwaitResumePartialFunctionSymbol(llvm::StringRef name);
142142

143143
enum DemangleMode { eSimplified, eTypeName, eDisplayTypeName };
144-
static std::string DemangleSymbolAsString(llvm::StringRef symbol,
145-
DemangleMode mode,
146-
const SymbolContext *sc = nullptr);
144+
static std::string
145+
DemangleSymbolAsString(llvm::StringRef symbol, DemangleMode mode,
146+
const SymbolContext *sc = nullptr,
147+
const ExecutionContext *exe_ctx = nullptr);
147148

148149
/// Demangle a symbol to a swift::Demangle node tree.
149150
///
@@ -246,7 +247,7 @@ class SwiftLanguageRuntime : public LanguageRuntime {
246247
/// Populate a map with the names of all archetypes in a function's generic
247248
/// context.
248249
static void GetGenericParameterNamesForFunction(
249-
const SymbolContext &sc,
250+
const SymbolContext &sc, const ExecutionContext *exe_ctx,
250251
llvm::DenseMap<ArchetypePath, llvm::StringRef> &dict);
251252

252253
/// Invoke callback for each DependentGenericParamType.

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

Lines changed: 38 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -642,7 +642,7 @@ bool SwiftLanguageRuntime::IsSwiftMangledName(llvm::StringRef name) {
642642
}
643643

644644
void SwiftLanguageRuntime::GetGenericParameterNamesForFunction(
645-
const SymbolContext &const_sc,
645+
const SymbolContext &const_sc, const ExecutionContext *exe_ctx,
646646
llvm::DenseMap<SwiftLanguageRuntime::ArchetypePath, StringRef> &dict) {
647647
// This terrifying cast avoids having too many differences with llvm.org.
648648
SymbolContext &sc = const_cast<SymbolContext &>(const_sc);
@@ -682,16 +682,47 @@ void SwiftLanguageRuntime::GetGenericParameterNamesForFunction(
682682
if (!name.empty())
683683
continue;
684684

685-
Type *archetype = var_sp->GetType();
686-
if (!archetype)
687-
continue;
685+
ConstString type_name;
688686

689-
dict.insert({{depth, index}, archetype->GetName().GetStringRef()});
687+
// Try to get bind the dynamic type from the exe_ctx.
688+
while (exe_ctx) {
689+
auto *frame = exe_ctx->GetFramePtr();
690+
auto *target = exe_ctx->GetTargetPtr();
691+
auto *process = exe_ctx->GetProcessPtr();
692+
auto *runtime = SwiftLanguageRuntime::Get(process);
693+
if (!frame || !target || !process || !runtime)
694+
break;
695+
auto type_system_or_err =
696+
target->GetScratchTypeSystemForLanguage(eLanguageTypeSwift);
697+
if (!type_system_or_err) {
698+
llvm::consumeError(type_system_or_err.takeError());
699+
break;
700+
}
701+
auto ts =
702+
llvm::dyn_cast_or_null<TypeSystemSwift>(type_system_or_err->get());
703+
if (!ts)
704+
break;
705+
CompilerType generic_type = ts->CreateGenericTypeParamType(depth, index);
706+
CompilerType bound_type =
707+
runtime->BindGenericTypeParameters(*frame, generic_type);
708+
type_name = bound_type.GetDisplayTypeName();
709+
break;
710+
}
711+
712+
// Otherwise return the static archetype name from the debug info.
713+
if (!type_name) {
714+
Type *archetype = var_sp->GetType();
715+
if (!archetype)
716+
continue;
717+
type_name = archetype->GetName();
718+
}
719+
dict.insert({{depth, index}, type_name.GetStringRef()});
690720
}
691721
}
692722

693723
std::string SwiftLanguageRuntime::DemangleSymbolAsString(
694-
StringRef symbol, DemangleMode mode, const SymbolContext *sc) {
724+
StringRef symbol, DemangleMode mode, const SymbolContext *sc,
725+
const ExecutionContext *exe_ctx) {
695726
bool did_init = false;
696727
llvm::DenseMap<ArchetypePath, StringRef> dict;
697728
swift::Demangle::DemangleOptions options;
@@ -723,7 +754,7 @@ std::string SwiftLanguageRuntime::DemangleSymbolAsString(
723754
// Resolve generic parameters in the current function.
724755
options.GenericParameterName = [&](uint64_t depth, uint64_t index) {
725756
if (!did_init) {
726-
GetGenericParameterNamesForFunction(*sc, dict);
757+
GetGenericParameterNamesForFunction(*sc, exe_ctx, dict);
727758
did_init = true;
728759
}
729760
auto it = dict.find({depth, index});

lldb/source/Plugins/TypeSystem/Swift/SwiftASTContext.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6004,7 +6004,8 @@ GetArchetypeNames(swift::Type swift_type, swift::ASTContext &ast_ctx,
60046004
return dict;
60056005

60066006
llvm::DenseMap<std::pair<uint64_t, uint64_t>, StringRef> names;
6007-
SwiftLanguageRuntime::GetGenericParameterNamesForFunction(*sc, names);
6007+
SwiftLanguageRuntime::GetGenericParameterNamesForFunction(*sc, nullptr,
6008+
names);
60086009
swift_type.visit([&](swift::Type type) {
60096010
if (!type->isTypeParameter() || dict.count(type->getCanonicalType()))
60106011
return;

lldb/source/Symbol/Function.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -498,10 +498,10 @@ bool Function::IsTopLevelFunction() {
498498
return result;
499499
}
500500

501-
ConstString Function::GetDisplayName(const SymbolContext *sc) const {
501+
ConstString Function::GetDisplayName() const {
502502
if (!m_mangled)
503503
return GetName();
504-
return m_mangled.GetDisplayDemangledName(sc);
504+
return m_mangled.GetDisplayDemangledName();
505505
}
506506

507507
CompilerDeclContext Function::GetDeclContext() {

lldb/test/API/lang/swift/bt_printing/TestSwiftBacktracePrinting.py

Lines changed: 4 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -24,35 +24,11 @@ class TestSwiftBacktracePrinting(TestBase):
2424
def test_swift_backtrace_printing(self):
2525
"""Test printing Swift backtrace"""
2626
self.build()
27-
self.do_test()
27+
target, process, thread, bkpt = lldbutil.run_to_source_breakpoint(
28+
self, 'break here', lldb.SBFileSpec('main.swift'))
2829

29-
def setUp(self):
30-
TestBase.setUp(self)
31-
self.main_source = "main.swift"
32-
self.main_source_spec = lldb.SBFileSpec(self.main_source)
33-
34-
def do_test(self):
35-
"""Test printing Swift backtrace"""
36-
exe_name = "a.out"
37-
exe = self.getBuildArtifact(exe_name)
38-
39-
# Create the target
40-
target = self.dbg.CreateTarget(exe)
41-
self.assertTrue(target, VALID_TARGET)
42-
43-
# Set the breakpoints
44-
breakpoint = target.BreakpointCreateBySourceRegex(
45-
'break here', self.main_source_spec)
46-
self.assertTrue(breakpoint.GetNumLocations() > 0, VALID_BREAKPOINT)
47-
48-
# Launch the process, and do not stop at the entry point.
49-
process = target.LaunchSimple(None, None, os.getcwd())
50-
51-
self.assertTrue(process, PROCESS_IS_VALID)
52-
53-
self.expect("bt", substrs=['h<T>',
54-
# FIXME: rdar://65956239 U and T are not resolved!
55-
'g<U, T>', 'pair', # '12', "Hello world",
30+
self.expect("bt", substrs=['h<Int>',
31+
'g<String, Int>', 'pair', # FIXME: values are still wrong!
5632
'arg1=12', 'arg2="Hello world"'])
5733
self.expect("breakpoint set -p other", substrs=['g<U, T>'])
5834

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
SWIFT_SOURCES := main.swift
2+
3+
include Makefile.rules
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import lldb
2+
from lldbsuite.test.decorators import *
3+
import lldbsuite.test.lldbtest as lldbtest
4+
import lldbsuite.test.lldbutil as lldbutil
5+
import unittest2
6+
7+
8+
class TestSwiftGenericFunction(lldbtest.TestBase):
9+
@swiftTest
10+
def test(self):
11+
"""Test display of generic function names"""
12+
self.build()
13+
target, process, thread, bkpt = lldbutil.run_to_name_breakpoint(
14+
self, 'f')
15+
16+
# Live process:
17+
stream = lldb.SBStream()
18+
self.frame().GetDescription(stream)
19+
desc = stream.GetData()
20+
# It's debatable whether C's generic parameter should be displayed here.
21+
self.assertIn("C.f<Int>(t=1, u=2)", desc)
22+
23+
# Dead process + debug info:
24+
process.Kill()
25+
stream = lldb.SBStream()
26+
bkpt.GetLocationAtIndex(0).GetDescription(stream, 1)
27+
desc = stream.GetData()
28+
self.assertIn("C.f<T>(T, U) -> ()", desc)
29+
30+
# Demangling only:
31+
fs = target.FindFunctions("f")
32+
self.assertTrue(fs)
33+
desc = fs[0].GetFunction().GetDisplayName()
34+
self.assertIn("C.f<τ_0_0>(_:_:)", desc)
35+
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
class C<T>
2+
{
3+
func f<U> (_ t: T, _ u: U) {
4+
print("break here")
5+
}
6+
}
7+
8+
C<Int>().f(1, 2 as Float)

0 commit comments

Comments
 (0)