Skip to content

Commit e51a289

Browse files
authored
Merge pull request #11529 from Steelskin/fabrice/cp-21-win-arm64-always-emit-seh-end-prologue
🍒 Aarch64: Emit a minimal SEH prologue when needed (llvm#158173)
2 parents 7a92b31 + 8205bcf commit e51a289

File tree

3 files changed

+63
-2
lines changed

3 files changed

+63
-2
lines changed

llvm/lib/Target/AArch64/AArch64FrameLowering.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1972,6 +1972,13 @@ void AArch64FrameLowering::emitPrologue(MachineFunction &MF,
19721972
// to determine the end of the prologue.
19731973
DebugLoc DL;
19741974

1975+
// In some cases, particularly with CallingConv::SwiftTail, it is possible to
1976+
// have a tail-call where the caller only needs to adjust the stack pointer in
1977+
// the epilogue. In this case, we still need to emit a SEH prologue sequence.
1978+
// See `seh-minimal-prologue-epilogue.ll` test cases.
1979+
if (AFI->getArgumentStackToRestore())
1980+
HasWinCFI = true;
1981+
19751982
const auto &MFnI = *MF.getInfo<AArch64FunctionInfo>();
19761983
if (MFnI.shouldSignReturnAddress(MF)) {
19771984
// If pac-ret+leaf is in effect, PAUTH_PROLOGUE pseudo instructions
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
; RUN: llc -mtriple=aarch64-windows %s -o - | FileCheck %s
2+
3+
; This test verifies that functions requiring Windows CFI that have minimal
4+
; or no prologue instructions still emit proper SEH directives, specifically
5+
; ensuring .seh_endprologue is emitted before .seh_startepilogue.
6+
;
7+
; This reproduces the issue where Swift async functions with swifttailcc
8+
; calling convention would fail with:
9+
; "error: starting epilogue (.seh_startepilogue) before prologue has ended (.seh_endprologue)"
10+
11+
; Test 1: Swift-style tail call function with minimal prologue
12+
define swifttailcc void @test_swifttailcc_minimal(ptr %async_ctx, ptr %arg1, ptr %arg2) {
13+
; CHECK-LABEL: test_swifttailcc_minimal:
14+
; CHECK-NOT: .seh_proc test_swifttailcc_minimal
15+
; CHECK-NOT: .seh_endprologue
16+
; CHECK-NOT: .seh_startepilogue
17+
; CHECK-NOT: .seh_endepilogue
18+
; CHECK-NOT: .seh_endproc
19+
entry:
20+
%ptr1 = getelementptr inbounds i8, ptr %async_ctx, i64 16
21+
%ptr2 = getelementptr inbounds i8, ptr %async_ctx, i64 24
22+
store ptr %arg1, ptr %ptr1, align 8
23+
store ptr %arg2, ptr %ptr2, align 8
24+
musttail call swifttailcc void @external_swift_function(ptr %async_ctx, ptr %arg1)
25+
ret void
26+
}
27+
28+
; Test 2: Function similar to the original failing case
29+
define linkonce_odr hidden swifttailcc void @test_linkonce_swifttailcc(ptr swiftasync %async_ctx, ptr %arg1, ptr noalias dereferenceable(40) %arg2, ptr %arg3, i64 %value, ptr %arg4, ptr %arg5, ptr %arg6, i1 %flag, ptr %arg7, ptr noalias dereferenceable(40) %arg8) {
30+
; CHECK-LABEL: test_linkonce_swifttailcc:
31+
; CHECK-NEXT: .seh_proc
32+
; CHECK: .seh_endprologue
33+
; CHECK: .seh_startepilogue
34+
; CHECK: .seh_endepilogue
35+
; CHECK: .seh_endproc
36+
entry:
37+
%frame_ptr = getelementptr inbounds nuw i8, ptr %async_ctx, i64 16
38+
%ctx1 = getelementptr inbounds nuw i8, ptr %async_ctx, i64 400
39+
%ctx2 = getelementptr inbounds nuw i8, ptr %async_ctx, i64 1168
40+
%spill1 = getelementptr inbounds nuw i8, ptr %async_ctx, i64 2392
41+
store ptr %arg8, ptr %spill1, align 8
42+
%spill2 = getelementptr inbounds nuw i8, ptr %async_ctx, i64 2384
43+
store ptr %arg7, ptr %spill2, align 8
44+
%spill3 = getelementptr inbounds nuw i8, ptr %async_ctx, i64 2225
45+
store i1 %flag, ptr %spill3, align 1
46+
%spill4 = getelementptr inbounds nuw i8, ptr %async_ctx, i64 2376
47+
store ptr %arg6, ptr %spill4, align 8
48+
musttail call swifttailcc void @external_swift_continuation(ptr swiftasync %async_ctx, i64 0, i64 0)
49+
ret void
50+
}
51+
52+
declare swifttailcc void @external_swift_function(ptr, ptr)
53+
declare swifttailcc void @external_swift_continuation(ptr swiftasync, i64, i64)

llvm/test/CodeGen/AArch64/wincfi-seh-only-in-epilogue.ll renamed to llvm/test/CodeGen/AArch64/wincfi-minimal-seh-prologue.ll

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,9 @@ entry:
55
ret void
66
}
77

8-
; Check that there is no .seh_endprologue but there is seh_startepilogue/seh_endepilogue.
9-
; CHECK-NOT: .seh_endprologue
8+
; Check that there is a minimal SEH prologue with seh_startepilogue/seh_endepilogue.
9+
; CHECK: .seh_proc test
10+
; CHECK: .seh_endprologue
1011
; CHECK: .seh_startepilogue
1112
; CHECK: add sp, sp, #48
1213
; CHECK: .seh_stackalloc 48

0 commit comments

Comments
 (0)