#include "M68kFrameLowering.h"
#include "M68kInstrBuilder.h"
#include "M68kInstrInfo.h"
#include "M68kMachineFunction.h"
#include "M68kSubtarget.h"
#include "llvm/ADT/SmallSet.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/Support/Alignment.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/TargetOptions.h"
using namespace llvm;
M68kFrameLowering::M68kFrameLowering(const M68kSubtarget &STI, Align Alignment)
: TargetFrameLowering(StackGrowsDown, Alignment, -4), STI(STI),
TII(*STI.getInstrInfo()), TRI(STI.getRegisterInfo()) {
SlotSize = STI.getSlotSize();
StackPtr = TRI->getStackRegister();
}
bool M68kFrameLowering::hasFP(const MachineFunction &MF) const {
const MachineFrameInfo &MFI = MF.getFrameInfo();
const TargetRegisterInfo *TRI = STI.getRegisterInfo();
return MF.getTarget().Options.DisableFramePointerElim(MF) ||
MFI.hasVarSizedObjects() || MFI.isFrameAddressTaken() ||
TRI->hasStackRealignment(MF);
}
bool M68kFrameLowering::hasReservedCallFrame(const MachineFunction &MF) const {
return !MF.getFrameInfo().hasVarSizedObjects() &&
!MF.getInfo<M68kMachineFunctionInfo>()->getHasPushSequences();
}
bool M68kFrameLowering::canSimplifyCallFramePseudos(
const MachineFunction &MF) const {
return hasReservedCallFrame(MF) ||
(hasFP(MF) && !TRI->hasStackRealignment(MF)) ||
TRI->hasBasePointer(MF);
}
bool M68kFrameLowering::needsFrameIndexResolution(
const MachineFunction &MF) const {
return MF.getFrameInfo().hasStackObjects() ||
MF.getInfo<M68kMachineFunctionInfo>()->getHasPushSequences();
}
StackOffset
M68kFrameLowering::getFrameIndexReference(const MachineFunction &MF, int FI,
Register &FrameReg) const {
const MachineFrameInfo &MFI = MF.getFrameInfo();
if (TRI->hasBasePointer(MF))
FrameReg = TRI->getBaseRegister();
else if (TRI->hasStackRealignment(MF))
FrameReg = TRI->getStackRegister();
else
FrameReg = TRI->getFrameRegister(MF);
int Offset = MFI.getObjectOffset(FI) - getOffsetOfLocalArea();
const M68kMachineFunctionInfo *MMFI = MF.getInfo<M68kMachineFunctionInfo>();
uint64_t StackSize = MFI.getStackSize();
bool HasFP = hasFP(MF);
if (TRI->hasBasePointer(MF)) {
assert(HasFP && "VLAs and dynamic stack realign, but no FP?!");
if (FI < 0) {
return StackOffset::getFixed(Offset + SlotSize);
}
assert((-(Offset + StackSize)) % MFI.getObjectAlign(FI).value() == 0);
return StackOffset::getFixed(Offset + StackSize);
}
if (TRI->hasStackRealignment(MF)) {
if (FI < 0) {
return StackOffset::getFixed(Offset + SlotSize);
}
assert((-(Offset + StackSize)) % MFI.getObjectAlign(FI).value() == 0);
return StackOffset::getFixed(Offset + StackSize);
}
if (!HasFP)
return StackOffset::getFixed(Offset + StackSize);
Offset += SlotSize;
int TailCallReturnAddrDelta = MMFI->getTCReturnAddrDelta();
if (TailCallReturnAddrDelta < 0)
Offset -= TailCallReturnAddrDelta;
return StackOffset::getFixed(Offset);
}
static unsigned findDeadCallerSavedReg(MachineBasicBlock &MBB,
MachineBasicBlock::iterator &MBBI,
const M68kRegisterInfo *TRI) {
const MachineFunction *MF = MBB.getParent();
if (MF->callsEHReturn())
return 0;
const TargetRegisterClass &AvailableRegs = *TRI->getRegsForTailCall(*MF);
if (MBBI == MBB.end())
return 0;
switch (MBBI->getOpcode()) {
default:
return 0;
case TargetOpcode::PATCHABLE_RET:
case M68k::RET: {
SmallSet<uint16_t, 8> Uses;
for (unsigned i = 0, e = MBBI->getNumOperands(); i != e; ++i) {
MachineOperand &MO = MBBI->getOperand(i);
if (!MO.isReg() || MO.isDef())
continue;
Register Reg = MO.getReg();
if (!Reg)
continue;
for (MCRegAliasIterator AI(Reg, TRI, true); AI.isValid(); ++AI)
Uses.insert(*AI);
}
for (auto CS : AvailableRegs)
if (!Uses.count(CS))
return CS;
}
}
return 0;
}
static bool isRegLiveIn(MachineBasicBlock &MBB, unsigned Reg) {
return llvm::any_of(MBB.liveins(),
[Reg](MachineBasicBlock::RegisterMaskPair RegMask) {
return RegMask.PhysReg == Reg;
});
}
uint64_t
M68kFrameLowering::calculateMaxStackAlign(const MachineFunction &MF) const {
const MachineFrameInfo &MFI = MF.getFrameInfo();
uint64_t MaxAlign = MFI.getMaxAlign().value(); unsigned StackAlign = getStackAlignment(); if (MF.getFunction().hasFnAttribute("stackrealign")) {
if (MFI.hasCalls())
MaxAlign = (StackAlign > MaxAlign) ? StackAlign : MaxAlign;
else if (MaxAlign < SlotSize)
MaxAlign = SlotSize;
}
return MaxAlign;
}
void M68kFrameLowering::BuildStackAlignAND(MachineBasicBlock &MBB,
MachineBasicBlock::iterator MBBI,
const DebugLoc &DL, unsigned Reg,
uint64_t MaxAlign) const {
uint64_t Val = -MaxAlign;
unsigned AndOp = M68k::AND32di;
unsigned MovOp = M68k::MOV32rr;
unsigned Tmp = M68k::D0;
BuildMI(MBB, MBBI, DL, TII.get(MovOp), Tmp)
.addReg(Reg)
.setMIFlag(MachineInstr::FrameSetup);
MachineInstr *MI = BuildMI(MBB, MBBI, DL, TII.get(AndOp), Tmp)
.addReg(Tmp)
.addImm(Val)
.setMIFlag(MachineInstr::FrameSetup);
MI->getOperand(3).setIsDead();
BuildMI(MBB, MBBI, DL, TII.get(MovOp), Reg)
.addReg(Tmp)
.setMIFlag(MachineInstr::FrameSetup);
}
MachineBasicBlock::iterator M68kFrameLowering::eliminateCallFramePseudoInstr(
MachineFunction &MF, MachineBasicBlock &MBB,
MachineBasicBlock::iterator I) const {
bool ReserveCallFrame = hasReservedCallFrame(MF);
unsigned Opcode = I->getOpcode();
bool IsDestroy = Opcode == TII.getCallFrameDestroyOpcode();
DebugLoc DL = I->getDebugLoc();
uint64_t Amount = !ReserveCallFrame ? I->getOperand(0).getImm() : 0;
uint64_t InternalAmt = (IsDestroy && Amount) ? I->getOperand(1).getImm() : 0;
I = MBB.erase(I);
if (!ReserveCallFrame) {
unsigned StackAlign = getStackAlignment();
Amount = alignTo(Amount, StackAlign);
MachineModuleInfo &MMI = MF.getMMI();
const auto &Fn = MF.getFunction();
bool DwarfCFI = MMI.hasDebugInfo() || Fn.needsUnwindTableEntry();
bool HasDwarfEHHandlers = !MF.getLandingPads().empty();
if (HasDwarfEHHandlers && !IsDestroy &&
MF.getInfo<M68kMachineFunctionInfo>()->getHasPushSequences()) {
BuildCFI(MBB, I, DL,
MCCFIInstruction::createGnuArgsSize(nullptr, Amount));
}
if (Amount == 0)
return I;
Amount -= InternalAmt;
if (IsDestroy && InternalAmt && DwarfCFI && !hasFP(MF))
BuildCFI(MBB, I, DL,
MCCFIInstruction::createAdjustCfaOffset(nullptr, -InternalAmt));
int64_t StackAdjustment = IsDestroy ? Amount : -Amount;
int64_t CfaAdjustment = -StackAdjustment;
if (StackAdjustment) {
StackAdjustment += mergeSPUpdates(MBB, I, true);
StackAdjustment += mergeSPUpdates(MBB, I, false);
if (StackAdjustment) {
BuildStackAdjustment(MBB, I, DL, StackAdjustment, false);
}
}
if (DwarfCFI && !hasFP(MF)) {
if (CfaAdjustment) {
BuildCFI(
MBB, I, DL,
MCCFIInstruction::createAdjustCfaOffset(nullptr, CfaAdjustment));
}
}
return I;
}
if (IsDestroy && InternalAmt) {
MachineBasicBlock::iterator CI = I;
MachineBasicBlock::iterator B = MBB.begin();
while (CI != B && !std::prev(CI)->isCall())
--CI;
BuildStackAdjustment(MBB, CI, DL, -InternalAmt, false);
}
return I;
}
void M68kFrameLowering::emitSPUpdate(MachineBasicBlock &MBB,
MachineBasicBlock::iterator &MBBI,
int64_t NumBytes, bool InEpilogue) const {
bool IsSub = NumBytes < 0;
uint64_t Offset = IsSub ? -NumBytes : NumBytes;
uint64_t Chunk = (1LL << 31) - 1;
DebugLoc DL = MBB.findDebugLoc(MBBI);
while (Offset) {
if (Offset > Chunk) {
Register Reg;
if (IsSub && !isRegLiveIn(MBB, M68k::D0))
Reg = M68k::D0;
else
Reg = findDeadCallerSavedReg(MBB, MBBI, TRI);
if (Reg) {
unsigned Opc = M68k::MOV32ri;
BuildMI(MBB, MBBI, DL, TII.get(Opc), Reg).addImm(Offset);
Opc = IsSub ? M68k::SUB32ar : M68k::ADD32ar;
MachineInstr *MI = BuildMI(MBB, MBBI, DL, TII.get(Opc), StackPtr)
.addReg(StackPtr)
.addReg(Reg);
MI->getOperand(3).setIsDead(); Offset = 0;
continue;
}
}
uint64_t ThisVal = std::min(Offset, Chunk);
MachineInstrBuilder MI = BuildStackAdjustment(
MBB, MBBI, DL, IsSub ? -ThisVal : ThisVal, InEpilogue);
if (IsSub)
MI.setMIFlag(MachineInstr::FrameSetup);
else
MI.setMIFlag(MachineInstr::FrameDestroy);
Offset -= ThisVal;
}
}
int M68kFrameLowering::mergeSPUpdates(MachineBasicBlock &MBB,
MachineBasicBlock::iterator &MBBI,
bool MergeWithPrevious) const {
if ((MergeWithPrevious && MBBI == MBB.begin()) ||
(!MergeWithPrevious && MBBI == MBB.end()))
return 0;
MachineBasicBlock::iterator PI = MergeWithPrevious ? std::prev(MBBI) : MBBI;
MachineBasicBlock::iterator NI =
MergeWithPrevious ? nullptr : std::next(MBBI);
unsigned Opc = PI->getOpcode();
int Offset = 0;
if (!MergeWithPrevious && NI != MBB.end() &&
NI->getOpcode() == TargetOpcode::CFI_INSTRUCTION) {
return Offset;
}
if (Opc == M68k::ADD32ai && PI->getOperand(0).getReg() == StackPtr) {
assert(PI->getOperand(1).getReg() == StackPtr);
Offset += PI->getOperand(2).getImm();
MBB.erase(PI);
if (!MergeWithPrevious)
MBBI = NI;
} else if (Opc == M68k::SUB32ai && PI->getOperand(0).getReg() == StackPtr) {
assert(PI->getOperand(1).getReg() == StackPtr);
Offset -= PI->getOperand(2).getImm();
MBB.erase(PI);
if (!MergeWithPrevious)
MBBI = NI;
}
return Offset;
}
MachineInstrBuilder M68kFrameLowering::BuildStackAdjustment(
MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
const DebugLoc &DL, int64_t Offset, bool InEpilogue) const {
assert(Offset != 0 && "zero offset stack adjustment requested");
bool IsSub = Offset < 0;
uint64_t AbsOffset = IsSub ? -Offset : Offset;
unsigned Opc = IsSub ? M68k::SUB32ai : M68k::ADD32ai;
MachineInstrBuilder MI = BuildMI(MBB, MBBI, DL, TII.get(Opc), StackPtr)
.addReg(StackPtr)
.addImm(AbsOffset);
MI->getOperand(3).setIsDead();
return MI;
}
void M68kFrameLowering::BuildCFI(MachineBasicBlock &MBB,
MachineBasicBlock::iterator MBBI,
const DebugLoc &DL,
const MCCFIInstruction &CFIInst) const {
MachineFunction &MF = *MBB.getParent();
unsigned CFIIndex = MF.addFrameInst(CFIInst);
BuildMI(MBB, MBBI, DL, TII.get(TargetOpcode::CFI_INSTRUCTION))
.addCFIIndex(CFIIndex);
}
void M68kFrameLowering::emitPrologueCalleeSavedFrameMoves(
MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
const DebugLoc &DL) const {
MachineFunction &MF = *MBB.getParent();
MachineFrameInfo &MFI = MF.getFrameInfo();
MachineModuleInfo &MMI = MF.getMMI();
const MCRegisterInfo *MRI = MMI.getContext().getRegisterInfo();
const auto &CSI = MFI.getCalleeSavedInfo();
if (CSI.empty())
return;
for (const auto &I : CSI) {
int64_t Offset = MFI.getObjectOffset(I.getFrameIdx());
Register Reg = I.getReg();
unsigned DwarfReg = MRI->getDwarfRegNum(Reg, true);
BuildCFI(MBB, MBBI, DL,
MCCFIInstruction::createOffset(nullptr, DwarfReg, Offset));
}
}
void M68kFrameLowering::emitPrologue(MachineFunction &MF,
MachineBasicBlock &MBB) const {
assert(&STI == &MF.getSubtarget<M68kSubtarget>() &&
"MF used frame lowering for wrong subtarget");
MachineBasicBlock::iterator MBBI = MBB.begin();
MachineFrameInfo &MFI = MF.getFrameInfo();
const auto &Fn = MF.getFunction();
MachineModuleInfo &MMI = MF.getMMI();
M68kMachineFunctionInfo *MMFI = MF.getInfo<M68kMachineFunctionInfo>();
uint64_t MaxAlign = calculateMaxStackAlign(MF); uint64_t StackSize = MFI.getStackSize(); bool HasFP = hasFP(MF);
bool NeedsDwarfCFI = MMI.hasDebugInfo() || Fn.needsUnwindTableEntry();
Register FramePtr = TRI->getFrameRegister(MF);
const unsigned MachineFramePtr = FramePtr;
unsigned BasePtr = TRI->getBaseRegister();
DebugLoc DL;
int TailCallReturnAddrDelta = MMFI->getTCReturnAddrDelta();
if (TailCallReturnAddrDelta < 0) {
MMFI->setCalleeSavedFrameSize(MMFI->getCalleeSavedFrameSize() -
TailCallReturnAddrDelta);
}
if (TailCallReturnAddrDelta < 0) {
BuildStackAdjustment(MBB, MBBI, DL, TailCallReturnAddrDelta,
false)
.setMIFlag(MachineInstr::FrameSetup);
}
uint64_t NumBytes = 0;
int stackGrowth = -SlotSize;
if (HasFP) {
uint64_t FrameSize = StackSize - SlotSize;
if (MMFI->getRestoreBasePointer())
FrameSize += SlotSize;
NumBytes = FrameSize - MMFI->getCalleeSavedFrameSize();
if (TRI->hasStackRealignment(MF))
NumBytes = alignTo(NumBytes, MaxAlign);
MFI.setOffsetAdjustment(-NumBytes);
BuildMI(MBB, MBBI, DL, TII.get(M68k::PUSH32r))
.addReg(MachineFramePtr, RegState::Kill)
.setMIFlag(MachineInstr::FrameSetup);
if (NeedsDwarfCFI) {
assert(StackSize);
BuildCFI(MBB, MBBI, DL,
MCCFIInstruction::cfiDefCfaOffset(nullptr, 2 * stackGrowth));
int DwarfFramePtr = TRI->getDwarfRegNum(MachineFramePtr, true);
assert(DwarfFramePtr > 0);
BuildCFI(MBB, MBBI, DL,
MCCFIInstruction::createOffset(nullptr, DwarfFramePtr,
2 * stackGrowth));
}
BuildMI(MBB, MBBI, DL, TII.get(M68k::MOV32aa), FramePtr)
.addReg(StackPtr)
.setMIFlag(MachineInstr::FrameSetup);
if (NeedsDwarfCFI) {
unsigned DwarfFramePtr = TRI->getDwarfRegNum(MachineFramePtr, true);
BuildCFI(MBB, MBBI, DL,
MCCFIInstruction::createDefCfaRegister(nullptr, DwarfFramePtr));
}
for (MachineBasicBlock &EveryMBB : MF)
EveryMBB.addLiveIn(MachineFramePtr);
} else {
NumBytes = StackSize - MMFI->getCalleeSavedFrameSize();
}
bool PushedRegs = false;
int StackOffset = 2 * stackGrowth;
while (MBBI != MBB.end() && MBBI->getFlag(MachineInstr::FrameSetup) &&
MBBI->getOpcode() == M68k::PUSH32r) {
PushedRegs = true;
++MBBI;
if (!HasFP && NeedsDwarfCFI) {
assert(StackSize);
BuildCFI(MBB, MBBI, DL,
MCCFIInstruction::cfiDefCfaOffset(nullptr, StackOffset));
StackOffset += stackGrowth;
}
}
if (TRI->hasStackRealignment(MF)) {
assert(HasFP && "There should be a frame pointer if stack is realigned.");
BuildStackAlignAND(MBB, MBBI, DL, StackPtr, MaxAlign);
}
NumBytes -= mergeSPUpdates(MBB, MBBI, true);
emitSPUpdate(MBB, MBBI, -(int64_t)NumBytes, false);
unsigned SPOrEstablisher = StackPtr;
if (TRI->hasBasePointer(MF)) {
BuildMI(MBB, MBBI, DL, TII.get(M68k::MOV32aa), BasePtr)
.addReg(SPOrEstablisher)
.setMIFlag(MachineInstr::FrameSetup);
if (MMFI->getRestoreBasePointer()) {
unsigned Opm = M68k::MOV32ja;
M68k::addRegIndirectWithDisp(BuildMI(MBB, MBBI, DL, TII.get(Opm)),
FramePtr, true,
MMFI->getRestoreBasePointerOffset())
.addReg(SPOrEstablisher)
.setMIFlag(MachineInstr::FrameSetup);
}
}
if (((!HasFP && NumBytes) || PushedRegs) && NeedsDwarfCFI) {
if (!HasFP && NumBytes) {
assert(StackSize);
BuildCFI(
MBB, MBBI, DL,
MCCFIInstruction::cfiDefCfaOffset(nullptr, -StackSize + stackGrowth));
}
if (PushedRegs)
emitPrologueCalleeSavedFrameMoves(MBB, MBBI, DL);
}
}
static bool isTailCallOpcode(unsigned Opc) {
return Opc == M68k::TCRETURNj || Opc == M68k::TCRETURNq;
}
void M68kFrameLowering::emitEpilogue(MachineFunction &MF,
MachineBasicBlock &MBB) const {
const MachineFrameInfo &MFI = MF.getFrameInfo();
M68kMachineFunctionInfo *MMFI = MF.getInfo<M68kMachineFunctionInfo>();
MachineBasicBlock::iterator MBBI = MBB.getFirstTerminator();
Optional<unsigned> RetOpcode;
if (MBBI != MBB.end())
RetOpcode = MBBI->getOpcode();
DebugLoc DL;
if (MBBI != MBB.end())
DL = MBBI->getDebugLoc();
Register FramePtr = TRI->getFrameRegister(MF);
unsigned MachineFramePtr = FramePtr;
uint64_t StackSize = MFI.getStackSize();
uint64_t MaxAlign = calculateMaxStackAlign(MF);
unsigned CSSize = MMFI->getCalleeSavedFrameSize();
uint64_t NumBytes = 0;
if (hasFP(MF)) {
uint64_t FrameSize = StackSize - SlotSize;
NumBytes = FrameSize - CSSize;
if (TRI->hasStackRealignment(MF))
NumBytes = alignTo(FrameSize, MaxAlign);
BuildMI(MBB, MBBI, DL, TII.get(M68k::POP32r), MachineFramePtr)
.setMIFlag(MachineInstr::FrameDestroy);
} else {
NumBytes = StackSize - CSSize;
}
while (MBBI != MBB.begin()) {
MachineBasicBlock::iterator PI = std::prev(MBBI);
unsigned Opc = PI->getOpcode();
if ((Opc != M68k::POP32r || !PI->getFlag(MachineInstr::FrameDestroy)) &&
Opc != M68k::DBG_VALUE && !PI->isTerminator())
break;
--MBBI;
}
MachineBasicBlock::iterator FirstCSPop = MBBI;
if (MBBI != MBB.end())
DL = MBBI->getDebugLoc();
if (NumBytes || MFI.hasVarSizedObjects())
NumBytes += mergeSPUpdates(MBB, MBBI, true);
if ((TRI->hasStackRealignment(MF) || MFI.hasVarSizedObjects())) {
if (TRI->hasStackRealignment(MF))
MBBI = FirstCSPop;
uint64_t LEAAmount = -CSSize;
if (LEAAmount != 0) {
unsigned Opc = M68k::LEA32p;
M68k::addRegIndirectWithDisp(
BuildMI(MBB, MBBI, DL, TII.get(Opc), StackPtr), FramePtr, false,
LEAAmount);
--MBBI;
} else {
unsigned Opc = (M68k::MOV32rr);
BuildMI(MBB, MBBI, DL, TII.get(Opc), StackPtr).addReg(FramePtr);
--MBBI;
}
} else if (NumBytes) {
emitSPUpdate(MBB, MBBI, NumBytes, true);
--MBBI;
}
if (!RetOpcode || !isTailCallOpcode(*RetOpcode)) {
int Offset = -1 * MMFI->getTCReturnAddrDelta();
assert(Offset >= 0 && "TCDelta should never be positive");
if (Offset) {
MBBI = MBB.getFirstTerminator();
Offset += mergeSPUpdates(MBB, MBBI, true);
emitSPUpdate(MBB, MBBI, Offset, true);
}
}
}
void M68kFrameLowering::determineCalleeSaves(MachineFunction &MF,
BitVector &SavedRegs,
RegScavenger *RS) const {
TargetFrameLowering::determineCalleeSaves(MF, SavedRegs, RS);
MachineFrameInfo &MFI = MF.getFrameInfo();
M68kMachineFunctionInfo *M68kFI = MF.getInfo<M68kMachineFunctionInfo>();
int64_t TailCallReturnAddrDelta = M68kFI->getTCReturnAddrDelta();
if (TailCallReturnAddrDelta < 0) {
MFI.CreateFixedObject(-TailCallReturnAddrDelta,
TailCallReturnAddrDelta - SlotSize, true);
}
if (TRI->hasBasePointer(MF)) {
SavedRegs.set(TRI->getBaseRegister());
}
}
bool M68kFrameLowering::assignCalleeSavedSpillSlots(
MachineFunction &MF, const TargetRegisterInfo *TRI,
std::vector<CalleeSavedInfo> &CSI) const {
MachineFrameInfo &MFI = MF.getFrameInfo();
M68kMachineFunctionInfo *M68kFI = MF.getInfo<M68kMachineFunctionInfo>();
int SpillSlotOffset = getOffsetOfLocalArea() + M68kFI->getTCReturnAddrDelta();
if (hasFP(MF)) {
SpillSlotOffset -= SlotSize;
MFI.CreateFixedSpillStackObject(SlotSize, SpillSlotOffset);
Register FPReg = TRI->getFrameRegister(MF);
for (unsigned i = 0, e = CSI.size(); i < e; ++i) {
if (TRI->regsOverlap(CSI[i].getReg(), FPReg)) {
CSI.erase(CSI.begin() + i);
break;
}
}
}
return false;
}
bool M68kFrameLowering::spillCalleeSavedRegisters(
MachineBasicBlock &MBB, MachineBasicBlock::iterator MI,
ArrayRef<CalleeSavedInfo> CSI, const TargetRegisterInfo *TRI) const {
auto &MRI = *static_cast<const M68kRegisterInfo *>(TRI);
auto DL = MBB.findDebugLoc(MI);
int FI = 0;
unsigned Mask = 0;
for (const auto &Info : CSI) {
FI = std::max(FI, Info.getFrameIdx());
Register Reg = Info.getReg();
unsigned Shift = MRI.getSpillRegisterOrder(Reg);
Mask |= 1 << Shift;
}
auto I =
M68k::addFrameReference(BuildMI(MBB, MI, DL, TII.get(M68k::MOVM32pm)), FI)
.addImm(Mask)
.setMIFlag(MachineInstr::FrameSetup);
const MachineFunction &MF = *MBB.getParent();
const MachineRegisterInfo &RI = MF.getRegInfo();
for (const auto &Info : CSI) {
Register Reg = Info.getReg();
bool IsLiveIn = RI.isLiveIn(Reg);
if (!IsLiveIn)
MBB.addLiveIn(Reg);
I.addReg(Reg, IsLiveIn ? RegState::Implicit : RegState::ImplicitKill);
M68k::addMemOperand(I, Info.getFrameIdx(), 0);
}
return true;
}
bool M68kFrameLowering::restoreCalleeSavedRegisters(
MachineBasicBlock &MBB, MachineBasicBlock::iterator MI,
MutableArrayRef<CalleeSavedInfo> CSI, const TargetRegisterInfo *TRI) const {
auto &MRI = *static_cast<const M68kRegisterInfo *>(TRI);
auto DL = MBB.findDebugLoc(MI);
int FI = 0;
unsigned Mask = 0;
for (const auto &Info : CSI) {
FI = std::max(FI, Info.getFrameIdx());
Register Reg = Info.getReg();
unsigned Shift = MRI.getSpillRegisterOrder(Reg);
Mask |= 1 << Shift;
}
auto I = M68k::addFrameReference(
BuildMI(MBB, MI, DL, TII.get(M68k::MOVM32mp)).addImm(Mask), FI)
.setMIFlag(MachineInstr::FrameDestroy);
for (const auto &Info : CSI) {
I.addReg(Info.getReg(), RegState::ImplicitDefine);
M68k::addMemOperand(I, Info.getFrameIdx(), 0);
}
return true;
}