diff --git a/llvm/lib/Target/ARM/ARMFrameLowering.cpp b/llvm/lib/Target/ARM/ARMFrameLowering.cpp --- a/llvm/lib/Target/ARM/ARMFrameLowering.cpp +++ b/llvm/lib/Target/ARM/ARMFrameLowering.cpp @@ -795,8 +795,12 @@ assert(getMaxFPOffset(STI, *AFI) <= FPOffset && "Max FP estimation is wrong"); FramePtrOffsetInPush = FPOffset + ArgRegsSaveSize + FPCXTSaveSize; - AFI->setFramePtrSpillOffset(MFI.getObjectOffset(FramePtrSpillFI) + - NumBytes); + int ObjectOffset = MFI.getObjectOffset(FramePtrSpillFI) + NumBytes; + if (NeedsWinCFI && + (MFI.hasVarSizedObjects() || AFI->getNumAlignedDPRCS2Regs() || + RegInfo->hasStackRealignment(MF))) + ObjectOffset = NumBytes - GPRCS1Size - GPRCS2Size; + AFI->setFramePtrSpillOffset(ObjectOffset); } AFI->setGPRCalleeSavedArea1Offset(GPRCS1Offset); AFI->setGPRCalleeSavedArea2Offset(GPRCS2Offset); @@ -975,10 +979,13 @@ if (HasFP) { MachineBasicBlock::iterator AfterPush = std::next(GPRCS1Push); unsigned PushSize = sizeOfSPAdjustment(*GPRCS1Push); - emitRegPlusImmediate(!AFI->isThumbFunction(), MBB, AfterPush, - dl, TII, FramePtr, ARM::SP, - PushSize + FramePtrOffsetInPush, - MachineInstr::FrameSetup); + int FPOffset = PushSize + FramePtrOffsetInPush; + if (NeedsWinCFI && + (MFI.hasVarSizedObjects() || AFI->getNumAlignedDPRCS2Regs() || + RegInfo->hasStackRealignment(MF))) + FPOffset = 0; + emitRegPlusImmediate(!AFI->isThumbFunction(), MBB, AfterPush, dl, TII, + FramePtr, ARM::SP, FPOffset, MachineInstr::FrameSetup); if (!NeedsWinCFI) { if (FramePtrOffsetInPush + PushSize != 0) { unsigned CFIIndex = MF.addFrameInst(MCCFIInstruction::cfiDefCfa( diff --git a/llvm/test/CodeGen/ARM/Windows/wineh-framepointer.ll b/llvm/test/CodeGen/ARM/Windows/wineh-framepointer.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/ARM/Windows/wineh-framepointer.ll @@ -0,0 +1,77 @@ +;; Check that this produces the expected assembly output +; RUN: llc -mtriple=thumbv7-windows -o - %s | FileCheck %s +;; Also try to write an object file, which verifies that the SEH opcodes +;; match the actual prologue/epilogue length. +; RUN: llc -mtriple=thumbv7-windows -filetype=obj -o %t.obj %s + +; CHECK-LABEL: alloc_local: +; CHECK-NEXT: .seh_proc alloc_local +; CHECK-NEXT: @ %bb.0: @ %entry +; CHECK-NEXT: push.w {r4, r5, r6, r9, r11, lr} +; CHECK-NEXT: .seh_save_regs_w {r4-r6, r9, r11, lr} +; CHECK-NEXT: mov r11, sp +; CHECK-NEXT: .seh_set_fp r11 +; CHECK-NEXT: sub sp, #32 +; CHECK-NEXT: .seh_stackalloc 32 +; CHECK-NEXT: .seh_endprologue + +; CHECK: ldr.w [[TMP:r[0-9]]], [r11, #24] +; CHECK: mov r0, [[TMP]] + +; CHECK: .seh_startepilogue +; CHECK-NEXT: mov sp, r11 +; CHECK-NEXT: .seh_set_fp r11 +; CHECK-NEXT: pop.w {r4, r5, r6, r9, r11, pc} +; CHECK-NEXT: .seh_save_regs_w {r4-r6, r9, r11, lr} +; CHECK-NEXT: .seh_endepilogue +; CHECK-NEXT: .seh_endproc + +define arm_aapcs_vfpcc void @alloc_local(i32 noundef %a, i32 noundef %b, i32 noundef %c, i32 noundef %d, i32 noundef %e) uwtable { +entry: + %buf2 = alloca [28 x i8], align 1 + %0 = alloca i8, i32 %a, align 8 + call void @llvm.lifetime.start.p0(i64 28, ptr nonnull %buf2) + call arm_aapcs_vfpcc void @other(i32 noundef %e, ptr noundef nonnull %0, ptr noundef nonnull %buf2) + call void asm sideeffect "", "~{r9}"() + call void @llvm.lifetime.end.p0(i64 28, ptr nonnull %buf2) + ret void +} + +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: align: +; CHECK-NEXT: .seh_proc align +; CHECK-NEXT: @ %bb.0: @ %entry +; CHECK-NEXT: push.w {r4, r7, r11, lr} +; CHECK-NEXT: .seh_save_regs_w {r4, r7, r11, lr} +; CHECK-NEXT: mov r11, sp +; CHECK-NEXT: .seh_set_fp r11 +; CHECK-NEXT: sub sp, #32 +; CHECK-NEXT: .seh_stackalloc 32 +; CHECK-NEXT: mov r4, sp +; CHECK-NEXT: .seh_nop +; CHECK-NEXT: bfc r4, #0, #4 +; CHECK-NEXT: .seh_nop_w +; CHECK-NEXT: mov sp, r4 +; CHECK-NEXT: .seh_nop +; CHECK-NEXT: .seh_endprologue + +; CHECK: .seh_startepilogue +; CHECK-NEXT: mov sp, r11 +; CHECK-NEXT: .seh_set_fp r11 +; CHECK-NEXT: pop.w {r4, r7, r11, pc} +; CHECK-NEXT: .seh_save_regs_w {r4, r7, r11, lr} +; CHECK-NEXT: .seh_endepilogue +; CHECK-NEXT: .seh_endproc + +define arm_aapcs_vfpcc void @align(i32 noundef %a) uwtable { +entry: + %buf = alloca [32 x i8], align 16 + call void @llvm.lifetime.start.p0(i64 32, ptr nonnull %buf) + call arm_aapcs_vfpcc void @other(i32 noundef %a, ptr noundef nonnull %buf, ptr noundef nonnull %buf) + call void @llvm.lifetime.end.p0(i64 32, ptr nonnull %buf) + ret void +}