Skip to content

Commit 2fa016a

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. (cherry picked from commit 3307906)
1 parent fe7ece8 commit 2fa016a

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
auto *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)