Index: llvm/lib/Target/AArch64/AArch64FrameLowering.cpp =================================================================== --- llvm/lib/Target/AArch64/AArch64FrameLowering.cpp +++ llvm/lib/Target/AArch64/AArch64FrameLowering.cpp @@ -1019,7 +1019,7 @@ if (HasFP) { // Only set up FP if we actually need to. - int FPOffset = isTargetDarwin(MF) ? (AFI->getCalleeSavedStackSize() - 16) : 0; + int FPOffset = AFI->getFrameRecordOffset(); if (CombineSPBump) FPOffset += AFI->getLocalStackSize(); @@ -1232,11 +1232,6 @@ } if (needsFrameMoves) { - const DataLayout &TD = MF.getDataLayout(); - const int StackGrowth = isTargetDarwin(MF) - ? (2 * -TD.getPointerSize(0)) - : -AFI->getCalleeSavedStackSize(); - Register FramePtr = RegInfo->getFrameRegister(MF); // An example of the prologue: // // .globl __foo @@ -1304,10 +1299,14 @@ // .cfi_offset w28, -32 if (HasFP) { + const int OffsetToFirstCalleeSaveFromFP = + AFI->getFrameRecordOffset() - AFI->getCalleeSavedStackSize(); + Register FramePtr = RegInfo->getFrameRegister(MF); + // Define the current CFA rule to use the provided FP. unsigned Reg = RegInfo->getDwarfRegNum(FramePtr, true); unsigned CFIIndex = MF.addFrameInst(MCCFIInstruction::createDefCfa( - nullptr, Reg, StackGrowth - FixedObject)); + nullptr, Reg, OffsetToFirstCalleeSaveFromFP - FixedObject)); BuildMI(MBB, MBBI, DL, TII->get(TargetOpcode::CFI_INSTRUCTION)) .addCFIIndex(CFIIndex) .setMIFlags(MachineInstr::FrameSetup); @@ -1614,8 +1613,7 @@ // non-post-indexed loads for the restores if we aren't actually going to // be able to save any instructions. if (!IsFunclet && (MFI.hasVarSizedObjects() || AFI->isStackRealigned())) { - int64_t OffsetToFrameRecord = - isTargetDarwin(MF) ? (-(int64_t)AFI->getCalleeSavedStackSize() + 16) : 0; + int64_t OffsetToFrameRecord = -AFI->getFrameRecordOffset();; emitFrameOffset(MBB, LastPopI, DL, AArch64::SP, AArch64::FP, {OffsetToFrameRecord, MVT::i8}, TII, MachineInstr::FrameDestroy, false, NeedsWinCFI); @@ -2061,6 +2059,11 @@ (RPI.isScalable() && RPI.Offset >= -256 && RPI.Offset <= 255)) && "Offset out of bounds for LDP/STP immediate"); + // Save the offset to frame record so that the FP register can point to the + // innermost frame record (spilled FP and LR registers). + if (NeedsFrameRecord && RPI.Reg1 == AArch64::LR && RPI.Reg2 == AArch64::FP) + AFI->setFrameRecordOffset(Offset); + RegPairs.push_back(RPI); if (RPI.isPaired()) ++i; Index: llvm/lib/Target/AArch64/AArch64MachineFunctionInfo.h =================================================================== --- llvm/lib/Target/AArch64/AArch64MachineFunctionInfo.h +++ llvm/lib/Target/AArch64/AArch64MachineFunctionInfo.h @@ -126,6 +126,10 @@ // stack slot. unsigned TaggedBasePointerOffset = 0; + // Offset from SP-after-callee-saved-spills (i.e. SP-at-entry minus + // CalleeSavedStackSize) to the address of the frame record. + int FrameRecordOffset = 0; + public: AArch64FunctionInfo() = default; @@ -325,6 +329,13 @@ TaggedBasePointerOffset = Offset; } + int getFrameRecordOffset() const { + return FrameRecordOffset; + } + void setFrameRecordOffset(int Offset) { + FrameRecordOffset = Offset; + } + private: // Hold the lists of LOHs. MILOHContainer LOHContainerSet; Index: llvm/test/CodeGen/AArch64/framelayout-frame-record.ll =================================================================== --- /dev/null +++ llvm/test/CodeGen/AArch64/framelayout-frame-record.ll @@ -0,0 +1,30 @@ +; RUN: llc < %s -mtriple=aarch64--linux-gnu | FileCheck %s + +target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128" +target triple = "aarch64--linux-gnu" + +declare void @escape.i64(i64) +declare void @escape.double(double) + +define void @test_frame_record_offset(i64 %a, i64 %b, double %c, double %d) "no-frame-pointer-elim"="true" { +; CHECK-LABEL: test_frame_record_offset: + +; CHECK: stp d9, d8, [sp, #-48]! +; CHECK: stp x29, x30, [sp, #[[FP_OFFSET:16]]] +; CHECK: str x19, [sp, #32] + +; CHECK: add x29, sp, #[[FP_OFFSET]] + +; CHECK: .cfi_def_cfa w29, 32 +; CHECK: .cfi_offset w19, -16 +; CHECK: .cfi_offset w30, -24 +; CHECK: .cfi_offset w29, -32 +; CHECK: .cfi_offset b8, -40 +; CHECK: .cfi_offset b9, -48 + + call void @escape.i64(i64 %a) + call void @escape.i64(i64 %b) + call void @escape.double(double %c) + call void @escape.double(double %d) + ret void +}