Skip to content

Commit 563a8f6

Browse files
committed
[lldb] Add synthetic formatter for Swift.CheckedContinuation
(cherry-picked from commit acc4f5e)
1 parent de4ceae commit 563a8f6

File tree

5 files changed

+128
-3
lines changed

5 files changed

+128
-3
lines changed

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

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1021,6 +1021,92 @@ class UnsafeContinuationSyntheticFrontEnd : public SyntheticChildrenFrontEnd {
10211021
ValueObjectSP m_task_sp;
10221022
};
10231023

1024+
class CheckedContinuationSyntheticFrontEnd : public SyntheticChildrenFrontEnd {
1025+
public:
1026+
CheckedContinuationSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp)
1027+
: SyntheticChildrenFrontEnd(*valobj_sp.get()) {
1028+
bool is_64bit = false;
1029+
if (auto target_sp = m_backend.GetTargetSP())
1030+
is_64bit = target_sp->GetArchitecture().GetTriple().isArch64Bit();
1031+
1032+
std::optional<uint32_t> concurrency_version;
1033+
if (auto process_sp = m_backend.GetProcessSP())
1034+
concurrency_version =
1035+
SwiftLanguageRuntime::FindConcurrencyDebugVersion(*process_sp);
1036+
1037+
bool is_supported_target = is_64bit && concurrency_version.value_or(0) == 1;
1038+
if (!is_supported_target)
1039+
return;
1040+
1041+
if (auto target_sp = m_backend.GetTargetSP()) {
1042+
if (auto ts_or_err =
1043+
target_sp->GetScratchTypeSystemForLanguage(eLanguageTypeSwift)) {
1044+
if (auto *ts = llvm::dyn_cast_or_null<TypeSystemSwiftTypeRef>(
1045+
ts_or_err->get()))
1046+
// TypeMangling for "Swift.UnsafeCurrentTask"
1047+
m_task_type = ts->GetTypeFromMangledTypename(ConstString("$sSctD"));
1048+
} else {
1049+
LLDB_LOG_ERROR(
1050+
GetLog(LLDBLog::DataFormatters | LLDBLog::Types),
1051+
ts_or_err.takeError(),
1052+
"could not get Swift type system for CheckedContinuation "
1053+
"synthetic provider: {0}");
1054+
}
1055+
}
1056+
}
1057+
1058+
llvm::Expected<uint32_t> CalculateNumChildren() override {
1059+
if (!m_task_sp)
1060+
return m_backend.GetNumChildren();
1061+
1062+
return 1;
1063+
}
1064+
1065+
bool MightHaveChildren() override { return true; }
1066+
1067+
lldb::ValueObjectSP GetChildAtIndex(uint32_t idx) override {
1068+
if (!m_task_sp)
1069+
return m_backend.GetChildAtIndex(idx);
1070+
1071+
if (idx == 0)
1072+
return m_task_sp;
1073+
1074+
return {};
1075+
}
1076+
1077+
size_t GetIndexOfChildWithName(ConstString name) override {
1078+
if (!m_task_sp)
1079+
return m_backend.GetIndexOfChildWithName(name);
1080+
1081+
if (name == "task")
1082+
return 0;
1083+
1084+
return UINT32_MAX;
1085+
}
1086+
1087+
lldb::ChildCacheState Update() override {
1088+
if (!m_task_type)
1089+
return ChildCacheState::eReuse;
1090+
1091+
size_t canary_task_offset = 0x10;
1092+
Status status;
1093+
if (auto canary_sp = m_backend.GetChildMemberWithName("canary"))
1094+
if (addr_t canary_addr = canary_sp->GetValueAsUnsigned(0))
1095+
if (addr_t task_addr = m_backend.GetProcessSP()->ReadPointerFromMemory(
1096+
canary_addr + canary_task_offset, status))
1097+
m_task_sp = ValueObject::CreateValueObjectFromAddress(
1098+
"task", task_addr, m_backend.GetExecutionContextRef(),
1099+
m_task_type, false);
1100+
if (auto synthetic_sp = m_task_sp->GetSyntheticValue())
1101+
m_task_sp = synthetic_sp;
1102+
return ChildCacheState::eRefetch;
1103+
}
1104+
1105+
private:
1106+
CompilerType m_task_type;
1107+
ValueObjectSP m_task_sp;
1108+
};
1109+
10241110
class TaskGroupSyntheticFrontEnd : public SyntheticChildrenFrontEnd {
10251111
public:
10261112
TaskGroupSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp)
@@ -1276,6 +1362,14 @@ lldb_private::formatters::swift::UnsafeContinuationSyntheticFrontEndCreator(
12761362
return new UnsafeContinuationSyntheticFrontEnd(valobj_sp);
12771363
}
12781364

1365+
SyntheticChildrenFrontEnd *
1366+
lldb_private::formatters::swift::CheckedContinuationSyntheticFrontEndCreator(
1367+
CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp) {
1368+
if (!valobj_sp)
1369+
return nullptr;
1370+
return new CheckedContinuationSyntheticFrontEnd(valobj_sp);
1371+
}
1372+
12791373
SyntheticChildrenFrontEnd *
12801374
lldb_private::formatters::swift::TaskGroupSyntheticFrontEndCreator(
12811375
CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp) {

lldb/source/Plugins/Language/Swift/SwiftFormatters.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,10 @@ SyntheticChildrenFrontEnd *
124124
UnsafeContinuationSyntheticFrontEndCreator(CXXSyntheticChildren *,
125125
lldb::ValueObjectSP);
126126

127+
SyntheticChildrenFrontEnd *
128+
CheckedContinuationSyntheticFrontEndCreator(CXXSyntheticChildren *,
129+
lldb::ValueObjectSP);
130+
127131
SyntheticChildrenFrontEnd *
128132
TaskGroupSyntheticFrontEndCreator(CXXSyntheticChildren *, lldb::ValueObjectSP);
129133
}

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

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -422,6 +422,12 @@ static void LoadSwiftFormatters(lldb::TypeCategoryImplSP swift_category_sp) {
422422
"Swift.UnsafeContinuation synthetic children",
423423
ConstString("^Swift\\.UnsafeContinuation<.+,.+>"),
424424
synth_flags, true);
425+
AddCXXSynthetic(swift_category_sp,
426+
lldb_private::formatters::swift::
427+
CheckedContinuationSyntheticFrontEndCreator,
428+
"Swift.CheckedContinuation synthetic children",
429+
ConstString("^Swift\\.CheckedContinuation<.+,.+>"),
430+
synth_flags, true);
425431
AddCXXSynthetic(
426432
swift_category_sp,
427433
lldb_private::formatters::swift::TaskGroupSyntheticFrontEndCreator,

lldb/test/API/lang/swift/async/continuations/TestSwiftContinuationSynthetic.py

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,11 @@
77
class TestCase(TestBase):
88

99
@swiftTest
10-
def test_value_printing(self):
10+
def test_unsafe_continuation_printing(self):
1111
"""Print an UnsafeContinuation and verify its children."""
1212
self.build()
1313
lldbutil.run_to_source_breakpoint(
14-
self, "break here", lldb.SBFileSpec("main.swift")
14+
self, "break unsafe continuation", lldb.SBFileSpec("main.swift")
1515
)
1616
self.expect(
1717
"v cont",
@@ -21,3 +21,19 @@ def test_value_printing(self):
2121
"isFuture = true",
2222
],
2323
)
24+
25+
@swiftTest
26+
def test_checked_continuation_printing(self):
27+
"""Print an CheckedContinuation and verify its children."""
28+
self.build()
29+
lldbutil.run_to_source_breakpoint(
30+
self, "break checked continuation", lldb.SBFileSpec("main.swift")
31+
)
32+
self.expect(
33+
"v cont",
34+
substrs=[
35+
"(CheckedContinuation<Int, Never>) cont = {",
36+
"task = {",
37+
"isFuture = true",
38+
],
39+
)
Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,13 @@
11
@main struct Main {
22
static func main() async {
33
await withUnsafeContinuation { (cont: UnsafeContinuation<Void, Never>) in
4-
print("break here")
4+
print("break unsafe continuation")
55
cont.resume()
66
}
7+
8+
_ = await withCheckedContinuation { (cont: CheckedContinuation<Int, Never>) in
9+
print("break checked continuation")
10+
cont.resume(returning: 15)
11+
}
712
}
813
}

0 commit comments

Comments
 (0)