Skip to content

Commit 3307906

Browse files
[lldb][swift] Increase number of Rows inspected when unwinding async functions (#10698)
We were overly conservatives in our initial estimations: if callee saved registers are used, they are usually spilled first, increasing the number of rows in the prologue. This also revealed a bug in computing the offset of a vector iterator: ``` - int row_idx = fp_locs.end() - it; + int row_idx = it - fp_locs.begin(); ``` Testing this is unfortunately difficult: a way of forcing register spilling is required. For now, this commit tweaks one of the existing tests in a way that seems to reliably spill more registers, but there are no guarantees this will continue to be the case. Other testing mechanisms need to be created.
1 parent f704129 commit 3307906

File tree

3 files changed

+13
-5
lines changed

3 files changed

+13
-5
lines changed

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

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2588,9 +2588,13 @@ GetFrameSetupInfo(UnwindPlan &unwind_plan, RegisterContext &regctx) {
25882588
if (!fp_unwind_regdomain)
25892589
return fp_unwind_regdomain.takeError();
25902590

2591-
// Look at the first few (4) rows of the plan and store FP's location.
2592-
const int upper_bound = std::min(4, unwind_plan.GetRowCount());
2593-
llvm::SmallVector<AbstractRegisterLocation, 4> fp_locs;
2591+
// Look at the first few (12) rows of the plan and store FP's location.
2592+
// This number is based on AAPCS, with 10 callee-saved GPRs and 8 floating
2593+
// point registers. When STP instructions are used, the plan would have one
2594+
// initial row, nine rows of saving callee-saved registers, and two standard
2595+
// prologue rows (fp+lr and sp).
2596+
const int upper_bound = std::min(12, unwind_plan.GetRowCount());
2597+
llvm::SmallVector<AbstractRegisterLocation, 12> fp_locs;
25942598
for (int row_idx = 0; row_idx < upper_bound; row_idx++) {
25952599
RowSP row = unwind_plan.GetRowAtIndex(row_idx);
25962600
AbstractRegisterLocation regloc;
@@ -2617,7 +2621,7 @@ GetFrameSetupInfo(UnwindPlan &unwind_plan, RegisterContext &regctx) {
26172621
// Use subsequent row, if available.
26182622
// Pointer auth may introduce more instructions, but they don't affect the
26192623
// unwinder rows / store to the stack.
2620-
int row_idx = fp_locs.end() - it;
2624+
int row_idx = it - fp_locs.begin();
26212625
int next_row_idx = row_idx + 1;
26222626

26232627
// If subsequent row is invalid, approximate through current row.

lldb/test/API/lang/swift/async/stepping/step_over_lots_of_tasks/TestSwiftAsyncSteppingManyTasks.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ def test_step_over_top_level_fibonacci(self):
5555
fib_bp.SetEnabled(False)
5656

5757
fib_first_line = thread_in_fib.frames[0].GetLineEntry().GetLine()
58-
num_lines_fib = 5
58+
num_lines_fib = 7
5959
for line_offset in range(1, num_lines_fib):
6060
thread_in_fib.StepOver()
6161
self.assertEqual(process.GetSelectedThread(), thread_in_fib)

lldb/test/API/lang/swift/async/stepping/step_over_lots_of_tasks/main.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,17 @@
1212

1313
func fib(n: Int) async -> Int {
1414
if (n == 0) {
15+
print("done!")
1516
return 1
1617
}
1718
if (n == 1) {
19+
print("done!")
1820
return 1
1921
}
2022
async let n1_task = fib(n: n - 1) // Breakpoint fib
2123
async let n2_task = fib(n: n - 2)
24+
print(n)
25+
if (n == 6) { do { try await Task.sleep(for: .seconds(1)) } catch {} }
2226
let n1 = await n1_task
2327
let n2 = await n2_task
2428
return n1 + n2

0 commit comments

Comments
 (0)