aboutsummaryrefslogtreecommitdiff
path: root/lib/Target/Lanai/LanaiFrameLowering.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Target/Lanai/LanaiFrameLowering.cpp')
-rw-r--r--lib/Target/Lanai/LanaiFrameLowering.cpp220
1 files changed, 220 insertions, 0 deletions
diff --git a/lib/Target/Lanai/LanaiFrameLowering.cpp b/lib/Target/Lanai/LanaiFrameLowering.cpp
new file mode 100644
index 000000000000..cb048d568df7
--- /dev/null
+++ b/lib/Target/Lanai/LanaiFrameLowering.cpp
@@ -0,0 +1,220 @@
+//===-- LanaiFrameLowering.cpp - Lanai Frame Information ------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains the Lanai implementation of TargetFrameLowering class.
+//
+//===----------------------------------------------------------------------===//
+
+#include "LanaiFrameLowering.h"
+
+#include "LanaiInstrInfo.h"
+#include "LanaiMachineFunctionInfo.h"
+#include "LanaiSubtarget.h"
+#include "llvm/CodeGen/MachineFrameInfo.h"
+#include "llvm/CodeGen/MachineFunction.h"
+#include "llvm/CodeGen/MachineInstrBuilder.h"
+#include "llvm/CodeGen/MachineRegisterInfo.h"
+#include "llvm/IR/Function.h"
+
+using namespace llvm;
+
+// Determines the size of the frame and maximum call frame size.
+void LanaiFrameLowering::determineFrameLayout(MachineFunction &MF) const {
+ MachineFrameInfo *MFI = MF.getFrameInfo();
+ const LanaiRegisterInfo *LRI = STI.getRegisterInfo();
+
+ // Get the number of bytes to allocate from the FrameInfo.
+ unsigned FrameSize = MFI->getStackSize();
+
+ // Get the alignment.
+ unsigned StackAlign = LRI->needsStackRealignment(MF) ? MFI->getMaxAlignment()
+ : getStackAlignment();
+
+ // Get the maximum call frame size of all the calls.
+ unsigned MaxCallFrameSize = MFI->getMaxCallFrameSize();
+
+ // If we have dynamic alloca then MaxCallFrameSize needs to be aligned so
+ // that allocations will be aligned.
+ if (MFI->hasVarSizedObjects())
+ MaxCallFrameSize = alignTo(MaxCallFrameSize, StackAlign);
+
+ // Update maximum call frame size.
+ MFI->setMaxCallFrameSize(MaxCallFrameSize);
+
+ // Include call frame size in total.
+ if (!(hasReservedCallFrame(MF) && MFI->adjustsStack()))
+ FrameSize += MaxCallFrameSize;
+
+ // Make sure the frame is aligned.
+ FrameSize = alignTo(FrameSize, StackAlign);
+
+ // Update frame info.
+ MFI->setStackSize(FrameSize);
+}
+
+// Iterates through each basic block in a machine function and replaces
+// ADJDYNALLOC pseudo instructions with a Lanai:ADDI with the
+// maximum call frame size as the immediate.
+void LanaiFrameLowering::replaceAdjDynAllocPseudo(MachineFunction &MF) const {
+ const LanaiInstrInfo &LII =
+ *static_cast<const LanaiInstrInfo *>(STI.getInstrInfo());
+ unsigned MaxCallFrameSize = MF.getFrameInfo()->getMaxCallFrameSize();
+
+ for (MachineFunction::iterator MBB = MF.begin(), E = MF.end(); MBB != E;
+ ++MBB) {
+ MachineBasicBlock::iterator MBBI = MBB->begin();
+ while (MBBI != MBB->end()) {
+ MachineInstr &MI = *MBBI++;
+ if (MI.getOpcode() == Lanai::ADJDYNALLOC) {
+ DebugLoc DL = MI.getDebugLoc();
+ unsigned Dst = MI.getOperand(0).getReg();
+ unsigned Src = MI.getOperand(1).getReg();
+
+ BuildMI(*MBB, MI, DL, LII.get(Lanai::ADD_I_LO), Dst)
+ .addReg(Src)
+ .addImm(MaxCallFrameSize);
+ MI.eraseFromParent();
+ }
+ }
+ }
+}
+
+// Generates the following sequence for function entry:
+// st %fp,-4[*%sp] !push old FP
+// add %sp,8,%fp !generate new FP
+// sub %sp,0x4,%sp !allocate stack space (as needed)
+void LanaiFrameLowering::emitPrologue(MachineFunction &MF,
+ MachineBasicBlock &MBB) const {
+ assert(&MF.front() == &MBB && "Shrink-wrapping not yet supported");
+
+ MachineFrameInfo *MFI = MF.getFrameInfo();
+ const LanaiInstrInfo &LII =
+ *static_cast<const LanaiInstrInfo *>(STI.getInstrInfo());
+ MachineBasicBlock::iterator MBBI = MBB.begin();
+
+ // Debug location must be unknown since the first debug location is used
+ // to determine the end of the prologue.
+ DebugLoc DL;
+
+ // Determine the correct frame layout
+ determineFrameLayout(MF);
+
+ // FIXME: This appears to be overallocating. Needs investigation.
+ // Get the number of bytes to allocate from the FrameInfo.
+ unsigned StackSize = MFI->getStackSize();
+
+ // Push old FP
+ // st %fp,-4[*%sp]
+ BuildMI(MBB, MBBI, DL, LII.get(Lanai::SW_RI))
+ .addReg(Lanai::FP)
+ .addReg(Lanai::SP)
+ .addImm(-4)
+ .addImm(LPAC::makePreOp(LPAC::ADD))
+ .setMIFlag(MachineInstr::FrameSetup);
+
+ // Generate new FP
+ // add %sp,8,%fp
+ BuildMI(MBB, MBBI, DL, LII.get(Lanai::ADD_I_LO), Lanai::FP)
+ .addReg(Lanai::SP)
+ .addImm(8)
+ .setMIFlag(MachineInstr::FrameSetup);
+
+ // Allocate space on the stack if needed
+ // sub %sp,StackSize,%sp
+ if (StackSize != 0) {
+ BuildMI(MBB, MBBI, DL, LII.get(Lanai::SUB_I_LO), Lanai::SP)
+ .addReg(Lanai::SP)
+ .addImm(StackSize)
+ .setMIFlag(MachineInstr::FrameSetup);
+ }
+
+ // Replace ADJDYNANALLOC
+ if (MFI->hasVarSizedObjects())
+ replaceAdjDynAllocPseudo(MF);
+}
+
+MachineBasicBlock::iterator LanaiFrameLowering::eliminateCallFramePseudoInstr(
+ MachineFunction & /*MF*/, MachineBasicBlock &MBB,
+ MachineBasicBlock::iterator I) const {
+ // Discard ADJCALLSTACKDOWN, ADJCALLSTACKUP instructions.
+ return MBB.erase(I);
+}
+
+// The function epilogue should not depend on the current stack pointer!
+// It should use the frame pointer only. This is mandatory because
+// of alloca; we also take advantage of it to omit stack adjustments
+// before returning.
+//
+// Note that when we go to restore the preserved register values we must
+// not try to address their slots by using offsets from the stack pointer.
+// That's because the stack pointer may have been moved during the function
+// execution due to a call to alloca(). Rather, we must restore all
+// preserved registers via offsets from the frame pointer value.
+//
+// Note also that when the current frame is being "popped" (by adjusting
+// the value of the stack pointer) on function exit, we must (for the
+// sake of alloca) set the new value of the stack pointer based upon
+// the current value of the frame pointer. We can't just add what we
+// believe to be the (static) frame size to the stack pointer because
+// if we did that, and alloca() had been called during this function,
+// we would end up returning *without* having fully deallocated all of
+// the space grabbed by alloca. If that happened, and a function
+// containing one or more alloca() calls was called over and over again,
+// then the stack would grow without limit!
+//
+// RET is lowered to
+// ld -4[%fp],%pc # modify %pc (two delay slots)
+// as the return address is in the stack frame and mov to pc is allowed.
+// emitEpilogue emits
+// mov %fp,%sp # restore the stack pointer
+// ld -8[%fp],%fp # restore the caller's frame pointer
+// before RET and the delay slot filler will move RET such that these
+// instructions execute in the delay slots of the load to PC.
+void LanaiFrameLowering::emitEpilogue(MachineFunction & /*MF*/,
+ MachineBasicBlock &MBB) const {
+ MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr();
+ const LanaiInstrInfo &LII =
+ *static_cast<const LanaiInstrInfo *>(STI.getInstrInfo());
+ DebugLoc DL = MBBI->getDebugLoc();
+
+ // Restore the stack pointer using the callee's frame pointer value.
+ BuildMI(MBB, MBBI, DL, LII.get(Lanai::ADD_I_LO), Lanai::SP)
+ .addReg(Lanai::FP)
+ .addImm(0);
+
+ // Restore the frame pointer from the stack.
+ BuildMI(MBB, MBBI, DL, LII.get(Lanai::LDW_RI), Lanai::FP)
+ .addReg(Lanai::FP)
+ .addImm(-8)
+ .addImm(LPAC::ADD);
+}
+
+void LanaiFrameLowering::determineCalleeSaves(MachineFunction &MF,
+ BitVector &SavedRegs,
+ RegScavenger *RS) const {
+ TargetFrameLowering::determineCalleeSaves(MF, SavedRegs, RS);
+
+ MachineFrameInfo *MFI = MF.getFrameInfo();
+ const LanaiRegisterInfo *LRI =
+ static_cast<const LanaiRegisterInfo *>(STI.getRegisterInfo());
+ int Offset = -4;
+
+ // Reserve 4 bytes for the saved RCA
+ MFI->CreateFixedObject(4, Offset, true);
+ Offset -= 4;
+
+ // Reserve 4 bytes for the saved FP
+ MFI->CreateFixedObject(4, Offset, true);
+ Offset -= 4;
+
+ if (LRI->hasBasePointer(MF)) {
+ MFI->CreateFixedObject(4, Offset, true);
+ SavedRegs.reset(LRI->getBaseRegister());
+ }
+}