MipsFrameLowering.cpp [plain text]
#include "MipsFrameLowering.h"
#include "MipsInstrInfo.h"
#include "MipsMachineFunction.h"
#include "llvm/Function.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/Support/CommandLine.h"
using namespace llvm;
bool MipsFrameLowering::hasFP(const MachineFunction &MF) const {
const MachineFrameInfo *MFI = MF.getFrameInfo();
return DisableFramePointerElim(MF) || MFI->hasVarSizedObjects();
}
void MipsFrameLowering::adjustMipsStackFrame(MachineFunction &MF) const {
MachineFrameInfo *MFI = MF.getFrameInfo();
MipsFunctionInfo *MipsFI = MF.getInfo<MipsFunctionInfo>();
const std::vector<CalleeSavedInfo> &CSI = MFI->getCalleeSavedInfo();
unsigned StackAlign = getStackAlignment();
unsigned RegSize = STI.isGP32bit() ? 4 : 8;
bool HasGP = MipsFI->needGPSaveRestore();
int MinCSFI = -1, MaxCSFI = -1;
int TopCPUSavedRegOff = -1, TopFPUSavedRegOff = -1;
MipsFI->adjustLoadArgsFI(MFI);
MipsFI->adjustStoreVarArgsFI(MFI);
unsigned CalleeSavedAreaSize = 0;
if (!CSI.empty()) {
MinCSFI = CSI[0].getFrameIdx();
MaxCSFI = CSI[CSI.size()-1].getFrameIdx();
}
for (unsigned i = 0, e = CSI.size(); i != e; ++i)
CalleeSavedAreaSize += MFI->getObjectAlignment(CSI[i].getFrameIdx());
unsigned StackOffset = HasGP ? (MipsFI->getGPStackOffset()+RegSize)
: (STI.isABI_O32() ? 16 : 0);
int LastOffsetFI = -1;
for (int i = 0, e = MFI->getObjectIndexEnd(); i != e; ++i) {
if (i >= MinCSFI && i <= MaxCSFI)
continue;
if (MFI->isDeadObjectIndex(i))
continue;
unsigned Offset =
StackOffset + MFI->getObjectOffset(i) - CalleeSavedAreaSize;
if (LastOffsetFI == -1)
LastOffsetFI = i;
if (Offset > MFI->getObjectOffset(LastOffsetFI))
LastOffsetFI = i;
MFI->setObjectOffset(i, Offset);
}
if (LastOffsetFI >= 0)
StackOffset = MFI->getObjectOffset(LastOffsetFI)+
MFI->getObjectSize(LastOffsetFI);
StackOffset = ((StackOffset+StackAlign-1)/StackAlign*StackAlign);
for (unsigned i = 0, e = CSI.size(); i != e ; ++i) {
unsigned Reg = CSI[i].getReg();
if (!Mips::CPURegsRegisterClass->contains(Reg))
break;
MFI->setObjectOffset(CSI[i].getFrameIdx(), StackOffset);
TopCPUSavedRegOff = StackOffset;
StackOffset += MFI->getObjectAlignment(CSI[i].getFrameIdx());
}
if (hasFP(MF) || MFI->adjustsStack()) {
MFI->setObjectOffset(MFI->CreateStackObject(RegSize, RegSize, true),
StackOffset);
MipsFI->setFPStackOffset(StackOffset);
TopCPUSavedRegOff = StackOffset;
StackOffset += RegSize;
MFI->setObjectOffset(MFI->CreateStackObject(RegSize, RegSize, true),
StackOffset);
MipsFI->setRAStackOffset(StackOffset);
StackOffset += RegSize;
if (MFI->adjustsStack())
TopCPUSavedRegOff += RegSize;
}
StackOffset = ((StackOffset+StackAlign-1)/StackAlign*StackAlign);
for (unsigned i = 0, e = CSI.size(); i != e; ++i) {
unsigned Reg = CSI[i].getReg();
if (Mips::CPURegsRegisterClass->contains(Reg))
continue;
MFI->setObjectOffset(CSI[i].getFrameIdx(), StackOffset);
TopFPUSavedRegOff = StackOffset;
StackOffset += MFI->getObjectAlignment(CSI[i].getFrameIdx());
}
StackOffset = ((StackOffset+StackAlign-1)/StackAlign*StackAlign);
MFI->setStackSize(StackOffset);
if (TopCPUSavedRegOff >= 0)
MipsFI->setCPUTopSavedRegOff(TopCPUSavedRegOff-StackOffset);
if (TopFPUSavedRegOff >= 0)
MipsFI->setFPUTopSavedRegOff(TopFPUSavedRegOff-StackOffset);
}
static bool expandRegLargeImmPair(unsigned OrigReg, int OrigImm,
unsigned& NewReg, int& NewImm,
MachineBasicBlock& MBB,
MachineBasicBlock::iterator I) {
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 = OrigImm & 0xffff;
int ImmHi = (((unsigned)OrigImm & 0xffff0000) >> 16) +
((OrigImm & 0x8000) != 0);
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;
}
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;
adjustMipsStackFrame(MF);
unsigned StackSize = MFI->getStackSize();
if (StackSize == 0 && !MFI->adjustsStack()) return;
int FPOffset = MipsFI->getFPStackOffset();
int RAOffset = MipsFI->getRAStackOffset();
BuildMI(MBB, MBBI, dl, TII.get(Mips::NOREORDER));
if (isPIC && STI.isABI_O32())
BuildMI(MBB, MBBI, dl, TII.get(Mips::CPLOAD))
.addReg(RegInfo->getPICCallReg());
BuildMI(MBB, MBBI, dl, TII.get(Mips::NOMACRO));
ATUsed = expandRegLargeImmPair(Mips::SP, -StackSize, NewReg, NewImm, MBB,
MBBI);
BuildMI(MBB, MBBI, dl, TII.get(Mips::ADDiu), Mips::SP)
.addReg(NewReg).addImm(NewImm);
if (ATUsed)
BuildMI(MBB, MBBI, dl, TII.get(Mips::ATMACRO));
if (MFI->adjustsStack()) {
ATUsed = expandRegLargeImmPair(Mips::SP, RAOffset, NewReg, NewImm, MBB,
MBBI);
BuildMI(MBB, MBBI, dl, TII.get(Mips::SW))
.addReg(Mips::RA).addImm(NewImm).addReg(NewReg);
if (ATUsed)
BuildMI(MBB, MBBI, dl, TII.get(Mips::ATMACRO));
}
if (hasFP(MF)) {
ATUsed = expandRegLargeImmPair(Mips::SP, FPOffset, NewReg, NewImm, MBB,
MBBI);
BuildMI(MBB, MBBI, dl, TII.get(Mips::SW))
.addReg(Mips::FP).addImm(NewImm).addReg(NewReg);
if (ATUsed)
BuildMI(MBB, MBBI, dl, TII.get(Mips::ATMACRO));
BuildMI(MBB, MBBI, dl, TII.get(Mips::ADDu), Mips::FP)
.addReg(Mips::SP).addReg(Mips::ZERO);
}
if (MipsFI->needGPSaveRestore())
BuildMI(MBB, MBBI, dl, TII.get(Mips::CPRESTORE))
.addImm(MipsFI->getGPStackOffset());
}
void MipsFrameLowering::emitEpilogue(MachineFunction &MF,
MachineBasicBlock &MBB) const {
MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr();
MachineFrameInfo *MFI = MF.getFrameInfo();
MipsFunctionInfo *MipsFI = MF.getInfo<MipsFunctionInfo>();
const MipsInstrInfo &TII =
*static_cast<const MipsInstrInfo*>(MF.getTarget().getInstrInfo());
DebugLoc dl = MBBI->getDebugLoc();
int NumBytes = (int) MFI->getStackSize();
int FPOffset = MipsFI->getFPStackOffset();
int RAOffset = MipsFI->getRAStackOffset();
unsigned NewReg = 0;
int NewImm = 0;
bool ATUsed = false;
if (hasFP(MF)) {
BuildMI(MBB, MBBI, dl, TII.get(Mips::ADDu), Mips::SP)
.addReg(Mips::FP).addReg(Mips::ZERO);
ATUsed = expandRegLargeImmPair(Mips::SP, FPOffset, NewReg, NewImm, MBB,
MBBI);
BuildMI(MBB, MBBI, dl, TII.get(Mips::LW), Mips::FP)
.addImm(NewImm).addReg(NewReg);
if (ATUsed)
BuildMI(MBB, MBBI, dl, TII.get(Mips::ATMACRO));
}
if (MFI->adjustsStack()) {
ATUsed = expandRegLargeImmPair(Mips::SP, RAOffset, NewReg, NewImm, MBB,
MBBI);
BuildMI(MBB, MBBI, dl, TII.get(Mips::LW), Mips::RA)
.addImm(NewImm).addReg(NewReg);
if (ATUsed)
BuildMI(MBB, MBBI, dl, TII.get(Mips::ATMACRO));
}
if (NumBytes) {
ATUsed = expandRegLargeImmPair(Mips::SP, NumBytes, NewReg, NewImm, MBB,
MBBI);
BuildMI(MBB, MBBI, dl, TII.get(Mips::ADDiu), Mips::SP)
.addReg(NewReg).addImm(NewImm);
if (ATUsed)
BuildMI(MBB, MBBI, dl, TII.get(Mips::ATMACRO));
}
}
void MipsFrameLowering::
processFunctionBeforeFrameFinalized(MachineFunction &MF) const {
const MipsRegisterInfo *RegInfo =
static_cast<const MipsRegisterInfo*>(MF.getTarget().getRegisterInfo());
RegInfo->processFunctionBeforeFrameFinalized(MF);
}