xref: /openbsd-src/gnu/llvm/llvm/lib/Target/Lanai/LanaiFrameLowering.cpp (revision d415bd752c734aee168c4ee86ff32e8cc249eb16)
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