//====- BlackfinFrameLowering.cpp - Blackfin Frame Information --*- C++ -*-===// // // 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 Blackfin implementation of TargetFrameLowering class. // //===----------------------------------------------------------------------===// #include "BlackfinFrameLowering.h" #include "BlackfinInstrInfo.h" #include "llvm/CodeGen/MachineFrameInfo.h" #include "llvm/CodeGen/MachineFunction.h" #include "llvm/CodeGen/MachineInstrBuilder.h" #include "llvm/CodeGen/RegisterScavenging.h" #include "llvm/Target/TargetOptions.h" using namespace llvm; // hasFP - Return true if the specified function should have a dedicated frame // pointer register. This is true if the function has variable sized allocas or // if frame pointer elimination is disabled. bool BlackfinFrameLowering::hasFP(const MachineFunction &MF) const { const MachineFrameInfo *MFI = MF.getFrameInfo(); return DisableFramePointerElim(MF) || MFI->adjustsStack() || MFI->hasVarSizedObjects(); } // Always reserve a call frame. We dont have enough registers to adjust SP. bool BlackfinFrameLowering:: hasReservedCallFrame(const MachineFunction &MF) const { return true; } // Emit a prologue that sets up a stack frame. // On function entry, R0-R2 and P0 may hold arguments. // R3, P1, and P2 may be used as scratch registers void BlackfinFrameLowering::emitPrologue(MachineFunction &MF) const { MachineBasicBlock &MBB = MF.front(); // Prolog goes in entry BB MachineBasicBlock::iterator MBBI = MBB.begin(); MachineFrameInfo *MFI = MF.getFrameInfo(); const BlackfinRegisterInfo *RegInfo = static_cast(MF.getTarget().getRegisterInfo()); const BlackfinInstrInfo &TII = *static_cast(MF.getTarget().getInstrInfo()); DebugLoc dl = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc(); int FrameSize = MFI->getStackSize(); if (FrameSize%4) { FrameSize = (FrameSize+3) & ~3; MFI->setStackSize(FrameSize); } if (!hasFP(MF)) { assert(!MFI->adjustsStack() && "FP elimination on a non-leaf function is not supported"); RegInfo->adjustRegister(MBB, MBBI, dl, BF::SP, BF::P1, -FrameSize); return; } // emit a LINK instruction if (FrameSize <= 0x3ffff) { BuildMI(MBB, MBBI, dl, TII.get(BF::LINK)).addImm(FrameSize); return; } // Frame is too big, do a manual LINK: // [--SP] = RETS; // [--SP] = FP; // FP = SP; // P1 = -FrameSize; // SP = SP + P1; BuildMI(MBB, MBBI, dl, TII.get(BF::PUSH)) .addReg(BF::RETS, RegState::Kill); BuildMI(MBB, MBBI, dl, TII.get(BF::PUSH)) .addReg(BF::FP, RegState::Kill); BuildMI(MBB, MBBI, dl, TII.get(BF::MOVE), BF::FP) .addReg(BF::SP); RegInfo->loadConstant(MBB, MBBI, dl, BF::P1, -FrameSize); BuildMI(MBB, MBBI, dl, TII.get(BF::ADDpp), BF::SP) .addReg(BF::SP, RegState::Kill) .addReg(BF::P1, RegState::Kill); } void BlackfinFrameLowering::emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const { MachineFrameInfo *MFI = MF.getFrameInfo(); const BlackfinRegisterInfo *RegInfo = static_cast(MF.getTarget().getRegisterInfo()); const BlackfinInstrInfo &TII = *static_cast(MF.getTarget().getInstrInfo()); MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr(); DebugLoc dl = MBBI->getDebugLoc(); int FrameSize = MFI->getStackSize(); assert(FrameSize%4 == 0 && "Misaligned frame size"); if (!hasFP(MF)) { assert(!MFI->adjustsStack() && "FP elimination on a non-leaf function is not supported"); RegInfo->adjustRegister(MBB, MBBI, dl, BF::SP, BF::P1, FrameSize); return; } // emit an UNLINK instruction BuildMI(MBB, MBBI, dl, TII.get(BF::UNLINK)); } void BlackfinFrameLowering:: processFunctionBeforeCalleeSavedScan(MachineFunction &MF, RegScavenger *RS) const { MachineFrameInfo *MFI = MF.getFrameInfo(); const BlackfinRegisterInfo *RegInfo = static_cast(MF.getTarget().getRegisterInfo()); const TargetRegisterClass *RC = BF::DPRegisterClass; if (RegInfo->requiresRegisterScavenging(MF)) { // Reserve a slot close to SP or frame pointer. RS->setScavengingFrameIndex(MFI->CreateStackObject(RC->getSize(), RC->getAlignment(), false)); } }