#include "M68kRegisterInfo.h"
#include "M68k.h"
#include "M68kMachineFunction.h"
#include "M68kSubtarget.h"
#include "MCTargetDesc/M68kMCTargetDesc.h"
#include "llvm/CodeGen/MachineFrameInfo.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/Type.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/raw_ostream.h"
#define GET_REGINFO_TARGET_DESC
#include "M68kGenRegisterInfo.inc"
#define DEBUG_TYPE "m68k-reg-info"
using namespace llvm;
static cl::opt<bool> EnableBasePointer(
"m68k-use-base-pointer", cl::Hidden, cl::init(true),
cl::desc("Enable use of a base pointer for complex stack frames"));
void M68kRegisterInfo::anchor() {}
M68kRegisterInfo::M68kRegisterInfo(const M68kSubtarget &ST)
: M68kGenRegisterInfo(M68k::A0, 0, 0, M68k::PC), Subtarget(ST) {
StackPtr = M68k::SP;
FramePtr = M68k::A6;
GlobalBasePtr = M68k::A5;
BasePtr = M68k::A4;
}
const MCPhysReg *
M68kRegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const {
return CSR_STD_SaveList;
}
const uint32_t *
M68kRegisterInfo::getCallPreservedMask(const MachineFunction &MF,
CallingConv::ID) const {
return CSR_STD_RegMask;
}
const TargetRegisterClass *
M68kRegisterInfo::getRegsForTailCall(const MachineFunction &MF) const {
return &M68k::XR32_TCRegClass;
}
unsigned
M68kRegisterInfo::getMatchingMegaReg(unsigned Reg,
const TargetRegisterClass *RC) const {
for (MCSuperRegIterator Super(Reg, this); Super.isValid(); ++Super)
if (RC->contains(*Super))
return *Super;
return 0;
}
const TargetRegisterClass *
M68kRegisterInfo::getMaximalPhysRegClass(unsigned reg, MVT VT) const {
assert(Register::isPhysicalRegister(reg) &&
"reg must be a physical register");
const TargetRegisterClass *BestRC = nullptr;
for (regclass_iterator I = regclass_begin(), E = regclass_end(); I != E;
++I) {
const TargetRegisterClass *RC = *I;
if ((VT == MVT::Other || isTypeLegalForClass(*RC, VT)) &&
RC->contains(reg) &&
(!BestRC ||
(BestRC->hasSubClass(RC) && RC->getNumRegs() > BestRC->getNumRegs())))
BestRC = RC;
}
assert(BestRC && "Couldn't find the register class");
return BestRC;
}
int M68kRegisterInfo::getRegisterOrder(unsigned Reg,
const TargetRegisterClass &TRC) const {
for (unsigned i = 0; i < TRC.getNumRegs(); ++i) {
if (regsOverlap(Reg, TRC.getRegister(i))) {
return i;
}
}
return -1;
}
int M68kRegisterInfo::getSpillRegisterOrder(unsigned Reg) const {
int Result = getRegisterOrder(Reg, *getRegClass(M68k::SPILLRegClassID));
assert(Result >= 0 && "Can not determine spill order");
return Result;
}
BitVector M68kRegisterInfo::getReservedRegs(const MachineFunction &MF) const {
const M68kFrameLowering *TFI = getFrameLowering(MF);
BitVector Reserved(getNumRegs());
auto setBitVector = [&Reserved, this](unsigned Reg) {
for (MCRegAliasIterator I(Reg, this, true); I.isValid(); ++I) {
Reserved.set(*I);
}
for (MCSubRegIterator I(Reg, this, true); I.isValid(); ++I) {
Reserved.set(*I);
}
};
for (size_t Reg = 0, Total = getNumRegs(); Reg != Total; ++Reg) {
if (MF.getSubtarget<M68kSubtarget>().isRegisterReservedByUser(Reg))
setBitVector(Reg);
}
setBitVector(M68k::PC);
setBitVector(M68k::SP);
if (TFI->hasFP(MF)) {
setBitVector(FramePtr);
}
if (hasBasePointer(MF)) {
CallingConv::ID CC = MF.getFunction().getCallingConv();
const uint32_t *RegMask = getCallPreservedMask(MF, CC);
if (MachineOperand::clobbersPhysReg(RegMask, getBaseRegister()))
report_fatal_error("Stack realignment in presence of dynamic allocas is "
"not supported with"
"this calling convention.");
setBitVector(getBaseRegister());
}
return Reserved;
}
void M68kRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
int SPAdj, unsigned FIOperandNum,
RegScavenger *RS) const {
MachineInstr &MI = *II;
MachineFunction &MF = *MI.getParent()->getParent();
const M68kFrameLowering *TFI = getFrameLowering(MF);
MachineOperand &Disp = MI.getOperand(FIOperandNum - 1);
MachineOperand &Base = MI.getOperand(FIOperandNum);
int Imm = (int)(Disp.getImm());
int FIndex = (int)(Base.getIndex());
bool AfterFPPop = false;
unsigned BasePtr;
if (hasBasePointer(MF))
BasePtr = (FIndex < 0 ? FramePtr : getBaseRegister());
else if (hasStackRealignment(MF))
BasePtr = (FIndex < 0 ? FramePtr : StackPtr);
else if (AfterFPPop)
BasePtr = StackPtr;
else
BasePtr = (TFI->hasFP(MF) ? FramePtr : StackPtr);
Base.ChangeToRegister(BasePtr, false);
int64_t FIOffset;
Register IgnoredFrameReg;
if (AfterFPPop) {
const MachineFrameInfo &MFI = MF.getFrameInfo();
FIOffset = MFI.getObjectOffset(FIndex) - TFI->getOffsetOfLocalArea();
} else {
FIOffset =
TFI->getFrameIndexReference(MF, FIndex, IgnoredFrameReg).getFixed();
}
if (BasePtr == StackPtr)
FIOffset += SPAdj;
Disp.ChangeToImmediate(FIOffset + Imm);
}
bool M68kRegisterInfo::requiresRegisterScavenging(
const MachineFunction &MF) const {
return true;
}
bool M68kRegisterInfo::trackLivenessAfterRegAlloc(
const MachineFunction &MF) const {
return true;
}
static bool CantUseSP(const MachineFrameInfo &MFI) {
return MFI.hasVarSizedObjects() || MFI.hasOpaqueSPAdjustment();
}
bool M68kRegisterInfo::hasBasePointer(const MachineFunction &MF) const {
const MachineFrameInfo &MFI = MF.getFrameInfo();
if (!EnableBasePointer)
return false;
bool CantUseFP = hasStackRealignment(MF);
return CantUseFP && CantUseSP(MFI);
}
bool M68kRegisterInfo::canRealignStack(const MachineFunction &MF) const {
if (!TargetRegisterInfo::canRealignStack(MF))
return false;
const MachineFrameInfo &MFI = MF.getFrameInfo();
const MachineRegisterInfo *MRI = &MF.getRegInfo();
if (!MRI->canReserveReg(FramePtr))
return false;
if (CantUseSP(MFI))
return MRI->canReserveReg(BasePtr);
return true;
}
Register M68kRegisterInfo::getFrameRegister(const MachineFunction &MF) const {
const TargetFrameLowering *TFI = MF.getSubtarget().getFrameLowering();
return TFI->hasFP(MF) ? FramePtr : StackPtr;
}
const TargetRegisterClass *M68kRegisterInfo::intRegClass(unsigned size) const {
return &M68k::DR32RegClass;
}