Skip to content

Commit 3e61754

Browse files
committed
[AArch64][Windows] Fix the slot offset of the swift async context register.
This fixes a code gen issue where savings the swift async context register (x22) accidentally overwrites the saved value of another callee-saved register, corrupts its value and causes a crash. Cherrypick https://reviews.llvm.org/rGa90228b911d3c70833a4abe63b81e02a7a8da1f5
1 parent c8ca153 commit 3e61754

File tree

2 files changed

+36
-2
lines changed

2 files changed

+36
-2
lines changed

llvm/lib/Target/AArch64/AArch64FrameLowering.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2699,7 +2699,8 @@ static void computeCalleeSaveRegisterPairs(
26992699
// Swift's async context is directly before FP, so allocate an extra
27002700
// 8 bytes for it.
27012701
if (NeedsFrameRecord && AFI->hasSwiftAsyncContext() &&
2702-
RPI.Reg2 == AArch64::FP)
2702+
((!IsWindows && RPI.Reg2 == AArch64::FP) ||
2703+
(IsWindows && RPI.Reg2 == AArch64::LR)))
27032704
ByteOffset += StackFillDir * 8;
27042705

27052706
assert(!(RPI.isScalable() && RPI.isPaired()) &&
@@ -2728,7 +2729,8 @@ static void computeCalleeSaveRegisterPairs(
27282729
// The FP, LR pair goes 8 bytes into our expanded 24-byte slot so that the
27292730
// Swift context can directly precede FP.
27302731
if (NeedsFrameRecord && AFI->hasSwiftAsyncContext() &&
2731-
RPI.Reg2 == AArch64::FP)
2732+
((!IsWindows && RPI.Reg2 == AArch64::FP) ||
2733+
(IsWindows && RPI.Reg2 == AArch64::LR)))
27322734
Offset += 8;
27332735
RPI.Offset = Offset / Scale;
27342736

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
; RUN: llc -mtriple aarch64-unknown-windows-msvc -filetype asm %s -o - | FileCheck %s
2+
3+
; Check that the slot offset of the async context (x22) doesn't
4+
; conflict with that of another callee-saved register (x21 here) and
5+
; saving it won't overwrite the saved value of the callee-saved
6+
; register.
7+
;
8+
; CHECK: sub sp, sp, #64
9+
; CHECK: str x19, [sp, #16]
10+
; CHECK: str x21, [sp, #24]
11+
; CHECK-NOT: stp x29, x30, [sp, #32]
12+
; CHECK: stp x29, x30, [sp, #40]
13+
; CHECK-NOT: str x22, [sp, #24]
14+
; CHECK: str x22, [sp, #32]
15+
16+
declare ptr @llvm.swift.async.context.addr()
17+
declare swiftcc i64 @foo(i64 %0, i64 %1)
18+
declare swifttailcc void @tail(ptr swiftasync %0, ptr swiftself dereferenceable(8) %1, i64 %2)
19+
define internal swifttailcc void @test(ptr swiftasync %0, ptr swiftself %1, i64 %2) {
20+
entry:
21+
%3 = load ptr, ptr %0, align 8
22+
%4 = call ptr @llvm.swift.async.context.addr()
23+
store ptr %3, ptr %4, align 8
24+
%5 = call swiftcc i64 @foo(i64 %2, i64 %2)
25+
%6 = call swiftcc i64 @foo(i64 %2, i64 %5)
26+
%7 = call swiftcc i64 @foo(i64 %5, i64 %2)
27+
%8 = call swiftcc i64 @foo(i64 %7, i64 %6)
28+
%9 = call swiftcc i64 @foo(i64 %2, i64 %8)
29+
%10 = call ptr @llvm.swift.async.context.addr()
30+
musttail call swifttailcc void @tail(ptr swiftasync %10, ptr swiftself %1, i64 %2)
31+
ret void
32+
}

0 commit comments

Comments
 (0)