Skip to content

Commit 69fb858

Browse files
danielframptontstellar
authored andcommitted
[AArch64] Fix mismatch in prologue and epilogue for funclets on Windows
The generated code for a funclet can have an add to sp in the epilogue for which there is no corresponding sub in the prologue. This patch removes the early return from emitPrologue that was preventing the sub to sp, and instead conditionalizes the appropriate parts of the rest of the function. Fixes https://bugs.llvm.org/show_bug.cgi?id=45345 Differential Revision: https://reviews.llvm.org/D77015 (cherry picked from commit 522b4c4)
1 parent 04b0a4e commit 69fb858

File tree

2 files changed

+82
-28
lines changed

2 files changed

+82
-28
lines changed

llvm/lib/Target/AArch64/AArch64FrameLowering.cpp

Lines changed: 20 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -993,32 +993,8 @@ void AArch64FrameLowering::emitPrologue(MachineFunction &MF,
993993
++MBBI;
994994
}
995995

996-
// The code below is not applicable to funclets. We have emitted all the SEH
997-
// opcodes that we needed to emit. The FP and BP belong to the containing
998-
// function.
999-
if (IsFunclet) {
1000-
if (NeedsWinCFI) {
1001-
HasWinCFI = true;
1002-
BuildMI(MBB, MBBI, DL, TII->get(AArch64::SEH_PrologEnd))
1003-
.setMIFlag(MachineInstr::FrameSetup);
1004-
}
1005-
1006-
// SEH funclets are passed the frame pointer in X1. If the parent
1007-
// function uses the base register, then the base register is used
1008-
// directly, and is not retrieved from X1.
1009-
if (F.hasPersonalityFn()) {
1010-
EHPersonality Per = classifyEHPersonality(F.getPersonalityFn());
1011-
if (isAsynchronousEHPersonality(Per)) {
1012-
BuildMI(MBB, MBBI, DL, TII->get(TargetOpcode::COPY), AArch64::FP)
1013-
.addReg(AArch64::X1).setMIFlag(MachineInstr::FrameSetup);
1014-
MBB.addLiveIn(AArch64::X1);
1015-
}
1016-
}
1017-
1018-
return;
1019-
}
1020-
1021-
if (HasFP) {
996+
// For funclets the FP belongs to the containing function.
997+
if (!IsFunclet && HasFP) {
1022998
// Only set up FP if we actually need to.
1023999
int64_t FPOffset = isTargetDarwin(MF) ? (AFI->getCalleeSavedStackSize() - 16) : 0;
10241000

@@ -1161,7 +1137,9 @@ void AArch64FrameLowering::emitPrologue(MachineFunction &MF,
11611137

11621138
// Allocate space for the rest of the frame.
11631139
if (NumBytes) {
1164-
const bool NeedsRealignment = RegInfo->needsStackRealignment(MF);
1140+
// Alignment is required for the parent frame, not the funclet
1141+
const bool NeedsRealignment =
1142+
!IsFunclet && RegInfo->needsStackRealignment(MF);
11651143
unsigned scratchSPReg = AArch64::SP;
11661144

11671145
if (NeedsRealignment) {
@@ -1215,7 +1193,8 @@ void AArch64FrameLowering::emitPrologue(MachineFunction &MF,
12151193
// FIXME: Clarify FrameSetup flags here.
12161194
// Note: Use emitFrameOffset() like above for FP if the FrameSetup flag is
12171195
// needed.
1218-
if (RegInfo->hasBasePointer(MF)) {
1196+
// For funclets the BP belongs to the containing function.
1197+
if (!IsFunclet && RegInfo->hasBasePointer(MF)) {
12191198
TII->copyPhysReg(MBB, MBBI, DL, RegInfo->getBaseRegister(), AArch64::SP,
12201199
false);
12211200
if (NeedsWinCFI) {
@@ -1232,6 +1211,19 @@ void AArch64FrameLowering::emitPrologue(MachineFunction &MF,
12321211
.setMIFlag(MachineInstr::FrameSetup);
12331212
}
12341213

1214+
// SEH funclets are passed the frame pointer in X1. If the parent
1215+
// function uses the base register, then the base register is used
1216+
// directly, and is not retrieved from X1.
1217+
if (IsFunclet && F.hasPersonalityFn()) {
1218+
EHPersonality Per = classifyEHPersonality(F.getPersonalityFn());
1219+
if (isAsynchronousEHPersonality(Per)) {
1220+
BuildMI(MBB, MBBI, DL, TII->get(TargetOpcode::COPY), AArch64::FP)
1221+
.addReg(AArch64::X1)
1222+
.setMIFlag(MachineInstr::FrameSetup);
1223+
MBB.addLiveIn(AArch64::X1);
1224+
}
1225+
}
1226+
12351227
if (needsFrameMoves) {
12361228
const DataLayout &TD = MF.getDataLayout();
12371229
const int StackGrowth = isTargetDarwin(MF)
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
; RUN: llc -o - %s -mtriple=aarch64-windows | FileCheck %s
2+
; Check that the stack bump around a funclet is computed correctly in both the
3+
; prologue and epilogue in the case we have a MaxCallFrameSize > 0 and are doing alloca
4+
target datalayout = "e-m:w-p:64:64-i32:32-i64:64-i128:128-n32:64-S128"
5+
target triple = "aarch64-pc-windows-msvc19.25.28611"
6+
7+
; // requires passing arguments on the stack
8+
; void test2(void*, int, int, int, int, int, int, int, int);
9+
;
10+
; // function with the funclet being checked
11+
; void test1(size_t bytes)
12+
; {
13+
; // alloca forces a separate callee save bump and stack bump
14+
; void *data = _alloca(bytes);
15+
; try {
16+
; test2(data, 0, 1, 2, 3, 4, 5, 6, 7);
17+
; } catch (...) {
18+
; // the funclet being checked
19+
; }
20+
; }
21+
22+
; CHECK-LABEL: ?catch$2@?0??test1@@YAX_K@Z@4HA
23+
; CHECK: sub sp, sp, #16
24+
; CHECK: add sp, sp, #16
25+
; Function Attrs: uwtable
26+
define dso_local void @"?test1@@YAX_K@Z"(i64 %0) #0 personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*) {
27+
%2 = alloca i64, align 8
28+
%3 = alloca i8*, align 8
29+
store i64 %0, i64* %2, align 8
30+
%4 = load i64, i64* %2, align 8
31+
%5 = alloca i8, i64 %4, align 16
32+
store i8* %5, i8** %3, align 8
33+
%6 = load i8*, i8** %3, align 8
34+
invoke void @"?test2@@YAXPEAXHHHHHHHH@Z"(i8* %6, i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7)
35+
to label %13 unwind label %7
36+
37+
7: ; preds = %1
38+
%8 = catchswitch within none [label %9] unwind to caller
39+
40+
9: ; preds = %7
41+
%10 = catchpad within %8 [i8* null, i32 64, i8* null]
42+
catchret from %10 to label %11
43+
44+
11: ; preds = %9
45+
br label %12
46+
47+
12: ; preds = %11, %13
48+
ret void
49+
50+
13: ; preds = %1
51+
br label %12
52+
}
53+
54+
declare dso_local void @"?test2@@YAXPEAXHHHHHHHH@Z"(i8*, i32, i32, i32, i32, i32, i32, i32, i32) #1
55+
56+
declare dso_local i32 @__CxxFrameHandler3(...)
57+
58+
attributes #0 = { uwtable }
59+
60+
!llvm.module.flags = !{!0}
61+
62+
!0 = !{i32 1, !"wchar_size", i32 2}

0 commit comments

Comments
 (0)