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