#include "MSP430FrameLowering.h"
#include "MSP430InstrInfo.h"
#include "MSP430MachineFunctionInfo.h"
#include "MSP430Subtarget.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/IR/DataLayout.h"
#include "llvm/IR/Function.h"
#include "llvm/Target/TargetOptions.h"
using namespace llvm;
bool MSP430FrameLowering::hasFP(const MachineFunction &MF) const {
const MachineFrameInfo &MFI = MF.getFrameInfo();
return (MF.getTarget().Options.DisableFramePointerElim(MF) ||
MF.getFrameInfo().hasVarSizedObjects() ||
MFI.isFrameAddressTaken());
}
bool MSP430FrameLowering::hasReservedCallFrame(const MachineFunction &MF) const {
return !MF.getFrameInfo().hasVarSizedObjects();
}
void MSP430FrameLowering::emitPrologue(MachineFunction &MF,
MachineBasicBlock &MBB) const {
assert(&MF.front() == &MBB && "Shrink-wrapping not yet supported");
MachineFrameInfo &MFI = MF.getFrameInfo();
MSP430MachineFunctionInfo *MSP430FI = MF.getInfo<MSP430MachineFunctionInfo>();
const MSP430InstrInfo &TII =
*static_cast<const MSP430InstrInfo *>(MF.getSubtarget().getInstrInfo());
MachineBasicBlock::iterator MBBI = MBB.begin();
DebugLoc DL = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc();
uint64_t StackSize = MFI.getStackSize();
uint64_t NumBytes = 0;
if (hasFP(MF)) {
uint64_t FrameSize = StackSize - 2;
NumBytes = FrameSize - MSP430FI->getCalleeSavedFrameSize();
MFI.setOffsetAdjustment(-NumBytes);
BuildMI(MBB, MBBI, DL, TII.get(MSP430::PUSH16r))
.addReg(MSP430::R4, RegState::Kill);
BuildMI(MBB, MBBI, DL, TII.get(MSP430::MOV16rr), MSP430::R4)
.addReg(MSP430::SP);
for (MachineBasicBlock &MBBJ : llvm::drop_begin(MF))
MBBJ.addLiveIn(MSP430::R4);
} else
NumBytes = StackSize - MSP430FI->getCalleeSavedFrameSize();
while (MBBI != MBB.end() && (MBBI->getOpcode() == MSP430::PUSH16r))
++MBBI;
if (MBBI != MBB.end())
DL = MBBI->getDebugLoc();
if (NumBytes) {
if (NumBytes) {
MachineInstr *MI =
BuildMI(MBB, MBBI, DL, TII.get(MSP430::SUB16ri), MSP430::SP)
.addReg(MSP430::SP).addImm(NumBytes);
MI->getOperand(3).setIsDead();
}
}
}
void MSP430FrameLowering::emitEpilogue(MachineFunction &MF,
MachineBasicBlock &MBB) const {
const MachineFrameInfo &MFI = MF.getFrameInfo();
MSP430MachineFunctionInfo *MSP430FI = MF.getInfo<MSP430MachineFunctionInfo>();
const MSP430InstrInfo &TII =
*static_cast<const MSP430InstrInfo *>(MF.getSubtarget().getInstrInfo());
MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr();
unsigned RetOpcode = MBBI->getOpcode();
DebugLoc DL = MBBI->getDebugLoc();
switch (RetOpcode) {
case MSP430::RET:
case MSP430::RETI: break; default:
llvm_unreachable("Can only insert epilog into returning blocks");
}
uint64_t StackSize = MFI.getStackSize();
unsigned CSSize = MSP430FI->getCalleeSavedFrameSize();
uint64_t NumBytes = 0;
if (hasFP(MF)) {
uint64_t FrameSize = StackSize - 2;
NumBytes = FrameSize - CSSize;
BuildMI(MBB, MBBI, DL, TII.get(MSP430::POP16r), MSP430::R4);
} else
NumBytes = StackSize - CSSize;
while (MBBI != MBB.begin()) {
MachineBasicBlock::iterator PI = std::prev(MBBI);
unsigned Opc = PI->getOpcode();
if (Opc != MSP430::POP16r && !PI->isTerminator())
break;
--MBBI;
}
DL = MBBI->getDebugLoc();
if (MFI.hasVarSizedObjects()) {
BuildMI(MBB, MBBI, DL,
TII.get(MSP430::MOV16rr), MSP430::SP).addReg(MSP430::R4);
if (CSSize) {
MachineInstr *MI =
BuildMI(MBB, MBBI, DL,
TII.get(MSP430::SUB16ri), MSP430::SP)
.addReg(MSP430::SP).addImm(CSSize);
MI->getOperand(3).setIsDead();
}
} else {
if (NumBytes) {
MachineInstr *MI =
BuildMI(MBB, MBBI, DL, TII.get(MSP430::ADD16ri), MSP430::SP)
.addReg(MSP430::SP).addImm(NumBytes);
MI->getOperand(3).setIsDead();
}
}
}
bool MSP430FrameLowering::spillCalleeSavedRegisters(
MachineBasicBlock &MBB, MachineBasicBlock::iterator MI,
ArrayRef<CalleeSavedInfo> CSI, const TargetRegisterInfo *TRI) const {
if (CSI.empty())
return false;
DebugLoc DL;
if (MI != MBB.end()) DL = MI->getDebugLoc();
MachineFunction &MF = *MBB.getParent();
const TargetInstrInfo &TII = *MF.getSubtarget().getInstrInfo();
MSP430MachineFunctionInfo *MFI = MF.getInfo<MSP430MachineFunctionInfo>();
MFI->setCalleeSavedFrameSize(CSI.size() * 2);
for (const CalleeSavedInfo &I : llvm::reverse(CSI)) {
Register Reg = I.getReg();
MBB.addLiveIn(Reg);
BuildMI(MBB, MI, DL, TII.get(MSP430::PUSH16r))
.addReg(Reg, RegState::Kill);
}
return true;
}
bool MSP430FrameLowering::restoreCalleeSavedRegisters(
MachineBasicBlock &MBB, MachineBasicBlock::iterator MI,
MutableArrayRef<CalleeSavedInfo> CSI, const TargetRegisterInfo *TRI) const {
if (CSI.empty())
return false;
DebugLoc DL;
if (MI != MBB.end()) DL = MI->getDebugLoc();
MachineFunction &MF = *MBB.getParent();
const TargetInstrInfo &TII = *MF.getSubtarget().getInstrInfo();
for (const CalleeSavedInfo &I : CSI)
BuildMI(MBB, MI, DL, TII.get(MSP430::POP16r), I.getReg());
return true;
}
MachineBasicBlock::iterator MSP430FrameLowering::eliminateCallFramePseudoInstr(
MachineFunction &MF, MachineBasicBlock &MBB,
MachineBasicBlock::iterator I) const {
const MSP430InstrInfo &TII =
*static_cast<const MSP430InstrInfo *>(MF.getSubtarget().getInstrInfo());
if (!hasReservedCallFrame(MF)) {
MachineInstr &Old = *I;
uint64_t Amount = TII.getFrameSize(Old);
if (Amount != 0) {
Amount = alignTo(Amount, getStackAlign());
MachineInstr *New = nullptr;
if (Old.getOpcode() == TII.getCallFrameSetupOpcode()) {
New =
BuildMI(MF, Old.getDebugLoc(), TII.get(MSP430::SUB16ri), MSP430::SP)
.addReg(MSP430::SP)
.addImm(Amount);
} else {
assert(Old.getOpcode() == TII.getCallFrameDestroyOpcode());
Amount -= TII.getFramePoppedByCallee(Old);
if (Amount)
New = BuildMI(MF, Old.getDebugLoc(), TII.get(MSP430::ADD16ri),
MSP430::SP)
.addReg(MSP430::SP)
.addImm(Amount);
}
if (New) {
New->getOperand(3).setIsDead();
MBB.insert(I, New);
}
}
} else if (I->getOpcode() == TII.getCallFrameDestroyOpcode()) {
if (uint64_t CalleeAmt = TII.getFramePoppedByCallee(*I)) {
MachineInstr &Old = *I;
MachineInstr *New =
BuildMI(MF, Old.getDebugLoc(), TII.get(MSP430::SUB16ri), MSP430::SP)
.addReg(MSP430::SP)
.addImm(CalleeAmt);
New->getOperand(3).setIsDead();
MBB.insert(I, New);
}
}
return MBB.erase(I);
}
void
MSP430FrameLowering::processFunctionBeforeFrameFinalized(MachineFunction &MF,
RegScavenger *) const {
if (hasFP(MF)) {
int FrameIdx = MF.getFrameInfo().CreateFixedObject(2, -4, true);
(void)FrameIdx;
assert(FrameIdx == MF.getFrameInfo().getObjectIndexBegin() &&
"Slot for FP register must be last in order to be found!");
}
}