| //====- 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<const BlackfinRegisterInfo*>(MF.getTarget().getRegisterInfo()); | |
| const BlackfinInstrInfo &TII = | |
| *static_cast<const BlackfinInstrInfo*>(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<const BlackfinRegisterInfo*>(MF.getTarget().getRegisterInfo()); | |
| const BlackfinInstrInfo &TII = | |
| *static_cast<const BlackfinInstrInfo*>(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<const BlackfinRegisterInfo*>(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)); | |
| } | |
| } |