Skip to content

Commit 42a9fa6

Browse files
committed
[AArch64][WinCFI] Handle cases where no SEH opcodes in the prologue
but there are some in the epilogue. Make a decision whether or not to have a startepilogue/endepilogue based on whether we actually insert SEH opcodes in the epilogue, rather than whether we had SEH opcodes in the prologue or not. This fixes an assert failure when there are no SEH opcodes in the prologue but there are SEH opcodes in the epilogue (for example, when there is no stack frame but there are stack arguments) which was not covered in https://reviews.llvm.org/D88641. Assertion failed: HasWinCFI == MF.hasWinCFI(), file C:\Users\hiroshi\llvm-project\llvm\lib\Target\AArch64\AArch64FrameLowering.cpp, line 1988 Differential Revision: https://reviews.llvm.org/D159238
1 parent f102d9d commit 42a9fa6

File tree

2 files changed

+36
-13
lines changed

2 files changed

+36
-13
lines changed

llvm/lib/Target/AArch64/AArch64FrameLowering.cpp

Lines changed: 23 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1948,23 +1948,32 @@ void AArch64FrameLowering::emitEpilogue(MachineFunction &MF,
19481948
bool EmitCFI = MF.getInfo<AArch64FunctionInfo>()->needsAsyncDwarfUnwindInfo();
19491949
bool HasWinCFI = false;
19501950
bool IsFunclet = false;
1951-
auto WinCFI = make_scope_exit([&]() { assert(HasWinCFI == MF.hasWinCFI()); });
19521951

19531952
if (MBB.end() != MBBI) {
19541953
DL = MBBI->getDebugLoc();
19551954
IsFunclet = isFuncletReturnInstr(*MBBI);
19561955
}
19571956

1957+
MachineBasicBlock::iterator EpilogStartI = MBB.end();
1958+
19581959
auto FinishingTouches = make_scope_exit([&]() {
19591960
InsertReturnAddressAuth(MF, MBB, NeedsWinCFI, &HasWinCFI);
19601961
if (needsShadowCallStackPrologueEpilogue(MF))
19611962
emitShadowCallStackEpilogue(*TII, MF, MBB, MBB.getFirstTerminator(), DL);
19621963
if (EmitCFI)
19631964
emitCalleeSavedGPRRestores(MBB, MBB.getFirstTerminator());
1964-
if (HasWinCFI)
1965+
if (HasWinCFI) {
19651966
BuildMI(MBB, MBB.getFirstTerminator(), DL,
19661967
TII->get(AArch64::SEH_EpilogEnd))
19671968
.setMIFlag(MachineInstr::FrameDestroy);
1969+
if (!MF.hasWinCFI())
1970+
MF.setHasWinCFI(true);
1971+
}
1972+
if (NeedsWinCFI) {
1973+
assert(EpilogStartI != MBB.end());
1974+
if (!HasWinCFI)
1975+
MBB.erase(EpilogStartI);
1976+
}
19681977
});
19691978

19701979
int64_t NumBytes = IsFunclet ? getWinEHFuncletFrameSize(MF)
@@ -2029,7 +2038,7 @@ void AArch64FrameLowering::emitEpilogue(MachineFunction &MF,
20292038
// Adjust local stack
20302039
emitFrameOffset(MBB, LastPopI, DL, AArch64::SP, AArch64::SP,
20312040
StackOffset::getFixed(AFI->getLocalStackSize()), TII,
2032-
MachineInstr::FrameDestroy, false, NeedsWinCFI);
2041+
MachineInstr::FrameDestroy, false, NeedsWinCFI, &HasWinCFI);
20332042

20342043
// SP has been already adjusted while restoring callee save regs.
20352044
// We've bailed-out the case with adjusting SP for arguments.
@@ -2081,16 +2090,17 @@ void AArch64FrameLowering::emitEpilogue(MachineFunction &MF,
20812090
NeedsWinCFI, &HasWinCFI);
20822091
}
20832092

2084-
if (MF.hasWinCFI()) {
2085-
// If the prologue didn't contain any SEH opcodes and didn't set the
2086-
// MF.hasWinCFI() flag, assume the epilogue won't either, and skip the
2087-
// EpilogStart - to avoid generating CFI for functions that don't need it.
2088-
// (And as we didn't generate any prologue at all, it would be asymmetrical
2089-
// to the epilogue.) By the end of the function, we assert that
2090-
// HasWinCFI is equal to MF.hasWinCFI(), to verify this assumption.
2091-
HasWinCFI = true;
2093+
if (NeedsWinCFI) {
2094+
// Note that there are cases where we insert SEH opcodes in the
2095+
// epilogue when we had no SEH opcodes in the prologue. For
2096+
// example, when there is no stack frame but there are stack
2097+
// arguments. Insert the SEH_EpilogStart and remove it later if it
2098+
// we didn't emit any SEH opcodes to avoid generating WinCFI for
2099+
// functions that don't need it.
20922100
BuildMI(MBB, LastPopI, DL, TII->get(AArch64::SEH_EpilogStart))
20932101
.setMIFlag(MachineInstr::FrameDestroy);
2102+
EpilogStartI = LastPopI;
2103+
--EpilogStartI;
20942104
}
20952105

20962106
if (hasFP(MF) && AFI->hasSwiftAsyncContext()) {
@@ -2244,11 +2254,11 @@ void AArch64FrameLowering::emitEpilogue(MachineFunction &MF,
22442254
emitFrameOffset(
22452255
MBB, LastPopI, DL, AArch64::SP, AArch64::FP,
22462256
StackOffset::getFixed(-AFI->getCalleeSaveBaseToFrameRecordOffset()),
2247-
TII, MachineInstr::FrameDestroy, false, NeedsWinCFI);
2257+
TII, MachineInstr::FrameDestroy, false, NeedsWinCFI, &HasWinCFI);
22482258
} else if (NumBytes)
22492259
emitFrameOffset(MBB, LastPopI, DL, AArch64::SP, AArch64::SP,
22502260
StackOffset::getFixed(NumBytes), TII,
2251-
MachineInstr::FrameDestroy, false, NeedsWinCFI);
2261+
MachineInstr::FrameDestroy, false, NeedsWinCFI, &HasWinCFI);
22522262

22532263
// When we are about to restore the CSRs, the CFA register is SP again.
22542264
if (EmitCFI && hasFP(MF)) {
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
; RUN: llc -mtriple=aarch64-windows %s -o - | FileCheck %s
2+
3+
define hidden swifttailcc void @test(ptr noalias nocapture %0, ptr swiftasync %1, ptr %2, ptr noalias nocapture %3, ptr nocapture dereferenceable(8) %4, ptr %5, ptr %6, ptr %Act, ptr %Err, ptr %Res, ptr %Act.DistributedActor, ptr %Err.Error, ptr %Res.Decodable, ptr %Res.Encodable, ptr swiftself %7) #0 {
4+
entry:
5+
ret void
6+
}
7+
8+
; Check that there is no .seh_endprologue but there is seh_startepilogue/seh_endepilogue.
9+
; CHECK-NOT: .seh_endprologue
10+
; CHECK: .seh_startepilogue
11+
; CHECK: add sp, sp, #48
12+
; CHECK: .seh_stackalloc 48
13+
; CHECK: .seh_endepilogue

0 commit comments

Comments
 (0)