211 lines · cpp
1//===-- LanaiFrameLowering.cpp - Lanai Frame Information ------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8//9// This file contains the Lanai implementation of TargetFrameLowering class.10//11//===----------------------------------------------------------------------===//12 13#include "LanaiFrameLowering.h"14 15#include "LanaiAluCode.h"16#include "LanaiInstrInfo.h"17#include "LanaiSubtarget.h"18#include "llvm/CodeGen/MachineFrameInfo.h"19#include "llvm/CodeGen/MachineFunction.h"20#include "llvm/CodeGen/MachineInstrBuilder.h"21 22using namespace llvm;23 24// Determines the size of the frame and maximum call frame size.25void LanaiFrameLowering::determineFrameLayout(MachineFunction &MF) const {26 MachineFrameInfo &MFI = MF.getFrameInfo();27 const LanaiRegisterInfo *LRI = STI.getRegisterInfo();28 29 // Get the number of bytes to allocate from the FrameInfo.30 unsigned FrameSize = MFI.getStackSize();31 32 // Get the alignment.33 Align StackAlign =34 LRI->hasStackRealignment(MF) ? MFI.getMaxAlign() : getStackAlign();35 36 // Get the maximum call frame size of all the calls.37 unsigned MaxCallFrameSize = MFI.getMaxCallFrameSize();38 39 // If we have dynamic alloca then MaxCallFrameSize needs to be aligned so40 // that allocations will be aligned.41 if (MFI.hasVarSizedObjects())42 MaxCallFrameSize = alignTo(MaxCallFrameSize, StackAlign);43 44 // Update maximum call frame size.45 MFI.setMaxCallFrameSize(MaxCallFrameSize);46 47 // Include call frame size in total.48 if (!(hasReservedCallFrame(MF) && MFI.adjustsStack()))49 FrameSize += MaxCallFrameSize;50 51 // Make sure the frame is aligned.52 FrameSize = alignTo(FrameSize, StackAlign);53 54 // Update frame info.55 MFI.setStackSize(FrameSize);56}57 58// Iterates through each basic block in a machine function and replaces59// ADJDYNALLOC pseudo instructions with a Lanai:ADDI with the60// maximum call frame size as the immediate.61void LanaiFrameLowering::replaceAdjDynAllocPseudo(MachineFunction &MF) const {62 const LanaiInstrInfo &LII = *STI.getInstrInfo();63 unsigned MaxCallFrameSize = MF.getFrameInfo().getMaxCallFrameSize();64 65 for (MachineBasicBlock &MBB : MF) {66 for (MachineInstr &MI : llvm::make_early_inc_range(MBB)) {67 if (MI.getOpcode() == Lanai::ADJDYNALLOC) {68 DebugLoc DL = MI.getDebugLoc();69 Register Dst = MI.getOperand(0).getReg();70 Register Src = MI.getOperand(1).getReg();71 72 BuildMI(MBB, MI, DL, LII.get(Lanai::ADD_I_LO), Dst)73 .addReg(Src)74 .addImm(MaxCallFrameSize);75 MI.eraseFromParent();76 }77 }78 }79}80 81// Generates the following sequence for function entry:82// st %fp,-4[*%sp] !push old FP83// add %sp,8,%fp !generate new FP84// sub %sp,0x4,%sp !allocate stack space (as needed)85void LanaiFrameLowering::emitPrologue(MachineFunction &MF,86 MachineBasicBlock &MBB) const {87 assert(&MF.front() == &MBB && "Shrink-wrapping not yet supported");88 89 MachineFrameInfo &MFI = MF.getFrameInfo();90 const LanaiInstrInfo &LII = *STI.getInstrInfo();91 MachineBasicBlock::iterator MBBI = MBB.begin();92 93 // Debug location must be unknown since the first debug location is used94 // to determine the end of the prologue.95 DebugLoc DL;96 97 // Determine the correct frame layout98 determineFrameLayout(MF);99 100 // FIXME: This appears to be overallocating. Needs investigation.101 // Get the number of bytes to allocate from the FrameInfo.102 unsigned StackSize = MFI.getStackSize();103 104 // Push old FP105 // st %fp,-4[*%sp]106 BuildMI(MBB, MBBI, DL, LII.get(Lanai::SW_RI))107 .addReg(Lanai::FP)108 .addReg(Lanai::SP)109 .addImm(-4)110 .addImm(LPAC::makePreOp(LPAC::ADD))111 .setMIFlag(MachineInstr::FrameSetup);112 113 // Generate new FP114 // add %sp,8,%fp115 BuildMI(MBB, MBBI, DL, LII.get(Lanai::ADD_I_LO), Lanai::FP)116 .addReg(Lanai::SP)117 .addImm(8)118 .setMIFlag(MachineInstr::FrameSetup);119 120 // Allocate space on the stack if needed121 // sub %sp,StackSize,%sp122 if (StackSize != 0) {123 BuildMI(MBB, MBBI, DL, LII.get(Lanai::SUB_I_LO), Lanai::SP)124 .addReg(Lanai::SP)125 .addImm(StackSize)126 .setMIFlag(MachineInstr::FrameSetup);127 }128 129 // Replace ADJDYNANALLOC130 if (MFI.hasVarSizedObjects())131 replaceAdjDynAllocPseudo(MF);132}133 134MachineBasicBlock::iterator LanaiFrameLowering::eliminateCallFramePseudoInstr(135 MachineFunction & /*MF*/, MachineBasicBlock &MBB,136 MachineBasicBlock::iterator I) const {137 // Discard ADJCALLSTACKDOWN, ADJCALLSTACKUP instructions.138 return MBB.erase(I);139}140 141// The function epilogue should not depend on the current stack pointer!142// It should use the frame pointer only. This is mandatory because143// of alloca; we also take advantage of it to omit stack adjustments144// before returning.145//146// Note that when we go to restore the preserved register values we must147// not try to address their slots by using offsets from the stack pointer.148// That's because the stack pointer may have been moved during the function149// execution due to a call to alloca(). Rather, we must restore all150// preserved registers via offsets from the frame pointer value.151//152// Note also that when the current frame is being "popped" (by adjusting153// the value of the stack pointer) on function exit, we must (for the154// sake of alloca) set the new value of the stack pointer based upon155// the current value of the frame pointer. We can't just add what we156// believe to be the (static) frame size to the stack pointer because157// if we did that, and alloca() had been called during this function,158// we would end up returning *without* having fully deallocated all of159// the space grabbed by alloca. If that happened, and a function160// containing one or more alloca() calls was called over and over again,161// then the stack would grow without limit!162//163// RET is lowered to164// ld -4[%fp],%pc # modify %pc (two delay slots)165// as the return address is in the stack frame and mov to pc is allowed.166// emitEpilogue emits167// mov %fp,%sp # restore the stack pointer168// ld -8[%fp],%fp # restore the caller's frame pointer169// before RET and the delay slot filler will move RET such that these170// instructions execute in the delay slots of the load to PC.171void LanaiFrameLowering::emitEpilogue(MachineFunction & /*MF*/,172 MachineBasicBlock &MBB) const {173 MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr();174 const LanaiInstrInfo &LII = *STI.getInstrInfo();175 DebugLoc DL = MBBI->getDebugLoc();176 177 // Restore the stack pointer using the callee's frame pointer value.178 BuildMI(MBB, MBBI, DL, LII.get(Lanai::ADD_I_LO), Lanai::SP)179 .addReg(Lanai::FP)180 .addImm(0);181 182 // Restore the frame pointer from the stack.183 BuildMI(MBB, MBBI, DL, LII.get(Lanai::LDW_RI), Lanai::FP)184 .addReg(Lanai::FP)185 .addImm(-8)186 .addImm(LPAC::ADD);187}188 189void LanaiFrameLowering::determineCalleeSaves(MachineFunction &MF,190 BitVector &SavedRegs,191 RegScavenger *RS) const {192 TargetFrameLowering::determineCalleeSaves(MF, SavedRegs, RS);193 194 MachineFrameInfo &MFI = MF.getFrameInfo();195 const LanaiRegisterInfo *LRI = STI.getRegisterInfo();196 int Offset = -4;197 198 // Reserve 4 bytes for the saved RCA199 MFI.CreateFixedObject(4, Offset, true);200 Offset -= 4;201 202 // Reserve 4 bytes for the saved FP203 MFI.CreateFixedObject(4, Offset, true);204 Offset -= 4;205 206 if (LRI->hasBasePointer(MF)) {207 MFI.CreateFixedObject(4, Offset, true);208 SavedRegs.reset(LRI->getBaseRegister());209 }210}211