From 40c937cba239db817b53d47c4525a751a8c488a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Storsj=C3=B6?= Date: Thu, 2 Jun 2022 13:17:14 +0300 Subject: [PATCH] [ARM] Fix restoring stack for varargs with SEH split frame pointer push Previously, the "add sp, #12" ended up inserted after "bx lr". Differential Revision: https://reviews.llvm.org/D126872 --- llvm/lib/Target/ARM/ARMFrameLowering.cpp | 6 +- .../CodeGen/ARM/Windows/wineh-framepointer.ll | 114 ++++++++++++++++++ 2 files changed, 119 insertions(+), 1 deletion(-) diff --git a/llvm/lib/Target/ARM/ARMFrameLowering.cpp b/llvm/lib/Target/ARM/ARMFrameLowering.cpp index 0916df31ac95..bb3e2478842d 100644 --- a/llvm/lib/Target/ARM/ARMFrameLowering.cpp +++ b/llvm/lib/Target/ARM/ARMFrameLowering.cpp @@ -1302,6 +1302,9 @@ void ARMFrameLowering::emitEpilogue(MachineFunction &MF, MachineInstr::FrameDestroy); // Increment past our save areas. + if (AFI->getGPRCalleeSavedArea2Size() && STI.splitFramePointerPush(MF)) + MBBI++; + if (MBBI != MBB.end() && AFI->getDPRCalleeSavedAreaSize()) { MBBI++; // Since vpop register list cannot have gaps, there may be multiple vpop @@ -1316,7 +1319,8 @@ void ARMFrameLowering::emitEpilogue(MachineFunction &MF, MachineInstr::FrameDestroy); } - if (AFI->getGPRCalleeSavedArea2Size()) MBBI++; + if (AFI->getGPRCalleeSavedArea2Size() && !STI.splitFramePointerPush(MF)) + MBBI++; if (AFI->getGPRCalleeSavedArea1Size()) MBBI++; if (ReservedArgStack || IncomingArgStackToRestore) { diff --git a/llvm/test/CodeGen/ARM/Windows/wineh-framepointer.ll b/llvm/test/CodeGen/ARM/Windows/wineh-framepointer.ll index 6b9a8a9b0520..17197006d826 100644 --- a/llvm/test/CodeGen/ARM/Windows/wineh-framepointer.ll +++ b/llvm/test/CodeGen/ARM/Windows/wineh-framepointer.ll @@ -60,3 +60,117 @@ declare void @llvm.lifetime.start.p0(i64 immarg, ptr nocapture) declare void @llvm.lifetime.end.p0(i64 immarg, ptr nocapture) declare arm_aapcs_vfpcc void @other(i32 noundef, ptr noundef, ptr noundef) + +; CHECK-LABEL: everything_varargs: +; CHECK-NEXT: .seh_proc everything_varargs +; CHECK-NEXT: @ %bb.0: @ %entry +; CHECK-NEXT: sub sp, #12 +; CHECK-NEXT: .seh_stackalloc 12 +; CHECK-NEXT: push.w {r4, r5, r6, r7, r8, r9} +; CHECK-NEXT: .seh_save_regs_w {r4-r9} +; CHECK-NEXT: sub sp, #4 +; CHECK-NEXT: .seh_stackalloc 4 +; CHECK-NEXT: vpush {d8, d9, d10, d11, d12, d13, d14, d15} +; CHECK-NEXT: .seh_save_fregs {d8-d15} +; CHECK-NEXT: push.w {r11, lr} +; CHECK-NEXT: .seh_save_regs_w {r11, lr} +; CHECK-NEXT: mov r11, sp +; CHECK-NEXT: .seh_save_sp r11 +; CHECK-NEXT: .seh_endprologue +; CHECK-NEXT: movw r4, #1258 +; CHECK-NEXT: bl __chkstk +; CHECK-NEXT: sub.w sp, sp, r4 +; CHECK-NEXT: mov r4, sp +; CHECK-NEXT: bfc r4, #0, #4 +; CHECK-NEXT: mov sp, r4 + +; CHECK: .seh_startepilogue +; CHECK-NEXT: mov sp, r11 +; CHECK-NEXT: .seh_save_sp r11 +; CHECK-NEXT: pop.w {r11, lr} +; CHECK-NEXT: .seh_save_regs_w {r11, lr} +; CHECK-NEXT: vpop {d8, d9, d10, d11, d12, d13, d14, d15} +; CHECK-NEXT: .seh_save_fregs {d8-d15} +; CHECK-NEXT: add sp, #4 +; CHECK-NEXT: .seh_stackalloc 4 +; CHECK-NEXT: pop.w {r4, r5, r6, r7, r8, r9} +; CHECK-NEXT: .seh_save_regs_w {r4-r9} +; CHECK-NEXT: add sp, #12 +; CHECK-NEXT: .seh_stackalloc 12 +; CHECK-NEXT: bx lr +; CHECK-NEXT: .seh_nop +; CHECK-NEXT: .seh_endepilogue +; CHECK-NEXT: .seh_endproc + +define arm_aapcs_vfpcc void @everything_varargs(i32 noundef %a, ...) { +entry: + %buf2 = alloca [5000 x i8], align 16 + %ap = alloca ptr, align 4 + %vla = alloca i8, i32 %a, align 1 + call void @llvm.lifetime.start.p0(i64 5000, ptr nonnull %buf2) + call void @llvm.lifetime.start.p0(i64 4, ptr nonnull %ap) + call void @llvm.va_start(ptr nonnull %ap) + %0 = load ptr, ptr %ap, align 4 + call arm_aapcs_vfpcc void @other2(i32 noundef %a, ptr noundef nonnull %vla, ptr noundef nonnull %buf2, ptr noundef %0) + call void @llvm.va_end(ptr nonnull %ap) + call void asm sideeffect "", "~{r4},~{r5},~{r6},~{r7},~{r8},~{r9},~{r11},~{r12}"() + call void asm sideeffect "", "~{d8},~{d9},~{d10},~{d11},~{d12},~{d13},~{d14},~{d15}"() + call void @llvm.lifetime.end.p0(i64 4, ptr nonnull %ap) + call void @llvm.lifetime.end.p0(i64 5000, ptr nonnull %buf2) + ret void +} + +; CHECK-LABEL: novector_varargs: +; CHECK-NEXT: .seh_proc novector_varargs +; CHECK-NEXT: @ %bb.0: @ %entry +; CHECK-NEXT: sub sp, #12 +; CHECK-NEXT: .seh_stackalloc 12 +; CHECK-NEXT: push.w {r4, r5, r6, r7, r8, r9} +; CHECK-NEXT: .seh_save_regs_w {r4-r9} +; CHECK-NEXT: push.w {r11, lr} +; CHECK-NEXT: .seh_save_regs_w {r11, lr} +; CHECK-NEXT: mov r11, sp +; CHECK-NEXT: .seh_save_sp r11 +; CHECK-NEXT: .seh_endprologue +; CHECK-NEXT: movw r4, #1259 +; CHECK-NEXT: bl __chkstk +; CHECK-NEXT: sub.w sp, sp, r4 +; CHECK-NEXT: mov r4, sp +; CHECK-NEXT: bfc r4, #0, #4 +; CHECK-NEXT: mov sp, r4 + +; CHECK: .seh_startepilogue +; CHECK-NEXT: mov sp, r11 +; CHECK-NEXT: .seh_save_sp r11 +; CHECK-NEXT: pop.w {r11, lr} +; CHECK-NEXT: .seh_save_regs_w {r11, lr} +; CHECK-NEXT: pop.w {r4, r5, r6, r7, r8, r9} +; CHECK-NEXT: .seh_save_regs_w {r4-r9} +; CHECK-NEXT: add sp, #12 +; CHECK-NEXT: .seh_stackalloc 12 +; CHECK-NEXT: bx lr +; CHECK-NEXT: .seh_nop +; CHECK-NEXT: .seh_endepilogue +; CHECK-NEXT: .seh_endproc + +define arm_aapcs_vfpcc void @novector_varargs(i32 noundef %a, ...) { +entry: + %buf2 = alloca [5000 x i8], align 16 + %ap = alloca ptr, align 4 + %vla = alloca i8, i32 %a, align 1 + call void @llvm.lifetime.start.p0(i64 5000, ptr nonnull %buf2) + call void @llvm.lifetime.start.p0(i64 4, ptr nonnull %ap) + call void @llvm.va_start(ptr nonnull %ap) + %0 = load ptr, ptr %ap, align 4 + call arm_aapcs_vfpcc void @other2(i32 noundef %a, ptr noundef nonnull %vla, ptr noundef nonnull %buf2, ptr noundef %0) + call void @llvm.va_end(ptr nonnull %ap) + call void asm sideeffect "", "~{r4},~{r5},~{r6},~{r7},~{r8},~{r9},~{r11},~{r12}"() + call void @llvm.lifetime.end.p0(i64 4, ptr nonnull %ap) + call void @llvm.lifetime.end.p0(i64 5000, ptr nonnull %buf2) + ret void +} + +declare void @llvm.va_start(ptr) +declare void @llvm.va_end(ptr) + +declare arm_aapcs_vfpcc void @other2(i32 noundef, ptr noundef, ptr noundef, ptr noundef)