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