-//=======- MipsFrameLowering.cpp - Mips Frame Information ------*- C++ -*-====//
+//===-- MipsFrameLowering.cpp - Mips Frame Information --------------------===//
//
// The LLVM Compiler Infrastructure
//
//===----------------------------------------------------------------------===//
#include "MipsFrameLowering.h"
+#include "MCTargetDesc/MipsBaseInfo.h"
+#include "MipsAnalyzeImmediate.h"
#include "MipsInstrInfo.h"
#include "MipsMachineFunction.h"
-#include "llvm/Function.h"
+#include "MipsTargetMachine.h"
#include "llvm/CodeGen/MachineFrameInfo.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/CodeGen/MachineModuleInfo.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
-#include "llvm/Target/TargetData.h"
-#include "llvm/Target/TargetOptions.h"
+#include "llvm/IR/DataLayout.h"
+#include "llvm/IR/Function.h"
#include "llvm/Support/CommandLine.h"
+#include "llvm/Target/TargetOptions.h"
using namespace llvm;
//
//===----------------------------------------------------------------------===//
+const MipsFrameLowering *MipsFrameLowering::create(const MipsSubtarget &ST) {
+ if (ST.inMips16Mode())
+ return llvm::createMips16FrameLowering(ST);
+
+ return llvm::createMipsSEFrameLowering(ST);
+}
+
// 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 MipsFrameLowering::hasFP(const MachineFunction &MF) const {
const MachineFrameInfo *MFI = MF.getFrameInfo();
- return DisableFramePointerElim(MF) || MFI->hasVarSizedObjects();
-}
-
-bool MipsFrameLowering::targetHandlesStackFrameRounding() const {
- return true;
-}
-
-static unsigned AlignOffset(unsigned Offset, unsigned Align) {
- return (Offset + Align - 1) / Align * Align;
-}
-
-// expand pair of register and immediate if the immediate doesn't fit in the
-// 16-bit offset field.
-// e.g.
-// if OrigImm = 0x10000, OrigReg = $sp:
-// generate the following sequence of instrs:
-// lui $at, hi(0x10000)
-// addu $at, $sp, $at
-//
-// (NewReg, NewImm) = ($at, lo(Ox10000))
-// return true
-static bool expandRegLargeImmPair(unsigned OrigReg, int OrigImm,
- unsigned& NewReg, int& NewImm,
- MachineBasicBlock& MBB,
- MachineBasicBlock::iterator I) {
- // OrigImm fits in the 16-bit field
- if (OrigImm < 0x8000 && OrigImm >= -0x8000) {
- NewReg = OrigReg;
- NewImm = OrigImm;
- return false;
- }
-
- MachineFunction* MF = MBB.getParent();
- const TargetInstrInfo *TII = MF->getTarget().getInstrInfo();
- DebugLoc DL = I->getDebugLoc();
- int ImmLo = (short)(OrigImm & 0xffff);
- int ImmHi = (((unsigned)OrigImm & 0xffff0000) >> 16) +
- ((OrigImm & 0x8000) != 0);
-
- // FIXME: change this when mips goes MC".
- BuildMI(MBB, I, DL, TII->get(Mips::NOAT));
- BuildMI(MBB, I, DL, TII->get(Mips::LUi), Mips::AT).addImm(ImmHi);
- BuildMI(MBB, I, DL, TII->get(Mips::ADDu), Mips::AT).addReg(OrigReg)
- .addReg(Mips::AT);
- NewReg = Mips::AT;
- NewImm = ImmLo;
-
- return true;
+ return MF.getTarget().Options.DisableFramePointerElim(MF) ||
+ MFI->hasVarSizedObjects() || MFI->isFrameAddressTaken();
}
-void MipsFrameLowering::emitPrologue(MachineFunction &MF) const {
- MachineBasicBlock &MBB = MF.front();
- MachineFrameInfo *MFI = MF.getFrameInfo();
- MipsFunctionInfo *MipsFI = MF.getInfo<MipsFunctionInfo>();
- const MipsRegisterInfo *RegInfo =
- static_cast<const MipsRegisterInfo*>(MF.getTarget().getRegisterInfo());
- const MipsInstrInfo &TII =
- *static_cast<const MipsInstrInfo*>(MF.getTarget().getInstrInfo());
- MachineBasicBlock::iterator MBBI = MBB.begin();
- DebugLoc dl = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc();
- bool isPIC = (MF.getTarget().getRelocationModel() == Reloc::PIC_);
- unsigned NewReg = 0;
- int NewImm = 0;
- bool ATUsed;
-
- // First, compute final stack size.
- unsigned RegSize = STI.isGP32bit() ? 4 : 8;
- unsigned StackAlign = getStackAlignment();
- unsigned LocalVarAreaOffset = MipsFI->needGPSaveRestore() ?
- (MFI->getObjectOffset(MipsFI->getGPFI()) + RegSize) :
- MipsFI->getMaxCallFrameSize();
- unsigned StackSize = AlignOffset(LocalVarAreaOffset, StackAlign) +
- AlignOffset(MFI->getStackSize(), StackAlign);
-
- // Update stack size
- MFI->setStackSize(StackSize);
-
- BuildMI(MBB, MBBI, dl, TII.get(Mips::NOREORDER));
-
- // TODO: check need from GP here.
- if (isPIC && STI.isABI_O32())
- BuildMI(MBB, MBBI, dl, TII.get(Mips::CPLOAD))
- .addReg(RegInfo->getPICCallReg());
- BuildMI(MBB, MBBI, dl, TII.get(Mips::NOMACRO));
-
- // No need to allocate space on the stack.
- if (StackSize == 0 && !MFI->adjustsStack()) return;
-
- // Adjust stack : addi sp, sp, (-imm)
- ATUsed = expandRegLargeImmPair(Mips::SP, -StackSize, NewReg, NewImm, MBB,
- MBBI);
- BuildMI(MBB, MBBI, dl, TII.get(Mips::ADDiu), Mips::SP)
- .addReg(NewReg).addImm(NewImm);
-
- // FIXME: change this when mips goes MC".
- if (ATUsed)
- BuildMI(MBB, MBBI, dl, TII.get(Mips::ATMACRO));
-
- // if framepointer enabled, set it to point to the stack pointer.
- if (hasFP(MF)) {
- // Find the instruction past the last instruction that saves a callee-saved
- // register to the stack.
- const std::vector<CalleeSavedInfo> &CSI = MFI->getCalleeSavedInfo();
-
- for (unsigned i = 0; i < CSI.size(); ++i)
- ++MBBI;
-
- // Insert instruction "move $fp, $sp" at this location.
- BuildMI(MBB, MBBI, dl, TII.get(Mips::ADDu), Mips::FP)
- .addReg(Mips::SP).addReg(Mips::ZERO);
- }
-
- // Restore GP from the saved stack location
- if (MipsFI->needGPSaveRestore())
- BuildMI(MBB, MBBI, dl, TII.get(Mips::CPRESTORE))
- .addImm(MFI->getObjectOffset(MipsFI->getGPFI()));
-}
-
-void MipsFrameLowering::emitEpilogue(MachineFunction &MF,
- MachineBasicBlock &MBB) const {
- MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr();
- MachineFrameInfo *MFI = MF.getFrameInfo();
- const MipsInstrInfo &TII =
- *static_cast<const MipsInstrInfo*>(MF.getTarget().getInstrInfo());
- DebugLoc dl = MBBI->getDebugLoc();
-
- // Get the number of bytes from FrameInfo
- unsigned StackSize = MFI->getStackSize();
+uint64_t MipsFrameLowering::estimateStackSize(const MachineFunction &MF) const {
+ const MachineFrameInfo *MFI = MF.getFrameInfo();
+ const TargetRegisterInfo &TRI = *STI.getRegisterInfo();
- unsigned NewReg = 0;
- int NewImm = 0;
- bool ATUsed = false;
+ int64_t Offset = 0;
- // if framepointer enabled, restore the stack pointer.
- if (hasFP(MF)) {
- // Find the first instruction that restores a callee-saved register.
- MachineBasicBlock::iterator I = MBBI;
-
- for (unsigned i = 0; i < MFI->getCalleeSavedInfo().size(); ++i)
- --I;
+ // Iterate over fixed sized objects.
+ for (int I = MFI->getObjectIndexBegin(); I != 0; ++I)
+ Offset = std::max(Offset, -MFI->getObjectOffset(I));
- // Insert instruction "move $sp, $fp" at this location.
- BuildMI(MBB, I, dl, TII.get(Mips::ADDu), Mips::SP)
- .addReg(Mips::FP).addReg(Mips::ZERO);
+ // Conservatively assume all callee-saved registers will be saved.
+ for (const MCPhysReg *R = TRI.getCalleeSavedRegs(&MF); *R; ++R) {
+ unsigned Size = TRI.getMinimalPhysRegClass(*R)->getSize();
+ Offset = RoundUpToAlignment(Offset + Size, Size);
}
- // adjust stack : insert addi sp, sp, (imm)
- if (StackSize) {
- ATUsed = expandRegLargeImmPair(Mips::SP, StackSize, NewReg, NewImm, MBB,
- MBBI);
- BuildMI(MBB, MBBI, dl, TII.get(Mips::ADDiu), Mips::SP)
- .addReg(NewReg).addImm(NewImm);
-
- // FIXME: change this when mips goes MC".
- if (ATUsed)
- BuildMI(MBB, MBBI, dl, TII.get(Mips::ATMACRO));
- }
-}
+ unsigned MaxAlign = MFI->getMaxAlignment();
-void MipsFrameLowering::
-processFunctionBeforeCalleeSavedScan(MachineFunction &MF,
- RegScavenger *RS) const {
- MachineRegisterInfo& MRI = MF.getRegInfo();
- MipsFunctionInfo *MipsFI = MF.getInfo<MipsFunctionInfo>();
+ // Check that MaxAlign is not zero if there is a stack object that is not a
+ // callee-saved spill.
+ assert(!MFI->getObjectIndexEnd() || MaxAlign);
- // FIXME: remove this code if register allocator can correctly mark
- // $fp and $ra used or unused.
+ // Iterate over other objects.
+ for (unsigned I = 0, E = MFI->getObjectIndexEnd(); I != E; ++I)
+ Offset = RoundUpToAlignment(Offset + MFI->getObjectSize(I), MaxAlign);
- // Mark $fp and $ra as used or unused.
- if (hasFP(MF))
- MRI.setPhysRegUsed(Mips::FP);
+ // Call frame.
+ if (MFI->adjustsStack() && hasReservedCallFrame(MF))
+ Offset = RoundUpToAlignment(Offset + MFI->getMaxCallFrameSize(),
+ std::max(MaxAlign, getStackAlignment()));
- // The register allocator might determine $ra is used after seeing
- // instruction "jr $ra", but we do not want PrologEpilogInserter to insert
- // instructions to save/restore $ra unless there is a function call.
- // To correct this, $ra is explicitly marked unused if there is no
- // function call.
- if (MipsFI->hasCall())
- MRI.setPhysRegUsed(Mips::RA);
- else
- MRI.setPhysRegUnused(Mips::RA);
+ return RoundUpToAlignment(Offset, getStackAlignment());
}