//===-- 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(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(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(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(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()); } }