Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 7 additions & 3 deletions llvm/lib/Target/AArch64/AArch64FrameLowering.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4479,7 +4479,11 @@ bool AArch64FrameLowering::assignCalleeSavedSpillSlots(
auto *AFI = MF.getInfo<AArch64FunctionInfo>();

bool UsesWinAAPCS = isTargetWindows(MF);
if (UsesWinAAPCS && hasFP(MF) && AFI->hasSwiftAsyncContext()) {
// Only the WinCFI path reverses CSI above, which is what places the frame
// record at the top of the callee-save area and lets the async context slot
// be allocated directly below FP inside the loop. Without that reversal the
// slot has to be carved out up front.
if (UsesWinAAPCS && !NeedsWinCFI && hasFP(MF) && AFI->hasSwiftAsyncContext()) {
int FrameIdx = MFI.CreateStackObject(8, Align(16), true);
AFI->setSwiftAsyncContextFrameIdx(FrameIdx);
if ((unsigned)FrameIdx < MinCSFrameIndex)
Expand Down Expand Up @@ -4548,8 +4552,8 @@ bool AArch64FrameLowering::assignCalleeSavedSpillSlots(
MaxCSFrameIndex = FrameIdx;

// Grab 8 bytes below FP for the extended asynchronous frame info.
if (hasFP(MF) && AFI->hasSwiftAsyncContext() && !UsesWinAAPCS &&
Reg == AArch64::FP) {
if (hasFP(MF) && AFI->hasSwiftAsyncContext() &&
(!UsesWinAAPCS || NeedsWinCFI) && Reg == AArch64::FP) {
FrameIdx = MFI.CreateStackObject(8, Alignment, true);
AFI->setSwiftAsyncContextFrameIdx(FrameIdx);
if ((unsigned)FrameIdx < MinCSFrameIndex)
Expand Down
103 changes: 103 additions & 0 deletions llvm/test/CodeGen/AArch64/swift-async-context-frame-record-win.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5
; RUN: llc -mtriple=aarch64-unknown-windows-msvc -O2 < %s | FileCheck %s

; The swift async context slot is allocated directly below the frame record. If
; it is allocated above it instead, MachineFrameInfo's view of the callee-save
; area disagrees with the prologue by 8 bytes, leaving a hole that PEI's stack
; slot scavenger hands to a live local, which then shares an address with the
; saved caller x29.
;
; The full frame layout is checked so that any object placed at or above the
; frame record shows up here as a diff: x29 is saved at sp+88, the async context
; sits below it at sp+80, and the spills land at sp+8 and sp+104.

declare ptr @llvm.swift.async.context.addr() nounwind
declare swiftcc void @swift_task_dealloc()

define swifttailcc void @test(ptr %ctx, ptr %vw0, ptr %vw1, ptr %vw2, ptr %vw3, ptr %obj0, ptr %obj1, ptr %obj2, ptr %obj3, ptr %obj4) {
; CHECK-LABEL: test:
; CHECK: .seh_proc test
; CHECK-NEXT: // %bb.0: // %entryresume.0
; CHECK-NEXT: orr x29, x29, #0x1000000000000000
; CHECK-NEXT: .seh_nop
; CHECK-NEXT: sub sp, sp, #112
; CHECK-NEXT: .seh_stackalloc 112
; CHECK-NEXT: str x19, [sp, #16] // 8-byte Folded Spill
; CHECK-NEXT: .seh_save_reg x19, 16
; CHECK-NEXT: str x21, [sp, #24] // 8-byte Folded Spill
; CHECK-NEXT: .seh_save_reg x21, 24
; CHECK-NEXT: stp x23, x24, [sp, #32] // 16-byte Folded Spill
; CHECK-NEXT: .seh_save_regp x23, 32
; CHECK-NEXT: stp x25, x26, [sp, #48] // 16-byte Folded Spill
; CHECK-NEXT: .seh_save_regp x25, 48
; CHECK-NEXT: stp x27, x28, [sp, #64] // 16-byte Folded Spill
; CHECK-NEXT: .seh_save_regp x27, 64
; CHECK-NEXT: stp x29, x30, [sp, #88] // 16-byte Folded Spill
; CHECK-NEXT: .seh_save_fplr 88
; CHECK-NEXT: str xzr, [sp, #80]
; CHECK-NEXT: .seh_nop
; CHECK-NEXT: add x29, sp, #88
; CHECK-NEXT: .seh_add_fp 88
; CHECK-NEXT: .seh_endprologue
; CHECK-NEXT: str x7, [sp, #8] // 8-byte Folded Spill
; CHECK-NEXT: mov x21, xzr
; CHECK-NEXT: mov x22, x6
; CHECK-NEXT: ldp x20, x27, [x29, #24]
; CHECK-NEXT: ldr x28, [x21]
; CHECK-NEXT: str x5, [x29, #16] // 8-byte Folded Spill
; CHECK-NEXT: mov x23, x4
; CHECK-NEXT: mov x24, x3
; CHECK-NEXT: mov x25, x2
; CHECK-NEXT: mov x26, x1
; CHECK-NEXT: mov x19, x0
; CHECK-NEXT: bl swift_task_dealloc
; CHECK-NEXT: ldr x8, [x19]
; CHECK-NEXT: mov x0, x28
; CHECK-NEXT: mov x1, x27
; CHECK-NEXT: blr x8
; CHECK-NEXT: ldr x8, [x22]
; CHECK-NEXT: mov x0, x24
; CHECK-NEXT: mov x1, xzr
; CHECK-NEXT: blr x8
; CHECK-NEXT: ldr x8, [x20]
; CHECK-NEXT: ldr x1, [sp, #8] // 8-byte Folded Reload
; CHECK-NEXT: mov x0, x25
; CHECK-NEXT: blr x8
; CHECK-NEXT: ldr x2, [x23]
; CHECK-NEXT: ldr x1, [x29, #16] // 8-byte Folded Reload
; CHECK-NEXT: mov x0, x26
; CHECK-NEXT: .seh_startepilogue
; CHECK-NEXT: ldp x29, x30, [sp, #88] // 16-byte Folded Reload
; CHECK-NEXT: .seh_save_fplr 88
; CHECK-NEXT: ldp x27, x28, [sp, #64] // 16-byte Folded Reload
; CHECK-NEXT: .seh_save_regp x27, 64
; CHECK-NEXT: ldp x25, x26, [sp, #48] // 16-byte Folded Reload
; CHECK-NEXT: .seh_save_regp x25, 48
; CHECK-NEXT: ldp x23, x24, [sp, #32] // 16-byte Folded Reload
; CHECK-NEXT: .seh_save_regp x23, 32
; CHECK-NEXT: ldr x21, [sp, #24] // 8-byte Folded Reload
; CHECK-NEXT: .seh_save_reg x21, 24
; CHECK-NEXT: ldr x19, [sp, #16] // 8-byte Folded Reload
; CHECK-NEXT: .seh_save_reg x19, 16
; CHECK-NEXT: and x29, x29, #0xefffffffffffffff
; CHECK-NEXT: .seh_nop
; CHECK-NEXT: add sp, sp, #112
; CHECK-NEXT: .seh_stackalloc 112
; CHECK-NEXT: .seh_endepilogue
; CHECK-NEXT: br x2
; CHECK-NEXT: .seh_endfunclet
; CHECK-NEXT: .seh_endproc
entryresume.0:
%ctxaddr = tail call ptr @llvm.swift.async.context.addr()
%reloaded = load ptr, ptr null, align 8
call swiftcc void @swift_task_dealloc()
%destroy0 = load ptr, ptr %ctx, align 8
tail call void %destroy0(ptr %reloaded, ptr %obj4)
%destroy1 = load ptr, ptr %obj1, align 8
tail call void %destroy1(ptr %vw2, ptr null)
%destroy2 = load ptr, ptr %obj3, align 8
tail call void %destroy2(ptr %vw1, ptr %obj2)
%destroy3 = load ptr, ptr %vw3, align 8
tail call void %destroy3(ptr %vw0, ptr %obj0)
ret void
}
2 changes: 1 addition & 1 deletion llvm/test/CodeGen/AArch64/swift-async-context-seh.ll
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

; CHECK: orr x29, x29, #0x1000000000000000
; CHECK-NEXT: .seh_nop
; CHECK: str x22, [sp, #16]
; CHECK: str x22, [sp]
; CHECK-NEXT: .seh_nop
; CHECK: and x29, x29, #0xefffffffffffffff
; CHECK-NEXT: .seh_nop
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,16 @@
; saving it won't overwrite the saved value of the callee-saved
; register.
;
; CHECK: sub sp, sp, #64
; CHECK: str x19, [sp, #16]
; CHECK: str x21, [sp, #24]
; CHECK-NOT: stp x29, x30, [sp, #32]
; CHECK: stp x29, x30, [sp, #40]
; CHECK-NOT: str x22, [sp, #24]
; CHECK: str x22, [sp, #32]
; The async context slot sits directly below the frame record, so the callee
; saves below it stay clear of both.
;
; CHECK: str x19, [sp, #-48]!
; CHECK: str x21, [sp, #8]
; CHECK-NOT: stp x29, x30, [sp, #16]
; CHECK: stp x29, x30, [sp, #24]
; CHECK-NOT: str x22, [sp, #8]
; CHECK: str x22, [sp, #16]
; CHECK: add x29, sp, #24

declare ptr @llvm.swift.async.context.addr()
declare swiftcc i64 @foo(i64 %0, i64 %1)
Expand Down