109467b48Spatrick //===-- LanaiFrameLowering.cpp - Lanai Frame Information ------------------===//
209467b48Spatrick //
309467b48Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
409467b48Spatrick // See https://llvm.org/LICENSE.txt for license information.
509467b48Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
609467b48Spatrick //
709467b48Spatrick //===----------------------------------------------------------------------===//
809467b48Spatrick //
909467b48Spatrick // This file contains the Lanai implementation of TargetFrameLowering class.
1009467b48Spatrick //
1109467b48Spatrick //===----------------------------------------------------------------------===//
1209467b48Spatrick
1309467b48Spatrick #include "LanaiFrameLowering.h"
1409467b48Spatrick
1509467b48Spatrick #include "LanaiAluCode.h"
1609467b48Spatrick #include "LanaiInstrInfo.h"
1709467b48Spatrick #include "LanaiSubtarget.h"
1809467b48Spatrick #include "llvm/CodeGen/MachineFrameInfo.h"
1909467b48Spatrick #include "llvm/CodeGen/MachineFunction.h"
2009467b48Spatrick #include "llvm/CodeGen/MachineInstrBuilder.h"
2109467b48Spatrick #include "llvm/CodeGen/MachineRegisterInfo.h"
2209467b48Spatrick #include "llvm/IR/Function.h"
2309467b48Spatrick
2409467b48Spatrick using namespace llvm;
2509467b48Spatrick
2609467b48Spatrick // Determines the size of the frame and maximum call frame size.
determineFrameLayout(MachineFunction & MF) const2709467b48Spatrick void LanaiFrameLowering::determineFrameLayout(MachineFunction &MF) const {
2809467b48Spatrick MachineFrameInfo &MFI = MF.getFrameInfo();
2909467b48Spatrick const LanaiRegisterInfo *LRI = STI.getRegisterInfo();
3009467b48Spatrick
3109467b48Spatrick // Get the number of bytes to allocate from the FrameInfo.
3209467b48Spatrick unsigned FrameSize = MFI.getStackSize();
3309467b48Spatrick
3409467b48Spatrick // Get the alignment.
35097a140dSpatrick Align StackAlign =
3673471bf0Spatrick LRI->hasStackRealignment(MF) ? MFI.getMaxAlign() : getStackAlign();
3709467b48Spatrick
3809467b48Spatrick // Get the maximum call frame size of all the calls.
3909467b48Spatrick unsigned MaxCallFrameSize = MFI.getMaxCallFrameSize();
4009467b48Spatrick
4109467b48Spatrick // If we have dynamic alloca then MaxCallFrameSize needs to be aligned so
4209467b48Spatrick // that allocations will be aligned.
4309467b48Spatrick if (MFI.hasVarSizedObjects())
4409467b48Spatrick MaxCallFrameSize = alignTo(MaxCallFrameSize, StackAlign);
4509467b48Spatrick
4609467b48Spatrick // Update maximum call frame size.
4709467b48Spatrick MFI.setMaxCallFrameSize(MaxCallFrameSize);
4809467b48Spatrick
4909467b48Spatrick // Include call frame size in total.
5009467b48Spatrick if (!(hasReservedCallFrame(MF) && MFI.adjustsStack()))
5109467b48Spatrick FrameSize += MaxCallFrameSize;
5209467b48Spatrick
5309467b48Spatrick // Make sure the frame is aligned.
5409467b48Spatrick FrameSize = alignTo(FrameSize, StackAlign);
5509467b48Spatrick
5609467b48Spatrick // Update frame info.
5709467b48Spatrick MFI.setStackSize(FrameSize);
5809467b48Spatrick }
5909467b48Spatrick
6009467b48Spatrick // Iterates through each basic block in a machine function and replaces
6109467b48Spatrick // ADJDYNALLOC pseudo instructions with a Lanai:ADDI with the
6209467b48Spatrick // maximum call frame size as the immediate.
replaceAdjDynAllocPseudo(MachineFunction & MF) const6309467b48Spatrick void LanaiFrameLowering::replaceAdjDynAllocPseudo(MachineFunction &MF) const {
6409467b48Spatrick const LanaiInstrInfo &LII =
6509467b48Spatrick *static_cast<const LanaiInstrInfo *>(STI.getInstrInfo());
6609467b48Spatrick unsigned MaxCallFrameSize = MF.getFrameInfo().getMaxCallFrameSize();
6709467b48Spatrick
68*d415bd75Srobert for (MachineBasicBlock &MBB : MF) {
69*d415bd75Srobert for (MachineInstr &MI : llvm::make_early_inc_range(MBB)) {
7009467b48Spatrick if (MI.getOpcode() == Lanai::ADJDYNALLOC) {
7109467b48Spatrick DebugLoc DL = MI.getDebugLoc();
7209467b48Spatrick Register Dst = MI.getOperand(0).getReg();
7309467b48Spatrick Register Src = MI.getOperand(1).getReg();
7409467b48Spatrick
75*d415bd75Srobert BuildMI(MBB, MI, DL, LII.get(Lanai::ADD_I_LO), Dst)
7609467b48Spatrick .addReg(Src)
7709467b48Spatrick .addImm(MaxCallFrameSize);
7809467b48Spatrick MI.eraseFromParent();
7909467b48Spatrick }
8009467b48Spatrick }
8109467b48Spatrick }
8209467b48Spatrick }
8309467b48Spatrick
8409467b48Spatrick // Generates the following sequence for function entry:
8509467b48Spatrick // st %fp,-4[*%sp] !push old FP
8609467b48Spatrick // add %sp,8,%fp !generate new FP
8709467b48Spatrick // sub %sp,0x4,%sp !allocate stack space (as needed)
emitPrologue(MachineFunction & MF,MachineBasicBlock & MBB) const8809467b48Spatrick void LanaiFrameLowering::emitPrologue(MachineFunction &MF,
8909467b48Spatrick MachineBasicBlock &MBB) const {
9009467b48Spatrick assert(&MF.front() == &MBB && "Shrink-wrapping not yet supported");
9109467b48Spatrick
9209467b48Spatrick MachineFrameInfo &MFI = MF.getFrameInfo();
9309467b48Spatrick const LanaiInstrInfo &LII =
9409467b48Spatrick *static_cast<const LanaiInstrInfo *>(STI.getInstrInfo());
9509467b48Spatrick MachineBasicBlock::iterator MBBI = MBB.begin();
9609467b48Spatrick
9709467b48Spatrick // Debug location must be unknown since the first debug location is used
9809467b48Spatrick // to determine the end of the prologue.
9909467b48Spatrick DebugLoc DL;
10009467b48Spatrick
10109467b48Spatrick // Determine the correct frame layout
10209467b48Spatrick determineFrameLayout(MF);
10309467b48Spatrick
10409467b48Spatrick // FIXME: This appears to be overallocating. Needs investigation.
10509467b48Spatrick // Get the number of bytes to allocate from the FrameInfo.
10609467b48Spatrick unsigned StackSize = MFI.getStackSize();
10709467b48Spatrick
10809467b48Spatrick // Push old FP
10909467b48Spatrick // st %fp,-4[*%sp]
11009467b48Spatrick BuildMI(MBB, MBBI, DL, LII.get(Lanai::SW_RI))
11109467b48Spatrick .addReg(Lanai::FP)
11209467b48Spatrick .addReg(Lanai::SP)
11309467b48Spatrick .addImm(-4)
11409467b48Spatrick .addImm(LPAC::makePreOp(LPAC::ADD))
11509467b48Spatrick .setMIFlag(MachineInstr::FrameSetup);
11609467b48Spatrick
11709467b48Spatrick // Generate new FP
11809467b48Spatrick // add %sp,8,%fp
11909467b48Spatrick BuildMI(MBB, MBBI, DL, LII.get(Lanai::ADD_I_LO), Lanai::FP)
12009467b48Spatrick .addReg(Lanai::SP)
12109467b48Spatrick .addImm(8)
12209467b48Spatrick .setMIFlag(MachineInstr::FrameSetup);
12309467b48Spatrick
12409467b48Spatrick // Allocate space on the stack if needed
12509467b48Spatrick // sub %sp,StackSize,%sp
12609467b48Spatrick if (StackSize != 0) {
12709467b48Spatrick BuildMI(MBB, MBBI, DL, LII.get(Lanai::SUB_I_LO), Lanai::SP)
12809467b48Spatrick .addReg(Lanai::SP)
12909467b48Spatrick .addImm(StackSize)
13009467b48Spatrick .setMIFlag(MachineInstr::FrameSetup);
13109467b48Spatrick }
13209467b48Spatrick
13309467b48Spatrick // Replace ADJDYNANALLOC
13409467b48Spatrick if (MFI.hasVarSizedObjects())
13509467b48Spatrick replaceAdjDynAllocPseudo(MF);
13609467b48Spatrick }
13709467b48Spatrick
eliminateCallFramePseudoInstr(MachineFunction &,MachineBasicBlock & MBB,MachineBasicBlock::iterator I) const13809467b48Spatrick MachineBasicBlock::iterator LanaiFrameLowering::eliminateCallFramePseudoInstr(
13909467b48Spatrick MachineFunction & /*MF*/, MachineBasicBlock &MBB,
14009467b48Spatrick MachineBasicBlock::iterator I) const {
14109467b48Spatrick // Discard ADJCALLSTACKDOWN, ADJCALLSTACKUP instructions.
14209467b48Spatrick return MBB.erase(I);
14309467b48Spatrick }
14409467b48Spatrick
14509467b48Spatrick // The function epilogue should not depend on the current stack pointer!
14609467b48Spatrick // It should use the frame pointer only. This is mandatory because
14709467b48Spatrick // of alloca; we also take advantage of it to omit stack adjustments
14809467b48Spatrick // before returning.
14909467b48Spatrick //
15009467b48Spatrick // Note that when we go to restore the preserved register values we must
15109467b48Spatrick // not try to address their slots by using offsets from the stack pointer.
15209467b48Spatrick // That's because the stack pointer may have been moved during the function
15309467b48Spatrick // execution due to a call to alloca(). Rather, we must restore all
15409467b48Spatrick // preserved registers via offsets from the frame pointer value.
15509467b48Spatrick //
15609467b48Spatrick // Note also that when the current frame is being "popped" (by adjusting
15709467b48Spatrick // the value of the stack pointer) on function exit, we must (for the
15809467b48Spatrick // sake of alloca) set the new value of the stack pointer based upon
15909467b48Spatrick // the current value of the frame pointer. We can't just add what we
16009467b48Spatrick // believe to be the (static) frame size to the stack pointer because
16109467b48Spatrick // if we did that, and alloca() had been called during this function,
16209467b48Spatrick // we would end up returning *without* having fully deallocated all of
16309467b48Spatrick // the space grabbed by alloca. If that happened, and a function
16409467b48Spatrick // containing one or more alloca() calls was called over and over again,
16509467b48Spatrick // then the stack would grow without limit!
16609467b48Spatrick //
16709467b48Spatrick // RET is lowered to
16809467b48Spatrick // ld -4[%fp],%pc # modify %pc (two delay slots)
16909467b48Spatrick // as the return address is in the stack frame and mov to pc is allowed.
17009467b48Spatrick // emitEpilogue emits
17109467b48Spatrick // mov %fp,%sp # restore the stack pointer
17209467b48Spatrick // ld -8[%fp],%fp # restore the caller's frame pointer
17309467b48Spatrick // before RET and the delay slot filler will move RET such that these
17409467b48Spatrick // instructions execute in the delay slots of the load to PC.
emitEpilogue(MachineFunction &,MachineBasicBlock & MBB) const17509467b48Spatrick void LanaiFrameLowering::emitEpilogue(MachineFunction & /*MF*/,
17609467b48Spatrick MachineBasicBlock &MBB) const {
17709467b48Spatrick MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr();
17809467b48Spatrick const LanaiInstrInfo &LII =
17909467b48Spatrick *static_cast<const LanaiInstrInfo *>(STI.getInstrInfo());
18009467b48Spatrick DebugLoc DL = MBBI->getDebugLoc();
18109467b48Spatrick
18209467b48Spatrick // Restore the stack pointer using the callee's frame pointer value.
18309467b48Spatrick BuildMI(MBB, MBBI, DL, LII.get(Lanai::ADD_I_LO), Lanai::SP)
18409467b48Spatrick .addReg(Lanai::FP)
18509467b48Spatrick .addImm(0);
18609467b48Spatrick
18709467b48Spatrick // Restore the frame pointer from the stack.
18809467b48Spatrick BuildMI(MBB, MBBI, DL, LII.get(Lanai::LDW_RI), Lanai::FP)
18909467b48Spatrick .addReg(Lanai::FP)
19009467b48Spatrick .addImm(-8)
19109467b48Spatrick .addImm(LPAC::ADD);
19209467b48Spatrick }
19309467b48Spatrick
determineCalleeSaves(MachineFunction & MF,BitVector & SavedRegs,RegScavenger * RS) const19409467b48Spatrick void LanaiFrameLowering::determineCalleeSaves(MachineFunction &MF,
19509467b48Spatrick BitVector &SavedRegs,
19609467b48Spatrick RegScavenger *RS) const {
19709467b48Spatrick TargetFrameLowering::determineCalleeSaves(MF, SavedRegs, RS);
19809467b48Spatrick
19909467b48Spatrick MachineFrameInfo &MFI = MF.getFrameInfo();
20009467b48Spatrick const LanaiRegisterInfo *LRI =
20109467b48Spatrick static_cast<const LanaiRegisterInfo *>(STI.getRegisterInfo());
20209467b48Spatrick int Offset = -4;
20309467b48Spatrick
20409467b48Spatrick // Reserve 4 bytes for the saved RCA
20509467b48Spatrick MFI.CreateFixedObject(4, Offset, true);
20609467b48Spatrick Offset -= 4;
20709467b48Spatrick
20809467b48Spatrick // Reserve 4 bytes for the saved FP
20909467b48Spatrick MFI.CreateFixedObject(4, Offset, true);
21009467b48Spatrick Offset -= 4;
21109467b48Spatrick
21209467b48Spatrick if (LRI->hasBasePointer(MF)) {
21309467b48Spatrick MFI.CreateFixedObject(4, Offset, true);
21409467b48Spatrick SavedRegs.reset(LRI->getBaseRegister());
21509467b48Spatrick }
21609467b48Spatrick }
217