forked from OSchip/llvm-project
First step of huge frame-related refactoring: move emit{Prologue,Epilogue} out of TargetRegisterInfo to TargetFrameInfo, which is definitely much better suitable place
llvm-svn: 119097
This commit is contained in:
parent
a5ab8f10e4
commit
f7183edb59
|
@ -17,6 +17,8 @@
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
namespace llvm {
|
namespace llvm {
|
||||||
|
class MachineFunction;
|
||||||
|
class MachineBasicBlock;
|
||||||
|
|
||||||
/// Information about stack frame layout on the target. It holds the direction
|
/// Information about stack frame layout on the target. It holds the direction
|
||||||
/// of stack growth, the known stack alignment on entry to each function, and
|
/// of stack growth, the known stack alignment on entry to each function, and
|
||||||
|
@ -90,6 +92,19 @@ public:
|
||||||
NumEntries = 0;
|
NumEntries = 0;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// targetHandlesStackFrameRounding - Returns true if the target is
|
||||||
|
/// responsible for rounding up the stack frame (probably at emitPrologue
|
||||||
|
/// time).
|
||||||
|
virtual bool targetHandlesStackFrameRounding() const {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// emitProlog/emitEpilog - These methods insert prolog and epilog code into
|
||||||
|
/// the function.
|
||||||
|
virtual void emitPrologue(MachineFunction &MF) const = 0;
|
||||||
|
virtual void emitEpilogue(MachineFunction &MF,
|
||||||
|
MachineBasicBlock &MBB) const = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // End llvm namespace
|
} // End llvm namespace
|
||||||
|
|
|
@ -577,13 +577,6 @@ public:
|
||||||
// Do nothing.
|
// Do nothing.
|
||||||
}
|
}
|
||||||
|
|
||||||
/// targetHandlesStackFrameRounding - Returns true if the target is
|
|
||||||
/// responsible for rounding up the stack frame (probably at emitPrologue
|
|
||||||
/// time).
|
|
||||||
virtual bool targetHandlesStackFrameRounding() const {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// requiresRegisterScavenging - returns true if the target requires (and can
|
/// requiresRegisterScavenging - returns true if the target requires (and can
|
||||||
/// make use of) the register scavenger.
|
/// make use of) the register scavenger.
|
||||||
virtual bool requiresRegisterScavenging(const MachineFunction &MF) const {
|
virtual bool requiresRegisterScavenging(const MachineFunction &MF) const {
|
||||||
|
@ -749,12 +742,6 @@ public:
|
||||||
virtual void eliminateFrameIndex(MachineBasicBlock::iterator MI,
|
virtual void eliminateFrameIndex(MachineBasicBlock::iterator MI,
|
||||||
int SPAdj, RegScavenger *RS=NULL) const = 0;
|
int SPAdj, RegScavenger *RS=NULL) const = 0;
|
||||||
|
|
||||||
/// emitProlog/emitEpilog - These methods insert prolog and epilog code into
|
|
||||||
/// the function.
|
|
||||||
virtual void emitPrologue(MachineFunction &MF) const = 0;
|
|
||||||
virtual void emitEpilogue(MachineFunction &MF,
|
|
||||||
MachineBasicBlock &MBB) const = 0;
|
|
||||||
|
|
||||||
//===--------------------------------------------------------------------===//
|
//===--------------------------------------------------------------------===//
|
||||||
/// Debug information queries.
|
/// Debug information queries.
|
||||||
|
|
||||||
|
|
|
@ -641,7 +641,7 @@ void PEI::calculateFrameObjectOffsets(MachineFunction &Fn) {
|
||||||
AdjustStackOffset(MFI, SFI, StackGrowsDown, Offset, MaxAlign);
|
AdjustStackOffset(MFI, SFI, StackGrowsDown, Offset, MaxAlign);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!RegInfo->targetHandlesStackFrameRounding()) {
|
if (!TFI.targetHandlesStackFrameRounding()) {
|
||||||
// If we have reserved argument space for call sites in the function
|
// If we have reserved argument space for call sites in the function
|
||||||
// immediately on entry to the current function, count it as part of the
|
// immediately on entry to the current function, count it as part of the
|
||||||
// overall stack size.
|
// overall stack size.
|
||||||
|
@ -676,16 +676,16 @@ void PEI::calculateFrameObjectOffsets(MachineFunction &Fn) {
|
||||||
/// prolog and epilog code to the function.
|
/// prolog and epilog code to the function.
|
||||||
///
|
///
|
||||||
void PEI::insertPrologEpilogCode(MachineFunction &Fn) {
|
void PEI::insertPrologEpilogCode(MachineFunction &Fn) {
|
||||||
const TargetRegisterInfo *TRI = Fn.getTarget().getRegisterInfo();
|
const TargetFrameInfo &TFI = *Fn.getTarget().getFrameInfo();
|
||||||
|
|
||||||
// Add prologue to the function...
|
// Add prologue to the function...
|
||||||
TRI->emitPrologue(Fn);
|
TFI.emitPrologue(Fn);
|
||||||
|
|
||||||
// Add epilogue to restore the callee-save registers in each exiting block
|
// Add epilogue to restore the callee-save registers in each exiting block
|
||||||
for (MachineFunction::iterator I = Fn.begin(), E = Fn.end(); I != E; ++I) {
|
for (MachineFunction::iterator I = Fn.begin(), E = Fn.end(); I != E; ++I) {
|
||||||
// If last instruction is a return instruction, add an epilogue
|
// If last instruction is a return instruction, add an epilogue
|
||||||
if (!I->empty() && I->back().getDesc().isReturn())
|
if (!I->empty() && I->back().getDesc().isReturn())
|
||||||
TRI->emitEpilogue(Fn, *I);
|
TFI.emitEpilogue(Fn, *I);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1659,335 +1659,4 @@ ARMBaseRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Move iterator past the next bunch of callee save load / store ops for
|
|
||||||
/// the particular spill area (1: integer area 1, 2: integer area 2,
|
|
||||||
/// 3: fp area, 0: don't care).
|
|
||||||
static void movePastCSLoadStoreOps(MachineBasicBlock &MBB,
|
|
||||||
MachineBasicBlock::iterator &MBBI,
|
|
||||||
int Opc1, int Opc2, unsigned Area,
|
|
||||||
const ARMSubtarget &STI) {
|
|
||||||
while (MBBI != MBB.end() &&
|
|
||||||
((MBBI->getOpcode() == Opc1) || (MBBI->getOpcode() == Opc2)) &&
|
|
||||||
MBBI->getOperand(1).isFI()) {
|
|
||||||
if (Area != 0) {
|
|
||||||
bool Done = false;
|
|
||||||
unsigned Category = 0;
|
|
||||||
switch (MBBI->getOperand(0).getReg()) {
|
|
||||||
case ARM::R4: case ARM::R5: case ARM::R6: case ARM::R7:
|
|
||||||
case ARM::LR:
|
|
||||||
Category = 1;
|
|
||||||
break;
|
|
||||||
case ARM::R8: case ARM::R9: case ARM::R10: case ARM::R11:
|
|
||||||
Category = STI.isTargetDarwin() ? 2 : 1;
|
|
||||||
break;
|
|
||||||
case ARM::D8: case ARM::D9: case ARM::D10: case ARM::D11:
|
|
||||||
case ARM::D12: case ARM::D13: case ARM::D14: case ARM::D15:
|
|
||||||
Category = 3;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
Done = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (Done || Category != Area)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
++MBBI;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ARMBaseRegisterInfo::
|
|
||||||
emitPrologue(MachineFunction &MF) const {
|
|
||||||
MachineBasicBlock &MBB = MF.front();
|
|
||||||
MachineBasicBlock::iterator MBBI = MBB.begin();
|
|
||||||
MachineFrameInfo *MFI = MF.getFrameInfo();
|
|
||||||
ARMFunctionInfo *AFI = MF.getInfo<ARMFunctionInfo>();
|
|
||||||
assert(!AFI->isThumb1OnlyFunction() &&
|
|
||||||
"This emitPrologue does not support Thumb1!");
|
|
||||||
bool isARM = !AFI->isThumbFunction();
|
|
||||||
unsigned VARegSaveSize = AFI->getVarArgsRegSaveSize();
|
|
||||||
unsigned NumBytes = MFI->getStackSize();
|
|
||||||
const std::vector<CalleeSavedInfo> &CSI = MFI->getCalleeSavedInfo();
|
|
||||||
DebugLoc dl = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc();
|
|
||||||
|
|
||||||
// Determine the sizes of each callee-save spill areas and record which frame
|
|
||||||
// belongs to which callee-save spill areas.
|
|
||||||
unsigned GPRCS1Size = 0, GPRCS2Size = 0, DPRCSSize = 0;
|
|
||||||
int FramePtrSpillFI = 0;
|
|
||||||
|
|
||||||
// Allocate the vararg register save area. This is not counted in NumBytes.
|
|
||||||
if (VARegSaveSize)
|
|
||||||
emitSPUpdate(isARM, MBB, MBBI, dl, TII, -VARegSaveSize);
|
|
||||||
|
|
||||||
if (!AFI->hasStackFrame()) {
|
|
||||||
if (NumBytes != 0)
|
|
||||||
emitSPUpdate(isARM, MBB, MBBI, dl, TII, -NumBytes);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (unsigned i = 0, e = CSI.size(); i != e; ++i) {
|
|
||||||
unsigned Reg = CSI[i].getReg();
|
|
||||||
int FI = CSI[i].getFrameIdx();
|
|
||||||
switch (Reg) {
|
|
||||||
case ARM::R4:
|
|
||||||
case ARM::R5:
|
|
||||||
case ARM::R6:
|
|
||||||
case ARM::R7:
|
|
||||||
case ARM::LR:
|
|
||||||
if (Reg == FramePtr)
|
|
||||||
FramePtrSpillFI = FI;
|
|
||||||
AFI->addGPRCalleeSavedArea1Frame(FI);
|
|
||||||
GPRCS1Size += 4;
|
|
||||||
break;
|
|
||||||
case ARM::R8:
|
|
||||||
case ARM::R9:
|
|
||||||
case ARM::R10:
|
|
||||||
case ARM::R11:
|
|
||||||
if (Reg == FramePtr)
|
|
||||||
FramePtrSpillFI = FI;
|
|
||||||
if (STI.isTargetDarwin()) {
|
|
||||||
AFI->addGPRCalleeSavedArea2Frame(FI);
|
|
||||||
GPRCS2Size += 4;
|
|
||||||
} else {
|
|
||||||
AFI->addGPRCalleeSavedArea1Frame(FI);
|
|
||||||
GPRCS1Size += 4;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
AFI->addDPRCalleeSavedAreaFrame(FI);
|
|
||||||
DPRCSSize += 8;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Build the new SUBri to adjust SP for integer callee-save spill area 1.
|
|
||||||
emitSPUpdate(isARM, MBB, MBBI, dl, TII, -GPRCS1Size);
|
|
||||||
movePastCSLoadStoreOps(MBB, MBBI, ARM::STRi12, ARM::t2STRi12, 1, STI);
|
|
||||||
|
|
||||||
// Set FP to point to the stack slot that contains the previous FP.
|
|
||||||
// For Darwin, FP is R7, which has now been stored in spill area 1.
|
|
||||||
// Otherwise, if this is not Darwin, all the callee-saved registers go
|
|
||||||
// into spill area 1, including the FP in R11. In either case, it is
|
|
||||||
// now safe to emit this assignment.
|
|
||||||
bool HasFP = hasFP(MF);
|
|
||||||
if (HasFP) {
|
|
||||||
unsigned ADDriOpc = !AFI->isThumbFunction() ? ARM::ADDri : ARM::t2ADDri;
|
|
||||||
MachineInstrBuilder MIB =
|
|
||||||
BuildMI(MBB, MBBI, dl, TII.get(ADDriOpc), FramePtr)
|
|
||||||
.addFrameIndex(FramePtrSpillFI).addImm(0);
|
|
||||||
AddDefaultCC(AddDefaultPred(MIB));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Build the new SUBri to adjust SP for integer callee-save spill area 2.
|
|
||||||
emitSPUpdate(isARM, MBB, MBBI, dl, TII, -GPRCS2Size);
|
|
||||||
|
|
||||||
// Build the new SUBri to adjust SP for FP callee-save spill area.
|
|
||||||
movePastCSLoadStoreOps(MBB, MBBI, ARM::STRi12, ARM::t2STRi12, 2, STI);
|
|
||||||
emitSPUpdate(isARM, MBB, MBBI, dl, TII, -DPRCSSize);
|
|
||||||
|
|
||||||
// Determine starting offsets of spill areas.
|
|
||||||
unsigned DPRCSOffset = NumBytes - (GPRCS1Size + GPRCS2Size + DPRCSSize);
|
|
||||||
unsigned GPRCS2Offset = DPRCSOffset + DPRCSSize;
|
|
||||||
unsigned GPRCS1Offset = GPRCS2Offset + GPRCS2Size;
|
|
||||||
if (HasFP)
|
|
||||||
AFI->setFramePtrSpillOffset(MFI->getObjectOffset(FramePtrSpillFI) +
|
|
||||||
NumBytes);
|
|
||||||
AFI->setGPRCalleeSavedArea1Offset(GPRCS1Offset);
|
|
||||||
AFI->setGPRCalleeSavedArea2Offset(GPRCS2Offset);
|
|
||||||
AFI->setDPRCalleeSavedAreaOffset(DPRCSOffset);
|
|
||||||
|
|
||||||
movePastCSLoadStoreOps(MBB, MBBI, ARM::VSTRD, 0, 3, STI);
|
|
||||||
NumBytes = DPRCSOffset;
|
|
||||||
if (NumBytes) {
|
|
||||||
// Adjust SP after all the callee-save spills.
|
|
||||||
emitSPUpdate(isARM, MBB, MBBI, dl, TII, -NumBytes);
|
|
||||||
if (HasFP)
|
|
||||||
AFI->setShouldRestoreSPFromFP(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (STI.isTargetELF() && hasFP(MF)) {
|
|
||||||
MFI->setOffsetAdjustment(MFI->getOffsetAdjustment() -
|
|
||||||
AFI->getFramePtrSpillOffset());
|
|
||||||
AFI->setShouldRestoreSPFromFP(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
AFI->setGPRCalleeSavedArea1Size(GPRCS1Size);
|
|
||||||
AFI->setGPRCalleeSavedArea2Size(GPRCS2Size);
|
|
||||||
AFI->setDPRCalleeSavedAreaSize(DPRCSSize);
|
|
||||||
|
|
||||||
// If we need dynamic stack realignment, do it here. Be paranoid and make
|
|
||||||
// sure if we also have VLAs, we have a base pointer for frame access.
|
|
||||||
if (needsStackRealignment(MF)) {
|
|
||||||
unsigned MaxAlign = MFI->getMaxAlignment();
|
|
||||||
assert (!AFI->isThumb1OnlyFunction());
|
|
||||||
if (!AFI->isThumbFunction()) {
|
|
||||||
// Emit bic sp, sp, MaxAlign
|
|
||||||
AddDefaultCC(AddDefaultPred(BuildMI(MBB, MBBI, dl,
|
|
||||||
TII.get(ARM::BICri), ARM::SP)
|
|
||||||
.addReg(ARM::SP, RegState::Kill)
|
|
||||||
.addImm(MaxAlign-1)));
|
|
||||||
} else {
|
|
||||||
// We cannot use sp as source/dest register here, thus we're emitting the
|
|
||||||
// following sequence:
|
|
||||||
// mov r4, sp
|
|
||||||
// bic r4, r4, MaxAlign
|
|
||||||
// mov sp, r4
|
|
||||||
// FIXME: It will be better just to find spare register here.
|
|
||||||
BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVgpr2tgpr), ARM::R4)
|
|
||||||
.addReg(ARM::SP, RegState::Kill);
|
|
||||||
AddDefaultCC(AddDefaultPred(BuildMI(MBB, MBBI, dl,
|
|
||||||
TII.get(ARM::t2BICri), ARM::R4)
|
|
||||||
.addReg(ARM::R4, RegState::Kill)
|
|
||||||
.addImm(MaxAlign-1)));
|
|
||||||
BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVtgpr2gpr), ARM::SP)
|
|
||||||
.addReg(ARM::R4, RegState::Kill);
|
|
||||||
}
|
|
||||||
|
|
||||||
AFI->setShouldRestoreSPFromFP(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
// If we need a base pointer, set it up here. It's whatever the value
|
|
||||||
// of the stack pointer is at this point. Any variable size objects
|
|
||||||
// will be allocated after this, so we can still use the base pointer
|
|
||||||
// to reference locals.
|
|
||||||
if (hasBasePointer(MF)) {
|
|
||||||
if (isARM)
|
|
||||||
BuildMI(MBB, MBBI, dl, TII.get(ARM::MOVr), BasePtr)
|
|
||||||
.addReg(ARM::SP)
|
|
||||||
.addImm((unsigned)ARMCC::AL).addReg(0).addReg(0);
|
|
||||||
else
|
|
||||||
BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVgpr2gpr), BasePtr)
|
|
||||||
.addReg(ARM::SP);
|
|
||||||
}
|
|
||||||
|
|
||||||
// If the frame has variable sized objects then the epilogue must restore
|
|
||||||
// the sp from fp.
|
|
||||||
if (!AFI->shouldRestoreSPFromFP() && MFI->hasVarSizedObjects())
|
|
||||||
AFI->setShouldRestoreSPFromFP(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool isCalleeSavedRegister(unsigned Reg, const unsigned *CSRegs) {
|
|
||||||
for (unsigned i = 0; CSRegs[i]; ++i)
|
|
||||||
if (Reg == CSRegs[i])
|
|
||||||
return true;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool isCSRestore(MachineInstr *MI,
|
|
||||||
const ARMBaseInstrInfo &TII,
|
|
||||||
const unsigned *CSRegs) {
|
|
||||||
return ((MI->getOpcode() == (int)ARM::VLDRD ||
|
|
||||||
MI->getOpcode() == (int)ARM::LDRi12 ||
|
|
||||||
MI->getOpcode() == (int)ARM::t2LDRi12) &&
|
|
||||||
MI->getOperand(1).isFI() &&
|
|
||||||
isCalleeSavedRegister(MI->getOperand(0).getReg(), CSRegs));
|
|
||||||
}
|
|
||||||
|
|
||||||
void ARMBaseRegisterInfo::
|
|
||||||
emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const {
|
|
||||||
MachineBasicBlock::iterator MBBI = prior(MBB.end());
|
|
||||||
assert(MBBI->getDesc().isReturn() &&
|
|
||||||
"Can only insert epilog into returning blocks");
|
|
||||||
unsigned RetOpcode = MBBI->getOpcode();
|
|
||||||
DebugLoc dl = MBBI->getDebugLoc();
|
|
||||||
MachineFrameInfo *MFI = MF.getFrameInfo();
|
|
||||||
ARMFunctionInfo *AFI = MF.getInfo<ARMFunctionInfo>();
|
|
||||||
assert(!AFI->isThumb1OnlyFunction() &&
|
|
||||||
"This emitEpilogue does not support Thumb1!");
|
|
||||||
bool isARM = !AFI->isThumbFunction();
|
|
||||||
|
|
||||||
unsigned VARegSaveSize = AFI->getVarArgsRegSaveSize();
|
|
||||||
int NumBytes = (int)MFI->getStackSize();
|
|
||||||
|
|
||||||
if (!AFI->hasStackFrame()) {
|
|
||||||
if (NumBytes != 0)
|
|
||||||
emitSPUpdate(isARM, MBB, MBBI, dl, TII, NumBytes);
|
|
||||||
} else {
|
|
||||||
// Unwind MBBI to point to first LDR / VLDRD.
|
|
||||||
const unsigned *CSRegs = getCalleeSavedRegs();
|
|
||||||
if (MBBI != MBB.begin()) {
|
|
||||||
do
|
|
||||||
--MBBI;
|
|
||||||
while (MBBI != MBB.begin() && isCSRestore(MBBI, TII, CSRegs));
|
|
||||||
if (!isCSRestore(MBBI, TII, CSRegs))
|
|
||||||
++MBBI;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Move SP to start of FP callee save spill area.
|
|
||||||
NumBytes -= (AFI->getGPRCalleeSavedArea1Size() +
|
|
||||||
AFI->getGPRCalleeSavedArea2Size() +
|
|
||||||
AFI->getDPRCalleeSavedAreaSize());
|
|
||||||
|
|
||||||
// Reset SP based on frame pointer only if the stack frame extends beyond
|
|
||||||
// frame pointer stack slot or target is ELF and the function has FP.
|
|
||||||
if (AFI->shouldRestoreSPFromFP()) {
|
|
||||||
NumBytes = AFI->getFramePtrSpillOffset() - NumBytes;
|
|
||||||
if (NumBytes) {
|
|
||||||
if (isARM)
|
|
||||||
emitARMRegPlusImmediate(MBB, MBBI, dl, ARM::SP, FramePtr, -NumBytes,
|
|
||||||
ARMCC::AL, 0, TII);
|
|
||||||
else
|
|
||||||
emitT2RegPlusImmediate(MBB, MBBI, dl, ARM::SP, FramePtr, -NumBytes,
|
|
||||||
ARMCC::AL, 0, TII);
|
|
||||||
} else {
|
|
||||||
// Thumb2 or ARM.
|
|
||||||
if (isARM)
|
|
||||||
BuildMI(MBB, MBBI, dl, TII.get(ARM::MOVr), ARM::SP)
|
|
||||||
.addReg(FramePtr).addImm((unsigned)ARMCC::AL).addReg(0).addReg(0);
|
|
||||||
else
|
|
||||||
BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVgpr2gpr), ARM::SP)
|
|
||||||
.addReg(FramePtr);
|
|
||||||
}
|
|
||||||
} else if (NumBytes)
|
|
||||||
emitSPUpdate(isARM, MBB, MBBI, dl, TII, NumBytes);
|
|
||||||
|
|
||||||
// Move SP to start of integer callee save spill area 2.
|
|
||||||
movePastCSLoadStoreOps(MBB, MBBI, ARM::VLDRD, 0, 3, STI);
|
|
||||||
emitSPUpdate(isARM, MBB, MBBI, dl, TII, AFI->getDPRCalleeSavedAreaSize());
|
|
||||||
|
|
||||||
// Move SP to start of integer callee save spill area 1.
|
|
||||||
movePastCSLoadStoreOps(MBB, MBBI, ARM::LDRi12, ARM::t2LDRi12, 2, STI);
|
|
||||||
emitSPUpdate(isARM, MBB, MBBI, dl, TII, AFI->getGPRCalleeSavedArea2Size());
|
|
||||||
|
|
||||||
// Move SP to SP upon entry to the function.
|
|
||||||
movePastCSLoadStoreOps(MBB, MBBI, ARM::LDRi12, ARM::t2LDRi12, 1, STI);
|
|
||||||
emitSPUpdate(isARM, MBB, MBBI, dl, TII, AFI->getGPRCalleeSavedArea1Size());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (RetOpcode == ARM::TCRETURNdi || RetOpcode == ARM::TCRETURNdiND ||
|
|
||||||
RetOpcode == ARM::TCRETURNri || RetOpcode == ARM::TCRETURNriND) {
|
|
||||||
// Tail call return: adjust the stack pointer and jump to callee.
|
|
||||||
MBBI = prior(MBB.end());
|
|
||||||
MachineOperand &JumpTarget = MBBI->getOperand(0);
|
|
||||||
|
|
||||||
// Jump to label or value in register.
|
|
||||||
if (RetOpcode == ARM::TCRETURNdi) {
|
|
||||||
BuildMI(MBB, MBBI, dl,
|
|
||||||
TII.get(STI.isThumb() ? ARM::TAILJMPdt : ARM::TAILJMPd)).
|
|
||||||
addGlobalAddress(JumpTarget.getGlobal(), JumpTarget.getOffset(),
|
|
||||||
JumpTarget.getTargetFlags());
|
|
||||||
} else if (RetOpcode == ARM::TCRETURNdiND) {
|
|
||||||
BuildMI(MBB, MBBI, dl,
|
|
||||||
TII.get(STI.isThumb() ? ARM::TAILJMPdNDt : ARM::TAILJMPdND)).
|
|
||||||
addGlobalAddress(JumpTarget.getGlobal(), JumpTarget.getOffset(),
|
|
||||||
JumpTarget.getTargetFlags());
|
|
||||||
} else if (RetOpcode == ARM::TCRETURNri) {
|
|
||||||
BuildMI(MBB, MBBI, dl, TII.get(ARM::TAILJMPr)).
|
|
||||||
addReg(JumpTarget.getReg(), RegState::Kill);
|
|
||||||
} else if (RetOpcode == ARM::TCRETURNriND) {
|
|
||||||
BuildMI(MBB, MBBI, dl, TII.get(ARM::TAILJMPrND)).
|
|
||||||
addReg(JumpTarget.getReg(), RegState::Kill);
|
|
||||||
}
|
|
||||||
|
|
||||||
MachineInstr *NewMI = prior(MBBI);
|
|
||||||
for (unsigned i = 1, e = MBBI->getNumOperands(); i != e; ++i)
|
|
||||||
NewMI->addOperand(MBBI->getOperand(i));
|
|
||||||
|
|
||||||
// Delete the pseudo instruction TCRETURN.
|
|
||||||
MBB.erase(MBBI);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (VARegSaveSize)
|
|
||||||
emitSPUpdate(isARM, MBB, MBBI, dl, TII, VARegSaveSize);
|
|
||||||
}
|
|
||||||
|
|
||||||
#include "ARMGenRegisterInfo.inc"
|
#include "ARMGenRegisterInfo.inc"
|
||||||
|
|
|
@ -122,6 +122,7 @@ public:
|
||||||
// Debug information queries.
|
// Debug information queries.
|
||||||
unsigned getRARegister() const;
|
unsigned getRARegister() const;
|
||||||
unsigned getFrameRegister(const MachineFunction &MF) const;
|
unsigned getFrameRegister(const MachineFunction &MF) const;
|
||||||
|
unsigned getBaseRegister() const { return BasePtr; };
|
||||||
int getFrameIndexReference(const MachineFunction &MF, int FI,
|
int getFrameIndexReference(const MachineFunction &MF, int FI,
|
||||||
unsigned &FrameReg) const;
|
unsigned &FrameReg) const;
|
||||||
int ResolveFrameIndexReference(const MachineFunction &MF, int FI,
|
int ResolveFrameIndexReference(const MachineFunction &MF, int FI,
|
||||||
|
@ -166,9 +167,6 @@ public:
|
||||||
virtual void eliminateFrameIndex(MachineBasicBlock::iterator II,
|
virtual void eliminateFrameIndex(MachineBasicBlock::iterator II,
|
||||||
int SPAdj, RegScavenger *RS = NULL) const;
|
int SPAdj, RegScavenger *RS = NULL) const;
|
||||||
|
|
||||||
virtual void emitPrologue(MachineFunction &MF) const;
|
|
||||||
virtual void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
unsigned estimateRSStackSizeLimit(MachineFunction &MF) const;
|
unsigned estimateRSStackSizeLimit(MachineFunction &MF) const;
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,376 @@
|
||||||
|
//=======- ARMFrameInfo.cpp - ARM Frame Information ------------*- C++ -*-====//
|
||||||
|
//
|
||||||
|
// The LLVM Compiler Infrastructure
|
||||||
|
//
|
||||||
|
// This file is distributed under the University of Illinois Open Source
|
||||||
|
// License. See LICENSE.TXT for details.
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
//
|
||||||
|
// This file contains the ARM implementation of TargetFrameInfo class.
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
#include "ARMFrameInfo.h"
|
||||||
|
#include "ARMBaseInstrInfo.h"
|
||||||
|
#include "ARMMachineFunctionInfo.h"
|
||||||
|
#include "llvm/CodeGen/MachineFrameInfo.h"
|
||||||
|
#include "llvm/CodeGen/MachineFunction.h"
|
||||||
|
#include "llvm/CodeGen/MachineInstrBuilder.h"
|
||||||
|
|
||||||
|
using namespace llvm;
|
||||||
|
|
||||||
|
/// Move iterator past the next bunch of callee save load / store ops for
|
||||||
|
/// the particular spill area (1: integer area 1, 2: integer area 2,
|
||||||
|
/// 3: fp area, 0: don't care).
|
||||||
|
static void movePastCSLoadStoreOps(MachineBasicBlock &MBB,
|
||||||
|
MachineBasicBlock::iterator &MBBI,
|
||||||
|
int Opc1, int Opc2, unsigned Area,
|
||||||
|
const ARMSubtarget &STI) {
|
||||||
|
while (MBBI != MBB.end() &&
|
||||||
|
((MBBI->getOpcode() == Opc1) || (MBBI->getOpcode() == Opc2)) &&
|
||||||
|
MBBI->getOperand(1).isFI()) {
|
||||||
|
if (Area != 0) {
|
||||||
|
bool Done = false;
|
||||||
|
unsigned Category = 0;
|
||||||
|
switch (MBBI->getOperand(0).getReg()) {
|
||||||
|
case ARM::R4: case ARM::R5: case ARM::R6: case ARM::R7:
|
||||||
|
case ARM::LR:
|
||||||
|
Category = 1;
|
||||||
|
break;
|
||||||
|
case ARM::R8: case ARM::R9: case ARM::R10: case ARM::R11:
|
||||||
|
Category = STI.isTargetDarwin() ? 2 : 1;
|
||||||
|
break;
|
||||||
|
case ARM::D8: case ARM::D9: case ARM::D10: case ARM::D11:
|
||||||
|
case ARM::D12: case ARM::D13: case ARM::D14: case ARM::D15:
|
||||||
|
Category = 3;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
Done = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (Done || Category != Area)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
++MBBI;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool isCalleeSavedRegister(unsigned Reg, const unsigned *CSRegs) {
|
||||||
|
for (unsigned i = 0; CSRegs[i]; ++i)
|
||||||
|
if (Reg == CSRegs[i])
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool isCSRestore(MachineInstr *MI,
|
||||||
|
const ARMBaseInstrInfo &TII,
|
||||||
|
const unsigned *CSRegs) {
|
||||||
|
return ((MI->getOpcode() == (int)ARM::VLDRD ||
|
||||||
|
MI->getOpcode() == (int)ARM::LDRi12 ||
|
||||||
|
MI->getOpcode() == (int)ARM::t2LDRi12) &&
|
||||||
|
MI->getOperand(1).isFI() &&
|
||||||
|
isCalleeSavedRegister(MI->getOperand(0).getReg(), CSRegs));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
emitSPUpdate(bool isARM,
|
||||||
|
MachineBasicBlock &MBB, MachineBasicBlock::iterator &MBBI,
|
||||||
|
DebugLoc dl, const ARMBaseInstrInfo &TII,
|
||||||
|
int NumBytes,
|
||||||
|
ARMCC::CondCodes Pred = ARMCC::AL, unsigned PredReg = 0) {
|
||||||
|
if (isARM)
|
||||||
|
emitARMRegPlusImmediate(MBB, MBBI, dl, ARM::SP, ARM::SP, NumBytes,
|
||||||
|
Pred, PredReg, TII);
|
||||||
|
else
|
||||||
|
emitT2RegPlusImmediate(MBB, MBBI, dl, ARM::SP, ARM::SP, NumBytes,
|
||||||
|
Pred, PredReg, TII);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ARMFrameInfo::emitPrologue(MachineFunction &MF) const {
|
||||||
|
MachineBasicBlock &MBB = MF.front();
|
||||||
|
MachineBasicBlock::iterator MBBI = MBB.begin();
|
||||||
|
MachineFrameInfo *MFI = MF.getFrameInfo();
|
||||||
|
ARMFunctionInfo *AFI = MF.getInfo<ARMFunctionInfo>();
|
||||||
|
const ARMBaseRegisterInfo *RegInfo =
|
||||||
|
static_cast<const ARMBaseRegisterInfo*>(MF.getTarget().getRegisterInfo());
|
||||||
|
const ARMBaseInstrInfo &TII =
|
||||||
|
*static_cast<const ARMBaseInstrInfo*>(MF.getTarget().getInstrInfo());
|
||||||
|
assert(!AFI->isThumb1OnlyFunction() &&
|
||||||
|
"This emitPrologue does not support Thumb1!");
|
||||||
|
bool isARM = !AFI->isThumbFunction();
|
||||||
|
unsigned VARegSaveSize = AFI->getVarArgsRegSaveSize();
|
||||||
|
unsigned NumBytes = MFI->getStackSize();
|
||||||
|
const std::vector<CalleeSavedInfo> &CSI = MFI->getCalleeSavedInfo();
|
||||||
|
DebugLoc dl = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc();
|
||||||
|
unsigned FramePtr = RegInfo->getFrameRegister(MF);
|
||||||
|
|
||||||
|
// Determine the sizes of each callee-save spill areas and record which frame
|
||||||
|
// belongs to which callee-save spill areas.
|
||||||
|
unsigned GPRCS1Size = 0, GPRCS2Size = 0, DPRCSSize = 0;
|
||||||
|
int FramePtrSpillFI = 0;
|
||||||
|
|
||||||
|
// Allocate the vararg register save area. This is not counted in NumBytes.
|
||||||
|
if (VARegSaveSize)
|
||||||
|
emitSPUpdate(isARM, MBB, MBBI, dl, TII, -VARegSaveSize);
|
||||||
|
|
||||||
|
if (!AFI->hasStackFrame()) {
|
||||||
|
if (NumBytes != 0)
|
||||||
|
emitSPUpdate(isARM, MBB, MBBI, dl, TII, -NumBytes);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (unsigned i = 0, e = CSI.size(); i != e; ++i) {
|
||||||
|
unsigned Reg = CSI[i].getReg();
|
||||||
|
int FI = CSI[i].getFrameIdx();
|
||||||
|
switch (Reg) {
|
||||||
|
case ARM::R4:
|
||||||
|
case ARM::R5:
|
||||||
|
case ARM::R6:
|
||||||
|
case ARM::R7:
|
||||||
|
case ARM::LR:
|
||||||
|
if (Reg == FramePtr)
|
||||||
|
FramePtrSpillFI = FI;
|
||||||
|
AFI->addGPRCalleeSavedArea1Frame(FI);
|
||||||
|
GPRCS1Size += 4;
|
||||||
|
break;
|
||||||
|
case ARM::R8:
|
||||||
|
case ARM::R9:
|
||||||
|
case ARM::R10:
|
||||||
|
case ARM::R11:
|
||||||
|
if (Reg == FramePtr)
|
||||||
|
FramePtrSpillFI = FI;
|
||||||
|
if (STI.isTargetDarwin()) {
|
||||||
|
AFI->addGPRCalleeSavedArea2Frame(FI);
|
||||||
|
GPRCS2Size += 4;
|
||||||
|
} else {
|
||||||
|
AFI->addGPRCalleeSavedArea1Frame(FI);
|
||||||
|
GPRCS1Size += 4;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
AFI->addDPRCalleeSavedAreaFrame(FI);
|
||||||
|
DPRCSSize += 8;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Build the new SUBri to adjust SP for integer callee-save spill area 1.
|
||||||
|
emitSPUpdate(isARM, MBB, MBBI, dl, TII, -GPRCS1Size);
|
||||||
|
movePastCSLoadStoreOps(MBB, MBBI, ARM::STRi12, ARM::t2STRi12, 1, STI);
|
||||||
|
|
||||||
|
// Set FP to point to the stack slot that contains the previous FP.
|
||||||
|
// For Darwin, FP is R7, which has now been stored in spill area 1.
|
||||||
|
// Otherwise, if this is not Darwin, all the callee-saved registers go
|
||||||
|
// into spill area 1, including the FP in R11. In either case, it is
|
||||||
|
// now safe to emit this assignment.
|
||||||
|
bool HasFP = RegInfo->hasFP(MF);
|
||||||
|
if (HasFP) {
|
||||||
|
unsigned ADDriOpc = !AFI->isThumbFunction() ? ARM::ADDri : ARM::t2ADDri;
|
||||||
|
MachineInstrBuilder MIB =
|
||||||
|
BuildMI(MBB, MBBI, dl, TII.get(ADDriOpc), FramePtr)
|
||||||
|
.addFrameIndex(FramePtrSpillFI).addImm(0);
|
||||||
|
AddDefaultCC(AddDefaultPred(MIB));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Build the new SUBri to adjust SP for integer callee-save spill area 2.
|
||||||
|
emitSPUpdate(isARM, MBB, MBBI, dl, TII, -GPRCS2Size);
|
||||||
|
|
||||||
|
// Build the new SUBri to adjust SP for FP callee-save spill area.
|
||||||
|
movePastCSLoadStoreOps(MBB, MBBI, ARM::STRi12, ARM::t2STRi12, 2, STI);
|
||||||
|
emitSPUpdate(isARM, MBB, MBBI, dl, TII, -DPRCSSize);
|
||||||
|
|
||||||
|
// Determine starting offsets of spill areas.
|
||||||
|
unsigned DPRCSOffset = NumBytes - (GPRCS1Size + GPRCS2Size + DPRCSSize);
|
||||||
|
unsigned GPRCS2Offset = DPRCSOffset + DPRCSSize;
|
||||||
|
unsigned GPRCS1Offset = GPRCS2Offset + GPRCS2Size;
|
||||||
|
if (HasFP)
|
||||||
|
AFI->setFramePtrSpillOffset(MFI->getObjectOffset(FramePtrSpillFI) +
|
||||||
|
NumBytes);
|
||||||
|
AFI->setGPRCalleeSavedArea1Offset(GPRCS1Offset);
|
||||||
|
AFI->setGPRCalleeSavedArea2Offset(GPRCS2Offset);
|
||||||
|
AFI->setDPRCalleeSavedAreaOffset(DPRCSOffset);
|
||||||
|
|
||||||
|
movePastCSLoadStoreOps(MBB, MBBI, ARM::VSTRD, 0, 3, STI);
|
||||||
|
NumBytes = DPRCSOffset;
|
||||||
|
if (NumBytes) {
|
||||||
|
// Adjust SP after all the callee-save spills.
|
||||||
|
emitSPUpdate(isARM, MBB, MBBI, dl, TII, -NumBytes);
|
||||||
|
if (HasFP)
|
||||||
|
AFI->setShouldRestoreSPFromFP(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (STI.isTargetELF() && RegInfo->hasFP(MF)) {
|
||||||
|
MFI->setOffsetAdjustment(MFI->getOffsetAdjustment() -
|
||||||
|
AFI->getFramePtrSpillOffset());
|
||||||
|
AFI->setShouldRestoreSPFromFP(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
AFI->setGPRCalleeSavedArea1Size(GPRCS1Size);
|
||||||
|
AFI->setGPRCalleeSavedArea2Size(GPRCS2Size);
|
||||||
|
AFI->setDPRCalleeSavedAreaSize(DPRCSSize);
|
||||||
|
|
||||||
|
// If we need dynamic stack realignment, do it here. Be paranoid and make
|
||||||
|
// sure if we also have VLAs, we have a base pointer for frame access.
|
||||||
|
if (RegInfo->needsStackRealignment(MF)) {
|
||||||
|
unsigned MaxAlign = MFI->getMaxAlignment();
|
||||||
|
assert (!AFI->isThumb1OnlyFunction());
|
||||||
|
if (!AFI->isThumbFunction()) {
|
||||||
|
// Emit bic sp, sp, MaxAlign
|
||||||
|
AddDefaultCC(AddDefaultPred(BuildMI(MBB, MBBI, dl,
|
||||||
|
TII.get(ARM::BICri), ARM::SP)
|
||||||
|
.addReg(ARM::SP, RegState::Kill)
|
||||||
|
.addImm(MaxAlign-1)));
|
||||||
|
} else {
|
||||||
|
// We cannot use sp as source/dest register here, thus we're emitting the
|
||||||
|
// following sequence:
|
||||||
|
// mov r4, sp
|
||||||
|
// bic r4, r4, MaxAlign
|
||||||
|
// mov sp, r4
|
||||||
|
// FIXME: It will be better just to find spare register here.
|
||||||
|
BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVgpr2tgpr), ARM::R4)
|
||||||
|
.addReg(ARM::SP, RegState::Kill);
|
||||||
|
AddDefaultCC(AddDefaultPred(BuildMI(MBB, MBBI, dl,
|
||||||
|
TII.get(ARM::t2BICri), ARM::R4)
|
||||||
|
.addReg(ARM::R4, RegState::Kill)
|
||||||
|
.addImm(MaxAlign-1)));
|
||||||
|
BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVtgpr2gpr), ARM::SP)
|
||||||
|
.addReg(ARM::R4, RegState::Kill);
|
||||||
|
}
|
||||||
|
|
||||||
|
AFI->setShouldRestoreSPFromFP(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we need a base pointer, set it up here. It's whatever the value
|
||||||
|
// of the stack pointer is at this point. Any variable size objects
|
||||||
|
// will be allocated after this, so we can still use the base pointer
|
||||||
|
// to reference locals.
|
||||||
|
if (RegInfo->hasBasePointer(MF)) {
|
||||||
|
if (isARM)
|
||||||
|
BuildMI(MBB, MBBI, dl,
|
||||||
|
TII.get(ARM::MOVr), RegInfo->getBaseRegister())
|
||||||
|
.addReg(ARM::SP)
|
||||||
|
.addImm((unsigned)ARMCC::AL).addReg(0).addReg(0);
|
||||||
|
else
|
||||||
|
BuildMI(MBB, MBBI, dl,
|
||||||
|
TII.get(ARM::tMOVgpr2gpr), RegInfo->getBaseRegister())
|
||||||
|
.addReg(ARM::SP);
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the frame has variable sized objects then the epilogue must restore
|
||||||
|
// the sp from fp.
|
||||||
|
if (!AFI->shouldRestoreSPFromFP() && MFI->hasVarSizedObjects())
|
||||||
|
AFI->setShouldRestoreSPFromFP(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ARMFrameInfo::emitEpilogue(MachineFunction &MF,
|
||||||
|
MachineBasicBlock &MBB) const {
|
||||||
|
MachineBasicBlock::iterator MBBI = prior(MBB.end());
|
||||||
|
assert(MBBI->getDesc().isReturn() &&
|
||||||
|
"Can only insert epilog into returning blocks");
|
||||||
|
unsigned RetOpcode = MBBI->getOpcode();
|
||||||
|
DebugLoc dl = MBBI->getDebugLoc();
|
||||||
|
MachineFrameInfo *MFI = MF.getFrameInfo();
|
||||||
|
ARMFunctionInfo *AFI = MF.getInfo<ARMFunctionInfo>();
|
||||||
|
const TargetRegisterInfo *RegInfo = MF.getTarget().getRegisterInfo();
|
||||||
|
const ARMBaseInstrInfo &TII =
|
||||||
|
*static_cast<const ARMBaseInstrInfo*>(MF.getTarget().getInstrInfo());
|
||||||
|
assert(!AFI->isThumb1OnlyFunction() &&
|
||||||
|
"This emitEpilogue does not support Thumb1!");
|
||||||
|
bool isARM = !AFI->isThumbFunction();
|
||||||
|
|
||||||
|
unsigned VARegSaveSize = AFI->getVarArgsRegSaveSize();
|
||||||
|
int NumBytes = (int)MFI->getStackSize();
|
||||||
|
unsigned FramePtr = RegInfo->getFrameRegister(MF);
|
||||||
|
|
||||||
|
if (!AFI->hasStackFrame()) {
|
||||||
|
if (NumBytes != 0)
|
||||||
|
emitSPUpdate(isARM, MBB, MBBI, dl, TII, NumBytes);
|
||||||
|
} else {
|
||||||
|
// Unwind MBBI to point to first LDR / VLDRD.
|
||||||
|
const unsigned *CSRegs = RegInfo->getCalleeSavedRegs();
|
||||||
|
if (MBBI != MBB.begin()) {
|
||||||
|
do
|
||||||
|
--MBBI;
|
||||||
|
while (MBBI != MBB.begin() && isCSRestore(MBBI, TII, CSRegs));
|
||||||
|
if (!isCSRestore(MBBI, TII, CSRegs))
|
||||||
|
++MBBI;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Move SP to start of FP callee save spill area.
|
||||||
|
NumBytes -= (AFI->getGPRCalleeSavedArea1Size() +
|
||||||
|
AFI->getGPRCalleeSavedArea2Size() +
|
||||||
|
AFI->getDPRCalleeSavedAreaSize());
|
||||||
|
|
||||||
|
// Reset SP based on frame pointer only if the stack frame extends beyond
|
||||||
|
// frame pointer stack slot or target is ELF and the function has FP.
|
||||||
|
if (AFI->shouldRestoreSPFromFP()) {
|
||||||
|
NumBytes = AFI->getFramePtrSpillOffset() - NumBytes;
|
||||||
|
if (NumBytes) {
|
||||||
|
if (isARM)
|
||||||
|
emitARMRegPlusImmediate(MBB, MBBI, dl, ARM::SP, FramePtr, -NumBytes,
|
||||||
|
ARMCC::AL, 0, TII);
|
||||||
|
else
|
||||||
|
emitT2RegPlusImmediate(MBB, MBBI, dl, ARM::SP, FramePtr, -NumBytes,
|
||||||
|
ARMCC::AL, 0, TII);
|
||||||
|
} else {
|
||||||
|
// Thumb2 or ARM.
|
||||||
|
if (isARM)
|
||||||
|
BuildMI(MBB, MBBI, dl, TII.get(ARM::MOVr), ARM::SP)
|
||||||
|
.addReg(FramePtr).addImm((unsigned)ARMCC::AL).addReg(0).addReg(0);
|
||||||
|
else
|
||||||
|
BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVgpr2gpr), ARM::SP)
|
||||||
|
.addReg(FramePtr);
|
||||||
|
}
|
||||||
|
} else if (NumBytes)
|
||||||
|
emitSPUpdate(isARM, MBB, MBBI, dl, TII, NumBytes);
|
||||||
|
|
||||||
|
// Move SP to start of integer callee save spill area 2.
|
||||||
|
movePastCSLoadStoreOps(MBB, MBBI, ARM::VLDRD, 0, 3, STI);
|
||||||
|
emitSPUpdate(isARM, MBB, MBBI, dl, TII, AFI->getDPRCalleeSavedAreaSize());
|
||||||
|
|
||||||
|
// Move SP to start of integer callee save spill area 1.
|
||||||
|
movePastCSLoadStoreOps(MBB, MBBI, ARM::LDRi12, ARM::t2LDRi12, 2, STI);
|
||||||
|
emitSPUpdate(isARM, MBB, MBBI, dl, TII, AFI->getGPRCalleeSavedArea2Size());
|
||||||
|
|
||||||
|
// Move SP to SP upon entry to the function.
|
||||||
|
movePastCSLoadStoreOps(MBB, MBBI, ARM::LDRi12, ARM::t2LDRi12, 1, STI);
|
||||||
|
emitSPUpdate(isARM, MBB, MBBI, dl, TII, AFI->getGPRCalleeSavedArea1Size());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (RetOpcode == ARM::TCRETURNdi || RetOpcode == ARM::TCRETURNdiND ||
|
||||||
|
RetOpcode == ARM::TCRETURNri || RetOpcode == ARM::TCRETURNriND) {
|
||||||
|
// Tail call return: adjust the stack pointer and jump to callee.
|
||||||
|
MBBI = prior(MBB.end());
|
||||||
|
MachineOperand &JumpTarget = MBBI->getOperand(0);
|
||||||
|
|
||||||
|
// Jump to label or value in register.
|
||||||
|
if (RetOpcode == ARM::TCRETURNdi) {
|
||||||
|
BuildMI(MBB, MBBI, dl,
|
||||||
|
TII.get(STI.isThumb() ? ARM::TAILJMPdt : ARM::TAILJMPd)).
|
||||||
|
addGlobalAddress(JumpTarget.getGlobal(), JumpTarget.getOffset(),
|
||||||
|
JumpTarget.getTargetFlags());
|
||||||
|
} else if (RetOpcode == ARM::TCRETURNdiND) {
|
||||||
|
BuildMI(MBB, MBBI, dl,
|
||||||
|
TII.get(STI.isThumb() ? ARM::TAILJMPdNDt : ARM::TAILJMPdND)).
|
||||||
|
addGlobalAddress(JumpTarget.getGlobal(), JumpTarget.getOffset(),
|
||||||
|
JumpTarget.getTargetFlags());
|
||||||
|
} else if (RetOpcode == ARM::TCRETURNri) {
|
||||||
|
BuildMI(MBB, MBBI, dl, TII.get(ARM::TAILJMPr)).
|
||||||
|
addReg(JumpTarget.getReg(), RegState::Kill);
|
||||||
|
} else if (RetOpcode == ARM::TCRETURNriND) {
|
||||||
|
BuildMI(MBB, MBBI, dl, TII.get(ARM::TAILJMPrND)).
|
||||||
|
addReg(JumpTarget.getReg(), RegState::Kill);
|
||||||
|
}
|
||||||
|
|
||||||
|
MachineInstr *NewMI = prior(MBBI);
|
||||||
|
for (unsigned i = 1, e = MBBI->getNumOperands(); i != e; ++i)
|
||||||
|
NewMI->addOperand(MBBI->getOperand(i));
|
||||||
|
|
||||||
|
// Delete the pseudo instruction TCRETURN.
|
||||||
|
MBB.erase(MBBI);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (VARegSaveSize)
|
||||||
|
emitSPUpdate(isARM, MBB, MBBI, dl, TII, VARegSaveSize);
|
||||||
|
}
|
|
@ -19,12 +19,21 @@
|
||||||
#include "llvm/Target/TargetFrameInfo.h"
|
#include "llvm/Target/TargetFrameInfo.h"
|
||||||
|
|
||||||
namespace llvm {
|
namespace llvm {
|
||||||
|
class ARMSubtarget;
|
||||||
|
|
||||||
class ARMFrameInfo : public TargetFrameInfo {
|
class ARMFrameInfo : public TargetFrameInfo {
|
||||||
|
protected:
|
||||||
|
const ARMSubtarget &STI;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit ARMFrameInfo(const ARMSubtarget &ST)
|
explicit ARMFrameInfo(const ARMSubtarget &sti)
|
||||||
: TargetFrameInfo(StackGrowsDown, ST.getStackAlignment(), 0, 4) {
|
: TargetFrameInfo(StackGrowsDown, sti.getStackAlignment(), 0, 4), STI(sti) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// emitProlog/emitEpilog - These methods insert prolog and epilog code into
|
||||||
|
/// the function.
|
||||||
|
void emitPrologue(MachineFunction &MF) const;
|
||||||
|
void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // End llvm namespace
|
} // End llvm namespace
|
||||||
|
|
|
@ -89,7 +89,6 @@ ARMBaseTargetMachine::ARMBaseTargetMachine(const Target &T,
|
||||||
bool isThumb)
|
bool isThumb)
|
||||||
: LLVMTargetMachine(T, TT),
|
: LLVMTargetMachine(T, TT),
|
||||||
Subtarget(TT, FS, isThumb),
|
Subtarget(TT, FS, isThumb),
|
||||||
FrameInfo(Subtarget),
|
|
||||||
JITInfo(),
|
JITInfo(),
|
||||||
InstrItins(Subtarget.getInstrItineraryData())
|
InstrItins(Subtarget.getInstrItineraryData())
|
||||||
{
|
{
|
||||||
|
@ -106,7 +105,8 @@ ARMTargetMachine::ARMTargetMachine(const Target &T, const std::string &TT,
|
||||||
"v128:64:128-v64:64:64-n32")),
|
"v128:64:128-v64:64:64-n32")),
|
||||||
ELFWriterInfo(*this),
|
ELFWriterInfo(*this),
|
||||||
TLInfo(*this),
|
TLInfo(*this),
|
||||||
TSInfo(*this) {
|
TSInfo(*this),
|
||||||
|
FrameInfo(Subtarget) {
|
||||||
if (!Subtarget.hasARMOps())
|
if (!Subtarget.hasARMOps())
|
||||||
report_fatal_error("CPU: '" + Subtarget.getCPUString() + "' does not "
|
report_fatal_error("CPU: '" + Subtarget.getCPUString() + "' does not "
|
||||||
"support ARM mode execution!");
|
"support ARM mode execution!");
|
||||||
|
@ -127,7 +127,10 @@ ThumbTargetMachine::ThumbTargetMachine(const Target &T, const std::string &TT,
|
||||||
"v128:64:128-v64:64:64-a:0:32-n32")),
|
"v128:64:128-v64:64:64-a:0:32-n32")),
|
||||||
ELFWriterInfo(*this),
|
ELFWriterInfo(*this),
|
||||||
TLInfo(*this),
|
TLInfo(*this),
|
||||||
TSInfo(*this) {
|
TSInfo(*this),
|
||||||
|
FrameInfo(Subtarget.hasThumb2()
|
||||||
|
? new ARMFrameInfo(Subtarget)
|
||||||
|
: (ARMFrameInfo*)new Thumb1FrameInfo(Subtarget)) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Pass Pipeline Configuration
|
// Pass Pipeline Configuration
|
||||||
|
|
|
@ -14,9 +14,6 @@
|
||||||
#ifndef ARMTARGETMACHINE_H
|
#ifndef ARMTARGETMACHINE_H
|
||||||
#define ARMTARGETMACHINE_H
|
#define ARMTARGETMACHINE_H
|
||||||
|
|
||||||
#include "llvm/Target/TargetMachine.h"
|
|
||||||
#include "llvm/Target/TargetData.h"
|
|
||||||
#include "llvm/MC/MCStreamer.h"
|
|
||||||
#include "ARMInstrInfo.h"
|
#include "ARMInstrInfo.h"
|
||||||
#include "ARMELFWriterInfo.h"
|
#include "ARMELFWriterInfo.h"
|
||||||
#include "ARMFrameInfo.h"
|
#include "ARMFrameInfo.h"
|
||||||
|
@ -25,7 +22,11 @@
|
||||||
#include "ARMISelLowering.h"
|
#include "ARMISelLowering.h"
|
||||||
#include "ARMSelectionDAGInfo.h"
|
#include "ARMSelectionDAGInfo.h"
|
||||||
#include "Thumb1InstrInfo.h"
|
#include "Thumb1InstrInfo.h"
|
||||||
|
#include "Thumb1FrameInfo.h"
|
||||||
#include "Thumb2InstrInfo.h"
|
#include "Thumb2InstrInfo.h"
|
||||||
|
#include "llvm/Target/TargetMachine.h"
|
||||||
|
#include "llvm/Target/TargetData.h"
|
||||||
|
#include "llvm/MC/MCStreamer.h"
|
||||||
#include "llvm/ADT/OwningPtr.h"
|
#include "llvm/ADT/OwningPtr.h"
|
||||||
|
|
||||||
namespace llvm {
|
namespace llvm {
|
||||||
|
@ -33,9 +34,7 @@ namespace llvm {
|
||||||
class ARMBaseTargetMachine : public LLVMTargetMachine {
|
class ARMBaseTargetMachine : public LLVMTargetMachine {
|
||||||
protected:
|
protected:
|
||||||
ARMSubtarget Subtarget;
|
ARMSubtarget Subtarget;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ARMFrameInfo FrameInfo;
|
|
||||||
ARMJITInfo JITInfo;
|
ARMJITInfo JITInfo;
|
||||||
InstrItineraryData InstrItins;
|
InstrItineraryData InstrItins;
|
||||||
Reloc::Model DefRelocModel; // Reloc model before it's overridden.
|
Reloc::Model DefRelocModel; // Reloc model before it's overridden.
|
||||||
|
@ -44,7 +43,6 @@ public:
|
||||||
ARMBaseTargetMachine(const Target &T, const std::string &TT,
|
ARMBaseTargetMachine(const Target &T, const std::string &TT,
|
||||||
const std::string &FS, bool isThumb);
|
const std::string &FS, bool isThumb);
|
||||||
|
|
||||||
virtual const ARMFrameInfo *getFrameInfo() const { return &FrameInfo; }
|
|
||||||
virtual ARMJITInfo *getJITInfo() { return &JITInfo; }
|
virtual ARMJITInfo *getJITInfo() { return &JITInfo; }
|
||||||
virtual const ARMSubtarget *getSubtargetImpl() const { return &Subtarget; }
|
virtual const ARMSubtarget *getSubtargetImpl() const { return &Subtarget; }
|
||||||
virtual const InstrItineraryData *getInstrItineraryData() const {
|
virtual const InstrItineraryData *getInstrItineraryData() const {
|
||||||
|
@ -69,7 +67,8 @@ class ARMTargetMachine : public ARMBaseTargetMachine {
|
||||||
ARMELFWriterInfo ELFWriterInfo;
|
ARMELFWriterInfo ELFWriterInfo;
|
||||||
ARMTargetLowering TLInfo;
|
ARMTargetLowering TLInfo;
|
||||||
ARMSelectionDAGInfo TSInfo;
|
ARMSelectionDAGInfo TSInfo;
|
||||||
public:
|
ARMFrameInfo FrameInfo;
|
||||||
|
public:
|
||||||
ARMTargetMachine(const Target &T, const std::string &TT,
|
ARMTargetMachine(const Target &T, const std::string &TT,
|
||||||
const std::string &FS);
|
const std::string &FS);
|
||||||
|
|
||||||
|
@ -84,6 +83,7 @@ public:
|
||||||
virtual const ARMSelectionDAGInfo* getSelectionDAGInfo() const {
|
virtual const ARMSelectionDAGInfo* getSelectionDAGInfo() const {
|
||||||
return &TSInfo;
|
return &TSInfo;
|
||||||
}
|
}
|
||||||
|
virtual const ARMFrameInfo *getFrameInfo() const { return &FrameInfo; }
|
||||||
|
|
||||||
virtual const ARMInstrInfo *getInstrInfo() const { return &InstrInfo; }
|
virtual const ARMInstrInfo *getInstrInfo() const { return &InstrInfo; }
|
||||||
virtual const TargetData *getTargetData() const { return &DataLayout; }
|
virtual const TargetData *getTargetData() const { return &DataLayout; }
|
||||||
|
@ -103,6 +103,8 @@ class ThumbTargetMachine : public ARMBaseTargetMachine {
|
||||||
ARMELFWriterInfo ELFWriterInfo;
|
ARMELFWriterInfo ELFWriterInfo;
|
||||||
ARMTargetLowering TLInfo;
|
ARMTargetLowering TLInfo;
|
||||||
ARMSelectionDAGInfo TSInfo;
|
ARMSelectionDAGInfo TSInfo;
|
||||||
|
// Either Thumb1FrameInfo or ARMFrameInfo.
|
||||||
|
OwningPtr<ARMFrameInfo> FrameInfo;
|
||||||
public:
|
public:
|
||||||
ThumbTargetMachine(const Target &T, const std::string &TT,
|
ThumbTargetMachine(const Target &T, const std::string &TT,
|
||||||
const std::string &FS);
|
const std::string &FS);
|
||||||
|
@ -124,6 +126,10 @@ public:
|
||||||
virtual const ARMBaseInstrInfo *getInstrInfo() const {
|
virtual const ARMBaseInstrInfo *getInstrInfo() const {
|
||||||
return InstrInfo.get();
|
return InstrInfo.get();
|
||||||
}
|
}
|
||||||
|
/// returns either Thumb1FrameInfo or ARMFrameInfo
|
||||||
|
virtual const ARMFrameInfo *getFrameInfo() const {
|
||||||
|
return FrameInfo.get();
|
||||||
|
}
|
||||||
virtual const TargetData *getTargetData() const { return &DataLayout; }
|
virtual const TargetData *getTargetData() const { return &DataLayout; }
|
||||||
virtual const ARMELFWriterInfo *getELFWriterInfo() const {
|
virtual const ARMELFWriterInfo *getELFWriterInfo() const {
|
||||||
return Subtarget.isTargetELF() ? &ELFWriterInfo : 0;
|
return Subtarget.isTargetELF() ? &ELFWriterInfo : 0;
|
||||||
|
|
|
@ -0,0 +1,246 @@
|
||||||
|
//=======- Thumb1FrameInfo.cpp - Thumb1 Frame Information ------*- C++ -*-====//
|
||||||
|
//
|
||||||
|
// The LLVM Compiler Infrastructure
|
||||||
|
//
|
||||||
|
// This file is distributed under the University of Illinois Open Source
|
||||||
|
// License. See LICENSE.TXT for details.
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
//
|
||||||
|
// This file contains the Thumb1 implementation of TargetFrameInfo class.
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
#include "Thumb1FrameInfo.h"
|
||||||
|
#include "ARMBaseInstrInfo.h"
|
||||||
|
#include "ARMMachineFunctionInfo.h"
|
||||||
|
#include "llvm/CodeGen/MachineFrameInfo.h"
|
||||||
|
#include "llvm/CodeGen/MachineFunction.h"
|
||||||
|
#include "llvm/CodeGen/MachineInstrBuilder.h"
|
||||||
|
|
||||||
|
using namespace llvm;
|
||||||
|
|
||||||
|
static void emitSPUpdate(MachineBasicBlock &MBB,
|
||||||
|
MachineBasicBlock::iterator &MBBI,
|
||||||
|
const TargetInstrInfo &TII, DebugLoc dl,
|
||||||
|
const Thumb1RegisterInfo &MRI,
|
||||||
|
int NumBytes) {
|
||||||
|
emitThumbRegPlusImmediate(MBB, MBBI, ARM::SP, ARM::SP, NumBytes, TII,
|
||||||
|
MRI, dl);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Thumb1FrameInfo::emitPrologue(MachineFunction &MF) const {
|
||||||
|
MachineBasicBlock &MBB = MF.front();
|
||||||
|
MachineBasicBlock::iterator MBBI = MBB.begin();
|
||||||
|
MachineFrameInfo *MFI = MF.getFrameInfo();
|
||||||
|
ARMFunctionInfo *AFI = MF.getInfo<ARMFunctionInfo>();
|
||||||
|
const Thumb1RegisterInfo *RegInfo =
|
||||||
|
static_cast<const Thumb1RegisterInfo*>(MF.getTarget().getRegisterInfo());
|
||||||
|
const Thumb1InstrInfo &TII =
|
||||||
|
*static_cast<const Thumb1InstrInfo*>(MF.getTarget().getInstrInfo());
|
||||||
|
|
||||||
|
unsigned VARegSaveSize = AFI->getVarArgsRegSaveSize();
|
||||||
|
unsigned NumBytes = MFI->getStackSize();
|
||||||
|
const std::vector<CalleeSavedInfo> &CSI = MFI->getCalleeSavedInfo();
|
||||||
|
DebugLoc dl = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc();
|
||||||
|
unsigned FramePtr = RegInfo->getFrameRegister(MF);
|
||||||
|
unsigned BasePtr = RegInfo->getBaseRegister();
|
||||||
|
|
||||||
|
// Thumb add/sub sp, imm8 instructions implicitly multiply the offset by 4.
|
||||||
|
NumBytes = (NumBytes + 3) & ~3;
|
||||||
|
MFI->setStackSize(NumBytes);
|
||||||
|
|
||||||
|
// Determine the sizes of each callee-save spill areas and record which frame
|
||||||
|
// belongs to which callee-save spill areas.
|
||||||
|
unsigned GPRCS1Size = 0, GPRCS2Size = 0, DPRCSSize = 0;
|
||||||
|
int FramePtrSpillFI = 0;
|
||||||
|
|
||||||
|
if (VARegSaveSize)
|
||||||
|
emitSPUpdate(MBB, MBBI, TII, dl, *RegInfo, -VARegSaveSize);
|
||||||
|
|
||||||
|
if (!AFI->hasStackFrame()) {
|
||||||
|
if (NumBytes != 0)
|
||||||
|
emitSPUpdate(MBB, MBBI, TII, dl, *RegInfo, -NumBytes);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (unsigned i = 0, e = CSI.size(); i != e; ++i) {
|
||||||
|
unsigned Reg = CSI[i].getReg();
|
||||||
|
int FI = CSI[i].getFrameIdx();
|
||||||
|
switch (Reg) {
|
||||||
|
case ARM::R4:
|
||||||
|
case ARM::R5:
|
||||||
|
case ARM::R6:
|
||||||
|
case ARM::R7:
|
||||||
|
case ARM::LR:
|
||||||
|
if (Reg == FramePtr)
|
||||||
|
FramePtrSpillFI = FI;
|
||||||
|
AFI->addGPRCalleeSavedArea1Frame(FI);
|
||||||
|
GPRCS1Size += 4;
|
||||||
|
break;
|
||||||
|
case ARM::R8:
|
||||||
|
case ARM::R9:
|
||||||
|
case ARM::R10:
|
||||||
|
case ARM::R11:
|
||||||
|
if (Reg == FramePtr)
|
||||||
|
FramePtrSpillFI = FI;
|
||||||
|
if (STI.isTargetDarwin()) {
|
||||||
|
AFI->addGPRCalleeSavedArea2Frame(FI);
|
||||||
|
GPRCS2Size += 4;
|
||||||
|
} else {
|
||||||
|
AFI->addGPRCalleeSavedArea1Frame(FI);
|
||||||
|
GPRCS1Size += 4;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
AFI->addDPRCalleeSavedAreaFrame(FI);
|
||||||
|
DPRCSSize += 8;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (MBBI != MBB.end() && MBBI->getOpcode() == ARM::tPUSH) {
|
||||||
|
++MBBI;
|
||||||
|
if (MBBI != MBB.end())
|
||||||
|
dl = MBBI->getDebugLoc();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Adjust FP so it point to the stack slot that contains the previous FP.
|
||||||
|
if (RegInfo->hasFP(MF)) {
|
||||||
|
BuildMI(MBB, MBBI, dl, TII.get(ARM::tADDrSPi), FramePtr)
|
||||||
|
.addFrameIndex(FramePtrSpillFI).addImm(0);
|
||||||
|
AFI->setShouldRestoreSPFromFP(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Determine starting offsets of spill areas.
|
||||||
|
unsigned DPRCSOffset = NumBytes - (GPRCS1Size + GPRCS2Size + DPRCSSize);
|
||||||
|
unsigned GPRCS2Offset = DPRCSOffset + DPRCSSize;
|
||||||
|
unsigned GPRCS1Offset = GPRCS2Offset + GPRCS2Size;
|
||||||
|
AFI->setFramePtrSpillOffset(MFI->getObjectOffset(FramePtrSpillFI) + NumBytes);
|
||||||
|
AFI->setGPRCalleeSavedArea1Offset(GPRCS1Offset);
|
||||||
|
AFI->setGPRCalleeSavedArea2Offset(GPRCS2Offset);
|
||||||
|
AFI->setDPRCalleeSavedAreaOffset(DPRCSOffset);
|
||||||
|
|
||||||
|
NumBytes = DPRCSOffset;
|
||||||
|
if (NumBytes) {
|
||||||
|
// Insert it after all the callee-save spills.
|
||||||
|
emitSPUpdate(MBB, MBBI, TII, dl, *RegInfo, -NumBytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (STI.isTargetELF() && RegInfo->hasFP(MF))
|
||||||
|
MFI->setOffsetAdjustment(MFI->getOffsetAdjustment() -
|
||||||
|
AFI->getFramePtrSpillOffset());
|
||||||
|
|
||||||
|
AFI->setGPRCalleeSavedArea1Size(GPRCS1Size);
|
||||||
|
AFI->setGPRCalleeSavedArea2Size(GPRCS2Size);
|
||||||
|
AFI->setDPRCalleeSavedAreaSize(DPRCSSize);
|
||||||
|
|
||||||
|
// If we need a base pointer, set it up here. It's whatever the value
|
||||||
|
// of the stack pointer is at this point. Any variable size objects
|
||||||
|
// will be allocated after this, so we can still use the base pointer
|
||||||
|
// to reference locals.
|
||||||
|
if (RegInfo->hasBasePointer(MF))
|
||||||
|
BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVgpr2gpr), BasePtr).addReg(ARM::SP);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool isCalleeSavedRegister(unsigned Reg, const unsigned *CSRegs) {
|
||||||
|
for (unsigned i = 0; CSRegs[i]; ++i)
|
||||||
|
if (Reg == CSRegs[i])
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool isCSRestore(MachineInstr *MI, const unsigned *CSRegs) {
|
||||||
|
if (MI->getOpcode() == ARM::tRestore &&
|
||||||
|
MI->getOperand(1).isFI() &&
|
||||||
|
isCalleeSavedRegister(MI->getOperand(0).getReg(), CSRegs))
|
||||||
|
return true;
|
||||||
|
else if (MI->getOpcode() == ARM::tPOP) {
|
||||||
|
// The first two operands are predicates. The last two are
|
||||||
|
// imp-def and imp-use of SP. Check everything in between.
|
||||||
|
for (int i = 2, e = MI->getNumOperands() - 2; i != e; ++i)
|
||||||
|
if (!isCalleeSavedRegister(MI->getOperand(i).getReg(), CSRegs))
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Thumb1FrameInfo::emitEpilogue(MachineFunction &MF,
|
||||||
|
MachineBasicBlock &MBB) const {
|
||||||
|
MachineBasicBlock::iterator MBBI = prior(MBB.end());
|
||||||
|
assert((MBBI->getOpcode() == ARM::tBX_RET ||
|
||||||
|
MBBI->getOpcode() == ARM::tPOP_RET) &&
|
||||||
|
"Can only insert epilog into returning blocks");
|
||||||
|
DebugLoc dl = MBBI->getDebugLoc();
|
||||||
|
MachineFrameInfo *MFI = MF.getFrameInfo();
|
||||||
|
ARMFunctionInfo *AFI = MF.getInfo<ARMFunctionInfo>();
|
||||||
|
const Thumb1RegisterInfo *RegInfo =
|
||||||
|
static_cast<const Thumb1RegisterInfo*>(MF.getTarget().getRegisterInfo());
|
||||||
|
const Thumb1InstrInfo &TII =
|
||||||
|
*static_cast<const Thumb1InstrInfo*>(MF.getTarget().getInstrInfo());
|
||||||
|
|
||||||
|
unsigned VARegSaveSize = AFI->getVarArgsRegSaveSize();
|
||||||
|
int NumBytes = (int)MFI->getStackSize();
|
||||||
|
const unsigned *CSRegs = RegInfo->getCalleeSavedRegs();
|
||||||
|
unsigned FramePtr = RegInfo->getFrameRegister(MF);
|
||||||
|
|
||||||
|
if (!AFI->hasStackFrame()) {
|
||||||
|
if (NumBytes != 0)
|
||||||
|
emitSPUpdate(MBB, MBBI, TII, dl, *RegInfo, NumBytes);
|
||||||
|
} else {
|
||||||
|
// Unwind MBBI to point to first LDR / VLDRD.
|
||||||
|
if (MBBI != MBB.begin()) {
|
||||||
|
do
|
||||||
|
--MBBI;
|
||||||
|
while (MBBI != MBB.begin() && isCSRestore(MBBI, CSRegs));
|
||||||
|
if (!isCSRestore(MBBI, CSRegs))
|
||||||
|
++MBBI;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Move SP to start of FP callee save spill area.
|
||||||
|
NumBytes -= (AFI->getGPRCalleeSavedArea1Size() +
|
||||||
|
AFI->getGPRCalleeSavedArea2Size() +
|
||||||
|
AFI->getDPRCalleeSavedAreaSize());
|
||||||
|
|
||||||
|
if (AFI->shouldRestoreSPFromFP()) {
|
||||||
|
NumBytes = AFI->getFramePtrSpillOffset() - NumBytes;
|
||||||
|
// Reset SP based on frame pointer only if the stack frame extends beyond
|
||||||
|
// frame pointer stack slot or target is ELF and the function has FP.
|
||||||
|
if (NumBytes)
|
||||||
|
emitThumbRegPlusImmediate(MBB, MBBI, ARM::SP, FramePtr, -NumBytes,
|
||||||
|
TII, *RegInfo, dl);
|
||||||
|
else
|
||||||
|
BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVtgpr2gpr), ARM::SP)
|
||||||
|
.addReg(FramePtr);
|
||||||
|
} else {
|
||||||
|
if (MBBI->getOpcode() == ARM::tBX_RET &&
|
||||||
|
&MBB.front() != MBBI &&
|
||||||
|
prior(MBBI)->getOpcode() == ARM::tPOP) {
|
||||||
|
MachineBasicBlock::iterator PMBBI = prior(MBBI);
|
||||||
|
emitSPUpdate(MBB, PMBBI, TII, dl, *RegInfo, NumBytes);
|
||||||
|
} else
|
||||||
|
emitSPUpdate(MBB, MBBI, TII, dl, *RegInfo, NumBytes);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (VARegSaveSize) {
|
||||||
|
// Unlike T2 and ARM mode, the T1 pop instruction cannot restore
|
||||||
|
// to LR, and we can't pop the value directly to the PC since
|
||||||
|
// we need to update the SP after popping the value. Therefore, we
|
||||||
|
// pop the old LR into R3 as a temporary.
|
||||||
|
|
||||||
|
// Move back past the callee-saved register restoration
|
||||||
|
while (MBBI != MBB.end() && isCSRestore(MBBI, CSRegs))
|
||||||
|
++MBBI;
|
||||||
|
// Epilogue for vararg functions: pop LR to R3 and branch off it.
|
||||||
|
AddDefaultPred(BuildMI(MBB, MBBI, dl, TII.get(ARM::tPOP)))
|
||||||
|
.addReg(ARM::R3, RegState::Define);
|
||||||
|
|
||||||
|
emitSPUpdate(MBB, MBBI, TII, dl, *RegInfo, VARegSaveSize);
|
||||||
|
|
||||||
|
BuildMI(MBB, MBBI, dl, TII.get(ARM::tBX_RET_vararg))
|
||||||
|
.addReg(ARM::R3, RegState::Kill);
|
||||||
|
// erase the old tBX_RET instruction
|
||||||
|
MBB.erase(MBBI);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,41 @@
|
||||||
|
//===-- Thumb1FrameInfo.h - Thumb1-specific frame info stuff ----*- C++ -*-===//
|
||||||
|
//
|
||||||
|
// The LLVM Compiler Infrastructure
|
||||||
|
//
|
||||||
|
// This file is distributed under the University of Illinois Open Source
|
||||||
|
// License. See LICENSE.TXT for details.
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
#ifndef __THUMB_FRAMEINFO_H_
|
||||||
|
#define __THUMM_FRAMEINFO_H_
|
||||||
|
|
||||||
|
#include "ARM.h"
|
||||||
|
#include "ARMFrameInfo.h"
|
||||||
|
#include "ARMSubtarget.h"
|
||||||
|
#include "Thumb1InstrInfo.h"
|
||||||
|
#include "Thumb1RegisterInfo.h"
|
||||||
|
#include "llvm/Target/TargetFrameInfo.h"
|
||||||
|
|
||||||
|
namespace llvm {
|
||||||
|
class ARMSubtarget;
|
||||||
|
|
||||||
|
class Thumb1FrameInfo : public ARMFrameInfo {
|
||||||
|
public:
|
||||||
|
explicit Thumb1FrameInfo(const ARMSubtarget &sti)
|
||||||
|
: ARMFrameInfo(sti) {
|
||||||
|
}
|
||||||
|
|
||||||
|
/// emitProlog/emitEpilog - These methods insert prolog and epilog code into
|
||||||
|
/// the function.
|
||||||
|
void emitPrologue(MachineFunction &MF) const;
|
||||||
|
void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // End llvm namespace
|
||||||
|
|
||||||
|
#endif
|
|
@ -691,206 +691,3 @@ Thumb1RegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
|
||||||
AddDefaultPred(MIB);
|
AddDefaultPred(MIB);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Thumb1RegisterInfo::emitPrologue(MachineFunction &MF) const {
|
|
||||||
MachineBasicBlock &MBB = MF.front();
|
|
||||||
MachineBasicBlock::iterator MBBI = MBB.begin();
|
|
||||||
MachineFrameInfo *MFI = MF.getFrameInfo();
|
|
||||||
ARMFunctionInfo *AFI = MF.getInfo<ARMFunctionInfo>();
|
|
||||||
unsigned VARegSaveSize = AFI->getVarArgsRegSaveSize();
|
|
||||||
unsigned NumBytes = MFI->getStackSize();
|
|
||||||
const std::vector<CalleeSavedInfo> &CSI = MFI->getCalleeSavedInfo();
|
|
||||||
DebugLoc dl = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc();
|
|
||||||
|
|
||||||
// Thumb add/sub sp, imm8 instructions implicitly multiply the offset by 4.
|
|
||||||
NumBytes = (NumBytes + 3) & ~3;
|
|
||||||
MFI->setStackSize(NumBytes);
|
|
||||||
|
|
||||||
// Determine the sizes of each callee-save spill areas and record which frame
|
|
||||||
// belongs to which callee-save spill areas.
|
|
||||||
unsigned GPRCS1Size = 0, GPRCS2Size = 0, DPRCSSize = 0;
|
|
||||||
int FramePtrSpillFI = 0;
|
|
||||||
|
|
||||||
if (VARegSaveSize)
|
|
||||||
emitSPUpdate(MBB, MBBI, TII, dl, *this, -VARegSaveSize);
|
|
||||||
|
|
||||||
if (!AFI->hasStackFrame()) {
|
|
||||||
if (NumBytes != 0)
|
|
||||||
emitSPUpdate(MBB, MBBI, TII, dl, *this, -NumBytes);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (unsigned i = 0, e = CSI.size(); i != e; ++i) {
|
|
||||||
unsigned Reg = CSI[i].getReg();
|
|
||||||
int FI = CSI[i].getFrameIdx();
|
|
||||||
switch (Reg) {
|
|
||||||
case ARM::R4:
|
|
||||||
case ARM::R5:
|
|
||||||
case ARM::R6:
|
|
||||||
case ARM::R7:
|
|
||||||
case ARM::LR:
|
|
||||||
if (Reg == FramePtr)
|
|
||||||
FramePtrSpillFI = FI;
|
|
||||||
AFI->addGPRCalleeSavedArea1Frame(FI);
|
|
||||||
GPRCS1Size += 4;
|
|
||||||
break;
|
|
||||||
case ARM::R8:
|
|
||||||
case ARM::R9:
|
|
||||||
case ARM::R10:
|
|
||||||
case ARM::R11:
|
|
||||||
if (Reg == FramePtr)
|
|
||||||
FramePtrSpillFI = FI;
|
|
||||||
if (STI.isTargetDarwin()) {
|
|
||||||
AFI->addGPRCalleeSavedArea2Frame(FI);
|
|
||||||
GPRCS2Size += 4;
|
|
||||||
} else {
|
|
||||||
AFI->addGPRCalleeSavedArea1Frame(FI);
|
|
||||||
GPRCS1Size += 4;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
AFI->addDPRCalleeSavedAreaFrame(FI);
|
|
||||||
DPRCSSize += 8;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (MBBI != MBB.end() && MBBI->getOpcode() == ARM::tPUSH) {
|
|
||||||
++MBBI;
|
|
||||||
if (MBBI != MBB.end())
|
|
||||||
dl = MBBI->getDebugLoc();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Adjust FP so it point to the stack slot that contains the previous FP.
|
|
||||||
if (hasFP(MF)) {
|
|
||||||
BuildMI(MBB, MBBI, dl, TII.get(ARM::tADDrSPi), FramePtr)
|
|
||||||
.addFrameIndex(FramePtrSpillFI).addImm(0);
|
|
||||||
AFI->setShouldRestoreSPFromFP(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Determine starting offsets of spill areas.
|
|
||||||
unsigned DPRCSOffset = NumBytes - (GPRCS1Size + GPRCS2Size + DPRCSSize);
|
|
||||||
unsigned GPRCS2Offset = DPRCSOffset + DPRCSSize;
|
|
||||||
unsigned GPRCS1Offset = GPRCS2Offset + GPRCS2Size;
|
|
||||||
AFI->setFramePtrSpillOffset(MFI->getObjectOffset(FramePtrSpillFI) + NumBytes);
|
|
||||||
AFI->setGPRCalleeSavedArea1Offset(GPRCS1Offset);
|
|
||||||
AFI->setGPRCalleeSavedArea2Offset(GPRCS2Offset);
|
|
||||||
AFI->setDPRCalleeSavedAreaOffset(DPRCSOffset);
|
|
||||||
|
|
||||||
NumBytes = DPRCSOffset;
|
|
||||||
if (NumBytes) {
|
|
||||||
// Insert it after all the callee-save spills.
|
|
||||||
emitSPUpdate(MBB, MBBI, TII, dl, *this, -NumBytes);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (STI.isTargetELF() && hasFP(MF))
|
|
||||||
MFI->setOffsetAdjustment(MFI->getOffsetAdjustment() -
|
|
||||||
AFI->getFramePtrSpillOffset());
|
|
||||||
|
|
||||||
AFI->setGPRCalleeSavedArea1Size(GPRCS1Size);
|
|
||||||
AFI->setGPRCalleeSavedArea2Size(GPRCS2Size);
|
|
||||||
AFI->setDPRCalleeSavedAreaSize(DPRCSSize);
|
|
||||||
|
|
||||||
// If we need a base pointer, set it up here. It's whatever the value
|
|
||||||
// of the stack pointer is at this point. Any variable size objects
|
|
||||||
// will be allocated after this, so we can still use the base pointer
|
|
||||||
// to reference locals.
|
|
||||||
if (hasBasePointer(MF))
|
|
||||||
BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVgpr2gpr), BasePtr).addReg(ARM::SP);
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool isCalleeSavedRegister(unsigned Reg, const unsigned *CSRegs) {
|
|
||||||
for (unsigned i = 0; CSRegs[i]; ++i)
|
|
||||||
if (Reg == CSRegs[i])
|
|
||||||
return true;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool isCSRestore(MachineInstr *MI, const unsigned *CSRegs) {
|
|
||||||
if (MI->getOpcode() == ARM::tRestore &&
|
|
||||||
MI->getOperand(1).isFI() &&
|
|
||||||
isCalleeSavedRegister(MI->getOperand(0).getReg(), CSRegs))
|
|
||||||
return true;
|
|
||||||
else if (MI->getOpcode() == ARM::tPOP) {
|
|
||||||
// The first two operands are predicates. The last two are
|
|
||||||
// imp-def and imp-use of SP. Check everything in between.
|
|
||||||
for (int i = 2, e = MI->getNumOperands() - 2; i != e; ++i)
|
|
||||||
if (!isCalleeSavedRegister(MI->getOperand(i).getReg(), CSRegs))
|
|
||||||
return false;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Thumb1RegisterInfo::emitEpilogue(MachineFunction &MF,
|
|
||||||
MachineBasicBlock &MBB) const {
|
|
||||||
MachineBasicBlock::iterator MBBI = prior(MBB.end());
|
|
||||||
assert((MBBI->getOpcode() == ARM::tBX_RET ||
|
|
||||||
MBBI->getOpcode() == ARM::tPOP_RET) &&
|
|
||||||
"Can only insert epilog into returning blocks");
|
|
||||||
DebugLoc dl = MBBI->getDebugLoc();
|
|
||||||
MachineFrameInfo *MFI = MF.getFrameInfo();
|
|
||||||
ARMFunctionInfo *AFI = MF.getInfo<ARMFunctionInfo>();
|
|
||||||
unsigned VARegSaveSize = AFI->getVarArgsRegSaveSize();
|
|
||||||
int NumBytes = (int)MFI->getStackSize();
|
|
||||||
const unsigned *CSRegs = getCalleeSavedRegs();
|
|
||||||
|
|
||||||
if (!AFI->hasStackFrame()) {
|
|
||||||
if (NumBytes != 0)
|
|
||||||
emitSPUpdate(MBB, MBBI, TII, dl, *this, NumBytes);
|
|
||||||
} else {
|
|
||||||
// Unwind MBBI to point to first LDR / VLDRD.
|
|
||||||
if (MBBI != MBB.begin()) {
|
|
||||||
do
|
|
||||||
--MBBI;
|
|
||||||
while (MBBI != MBB.begin() && isCSRestore(MBBI, CSRegs));
|
|
||||||
if (!isCSRestore(MBBI, CSRegs))
|
|
||||||
++MBBI;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Move SP to start of FP callee save spill area.
|
|
||||||
NumBytes -= (AFI->getGPRCalleeSavedArea1Size() +
|
|
||||||
AFI->getGPRCalleeSavedArea2Size() +
|
|
||||||
AFI->getDPRCalleeSavedAreaSize());
|
|
||||||
|
|
||||||
if (AFI->shouldRestoreSPFromFP()) {
|
|
||||||
NumBytes = AFI->getFramePtrSpillOffset() - NumBytes;
|
|
||||||
// Reset SP based on frame pointer only if the stack frame extends beyond
|
|
||||||
// frame pointer stack slot or target is ELF and the function has FP.
|
|
||||||
if (NumBytes)
|
|
||||||
emitThumbRegPlusImmediate(MBB, MBBI, ARM::SP, FramePtr, -NumBytes,
|
|
||||||
TII, *this, dl);
|
|
||||||
else
|
|
||||||
BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVtgpr2gpr), ARM::SP)
|
|
||||||
.addReg(FramePtr);
|
|
||||||
} else {
|
|
||||||
if (MBBI->getOpcode() == ARM::tBX_RET &&
|
|
||||||
&MBB.front() != MBBI &&
|
|
||||||
prior(MBBI)->getOpcode() == ARM::tPOP) {
|
|
||||||
MachineBasicBlock::iterator PMBBI = prior(MBBI);
|
|
||||||
emitSPUpdate(MBB, PMBBI, TII, dl, *this, NumBytes);
|
|
||||||
} else
|
|
||||||
emitSPUpdate(MBB, MBBI, TII, dl, *this, NumBytes);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (VARegSaveSize) {
|
|
||||||
// Unlike T2 and ARM mode, the T1 pop instruction cannot restore
|
|
||||||
// to LR, and we can't pop the value directly to the PC since
|
|
||||||
// we need to update the SP after popping the value. Therefore, we
|
|
||||||
// pop the old LR into R3 as a temporary.
|
|
||||||
|
|
||||||
// Move back past the callee-saved register restoration
|
|
||||||
while (MBBI != MBB.end() && isCSRestore(MBBI, CSRegs))
|
|
||||||
++MBBI;
|
|
||||||
// Epilogue for vararg functions: pop LR to R3 and branch off it.
|
|
||||||
AddDefaultPred(BuildMI(MBB, MBBI, dl, TII.get(ARM::tPOP)))
|
|
||||||
.addReg(ARM::R3, RegState::Define);
|
|
||||||
|
|
||||||
emitSPUpdate(MBB, MBBI, TII, dl, *this, VARegSaveSize);
|
|
||||||
|
|
||||||
BuildMI(MBB, MBBI, dl, TII.get(ARM::tBX_RET_vararg))
|
|
||||||
.addReg(ARM::R3, RegState::Kill);
|
|
||||||
// erase the old tBX_RET instruction
|
|
||||||
MBB.erase(MBBI);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -59,9 +59,6 @@ public:
|
||||||
unsigned Reg) const;
|
unsigned Reg) const;
|
||||||
void eliminateFrameIndex(MachineBasicBlock::iterator II,
|
void eliminateFrameIndex(MachineBasicBlock::iterator II,
|
||||||
int SPAdj, RegScavenger *RS = NULL) const;
|
int SPAdj, RegScavenger *RS = NULL) const;
|
||||||
|
|
||||||
void emitPrologue(MachineFunction &MF) const;
|
|
||||||
void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const;
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,13 @@
|
||||||
#include "llvm/Target/TargetMachine.h"
|
#include "llvm/Target/TargetMachine.h"
|
||||||
|
|
||||||
namespace llvm {
|
namespace llvm {
|
||||||
|
namespace Alpha {
|
||||||
|
// These describe LDAx
|
||||||
|
|
||||||
|
static const int IMM_LOW = -32768;
|
||||||
|
static const int IMM_HIGH = 32767;
|
||||||
|
static const int IMM_MULT = 65536;
|
||||||
|
}
|
||||||
|
|
||||||
class AlphaTargetMachine;
|
class AlphaTargetMachine;
|
||||||
class FunctionPass;
|
class FunctionPass;
|
||||||
|
|
|
@ -0,0 +1,140 @@
|
||||||
|
//=====- AlphaFrameInfo.cpp - Alpha Frame Information ----------*- C++ -*-====//
|
||||||
|
//
|
||||||
|
// The LLVM Compiler Infrastructure
|
||||||
|
//
|
||||||
|
// This file is distributed under the University of Illinois Open Source
|
||||||
|
// License. See LICENSE.TXT for details.
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
//
|
||||||
|
// This file contains the Alpha implementation of TargetFrameInfo class.
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
#include "AlphaFrameInfo.h"
|
||||||
|
#include "AlphaInstrInfo.h"
|
||||||
|
#include "AlphaMachineFunctionInfo.h"
|
||||||
|
#include "llvm/Function.h"
|
||||||
|
#include "llvm/CodeGen/MachineFrameInfo.h"
|
||||||
|
#include "llvm/CodeGen/MachineFunction.h"
|
||||||
|
#include "llvm/CodeGen/MachineInstrBuilder.h"
|
||||||
|
#include "llvm/ADT/Twine.h"
|
||||||
|
|
||||||
|
using namespace llvm;
|
||||||
|
|
||||||
|
static long getUpper16(long l) {
|
||||||
|
long y = l / Alpha::IMM_MULT;
|
||||||
|
if (l % Alpha::IMM_MULT > Alpha::IMM_HIGH)
|
||||||
|
++y;
|
||||||
|
return y;
|
||||||
|
}
|
||||||
|
|
||||||
|
static long getLower16(long l) {
|
||||||
|
long h = getUpper16(l);
|
||||||
|
return l - h * Alpha::IMM_MULT;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AlphaFrameInfo::emitPrologue(MachineFunction &MF) const {
|
||||||
|
MachineBasicBlock &MBB = MF.front(); // Prolog goes in entry BB
|
||||||
|
MachineBasicBlock::iterator MBBI = MBB.begin();
|
||||||
|
MachineFrameInfo *MFI = MF.getFrameInfo();
|
||||||
|
const AlphaRegisterInfo *RegInfo =
|
||||||
|
static_cast<const AlphaRegisterInfo*>(MF.getTarget().getRegisterInfo());
|
||||||
|
const AlphaInstrInfo &TII =
|
||||||
|
*static_cast<const AlphaInstrInfo*>(MF.getTarget().getInstrInfo());
|
||||||
|
|
||||||
|
DebugLoc dl = (MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc());
|
||||||
|
bool FP = RegInfo->hasFP(MF);
|
||||||
|
|
||||||
|
// Handle GOP offset
|
||||||
|
BuildMI(MBB, MBBI, dl, TII.get(Alpha::LDAHg), Alpha::R29)
|
||||||
|
.addGlobalAddress(MF.getFunction()).addReg(Alpha::R27).addImm(++curgpdist);
|
||||||
|
BuildMI(MBB, MBBI, dl, TII.get(Alpha::LDAg), Alpha::R29)
|
||||||
|
.addGlobalAddress(MF.getFunction()).addReg(Alpha::R29).addImm(curgpdist);
|
||||||
|
|
||||||
|
BuildMI(MBB, MBBI, dl, TII.get(Alpha::ALTENT))
|
||||||
|
.addGlobalAddress(MF.getFunction());
|
||||||
|
|
||||||
|
// Get the number of bytes to allocate from the FrameInfo
|
||||||
|
long NumBytes = MFI->getStackSize();
|
||||||
|
|
||||||
|
if (FP)
|
||||||
|
NumBytes += 8; //reserve space for the old FP
|
||||||
|
|
||||||
|
// Do we need to allocate space on the stack?
|
||||||
|
if (NumBytes == 0) return;
|
||||||
|
|
||||||
|
unsigned Align = getStackAlignment();
|
||||||
|
NumBytes = (NumBytes+Align-1)/Align*Align;
|
||||||
|
|
||||||
|
// Update frame info to pretend that this is part of the stack...
|
||||||
|
MFI->setStackSize(NumBytes);
|
||||||
|
|
||||||
|
// adjust stack pointer: r30 -= numbytes
|
||||||
|
NumBytes = -NumBytes;
|
||||||
|
if (NumBytes >= Alpha::IMM_LOW) {
|
||||||
|
BuildMI(MBB, MBBI, dl, TII.get(Alpha::LDA), Alpha::R30).addImm(NumBytes)
|
||||||
|
.addReg(Alpha::R30);
|
||||||
|
} else if (getUpper16(NumBytes) >= Alpha::IMM_LOW) {
|
||||||
|
BuildMI(MBB, MBBI, dl, TII.get(Alpha::LDAH), Alpha::R30)
|
||||||
|
.addImm(getUpper16(NumBytes)).addReg(Alpha::R30);
|
||||||
|
BuildMI(MBB, MBBI, dl, TII.get(Alpha::LDA), Alpha::R30)
|
||||||
|
.addImm(getLower16(NumBytes)).addReg(Alpha::R30);
|
||||||
|
} else {
|
||||||
|
report_fatal_error("Too big a stack frame at " + Twine(NumBytes));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now if we need to, save the old FP and set the new
|
||||||
|
if (FP) {
|
||||||
|
BuildMI(MBB, MBBI, dl, TII.get(Alpha::STQ))
|
||||||
|
.addReg(Alpha::R15).addImm(0).addReg(Alpha::R30);
|
||||||
|
// This must be the last instr in the prolog
|
||||||
|
BuildMI(MBB, MBBI, dl, TII.get(Alpha::BISr), Alpha::R15)
|
||||||
|
.addReg(Alpha::R30).addReg(Alpha::R30);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void AlphaFrameInfo::emitEpilogue(MachineFunction &MF,
|
||||||
|
MachineBasicBlock &MBB) const {
|
||||||
|
const MachineFrameInfo *MFI = MF.getFrameInfo();
|
||||||
|
MachineBasicBlock::iterator MBBI = prior(MBB.end());
|
||||||
|
const AlphaRegisterInfo *RegInfo =
|
||||||
|
static_cast<const AlphaRegisterInfo*>(MF.getTarget().getRegisterInfo());
|
||||||
|
const AlphaInstrInfo &TII =
|
||||||
|
*static_cast<const AlphaInstrInfo*>(MF.getTarget().getInstrInfo());
|
||||||
|
|
||||||
|
assert((MBBI->getOpcode() == Alpha::RETDAG ||
|
||||||
|
MBBI->getOpcode() == Alpha::RETDAGp)
|
||||||
|
&& "Can only insert epilog into returning blocks");
|
||||||
|
DebugLoc dl = MBBI->getDebugLoc();
|
||||||
|
|
||||||
|
bool FP = RegInfo->hasFP(MF);
|
||||||
|
|
||||||
|
// Get the number of bytes allocated from the FrameInfo...
|
||||||
|
long NumBytes = MFI->getStackSize();
|
||||||
|
|
||||||
|
//now if we need to, restore the old FP
|
||||||
|
if (FP) {
|
||||||
|
//copy the FP into the SP (discards allocas)
|
||||||
|
BuildMI(MBB, MBBI, dl, TII.get(Alpha::BISr), Alpha::R30).addReg(Alpha::R15)
|
||||||
|
.addReg(Alpha::R15);
|
||||||
|
//restore the FP
|
||||||
|
BuildMI(MBB, MBBI, dl, TII.get(Alpha::LDQ), Alpha::R15)
|
||||||
|
.addImm(0).addReg(Alpha::R15);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (NumBytes != 0) {
|
||||||
|
if (NumBytes <= Alpha::IMM_HIGH) {
|
||||||
|
BuildMI(MBB, MBBI, dl, TII.get(Alpha::LDA), Alpha::R30).addImm(NumBytes)
|
||||||
|
.addReg(Alpha::R30);
|
||||||
|
} else if (getUpper16(NumBytes) <= Alpha::IMM_HIGH) {
|
||||||
|
BuildMI(MBB, MBBI, dl, TII.get(Alpha::LDAH), Alpha::R30)
|
||||||
|
.addImm(getUpper16(NumBytes)).addReg(Alpha::R30);
|
||||||
|
BuildMI(MBB, MBBI, dl, TII.get(Alpha::LDA), Alpha::R30)
|
||||||
|
.addImm(getLower16(NumBytes)).addReg(Alpha::R30);
|
||||||
|
} else {
|
||||||
|
report_fatal_error("Too big a stack frame at " + Twine(NumBytes));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,41 @@
|
||||||
|
//===--- AlphaFrameInfo.h - Define TargetFrameInfo for Alpha --*- C++ -*---===//
|
||||||
|
//
|
||||||
|
// The LLVM Compiler Infrastructure
|
||||||
|
//
|
||||||
|
// This file is distributed under the University of Illinois Open Source
|
||||||
|
// License. See LICENSE.TXT for details.
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
#ifndef ALPHA_FRAMEINFO_H
|
||||||
|
#define ALPHA_FRAMEINFO_H
|
||||||
|
|
||||||
|
#include "Alpha.h"
|
||||||
|
#include "AlphaSubtarget.h"
|
||||||
|
#include "llvm/Target/TargetFrameInfo.h"
|
||||||
|
|
||||||
|
namespace llvm {
|
||||||
|
class AlphaSubtarget;
|
||||||
|
|
||||||
|
class AlphaFrameInfo : public TargetFrameInfo {
|
||||||
|
const AlphaSubtarget &STI;
|
||||||
|
// FIXME: This should end in MachineFunctionInfo, not here!
|
||||||
|
mutable int curgpdist;
|
||||||
|
public:
|
||||||
|
explicit AlphaFrameInfo(const AlphaSubtarget &sti)
|
||||||
|
: TargetFrameInfo(StackGrowsDown, 16, 0), STI(sti), curgpdist(0) {
|
||||||
|
}
|
||||||
|
|
||||||
|
/// emitProlog/emitEpilog - These methods insert prolog and epilog code into
|
||||||
|
/// the function.
|
||||||
|
void emitPrologue(MachineFunction &MF) const;
|
||||||
|
void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // End llvm namespace
|
||||||
|
|
||||||
|
#endif
|
|
@ -35,29 +35,21 @@
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
using namespace llvm;
|
using namespace llvm;
|
||||||
|
|
||||||
//These describe LDAx
|
AlphaRegisterInfo::AlphaRegisterInfo(const TargetInstrInfo &tii)
|
||||||
static const int IMM_LOW = -32768;
|
: AlphaGenRegisterInfo(Alpha::ADJUSTSTACKDOWN, Alpha::ADJUSTSTACKUP),
|
||||||
static const int IMM_HIGH = 32767;
|
TII(tii) {
|
||||||
static const int IMM_MULT = 65536;
|
}
|
||||||
|
|
||||||
static long getUpper16(long l)
|
static long getUpper16(long l) {
|
||||||
{
|
long y = l / Alpha::IMM_MULT;
|
||||||
long y = l / IMM_MULT;
|
if (l % Alpha::IMM_MULT > Alpha::IMM_HIGH)
|
||||||
if (l % IMM_MULT > IMM_HIGH)
|
|
||||||
++y;
|
++y;
|
||||||
return y;
|
return y;
|
||||||
}
|
}
|
||||||
|
|
||||||
static long getLower16(long l)
|
static long getLower16(long l) {
|
||||||
{
|
|
||||||
long h = getUpper16(l);
|
long h = getUpper16(l);
|
||||||
return l - h * IMM_MULT;
|
return l - h * Alpha::IMM_MULT;
|
||||||
}
|
|
||||||
|
|
||||||
AlphaRegisterInfo::AlphaRegisterInfo(const TargetInstrInfo &tii)
|
|
||||||
: AlphaGenRegisterInfo(Alpha::ADJUSTSTACKDOWN, Alpha::ADJUSTSTACKUP),
|
|
||||||
TII(tii), curgpdist(0)
|
|
||||||
{
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const unsigned* AlphaRegisterInfo::getCalleeSavedRegs(const MachineFunction *MF)
|
const unsigned* AlphaRegisterInfo::getCalleeSavedRegs(const MachineFunction *MF)
|
||||||
|
@ -168,7 +160,7 @@ AlphaRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
|
||||||
DEBUG(errs() << "Corrected Offset " << Offset
|
DEBUG(errs() << "Corrected Offset " << Offset
|
||||||
<< " for stack size: " << MF.getFrameInfo()->getStackSize() << "\n");
|
<< " for stack size: " << MF.getFrameInfo()->getStackSize() << "\n");
|
||||||
|
|
||||||
if (Offset > IMM_HIGH || Offset < IMM_LOW) {
|
if (Offset > Alpha::IMM_HIGH || Offset < Alpha::IMM_LOW) {
|
||||||
DEBUG(errs() << "Unconditionally using R28 for evil purposes Offset: "
|
DEBUG(errs() << "Unconditionally using R28 for evil purposes Offset: "
|
||||||
<< Offset << "\n");
|
<< Offset << "\n");
|
||||||
//so in this case, we need to use a temporary register, and move the
|
//so in this case, we need to use a temporary register, and move the
|
||||||
|
@ -186,105 +178,6 @@ AlphaRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void AlphaRegisterInfo::emitPrologue(MachineFunction &MF) const {
|
|
||||||
MachineBasicBlock &MBB = MF.front(); // Prolog goes in entry BB
|
|
||||||
MachineBasicBlock::iterator MBBI = MBB.begin();
|
|
||||||
MachineFrameInfo *MFI = MF.getFrameInfo();
|
|
||||||
DebugLoc dl = (MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc());
|
|
||||||
bool FP = hasFP(MF);
|
|
||||||
|
|
||||||
//handle GOP offset
|
|
||||||
BuildMI(MBB, MBBI, dl, TII.get(Alpha::LDAHg), Alpha::R29)
|
|
||||||
.addGlobalAddress(MF.getFunction())
|
|
||||||
.addReg(Alpha::R27).addImm(++curgpdist);
|
|
||||||
BuildMI(MBB, MBBI, dl, TII.get(Alpha::LDAg), Alpha::R29)
|
|
||||||
.addGlobalAddress(MF.getFunction())
|
|
||||||
.addReg(Alpha::R29).addImm(curgpdist);
|
|
||||||
|
|
||||||
BuildMI(MBB, MBBI, dl, TII.get(Alpha::ALTENT))
|
|
||||||
.addGlobalAddress(MF.getFunction());
|
|
||||||
|
|
||||||
// Get the number of bytes to allocate from the FrameInfo
|
|
||||||
long NumBytes = MFI->getStackSize();
|
|
||||||
|
|
||||||
if (FP)
|
|
||||||
NumBytes += 8; //reserve space for the old FP
|
|
||||||
|
|
||||||
// Do we need to allocate space on the stack?
|
|
||||||
if (NumBytes == 0) return;
|
|
||||||
|
|
||||||
unsigned Align = MF.getTarget().getFrameInfo()->getStackAlignment();
|
|
||||||
NumBytes = (NumBytes+Align-1)/Align*Align;
|
|
||||||
|
|
||||||
// Update frame info to pretend that this is part of the stack...
|
|
||||||
MFI->setStackSize(NumBytes);
|
|
||||||
|
|
||||||
// adjust stack pointer: r30 -= numbytes
|
|
||||||
NumBytes = -NumBytes;
|
|
||||||
if (NumBytes >= IMM_LOW) {
|
|
||||||
BuildMI(MBB, MBBI, dl, TII.get(Alpha::LDA), Alpha::R30).addImm(NumBytes)
|
|
||||||
.addReg(Alpha::R30);
|
|
||||||
} else if (getUpper16(NumBytes) >= IMM_LOW) {
|
|
||||||
BuildMI(MBB, MBBI, dl, TII.get(Alpha::LDAH), Alpha::R30)
|
|
||||||
.addImm(getUpper16(NumBytes)).addReg(Alpha::R30);
|
|
||||||
BuildMI(MBB, MBBI, dl, TII.get(Alpha::LDA), Alpha::R30)
|
|
||||||
.addImm(getLower16(NumBytes)).addReg(Alpha::R30);
|
|
||||||
} else {
|
|
||||||
report_fatal_error("Too big a stack frame at " + Twine(NumBytes));
|
|
||||||
}
|
|
||||||
|
|
||||||
//now if we need to, save the old FP and set the new
|
|
||||||
if (FP)
|
|
||||||
{
|
|
||||||
BuildMI(MBB, MBBI, dl, TII.get(Alpha::STQ))
|
|
||||||
.addReg(Alpha::R15).addImm(0).addReg(Alpha::R30);
|
|
||||||
//this must be the last instr in the prolog
|
|
||||||
BuildMI(MBB, MBBI, dl, TII.get(Alpha::BISr), Alpha::R15)
|
|
||||||
.addReg(Alpha::R30).addReg(Alpha::R30);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void AlphaRegisterInfo::emitEpilogue(MachineFunction &MF,
|
|
||||||
MachineBasicBlock &MBB) const {
|
|
||||||
const MachineFrameInfo *MFI = MF.getFrameInfo();
|
|
||||||
MachineBasicBlock::iterator MBBI = prior(MBB.end());
|
|
||||||
assert((MBBI->getOpcode() == Alpha::RETDAG ||
|
|
||||||
MBBI->getOpcode() == Alpha::RETDAGp)
|
|
||||||
&& "Can only insert epilog into returning blocks");
|
|
||||||
DebugLoc dl = MBBI->getDebugLoc();
|
|
||||||
|
|
||||||
bool FP = hasFP(MF);
|
|
||||||
|
|
||||||
// Get the number of bytes allocated from the FrameInfo...
|
|
||||||
long NumBytes = MFI->getStackSize();
|
|
||||||
|
|
||||||
//now if we need to, restore the old FP
|
|
||||||
if (FP) {
|
|
||||||
//copy the FP into the SP (discards allocas)
|
|
||||||
BuildMI(MBB, MBBI, dl, TII.get(Alpha::BISr), Alpha::R30).addReg(Alpha::R15)
|
|
||||||
.addReg(Alpha::R15);
|
|
||||||
//restore the FP
|
|
||||||
BuildMI(MBB, MBBI, dl, TII.get(Alpha::LDQ), Alpha::R15)
|
|
||||||
.addImm(0).addReg(Alpha::R15);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (NumBytes != 0) {
|
|
||||||
if (NumBytes <= IMM_HIGH) {
|
|
||||||
BuildMI(MBB, MBBI, dl, TII.get(Alpha::LDA), Alpha::R30).addImm(NumBytes)
|
|
||||||
.addReg(Alpha::R30);
|
|
||||||
} else if (getUpper16(NumBytes) <= IMM_HIGH) {
|
|
||||||
BuildMI(MBB, MBBI, dl, TII.get(Alpha::LDAH), Alpha::R30)
|
|
||||||
.addImm(getUpper16(NumBytes)).addReg(Alpha::R30);
|
|
||||||
BuildMI(MBB, MBBI, dl, TII.get(Alpha::LDA), Alpha::R30)
|
|
||||||
.addImm(getLower16(NumBytes)).addReg(Alpha::R30);
|
|
||||||
} else {
|
|
||||||
report_fatal_error("Too big a stack frame at " + Twine(NumBytes));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned AlphaRegisterInfo::getRARegister() const {
|
unsigned AlphaRegisterInfo::getRARegister() const {
|
||||||
return Alpha::R26;
|
return Alpha::R26;
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,11 +41,6 @@ struct AlphaRegisterInfo : public AlphaGenRegisterInfo {
|
||||||
void eliminateFrameIndex(MachineBasicBlock::iterator II,
|
void eliminateFrameIndex(MachineBasicBlock::iterator II,
|
||||||
int SPAdj, RegScavenger *RS = NULL) const;
|
int SPAdj, RegScavenger *RS = NULL) const;
|
||||||
|
|
||||||
//void processFunctionBeforeFrameFinalized(MachineFunction &MF) const;
|
|
||||||
|
|
||||||
void emitPrologue(MachineFunction &MF) const;
|
|
||||||
void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const;
|
|
||||||
|
|
||||||
// Debug information queries.
|
// Debug information queries.
|
||||||
unsigned getRARegister() const;
|
unsigned getRARegister() const;
|
||||||
unsigned getFrameRegister(const MachineFunction &MF) const;
|
unsigned getFrameRegister(const MachineFunction &MF) const;
|
||||||
|
@ -57,9 +52,6 @@ struct AlphaRegisterInfo : public AlphaGenRegisterInfo {
|
||||||
int getDwarfRegNum(unsigned RegNum, bool isEH) const;
|
int getDwarfRegNum(unsigned RegNum, bool isEH) const;
|
||||||
|
|
||||||
static std::string getPrettyName(unsigned reg);
|
static std::string getPrettyName(unsigned reg);
|
||||||
|
|
||||||
private:
|
|
||||||
mutable int curgpdist;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // end namespace llvm
|
} // end namespace llvm
|
||||||
|
|
|
@ -28,7 +28,7 @@ AlphaTargetMachine::AlphaTargetMachine(const Target &T, const std::string &TT,
|
||||||
const std::string &FS)
|
const std::string &FS)
|
||||||
: LLVMTargetMachine(T, TT),
|
: LLVMTargetMachine(T, TT),
|
||||||
DataLayout("e-f128:128:128-n64"),
|
DataLayout("e-f128:128:128-n64"),
|
||||||
FrameInfo(TargetFrameInfo::StackGrowsDown, 16, 0),
|
FrameInfo(Subtarget),
|
||||||
Subtarget(TT, FS),
|
Subtarget(TT, FS),
|
||||||
TLInfo(*this),
|
TLInfo(*this),
|
||||||
TSInfo(*this) {
|
TSInfo(*this) {
|
||||||
|
|
|
@ -14,13 +14,14 @@
|
||||||
#ifndef ALPHA_TARGETMACHINE_H
|
#ifndef ALPHA_TARGETMACHINE_H
|
||||||
#define ALPHA_TARGETMACHINE_H
|
#define ALPHA_TARGETMACHINE_H
|
||||||
|
|
||||||
|
#include "AlphaInstrInfo.h"
|
||||||
|
#include "AlphaISelLowering.h"
|
||||||
|
#include "AlphaFrameInfo.h"
|
||||||
|
#include "AlphaSelectionDAGInfo.h"
|
||||||
|
#include "AlphaSubtarget.h"
|
||||||
#include "llvm/Target/TargetMachine.h"
|
#include "llvm/Target/TargetMachine.h"
|
||||||
#include "llvm/Target/TargetData.h"
|
#include "llvm/Target/TargetData.h"
|
||||||
#include "llvm/Target/TargetFrameInfo.h"
|
#include "llvm/Target/TargetFrameInfo.h"
|
||||||
#include "AlphaInstrInfo.h"
|
|
||||||
#include "AlphaISelLowering.h"
|
|
||||||
#include "AlphaSelectionDAGInfo.h"
|
|
||||||
#include "AlphaSubtarget.h"
|
|
||||||
|
|
||||||
namespace llvm {
|
namespace llvm {
|
||||||
|
|
||||||
|
@ -29,7 +30,7 @@ class GlobalValue;
|
||||||
class AlphaTargetMachine : public LLVMTargetMachine {
|
class AlphaTargetMachine : public LLVMTargetMachine {
|
||||||
const TargetData DataLayout; // Calculates type size & alignment
|
const TargetData DataLayout; // Calculates type size & alignment
|
||||||
AlphaInstrInfo InstrInfo;
|
AlphaInstrInfo InstrInfo;
|
||||||
TargetFrameInfo FrameInfo;
|
AlphaFrameInfo FrameInfo;
|
||||||
AlphaSubtarget Subtarget;
|
AlphaSubtarget Subtarget;
|
||||||
AlphaTargetLowering TLInfo;
|
AlphaTargetLowering TLInfo;
|
||||||
AlphaSelectionDAGInfo TSInfo;
|
AlphaSelectionDAGInfo TSInfo;
|
||||||
|
|
|
@ -0,0 +1,97 @@
|
||||||
|
//====- BlackfinFrameInfo.cpp - Blackfin Frame Information ------*- C++ -*-===//
|
||||||
|
//
|
||||||
|
// The LLVM Compiler Infrastructure
|
||||||
|
//
|
||||||
|
// This file is distributed under the University of Illinois Open Source
|
||||||
|
// License. See LICENSE.TXT for details.
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
//
|
||||||
|
// This file contains the Blackfin implementation of TargetFrameInfo class.
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
#include "BlackfinFrameInfo.h"
|
||||||
|
#include "BlackfinInstrInfo.h"
|
||||||
|
#include "llvm/CodeGen/MachineFrameInfo.h"
|
||||||
|
#include "llvm/CodeGen/MachineFunction.h"
|
||||||
|
#include "llvm/CodeGen/MachineInstrBuilder.h"
|
||||||
|
|
||||||
|
using namespace llvm;
|
||||||
|
|
||||||
|
|
||||||
|
// Emit a prologue that sets up a stack frame.
|
||||||
|
// On function entry, R0-R2 and P0 may hold arguments.
|
||||||
|
// R3, P1, and P2 may be used as scratch registers
|
||||||
|
void BlackfinFrameInfo::emitPrologue(MachineFunction &MF) const {
|
||||||
|
MachineBasicBlock &MBB = MF.front(); // Prolog goes in entry BB
|
||||||
|
MachineBasicBlock::iterator MBBI = MBB.begin();
|
||||||
|
MachineFrameInfo *MFI = MF.getFrameInfo();
|
||||||
|
const BlackfinRegisterInfo *RegInfo =
|
||||||
|
static_cast<const BlackfinRegisterInfo*>(MF.getTarget().getRegisterInfo());
|
||||||
|
const BlackfinInstrInfo &TII =
|
||||||
|
*static_cast<const BlackfinInstrInfo*>(MF.getTarget().getInstrInfo());
|
||||||
|
|
||||||
|
DebugLoc dl = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc();
|
||||||
|
|
||||||
|
int FrameSize = MFI->getStackSize();
|
||||||
|
if (FrameSize%4) {
|
||||||
|
FrameSize = (FrameSize+3) & ~3;
|
||||||
|
MFI->setStackSize(FrameSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!RegInfo->hasFP(MF)) {
|
||||||
|
assert(!MFI->adjustsStack() &&
|
||||||
|
"FP elimination on a non-leaf function is not supported");
|
||||||
|
RegInfo->adjustRegister(MBB, MBBI, dl, BF::SP, BF::P1, -FrameSize);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// emit a LINK instruction
|
||||||
|
if (FrameSize <= 0x3ffff) {
|
||||||
|
BuildMI(MBB, MBBI, dl, TII.get(BF::LINK)).addImm(FrameSize);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Frame is too big, do a manual LINK:
|
||||||
|
// [--SP] = RETS;
|
||||||
|
// [--SP] = FP;
|
||||||
|
// FP = SP;
|
||||||
|
// P1 = -FrameSize;
|
||||||
|
// SP = SP + P1;
|
||||||
|
BuildMI(MBB, MBBI, dl, TII.get(BF::PUSH))
|
||||||
|
.addReg(BF::RETS, RegState::Kill);
|
||||||
|
BuildMI(MBB, MBBI, dl, TII.get(BF::PUSH))
|
||||||
|
.addReg(BF::FP, RegState::Kill);
|
||||||
|
BuildMI(MBB, MBBI, dl, TII.get(BF::MOVE), BF::FP)
|
||||||
|
.addReg(BF::SP);
|
||||||
|
RegInfo->loadConstant(MBB, MBBI, dl, BF::P1, -FrameSize);
|
||||||
|
BuildMI(MBB, MBBI, dl, TII.get(BF::ADDpp), BF::SP)
|
||||||
|
.addReg(BF::SP, RegState::Kill)
|
||||||
|
.addReg(BF::P1, RegState::Kill);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void BlackfinFrameInfo::emitEpilogue(MachineFunction &MF,
|
||||||
|
MachineBasicBlock &MBB) const {
|
||||||
|
MachineFrameInfo *MFI = MF.getFrameInfo();
|
||||||
|
const BlackfinRegisterInfo *RegInfo =
|
||||||
|
static_cast<const BlackfinRegisterInfo*>(MF.getTarget().getRegisterInfo());
|
||||||
|
const BlackfinInstrInfo &TII =
|
||||||
|
*static_cast<const BlackfinInstrInfo*>(MF.getTarget().getInstrInfo());
|
||||||
|
MachineBasicBlock::iterator MBBI = prior(MBB.end());
|
||||||
|
DebugLoc dl = MBBI->getDebugLoc();
|
||||||
|
|
||||||
|
int FrameSize = MFI->getStackSize();
|
||||||
|
assert(FrameSize%4 == 0 && "Misaligned frame size");
|
||||||
|
|
||||||
|
if (!RegInfo->hasFP(MF)) {
|
||||||
|
assert(!MFI->adjustsStack() &&
|
||||||
|
"FP elimination on a non-leaf function is not supported");
|
||||||
|
RegInfo->adjustRegister(MBB, MBBI, dl, BF::SP, BF::P1, FrameSize);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// emit an UNLINK instruction
|
||||||
|
BuildMI(MBB, MBBI, dl, TII.get(BF::UNLINK));
|
||||||
|
}
|
|
@ -0,0 +1,41 @@
|
||||||
|
//=- BlackfinFrameInfo.h - Define TargetFrameInfo for Blackfin --*- C++ -*--==//
|
||||||
|
//
|
||||||
|
// The LLVM Compiler Infrastructure
|
||||||
|
//
|
||||||
|
// This file is distributed under the University of Illinois Open Source
|
||||||
|
// License. See LICENSE.TXT for details.
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
#ifndef ALPHA_FRAMEINFO_H
|
||||||
|
#define ALPHA_FRAMEINFO_H
|
||||||
|
|
||||||
|
#include "Blackfin.h"
|
||||||
|
#include "BlackfinSubtarget.h"
|
||||||
|
#include "llvm/Target/TargetFrameInfo.h"
|
||||||
|
|
||||||
|
namespace llvm {
|
||||||
|
class BlackfinSubtarget;
|
||||||
|
|
||||||
|
class BlackfinFrameInfo : public TargetFrameInfo {
|
||||||
|
protected:
|
||||||
|
const BlackfinSubtarget &STI;
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit BlackfinFrameInfo(const BlackfinSubtarget &sti)
|
||||||
|
: TargetFrameInfo(TargetFrameInfo::StackGrowsDown, 4, 0), STI(sti) {
|
||||||
|
}
|
||||||
|
|
||||||
|
/// emitProlog/emitEpilog - These methods insert prolog and epilog code into
|
||||||
|
/// the function.
|
||||||
|
void emitPrologue(MachineFunction &MF) const;
|
||||||
|
void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // End llvm namespace
|
||||||
|
|
||||||
|
#endif
|
|
@ -342,73 +342,6 @@ processFunctionBeforeCalleeSavedScan(MachineFunction &MF,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Emit a prologue that sets up a stack frame.
|
|
||||||
// On function entry, R0-R2 and P0 may hold arguments.
|
|
||||||
// R3, P1, and P2 may be used as scratch registers
|
|
||||||
void BlackfinRegisterInfo::emitPrologue(MachineFunction &MF) const {
|
|
||||||
MachineBasicBlock &MBB = MF.front(); // Prolog goes in entry BB
|
|
||||||
MachineBasicBlock::iterator MBBI = MBB.begin();
|
|
||||||
MachineFrameInfo *MFI = MF.getFrameInfo();
|
|
||||||
DebugLoc dl = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc();
|
|
||||||
|
|
||||||
int FrameSize = MFI->getStackSize();
|
|
||||||
if (FrameSize%4) {
|
|
||||||
FrameSize = (FrameSize+3) & ~3;
|
|
||||||
MFI->setStackSize(FrameSize);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!hasFP(MF)) {
|
|
||||||
assert(!MFI->adjustsStack() &&
|
|
||||||
"FP elimination on a non-leaf function is not supported");
|
|
||||||
adjustRegister(MBB, MBBI, dl, BF::SP, BF::P1, -FrameSize);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// emit a LINK instruction
|
|
||||||
if (FrameSize <= 0x3ffff) {
|
|
||||||
BuildMI(MBB, MBBI, dl, TII.get(BF::LINK)).addImm(FrameSize);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Frame is too big, do a manual LINK:
|
|
||||||
// [--SP] = RETS;
|
|
||||||
// [--SP] = FP;
|
|
||||||
// FP = SP;
|
|
||||||
// P1 = -FrameSize;
|
|
||||||
// SP = SP + P1;
|
|
||||||
BuildMI(MBB, MBBI, dl, TII.get(BF::PUSH))
|
|
||||||
.addReg(BF::RETS, RegState::Kill);
|
|
||||||
BuildMI(MBB, MBBI, dl, TII.get(BF::PUSH))
|
|
||||||
.addReg(BF::FP, RegState::Kill);
|
|
||||||
BuildMI(MBB, MBBI, dl, TII.get(BF::MOVE), BF::FP)
|
|
||||||
.addReg(BF::SP);
|
|
||||||
loadConstant(MBB, MBBI, dl, BF::P1, -FrameSize);
|
|
||||||
BuildMI(MBB, MBBI, dl, TII.get(BF::ADDpp), BF::SP)
|
|
||||||
.addReg(BF::SP, RegState::Kill)
|
|
||||||
.addReg(BF::P1, RegState::Kill);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void BlackfinRegisterInfo::emitEpilogue(MachineFunction &MF,
|
|
||||||
MachineBasicBlock &MBB) const {
|
|
||||||
MachineFrameInfo *MFI = MF.getFrameInfo();
|
|
||||||
MachineBasicBlock::iterator MBBI = prior(MBB.end());
|
|
||||||
DebugLoc dl = MBBI->getDebugLoc();
|
|
||||||
|
|
||||||
int FrameSize = MFI->getStackSize();
|
|
||||||
assert(FrameSize%4 == 0 && "Misaligned frame size");
|
|
||||||
|
|
||||||
if (!hasFP(MF)) {
|
|
||||||
assert(!MFI->adjustsStack() &&
|
|
||||||
"FP elimination on a non-leaf function is not supported");
|
|
||||||
adjustRegister(MBB, MBBI, dl, BF::SP, BF::P1, FrameSize);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// emit an UNLINK instruction
|
|
||||||
BuildMI(MBB, MBBI, dl, TII.get(BF::UNLINK));
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned BlackfinRegisterInfo::getRARegister() const {
|
unsigned BlackfinRegisterInfo::getRARegister() const {
|
||||||
return BF::RETS;
|
return BF::RETS;
|
||||||
}
|
}
|
||||||
|
|
|
@ -57,9 +57,6 @@ namespace llvm {
|
||||||
void processFunctionBeforeCalleeSavedScan(MachineFunction &MF,
|
void processFunctionBeforeCalleeSavedScan(MachineFunction &MF,
|
||||||
RegScavenger *RS) const;
|
RegScavenger *RS) const;
|
||||||
|
|
||||||
void emitPrologue(MachineFunction &MF) const;
|
|
||||||
void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const;
|
|
||||||
|
|
||||||
unsigned getFrameRegister(const MachineFunction &MF) const;
|
unsigned getFrameRegister(const MachineFunction &MF) const;
|
||||||
unsigned getRARegister() const;
|
unsigned getRARegister() const;
|
||||||
|
|
||||||
|
|
|
@ -33,7 +33,7 @@ BlackfinTargetMachine::BlackfinTargetMachine(const Target &T,
|
||||||
TLInfo(*this),
|
TLInfo(*this),
|
||||||
TSInfo(*this),
|
TSInfo(*this),
|
||||||
InstrInfo(Subtarget),
|
InstrInfo(Subtarget),
|
||||||
FrameInfo(TargetFrameInfo::StackGrowsDown, 4, 0) {
|
FrameInfo(Subtarget) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool BlackfinTargetMachine::addInstSelector(PassManagerBase &PM,
|
bool BlackfinTargetMachine::addInstSelector(PassManagerBase &PM,
|
||||||
|
|
|
@ -14,14 +14,15 @@
|
||||||
#ifndef BLACKFINTARGETMACHINE_H
|
#ifndef BLACKFINTARGETMACHINE_H
|
||||||
#define BLACKFINTARGETMACHINE_H
|
#define BLACKFINTARGETMACHINE_H
|
||||||
|
|
||||||
|
#include "BlackfinInstrInfo.h"
|
||||||
|
#include "BlackfinIntrinsicInfo.h"
|
||||||
|
#include "BlackfinISelLowering.h"
|
||||||
|
#include "BlackfinFrameInfo.h"
|
||||||
|
#include "BlackfinSubtarget.h"
|
||||||
|
#include "BlackfinSelectionDAGInfo.h"
|
||||||
#include "llvm/Target/TargetMachine.h"
|
#include "llvm/Target/TargetMachine.h"
|
||||||
#include "llvm/Target/TargetData.h"
|
#include "llvm/Target/TargetData.h"
|
||||||
#include "llvm/Target/TargetFrameInfo.h"
|
#include "llvm/Target/TargetFrameInfo.h"
|
||||||
#include "BlackfinInstrInfo.h"
|
|
||||||
#include "BlackfinSubtarget.h"
|
|
||||||
#include "BlackfinISelLowering.h"
|
|
||||||
#include "BlackfinSelectionDAGInfo.h"
|
|
||||||
#include "BlackfinIntrinsicInfo.h"
|
|
||||||
|
|
||||||
namespace llvm {
|
namespace llvm {
|
||||||
|
|
||||||
|
@ -31,7 +32,7 @@ namespace llvm {
|
||||||
BlackfinTargetLowering TLInfo;
|
BlackfinTargetLowering TLInfo;
|
||||||
BlackfinSelectionDAGInfo TSInfo;
|
BlackfinSelectionDAGInfo TSInfo;
|
||||||
BlackfinInstrInfo InstrInfo;
|
BlackfinInstrInfo InstrInfo;
|
||||||
TargetFrameInfo FrameInfo;
|
BlackfinFrameInfo FrameInfo;
|
||||||
BlackfinIntrinsicInfo IntrinsicInfo;
|
BlackfinIntrinsicInfo IntrinsicInfo;
|
||||||
public:
|
public:
|
||||||
BlackfinTargetMachine(const Target &T, const std::string &TT,
|
BlackfinTargetMachine(const Target &T, const std::string &TT,
|
||||||
|
|
|
@ -14,16 +14,225 @@
|
||||||
#include "SPU.h"
|
#include "SPU.h"
|
||||||
#include "SPUFrameInfo.h"
|
#include "SPUFrameInfo.h"
|
||||||
#include "SPURegisterNames.h"
|
#include "SPURegisterNames.h"
|
||||||
|
#include "SPUInstrBuilder.h"
|
||||||
|
#include "SPUInstrInfo.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;
|
using namespace llvm;
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
// SPUFrameInfo:
|
// SPUFrameInfo:
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
SPUFrameInfo::SPUFrameInfo(const TargetMachine &tm):
|
SPUFrameInfo::SPUFrameInfo(const SPUSubtarget &sti)
|
||||||
TargetFrameInfo(TargetFrameInfo::StackGrowsDown, 16, 0),
|
: TargetFrameInfo(TargetFrameInfo::StackGrowsDown, 16, 0),
|
||||||
TM(tm)
|
Subtarget(sti) {
|
||||||
{
|
|
||||||
LR[0].first = SPU::R0;
|
LR[0].first = SPU::R0;
|
||||||
LR[0].second = 16;
|
LR[0].second = 16;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// determineFrameLayout - Determine the size of the frame and maximum call
|
||||||
|
/// frame size.
|
||||||
|
void SPUFrameInfo::determineFrameLayout(MachineFunction &MF) const {
|
||||||
|
MachineFrameInfo *MFI = MF.getFrameInfo();
|
||||||
|
|
||||||
|
// Get the number of bytes to allocate from the FrameInfo
|
||||||
|
unsigned FrameSize = MFI->getStackSize();
|
||||||
|
|
||||||
|
// Get the alignments provided by the target, and the maximum alignment
|
||||||
|
// (if any) of the fixed frame objects.
|
||||||
|
unsigned TargetAlign = MF.getTarget().getFrameInfo()->getStackAlignment();
|
||||||
|
unsigned Align = std::max(TargetAlign, MFI->getMaxAlignment());
|
||||||
|
assert(isPowerOf2_32(Align) && "Alignment is not power of 2");
|
||||||
|
unsigned AlignMask = Align - 1;
|
||||||
|
|
||||||
|
// Get the maximum call frame size of all the calls.
|
||||||
|
unsigned maxCallFrameSize = MFI->getMaxCallFrameSize();
|
||||||
|
|
||||||
|
// If we have dynamic alloca then maxCallFrameSize needs to be aligned so
|
||||||
|
// that allocations will be aligned.
|
||||||
|
if (MFI->hasVarSizedObjects())
|
||||||
|
maxCallFrameSize = (maxCallFrameSize + AlignMask) & ~AlignMask;
|
||||||
|
|
||||||
|
// Update maximum call frame size.
|
||||||
|
MFI->setMaxCallFrameSize(maxCallFrameSize);
|
||||||
|
|
||||||
|
// Include call frame size in total.
|
||||||
|
FrameSize += maxCallFrameSize;
|
||||||
|
|
||||||
|
// Make sure the frame is aligned.
|
||||||
|
FrameSize = (FrameSize + AlignMask) & ~AlignMask;
|
||||||
|
|
||||||
|
// Update frame info.
|
||||||
|
MFI->setStackSize(FrameSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SPUFrameInfo::emitPrologue(MachineFunction &MF) const {
|
||||||
|
MachineBasicBlock &MBB = MF.front(); // Prolog goes in entry BB
|
||||||
|
MachineBasicBlock::iterator MBBI = MBB.begin();
|
||||||
|
MachineFrameInfo *MFI = MF.getFrameInfo();
|
||||||
|
const SPUInstrInfo &TII =
|
||||||
|
*static_cast<const SPUInstrInfo*>(MF.getTarget().getInstrInfo());
|
||||||
|
MachineModuleInfo &MMI = MF.getMMI();
|
||||||
|
DebugLoc dl = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc();
|
||||||
|
|
||||||
|
// Prepare for debug frame info.
|
||||||
|
bool hasDebugInfo = MMI.hasDebugInfo();
|
||||||
|
MCSymbol *FrameLabel = 0;
|
||||||
|
|
||||||
|
// Move MBBI back to the beginning of the function.
|
||||||
|
MBBI = MBB.begin();
|
||||||
|
|
||||||
|
// Work out frame sizes.
|
||||||
|
determineFrameLayout(MF);
|
||||||
|
int FrameSize = MFI->getStackSize();
|
||||||
|
|
||||||
|
assert((FrameSize & 0xf) == 0
|
||||||
|
&& "SPURegisterInfo::emitPrologue: FrameSize not aligned");
|
||||||
|
|
||||||
|
// the "empty" frame size is 16 - just the register scavenger spill slot
|
||||||
|
if (FrameSize > 16 || MFI->adjustsStack()) {
|
||||||
|
FrameSize = -(FrameSize + SPUFrameInfo::minStackSize());
|
||||||
|
if (hasDebugInfo) {
|
||||||
|
// Mark effective beginning of when frame pointer becomes valid.
|
||||||
|
FrameLabel = MMI.getContext().CreateTempSymbol();
|
||||||
|
BuildMI(MBB, MBBI, dl, TII.get(SPU::PROLOG_LABEL)).addSym(FrameLabel);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Adjust stack pointer, spilling $lr -> 16($sp) and $sp -> -FrameSize($sp)
|
||||||
|
// for the ABI
|
||||||
|
BuildMI(MBB, MBBI, dl, TII.get(SPU::STQDr32), SPU::R0).addImm(16)
|
||||||
|
.addReg(SPU::R1);
|
||||||
|
if (isInt<10>(FrameSize)) {
|
||||||
|
// Spill $sp to adjusted $sp
|
||||||
|
BuildMI(MBB, MBBI, dl, TII.get(SPU::STQDr32), SPU::R1).addImm(FrameSize)
|
||||||
|
.addReg(SPU::R1);
|
||||||
|
// Adjust $sp by required amout
|
||||||
|
BuildMI(MBB, MBBI, dl, TII.get(SPU::AIr32), SPU::R1).addReg(SPU::R1)
|
||||||
|
.addImm(FrameSize);
|
||||||
|
} else if (isInt<16>(FrameSize)) {
|
||||||
|
// Frame size can be loaded into ILr32n, so temporarily spill $r2 and use
|
||||||
|
// $r2 to adjust $sp:
|
||||||
|
BuildMI(MBB, MBBI, dl, TII.get(SPU::STQDr128), SPU::R2)
|
||||||
|
.addImm(-16)
|
||||||
|
.addReg(SPU::R1);
|
||||||
|
BuildMI(MBB, MBBI, dl, TII.get(SPU::ILr32), SPU::R2)
|
||||||
|
.addImm(FrameSize);
|
||||||
|
BuildMI(MBB, MBBI, dl, TII.get(SPU::STQXr32), SPU::R1)
|
||||||
|
.addReg(SPU::R2)
|
||||||
|
.addReg(SPU::R1);
|
||||||
|
BuildMI(MBB, MBBI, dl, TII.get(SPU::Ar32), SPU::R1)
|
||||||
|
.addReg(SPU::R1)
|
||||||
|
.addReg(SPU::R2);
|
||||||
|
BuildMI(MBB, MBBI, dl, TII.get(SPU::SFIr32), SPU::R2)
|
||||||
|
.addReg(SPU::R2)
|
||||||
|
.addImm(16);
|
||||||
|
BuildMI(MBB, MBBI, dl, TII.get(SPU::LQXr128), SPU::R2)
|
||||||
|
.addReg(SPU::R2)
|
||||||
|
.addReg(SPU::R1);
|
||||||
|
} else {
|
||||||
|
report_fatal_error("Unhandled frame size: " + Twine(FrameSize));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hasDebugInfo) {
|
||||||
|
std::vector<MachineMove> &Moves = MMI.getFrameMoves();
|
||||||
|
|
||||||
|
// Show update of SP.
|
||||||
|
MachineLocation SPDst(MachineLocation::VirtualFP);
|
||||||
|
MachineLocation SPSrc(MachineLocation::VirtualFP, -FrameSize);
|
||||||
|
Moves.push_back(MachineMove(FrameLabel, SPDst, SPSrc));
|
||||||
|
|
||||||
|
// Add callee saved registers to move list.
|
||||||
|
const std::vector<CalleeSavedInfo> &CSI = MFI->getCalleeSavedInfo();
|
||||||
|
for (unsigned I = 0, E = CSI.size(); I != E; ++I) {
|
||||||
|
int Offset = MFI->getObjectOffset(CSI[I].getFrameIdx());
|
||||||
|
unsigned Reg = CSI[I].getReg();
|
||||||
|
if (Reg == SPU::R0) continue;
|
||||||
|
MachineLocation CSDst(MachineLocation::VirtualFP, Offset);
|
||||||
|
MachineLocation CSSrc(Reg);
|
||||||
|
Moves.push_back(MachineMove(FrameLabel, CSDst, CSSrc));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mark effective beginning of when frame pointer is ready.
|
||||||
|
MCSymbol *ReadyLabel = MMI.getContext().CreateTempSymbol();
|
||||||
|
BuildMI(MBB, MBBI, dl, TII.get(SPU::PROLOG_LABEL)).addSym(ReadyLabel);
|
||||||
|
|
||||||
|
MachineLocation FPDst(SPU::R1);
|
||||||
|
MachineLocation FPSrc(MachineLocation::VirtualFP);
|
||||||
|
Moves.push_back(MachineMove(ReadyLabel, FPDst, FPSrc));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// This is a leaf function -- insert a branch hint iff there are
|
||||||
|
// sufficient number instructions in the basic block. Note that
|
||||||
|
// this is just a best guess based on the basic block's size.
|
||||||
|
if (MBB.size() >= (unsigned) SPUFrameInfo::branchHintPenalty()) {
|
||||||
|
MachineBasicBlock::iterator MBBI = prior(MBB.end());
|
||||||
|
dl = MBBI->getDebugLoc();
|
||||||
|
|
||||||
|
// Insert terminator label
|
||||||
|
BuildMI(MBB, MBBI, dl, TII.get(SPU::PROLOG_LABEL))
|
||||||
|
.addSym(MMI.getContext().CreateTempSymbol());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SPUFrameInfo::emitEpilogue(MachineFunction &MF,
|
||||||
|
MachineBasicBlock &MBB) const {
|
||||||
|
MachineBasicBlock::iterator MBBI = prior(MBB.end());
|
||||||
|
const SPUInstrInfo &TII =
|
||||||
|
*static_cast<const SPUInstrInfo*>(MF.getTarget().getInstrInfo());
|
||||||
|
const MachineFrameInfo *MFI = MF.getFrameInfo();
|
||||||
|
int FrameSize = MFI->getStackSize();
|
||||||
|
int LinkSlotOffset = SPUFrameInfo::stackSlotSize();
|
||||||
|
DebugLoc dl = MBBI->getDebugLoc();
|
||||||
|
|
||||||
|
assert(MBBI->getOpcode() == SPU::RET &&
|
||||||
|
"Can only insert epilog into returning blocks");
|
||||||
|
assert((FrameSize & 0xf) == 0 && "FrameSize not aligned");
|
||||||
|
|
||||||
|
// the "empty" frame size is 16 - just the register scavenger spill slot
|
||||||
|
if (FrameSize > 16 || MFI->adjustsStack()) {
|
||||||
|
FrameSize = FrameSize + SPUFrameInfo::minStackSize();
|
||||||
|
if (isInt<10>(FrameSize + LinkSlotOffset)) {
|
||||||
|
// Reload $lr, adjust $sp by required amount
|
||||||
|
// Note: We do this to slightly improve dual issue -- not by much, but it
|
||||||
|
// is an opportunity for dual issue.
|
||||||
|
BuildMI(MBB, MBBI, dl, TII.get(SPU::LQDr128), SPU::R0)
|
||||||
|
.addImm(FrameSize + LinkSlotOffset)
|
||||||
|
.addReg(SPU::R1);
|
||||||
|
BuildMI(MBB, MBBI, dl, TII.get(SPU::AIr32), SPU::R1)
|
||||||
|
.addReg(SPU::R1)
|
||||||
|
.addImm(FrameSize);
|
||||||
|
} else if (FrameSize <= (1 << 16) - 1 && FrameSize >= -(1 << 16)) {
|
||||||
|
// Frame size can be loaded into ILr32n, so temporarily spill $r2 and use
|
||||||
|
// $r2 to adjust $sp:
|
||||||
|
BuildMI(MBB, MBBI, dl, TII.get(SPU::STQDr128), SPU::R2)
|
||||||
|
.addImm(16)
|
||||||
|
.addReg(SPU::R1);
|
||||||
|
BuildMI(MBB, MBBI, dl, TII.get(SPU::ILr32), SPU::R2)
|
||||||
|
.addImm(FrameSize);
|
||||||
|
BuildMI(MBB, MBBI, dl, TII.get(SPU::Ar32), SPU::R1)
|
||||||
|
.addReg(SPU::R1)
|
||||||
|
.addReg(SPU::R2);
|
||||||
|
BuildMI(MBB, MBBI, dl, TII.get(SPU::LQDr128), SPU::R0)
|
||||||
|
.addImm(16)
|
||||||
|
.addReg(SPU::R1);
|
||||||
|
BuildMI(MBB, MBBI, dl, TII.get(SPU::SFIr32), SPU::R2).
|
||||||
|
addReg(SPU::R2)
|
||||||
|
.addImm(16);
|
||||||
|
BuildMI(MBB, MBBI, dl, TII.get(SPU::LQXr128), SPU::R2)
|
||||||
|
.addReg(SPU::R2)
|
||||||
|
.addReg(SPU::R1);
|
||||||
|
} else {
|
||||||
|
report_fatal_error("Unhandled frame size: " + Twine(FrameSize));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -12,19 +12,30 @@
|
||||||
//
|
//
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
#if !defined(SPUFRAMEINFO_H)
|
#ifndef SPU_FRAMEINFO_H
|
||||||
|
#define SPU_FRAMEINFO_H
|
||||||
|
|
||||||
|
#include "SPURegisterInfo.h"
|
||||||
#include "llvm/Target/TargetFrameInfo.h"
|
#include "llvm/Target/TargetFrameInfo.h"
|
||||||
#include "llvm/Target/TargetMachine.h"
|
#include "llvm/Target/TargetMachine.h"
|
||||||
#include "SPURegisterInfo.h"
|
|
||||||
|
|
||||||
namespace llvm {
|
namespace llvm {
|
||||||
|
class SPUSubtarget;
|
||||||
|
|
||||||
class SPUFrameInfo: public TargetFrameInfo {
|
class SPUFrameInfo: public TargetFrameInfo {
|
||||||
const TargetMachine &TM;
|
const SPUSubtarget &Subtarget;
|
||||||
std::pair<unsigned, int> LR[1];
|
std::pair<unsigned, int> LR[1];
|
||||||
|
|
||||||
public:
|
public:
|
||||||
SPUFrameInfo(const TargetMachine &tm);
|
SPUFrameInfo(const SPUSubtarget &sti);
|
||||||
|
|
||||||
|
//! Determine the frame's layour
|
||||||
|
void determineFrameLayout(MachineFunction &MF) const;
|
||||||
|
|
||||||
|
/// emitProlog/emitEpilog - These methods insert prolog and epilog code into
|
||||||
|
/// the function.
|
||||||
|
void emitPrologue(MachineFunction &MF) const;
|
||||||
|
void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const;
|
||||||
|
|
||||||
//! Return a function's saved spill slots
|
//! Return a function's saved spill slots
|
||||||
/*!
|
/*!
|
||||||
|
@ -71,5 +82,4 @@ namespace llvm {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#define SPUFRAMEINFO_H 1
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -329,44 +329,6 @@ SPURegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II, int SPAdj,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// determineFrameLayout - Determine the size of the frame and maximum call
|
|
||||||
/// frame size.
|
|
||||||
void
|
|
||||||
SPURegisterInfo::determineFrameLayout(MachineFunction &MF) const
|
|
||||||
{
|
|
||||||
MachineFrameInfo *MFI = MF.getFrameInfo();
|
|
||||||
|
|
||||||
// Get the number of bytes to allocate from the FrameInfo
|
|
||||||
unsigned FrameSize = MFI->getStackSize();
|
|
||||||
|
|
||||||
// Get the alignments provided by the target, and the maximum alignment
|
|
||||||
// (if any) of the fixed frame objects.
|
|
||||||
unsigned TargetAlign = MF.getTarget().getFrameInfo()->getStackAlignment();
|
|
||||||
unsigned Align = std::max(TargetAlign, MFI->getMaxAlignment());
|
|
||||||
assert(isPowerOf2_32(Align) && "Alignment is not power of 2");
|
|
||||||
unsigned AlignMask = Align - 1;
|
|
||||||
|
|
||||||
// Get the maximum call frame size of all the calls.
|
|
||||||
unsigned maxCallFrameSize = MFI->getMaxCallFrameSize();
|
|
||||||
|
|
||||||
// If we have dynamic alloca then maxCallFrameSize needs to be aligned so
|
|
||||||
// that allocations will be aligned.
|
|
||||||
if (MFI->hasVarSizedObjects())
|
|
||||||
maxCallFrameSize = (maxCallFrameSize + AlignMask) & ~AlignMask;
|
|
||||||
|
|
||||||
// Update maximum call frame size.
|
|
||||||
MFI->setMaxCallFrameSize(maxCallFrameSize);
|
|
||||||
|
|
||||||
// Include call frame size in total.
|
|
||||||
FrameSize += maxCallFrameSize;
|
|
||||||
|
|
||||||
// Make sure the frame is aligned.
|
|
||||||
FrameSize = (FrameSize + AlignMask) & ~AlignMask;
|
|
||||||
|
|
||||||
// Update frame info.
|
|
||||||
MFI->setStackSize(FrameSize);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SPURegisterInfo::processFunctionBeforeCalleeSavedScan(MachineFunction &MF,
|
void SPURegisterInfo::processFunctionBeforeCalleeSavedScan(MachineFunction &MF,
|
||||||
RegScavenger *RS)
|
RegScavenger *RS)
|
||||||
const {
|
const {
|
||||||
|
@ -383,169 +345,6 @@ void SPURegisterInfo::processFunctionBeforeCalleeSavedScan(MachineFunction &MF,
|
||||||
RS->setScavengingFrameIndex(MFI->CreateStackObject(RC->getSize(),
|
RS->setScavengingFrameIndex(MFI->CreateStackObject(RC->getSize(),
|
||||||
RC->getAlignment(),
|
RC->getAlignment(),
|
||||||
false));
|
false));
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void SPURegisterInfo::emitPrologue(MachineFunction &MF) const
|
|
||||||
{
|
|
||||||
MachineBasicBlock &MBB = MF.front(); // Prolog goes in entry BB
|
|
||||||
MachineBasicBlock::iterator MBBI = MBB.begin();
|
|
||||||
MachineFrameInfo *MFI = MF.getFrameInfo();
|
|
||||||
MachineModuleInfo &MMI = MF.getMMI();
|
|
||||||
DebugLoc dl = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc();
|
|
||||||
|
|
||||||
// Prepare for debug frame info.
|
|
||||||
bool hasDebugInfo = MMI.hasDebugInfo();
|
|
||||||
MCSymbol *FrameLabel = 0;
|
|
||||||
|
|
||||||
// Move MBBI back to the beginning of the function.
|
|
||||||
MBBI = MBB.begin();
|
|
||||||
|
|
||||||
// Work out frame sizes.
|
|
||||||
determineFrameLayout(MF);
|
|
||||||
int FrameSize = MFI->getStackSize();
|
|
||||||
|
|
||||||
assert((FrameSize & 0xf) == 0
|
|
||||||
&& "SPURegisterInfo::emitPrologue: FrameSize not aligned");
|
|
||||||
|
|
||||||
// the "empty" frame size is 16 - just the register scavenger spill slot
|
|
||||||
if (FrameSize > 16 || MFI->adjustsStack()) {
|
|
||||||
FrameSize = -(FrameSize + SPUFrameInfo::minStackSize());
|
|
||||||
if (hasDebugInfo) {
|
|
||||||
// Mark effective beginning of when frame pointer becomes valid.
|
|
||||||
FrameLabel = MMI.getContext().CreateTempSymbol();
|
|
||||||
BuildMI(MBB, MBBI, dl, TII.get(SPU::PROLOG_LABEL)).addSym(FrameLabel);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Adjust stack pointer, spilling $lr -> 16($sp) and $sp -> -FrameSize($sp)
|
|
||||||
// for the ABI
|
|
||||||
BuildMI(MBB, MBBI, dl, TII.get(SPU::STQDr32), SPU::R0).addImm(16)
|
|
||||||
.addReg(SPU::R1);
|
|
||||||
if (isInt<10>(FrameSize)) {
|
|
||||||
// Spill $sp to adjusted $sp
|
|
||||||
BuildMI(MBB, MBBI, dl, TII.get(SPU::STQDr32), SPU::R1).addImm(FrameSize)
|
|
||||||
.addReg(SPU::R1);
|
|
||||||
// Adjust $sp by required amout
|
|
||||||
BuildMI(MBB, MBBI, dl, TII.get(SPU::AIr32), SPU::R1).addReg(SPU::R1)
|
|
||||||
.addImm(FrameSize);
|
|
||||||
} else if (isInt<16>(FrameSize)) {
|
|
||||||
// Frame size can be loaded into ILr32n, so temporarily spill $r2 and use
|
|
||||||
// $r2 to adjust $sp:
|
|
||||||
BuildMI(MBB, MBBI, dl, TII.get(SPU::STQDr128), SPU::R2)
|
|
||||||
.addImm(-16)
|
|
||||||
.addReg(SPU::R1);
|
|
||||||
BuildMI(MBB, MBBI, dl, TII.get(SPU::ILr32), SPU::R2)
|
|
||||||
.addImm(FrameSize);
|
|
||||||
BuildMI(MBB, MBBI, dl, TII.get(SPU::STQXr32), SPU::R1)
|
|
||||||
.addReg(SPU::R2)
|
|
||||||
.addReg(SPU::R1);
|
|
||||||
BuildMI(MBB, MBBI, dl, TII.get(SPU::Ar32), SPU::R1)
|
|
||||||
.addReg(SPU::R1)
|
|
||||||
.addReg(SPU::R2);
|
|
||||||
BuildMI(MBB, MBBI, dl, TII.get(SPU::SFIr32), SPU::R2)
|
|
||||||
.addReg(SPU::R2)
|
|
||||||
.addImm(16);
|
|
||||||
BuildMI(MBB, MBBI, dl, TII.get(SPU::LQXr128), SPU::R2)
|
|
||||||
.addReg(SPU::R2)
|
|
||||||
.addReg(SPU::R1);
|
|
||||||
} else {
|
|
||||||
report_fatal_error("Unhandled frame size: " + Twine(FrameSize));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (hasDebugInfo) {
|
|
||||||
std::vector<MachineMove> &Moves = MMI.getFrameMoves();
|
|
||||||
|
|
||||||
// Show update of SP.
|
|
||||||
MachineLocation SPDst(MachineLocation::VirtualFP);
|
|
||||||
MachineLocation SPSrc(MachineLocation::VirtualFP, -FrameSize);
|
|
||||||
Moves.push_back(MachineMove(FrameLabel, SPDst, SPSrc));
|
|
||||||
|
|
||||||
// Add callee saved registers to move list.
|
|
||||||
const std::vector<CalleeSavedInfo> &CSI = MFI->getCalleeSavedInfo();
|
|
||||||
for (unsigned I = 0, E = CSI.size(); I != E; ++I) {
|
|
||||||
int Offset = MFI->getObjectOffset(CSI[I].getFrameIdx());
|
|
||||||
unsigned Reg = CSI[I].getReg();
|
|
||||||
if (Reg == SPU::R0) continue;
|
|
||||||
MachineLocation CSDst(MachineLocation::VirtualFP, Offset);
|
|
||||||
MachineLocation CSSrc(Reg);
|
|
||||||
Moves.push_back(MachineMove(FrameLabel, CSDst, CSSrc));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Mark effective beginning of when frame pointer is ready.
|
|
||||||
MCSymbol *ReadyLabel = MMI.getContext().CreateTempSymbol();
|
|
||||||
BuildMI(MBB, MBBI, dl, TII.get(SPU::PROLOG_LABEL)).addSym(ReadyLabel);
|
|
||||||
|
|
||||||
MachineLocation FPDst(SPU::R1);
|
|
||||||
MachineLocation FPSrc(MachineLocation::VirtualFP);
|
|
||||||
Moves.push_back(MachineMove(ReadyLabel, FPDst, FPSrc));
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// This is a leaf function -- insert a branch hint iff there are
|
|
||||||
// sufficient number instructions in the basic block. Note that
|
|
||||||
// this is just a best guess based on the basic block's size.
|
|
||||||
if (MBB.size() >= (unsigned) SPUFrameInfo::branchHintPenalty()) {
|
|
||||||
MachineBasicBlock::iterator MBBI = prior(MBB.end());
|
|
||||||
dl = MBBI->getDebugLoc();
|
|
||||||
|
|
||||||
// Insert terminator label
|
|
||||||
BuildMI(MBB, MBBI, dl, TII.get(SPU::PROLOG_LABEL))
|
|
||||||
.addSym(MMI.getContext().CreateTempSymbol());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
SPURegisterInfo::emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const
|
|
||||||
{
|
|
||||||
MachineBasicBlock::iterator MBBI = prior(MBB.end());
|
|
||||||
const MachineFrameInfo *MFI = MF.getFrameInfo();
|
|
||||||
int FrameSize = MFI->getStackSize();
|
|
||||||
int LinkSlotOffset = SPUFrameInfo::stackSlotSize();
|
|
||||||
DebugLoc dl = MBBI->getDebugLoc();
|
|
||||||
|
|
||||||
assert(MBBI->getOpcode() == SPU::RET &&
|
|
||||||
"Can only insert epilog into returning blocks");
|
|
||||||
assert((FrameSize & 0xf) == 0
|
|
||||||
&& "SPURegisterInfo::emitEpilogue: FrameSize not aligned");
|
|
||||||
|
|
||||||
// the "empty" frame size is 16 - just the register scavenger spill slot
|
|
||||||
if (FrameSize > 16 || MFI->adjustsStack()) {
|
|
||||||
FrameSize = FrameSize + SPUFrameInfo::minStackSize();
|
|
||||||
if (isInt<10>(FrameSize + LinkSlotOffset)) {
|
|
||||||
// Reload $lr, adjust $sp by required amount
|
|
||||||
// Note: We do this to slightly improve dual issue -- not by much, but it
|
|
||||||
// is an opportunity for dual issue.
|
|
||||||
BuildMI(MBB, MBBI, dl, TII.get(SPU::LQDr128), SPU::R0)
|
|
||||||
.addImm(FrameSize + LinkSlotOffset)
|
|
||||||
.addReg(SPU::R1);
|
|
||||||
BuildMI(MBB, MBBI, dl, TII.get(SPU::AIr32), SPU::R1)
|
|
||||||
.addReg(SPU::R1)
|
|
||||||
.addImm(FrameSize);
|
|
||||||
} else if (FrameSize <= (1 << 16) - 1 && FrameSize >= -(1 << 16)) {
|
|
||||||
// Frame size can be loaded into ILr32n, so temporarily spill $r2 and use
|
|
||||||
// $r2 to adjust $sp:
|
|
||||||
BuildMI(MBB, MBBI, dl, TII.get(SPU::STQDr128), SPU::R2)
|
|
||||||
.addImm(16)
|
|
||||||
.addReg(SPU::R1);
|
|
||||||
BuildMI(MBB, MBBI, dl, TII.get(SPU::ILr32), SPU::R2)
|
|
||||||
.addImm(FrameSize);
|
|
||||||
BuildMI(MBB, MBBI, dl, TII.get(SPU::Ar32), SPU::R1)
|
|
||||||
.addReg(SPU::R1)
|
|
||||||
.addReg(SPU::R2);
|
|
||||||
BuildMI(MBB, MBBI, dl, TII.get(SPU::LQDr128), SPU::R0)
|
|
||||||
.addImm(16)
|
|
||||||
.addReg(SPU::R1);
|
|
||||||
BuildMI(MBB, MBBI, dl, TII.get(SPU::SFIr32), SPU::R2).
|
|
||||||
addReg(SPU::R2)
|
|
||||||
.addImm(16);
|
|
||||||
BuildMI(MBB, MBBI, dl, TII.get(SPU::LQXr128), SPU::R2)
|
|
||||||
.addReg(SPU::R2)
|
|
||||||
.addReg(SPU::R1);
|
|
||||||
} else {
|
|
||||||
report_fatal_error("Unhandled frame size: " + Twine(FrameSize));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned
|
unsigned
|
||||||
|
|
|
@ -65,15 +65,10 @@ namespace llvm {
|
||||||
//! Convert frame indicies into machine operands
|
//! Convert frame indicies into machine operands
|
||||||
void eliminateFrameIndex(MachineBasicBlock::iterator II, int SPAdj,
|
void eliminateFrameIndex(MachineBasicBlock::iterator II, int SPAdj,
|
||||||
RegScavenger *RS = NULL) const;
|
RegScavenger *RS = NULL) const;
|
||||||
//! Determine the frame's layour
|
|
||||||
void determineFrameLayout(MachineFunction &MF) const;
|
|
||||||
|
|
||||||
void processFunctionBeforeCalleeSavedScan(MachineFunction &MF,
|
void processFunctionBeforeCalleeSavedScan(MachineFunction &MF,
|
||||||
RegScavenger *RS = NULL) const;
|
RegScavenger *RS = NULL) const;
|
||||||
//! Emit the function prologue
|
|
||||||
void emitPrologue(MachineFunction &MF) const;
|
|
||||||
//! Emit the function epilogue
|
|
||||||
void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const;
|
|
||||||
//! Get return address register (LR, aka R0)
|
//! Get return address register (LR, aka R0)
|
||||||
unsigned getRARegister() const;
|
unsigned getRARegister() const;
|
||||||
//! Get the stack frame register (SP, aka R1)
|
//! Get the stack frame register (SP, aka R1)
|
||||||
|
|
|
@ -40,7 +40,7 @@ SPUTargetMachine::SPUTargetMachine(const Target &T, const std::string &TT,
|
||||||
Subtarget(TT, FS),
|
Subtarget(TT, FS),
|
||||||
DataLayout(Subtarget.getTargetDataString()),
|
DataLayout(Subtarget.getTargetDataString()),
|
||||||
InstrInfo(*this),
|
InstrInfo(*this),
|
||||||
FrameInfo(*this),
|
FrameInfo(Subtarget),
|
||||||
TLInfo(*this),
|
TLInfo(*this),
|
||||||
TSInfo(*this),
|
TSInfo(*this),
|
||||||
InstrItins(Subtarget.getInstrItineraryData()) {
|
InstrItins(Subtarget.getInstrItineraryData()) {
|
||||||
|
|
|
@ -0,0 +1,183 @@
|
||||||
|
//=======- MBlazeFrameInfo.cpp - MBlaze Frame Information ------*- C++ -*-====//
|
||||||
|
//
|
||||||
|
// The LLVM Compiler Infrastructure
|
||||||
|
//
|
||||||
|
// This file is distributed under the University of Illinois Open Source
|
||||||
|
// License. See LICENSE.TXT for details.
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
//
|
||||||
|
// This file contains the MBlaze implementation of TargetFrameInfo class.
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
#include "MBlazeFrameInfo.h"
|
||||||
|
#include "MBlazeInstrInfo.h"
|
||||||
|
#include "MBlazeMachineFunction.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;
|
||||||
|
|
||||||
|
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
//
|
||||||
|
// Stack Frame Processing methods
|
||||||
|
// +----------------------------+
|
||||||
|
//
|
||||||
|
// The stack is allocated decrementing the stack pointer on
|
||||||
|
// the first instruction of a function prologue. Once decremented,
|
||||||
|
// all stack references are are done through a positive offset
|
||||||
|
// from the stack/frame pointer, so the stack is considered
|
||||||
|
// to grow up.
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
void MBlazeFrameInfo::adjustMBlazeStackFrame(MachineFunction &MF) const {
|
||||||
|
MachineFrameInfo *MFI = MF.getFrameInfo();
|
||||||
|
MBlazeFunctionInfo *MBlazeFI = MF.getInfo<MBlazeFunctionInfo>();
|
||||||
|
const MBlazeRegisterInfo *RegInfo =
|
||||||
|
static_cast<const MBlazeRegisterInfo*>(MF.getTarget().getRegisterInfo());
|
||||||
|
|
||||||
|
// See the description at MicroBlazeMachineFunction.h
|
||||||
|
int TopCPUSavedRegOff = -1;
|
||||||
|
|
||||||
|
// Adjust CPU Callee Saved Registers Area. Registers RA and FP must
|
||||||
|
// be saved in this CPU Area there is the need. This whole Area must
|
||||||
|
// be aligned to the default Stack Alignment requirements.
|
||||||
|
unsigned StackOffset = MFI->getStackSize();
|
||||||
|
unsigned RegSize = 4;
|
||||||
|
|
||||||
|
// Replace the dummy '0' SPOffset by the negative offsets, as explained on
|
||||||
|
// LowerFORMAL_ARGUMENTS. Leaving '0' for while is necessary to avoid
|
||||||
|
// the approach done by calculateFrameObjectOffsets to the stack frame.
|
||||||
|
MBlazeFI->adjustLoadArgsFI(MFI);
|
||||||
|
MBlazeFI->adjustStoreVarArgsFI(MFI);
|
||||||
|
|
||||||
|
if (RegInfo->hasFP(MF)) {
|
||||||
|
MFI->setObjectOffset(MFI->CreateStackObject(RegSize, RegSize, true),
|
||||||
|
StackOffset);
|
||||||
|
MBlazeFI->setFPStackOffset(StackOffset);
|
||||||
|
TopCPUSavedRegOff = StackOffset;
|
||||||
|
StackOffset += RegSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (MFI->adjustsStack()) {
|
||||||
|
MBlazeFI->setRAStackOffset(0);
|
||||||
|
MFI->setObjectOffset(MFI->CreateStackObject(RegSize, RegSize, true),
|
||||||
|
StackOffset);
|
||||||
|
TopCPUSavedRegOff = StackOffset;
|
||||||
|
StackOffset += RegSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update frame info
|
||||||
|
MFI->setStackSize(StackOffset);
|
||||||
|
|
||||||
|
// Recalculate the final tops offset. The final values must be '0'
|
||||||
|
// if there isn't a callee saved register for CPU or FPU, otherwise
|
||||||
|
// a negative offset is needed.
|
||||||
|
if (TopCPUSavedRegOff >= 0)
|
||||||
|
MBlazeFI->setCPUTopSavedRegOff(TopCPUSavedRegOff-StackOffset);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MBlazeFrameInfo::emitPrologue(MachineFunction &MF) const {
|
||||||
|
MachineBasicBlock &MBB = MF.front();
|
||||||
|
MachineFrameInfo *MFI = MF.getFrameInfo();
|
||||||
|
const MBlazeRegisterInfo *RegInfo =
|
||||||
|
static_cast<const MBlazeRegisterInfo*>(MF.getTarget().getRegisterInfo());
|
||||||
|
const MBlazeInstrInfo &TII =
|
||||||
|
*static_cast<const MBlazeInstrInfo*>(MF.getTarget().getInstrInfo());
|
||||||
|
MBlazeFunctionInfo *MBlazeFI = MF.getInfo<MBlazeFunctionInfo>();
|
||||||
|
MachineBasicBlock::iterator MBBI = MBB.begin();
|
||||||
|
DebugLoc DL = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc();
|
||||||
|
|
||||||
|
// Get the right frame order for MBlaze.
|
||||||
|
adjustMBlazeStackFrame(MF);
|
||||||
|
|
||||||
|
// Get the number of bytes to allocate from the FrameInfo.
|
||||||
|
unsigned StackSize = MFI->getStackSize();
|
||||||
|
|
||||||
|
// No need to allocate space on the stack.
|
||||||
|
if (StackSize == 0 && !MFI->adjustsStack()) return;
|
||||||
|
if (StackSize < 28 && MFI->adjustsStack()) StackSize = 28;
|
||||||
|
|
||||||
|
int FPOffset = MBlazeFI->getFPStackOffset();
|
||||||
|
int RAOffset = MBlazeFI->getRAStackOffset();
|
||||||
|
|
||||||
|
// Adjust stack : addi R1, R1, -imm
|
||||||
|
BuildMI(MBB, MBBI, DL, TII.get(MBlaze::ADDI), MBlaze::R1)
|
||||||
|
.addReg(MBlaze::R1).addImm(-StackSize);
|
||||||
|
|
||||||
|
// Save the return address only if the function isnt a leaf one.
|
||||||
|
// swi R15, R1, stack_loc
|
||||||
|
if (MFI->adjustsStack()) {
|
||||||
|
BuildMI(MBB, MBBI, DL, TII.get(MBlaze::SWI))
|
||||||
|
.addReg(MBlaze::R15).addReg(MBlaze::R1).addImm(RAOffset);
|
||||||
|
}
|
||||||
|
|
||||||
|
// if framepointer enabled, save it and set it
|
||||||
|
// to point to the stack pointer
|
||||||
|
if (RegInfo->hasFP(MF)) {
|
||||||
|
// swi R19, R1, stack_loc
|
||||||
|
BuildMI(MBB, MBBI, DL, TII.get(MBlaze::SWI))
|
||||||
|
.addReg(MBlaze::R19).addReg(MBlaze::R1).addImm(FPOffset);
|
||||||
|
|
||||||
|
// add R19, R1, R0
|
||||||
|
BuildMI(MBB, MBBI, DL, TII.get(MBlaze::ADD), MBlaze::R19)
|
||||||
|
.addReg(MBlaze::R1).addReg(MBlaze::R0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MBlazeFrameInfo::emitEpilogue(MachineFunction &MF,
|
||||||
|
MachineBasicBlock &MBB) const {
|
||||||
|
MachineBasicBlock::iterator MBBI = prior(MBB.end());
|
||||||
|
MachineFrameInfo *MFI = MF.getFrameInfo();
|
||||||
|
MBlazeFunctionInfo *MBlazeFI = MF.getInfo<MBlazeFunctionInfo>();
|
||||||
|
const MBlazeRegisterInfo *RegInfo =
|
||||||
|
static_cast<const MBlazeRegisterInfo*>(MF.getTarget().getRegisterInfo());
|
||||||
|
const MBlazeInstrInfo &TII =
|
||||||
|
*static_cast<const MBlazeInstrInfo*>(MF.getTarget().getInstrInfo());
|
||||||
|
|
||||||
|
DebugLoc dl = MBBI->getDebugLoc();
|
||||||
|
|
||||||
|
// Get the FI's where RA and FP are saved.
|
||||||
|
int FPOffset = MBlazeFI->getFPStackOffset();
|
||||||
|
int RAOffset = MBlazeFI->getRAStackOffset();
|
||||||
|
|
||||||
|
// if framepointer enabled, restore it and restore the
|
||||||
|
// stack pointer
|
||||||
|
if (RegInfo->hasFP(MF)) {
|
||||||
|
// add R1, R19, R0
|
||||||
|
BuildMI(MBB, MBBI, dl, TII.get(MBlaze::ADD), MBlaze::R1)
|
||||||
|
.addReg(MBlaze::R19).addReg(MBlaze::R0);
|
||||||
|
|
||||||
|
// lwi R19, R1, stack_loc
|
||||||
|
BuildMI(MBB, MBBI, dl, TII.get(MBlaze::LWI), MBlaze::R19)
|
||||||
|
.addReg(MBlaze::R1).addImm(FPOffset);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Restore the return address only if the function isnt a leaf one.
|
||||||
|
// lwi R15, R1, stack_loc
|
||||||
|
if (MFI->adjustsStack()) {
|
||||||
|
BuildMI(MBB, MBBI, dl, TII.get(MBlaze::LWI), MBlaze::R15)
|
||||||
|
.addReg(MBlaze::R1).addImm(RAOffset);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the number of bytes from FrameInfo
|
||||||
|
int StackSize = (int) MFI->getStackSize();
|
||||||
|
if (StackSize < 28 && MFI->adjustsStack()) StackSize = 28;
|
||||||
|
|
||||||
|
// adjust stack.
|
||||||
|
// addi R1, R1, imm
|
||||||
|
if (StackSize) {
|
||||||
|
BuildMI(MBB, MBBI, dl, TII.get(MBlaze::ADDI), MBlaze::R1)
|
||||||
|
.addReg(MBlaze::R1).addImm(StackSize);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,48 @@
|
||||||
|
//=-- MBlazeFrameInfo.h - Define TargetFrameInfo for MicroBlaze --*- C++ -*--=//
|
||||||
|
//
|
||||||
|
// The LLVM Compiler Infrastructure
|
||||||
|
//
|
||||||
|
// This file is distributed under the University of Illinois Open Source
|
||||||
|
// License. See LICENSE.TXT for details.
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
#ifndef ALPHA_FRAMEINFO_H
|
||||||
|
#define ALPHA_FRAMEINFO_H
|
||||||
|
|
||||||
|
#include "MBlaze.h"
|
||||||
|
#include "MBlazeSubtarget.h"
|
||||||
|
#include "llvm/Target/TargetFrameInfo.h"
|
||||||
|
|
||||||
|
namespace llvm {
|
||||||
|
class MBlazeSubtarget;
|
||||||
|
|
||||||
|
class MBlazeFrameInfo : public TargetFrameInfo {
|
||||||
|
protected:
|
||||||
|
const MBlazeSubtarget &STI;
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit MBlazeFrameInfo(const MBlazeSubtarget &sti)
|
||||||
|
: TargetFrameInfo(TargetFrameInfo::StackGrowsUp, 8, 0), STI(sti) {
|
||||||
|
}
|
||||||
|
|
||||||
|
void adjustMBlazeStackFrame(MachineFunction &MF) const;
|
||||||
|
|
||||||
|
/// targetHandlesStackFrameRounding - Returns true if the target is
|
||||||
|
/// responsible for rounding up the stack frame (probably at emitPrologue
|
||||||
|
/// time).
|
||||||
|
bool targetHandlesStackFrameRounding() const { return true; }
|
||||||
|
|
||||||
|
/// emitProlog/emitEpilog - These methods insert prolog and epilog code into
|
||||||
|
/// the function.
|
||||||
|
void emitPrologue(MachineFunction &MF) const;
|
||||||
|
void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // End llvm namespace
|
||||||
|
|
||||||
|
#endif
|
|
@ -164,64 +164,6 @@ getReservedRegs(const MachineFunction &MF) const {
|
||||||
return Reserved;
|
return Reserved;
|
||||||
}
|
}
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
//
|
|
||||||
// Stack Frame Processing methods
|
|
||||||
// +----------------------------+
|
|
||||||
//
|
|
||||||
// The stack is allocated decrementing the stack pointer on
|
|
||||||
// the first instruction of a function prologue. Once decremented,
|
|
||||||
// all stack references are are done through a positive offset
|
|
||||||
// from the stack/frame pointer, so the stack is considered
|
|
||||||
// to grow up.
|
|
||||||
//
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
|
|
||||||
void MBlazeRegisterInfo::adjustMBlazeStackFrame(MachineFunction &MF) const {
|
|
||||||
MachineFrameInfo *MFI = MF.getFrameInfo();
|
|
||||||
MBlazeFunctionInfo *MBlazeFI = MF.getInfo<MBlazeFunctionInfo>();
|
|
||||||
|
|
||||||
// See the description at MicroBlazeMachineFunction.h
|
|
||||||
int TopCPUSavedRegOff = -1;
|
|
||||||
|
|
||||||
// Adjust CPU Callee Saved Registers Area. Registers RA and FP must
|
|
||||||
// be saved in this CPU Area there is the need. This whole Area must
|
|
||||||
// be aligned to the default Stack Alignment requirements.
|
|
||||||
unsigned StackOffset = MFI->getStackSize();
|
|
||||||
unsigned RegSize = 4;
|
|
||||||
|
|
||||||
// Replace the dummy '0' SPOffset by the negative offsets, as explained on
|
|
||||||
// LowerFORMAL_ARGUMENTS. Leaving '0' for while is necessary to avoid
|
|
||||||
// the approach done by calculateFrameObjectOffsets to the stack frame.
|
|
||||||
MBlazeFI->adjustLoadArgsFI(MFI);
|
|
||||||
MBlazeFI->adjustStoreVarArgsFI(MFI);
|
|
||||||
|
|
||||||
if (hasFP(MF)) {
|
|
||||||
MFI->setObjectOffset(MFI->CreateStackObject(RegSize, RegSize, true),
|
|
||||||
StackOffset);
|
|
||||||
MBlazeFI->setFPStackOffset(StackOffset);
|
|
||||||
TopCPUSavedRegOff = StackOffset;
|
|
||||||
StackOffset += RegSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (MFI->adjustsStack()) {
|
|
||||||
MBlazeFI->setRAStackOffset(0);
|
|
||||||
MFI->setObjectOffset(MFI->CreateStackObject(RegSize, RegSize, true),
|
|
||||||
StackOffset);
|
|
||||||
TopCPUSavedRegOff = StackOffset;
|
|
||||||
StackOffset += RegSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update frame info
|
|
||||||
MFI->setStackSize(StackOffset);
|
|
||||||
|
|
||||||
// Recalculate the final tops offset. The final values must be '0'
|
|
||||||
// if there isn't a callee saved register for CPU or FPU, otherwise
|
|
||||||
// a negative offset is needed.
|
|
||||||
if (TopCPUSavedRegOff >= 0)
|
|
||||||
MBlazeFI->setCPUTopSavedRegOff(TopCPUSavedRegOff-StackOffset);
|
|
||||||
}
|
|
||||||
|
|
||||||
// hasFP - Return true if the specified function should have a dedicated frame
|
// 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
|
// pointer register. This is true if the function has variable sized allocas or
|
||||||
// if frame pointer elimination is disabled.
|
// if frame pointer elimination is disabled.
|
||||||
|
@ -279,94 +221,6 @@ eliminateFrameIndex(MachineBasicBlock::iterator II, int SPAdj,
|
||||||
MI.getOperand(i).ChangeToRegister(getFrameRegister(MF), false);
|
MI.getOperand(i).ChangeToRegister(getFrameRegister(MF), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MBlazeRegisterInfo::
|
|
||||||
emitPrologue(MachineFunction &MF) const {
|
|
||||||
MachineBasicBlock &MBB = MF.front();
|
|
||||||
MachineFrameInfo *MFI = MF.getFrameInfo();
|
|
||||||
MBlazeFunctionInfo *MBlazeFI = MF.getInfo<MBlazeFunctionInfo>();
|
|
||||||
MachineBasicBlock::iterator MBBI = MBB.begin();
|
|
||||||
DebugLoc DL = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc();
|
|
||||||
|
|
||||||
// Get the right frame order for MBlaze.
|
|
||||||
adjustMBlazeStackFrame(MF);
|
|
||||||
|
|
||||||
// Get the number of bytes to allocate from the FrameInfo.
|
|
||||||
unsigned StackSize = MFI->getStackSize();
|
|
||||||
|
|
||||||
// No need to allocate space on the stack.
|
|
||||||
if (StackSize == 0 && !MFI->adjustsStack()) return;
|
|
||||||
if (StackSize < 28 && MFI->adjustsStack()) StackSize = 28;
|
|
||||||
|
|
||||||
int FPOffset = MBlazeFI->getFPStackOffset();
|
|
||||||
int RAOffset = MBlazeFI->getRAStackOffset();
|
|
||||||
|
|
||||||
// Adjust stack : addi R1, R1, -imm
|
|
||||||
BuildMI(MBB, MBBI, DL, TII.get(MBlaze::ADDI), MBlaze::R1)
|
|
||||||
.addReg(MBlaze::R1).addImm(-StackSize);
|
|
||||||
|
|
||||||
// Save the return address only if the function isnt a leaf one.
|
|
||||||
// swi R15, R1, stack_loc
|
|
||||||
if (MFI->adjustsStack()) {
|
|
||||||
BuildMI(MBB, MBBI, DL, TII.get(MBlaze::SWI))
|
|
||||||
.addReg(MBlaze::R15).addReg(MBlaze::R1).addImm(RAOffset);
|
|
||||||
}
|
|
||||||
|
|
||||||
// if framepointer enabled, save it and set it
|
|
||||||
// to point to the stack pointer
|
|
||||||
if (hasFP(MF)) {
|
|
||||||
// swi R19, R1, stack_loc
|
|
||||||
BuildMI(MBB, MBBI, DL, TII.get(MBlaze::SWI))
|
|
||||||
.addReg(MBlaze::R19).addReg(MBlaze::R1).addImm(FPOffset);
|
|
||||||
|
|
||||||
// add R19, R1, R0
|
|
||||||
BuildMI(MBB, MBBI, DL, TII.get(MBlaze::ADD), MBlaze::R19)
|
|
||||||
.addReg(MBlaze::R1).addReg(MBlaze::R0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void MBlazeRegisterInfo::
|
|
||||||
emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const {
|
|
||||||
MachineBasicBlock::iterator MBBI = prior(MBB.end());
|
|
||||||
MachineFrameInfo *MFI = MF.getFrameInfo();
|
|
||||||
MBlazeFunctionInfo *MBlazeFI = MF.getInfo<MBlazeFunctionInfo>();
|
|
||||||
DebugLoc dl = MBBI->getDebugLoc();
|
|
||||||
|
|
||||||
// Get the FI's where RA and FP are saved.
|
|
||||||
int FPOffset = MBlazeFI->getFPStackOffset();
|
|
||||||
int RAOffset = MBlazeFI->getRAStackOffset();
|
|
||||||
|
|
||||||
// if framepointer enabled, restore it and restore the
|
|
||||||
// stack pointer
|
|
||||||
if (hasFP(MF)) {
|
|
||||||
// add R1, R19, R0
|
|
||||||
BuildMI(MBB, MBBI, dl, TII.get(MBlaze::ADD), MBlaze::R1)
|
|
||||||
.addReg(MBlaze::R19).addReg(MBlaze::R0);
|
|
||||||
|
|
||||||
// lwi R19, R1, stack_loc
|
|
||||||
BuildMI(MBB, MBBI, dl, TII.get(MBlaze::LWI), MBlaze::R19)
|
|
||||||
.addReg(MBlaze::R1).addImm(FPOffset);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Restore the return address only if the function isnt a leaf one.
|
|
||||||
// lwi R15, R1, stack_loc
|
|
||||||
if (MFI->adjustsStack()) {
|
|
||||||
BuildMI(MBB, MBBI, dl, TII.get(MBlaze::LWI), MBlaze::R15)
|
|
||||||
.addReg(MBlaze::R1).addImm(RAOffset);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get the number of bytes from FrameInfo
|
|
||||||
int StackSize = (int) MFI->getStackSize();
|
|
||||||
if (StackSize < 28 && MFI->adjustsStack()) StackSize = 28;
|
|
||||||
|
|
||||||
// adjust stack.
|
|
||||||
// addi R1, R1, imm
|
|
||||||
if (StackSize) {
|
|
||||||
BuildMI(MBB, MBBI, dl, TII.get(MBlaze::ADDI), MBlaze::R1)
|
|
||||||
.addReg(MBlaze::R1).addImm(StackSize);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void MBlazeRegisterInfo::
|
void MBlazeRegisterInfo::
|
||||||
processFunctionBeforeFrameFinalized(MachineFunction &MF) const {
|
processFunctionBeforeFrameFinalized(MachineFunction &MF) const {
|
||||||
// Set the stack offset where GP must be saved/loaded from.
|
// Set the stack offset where GP must be saved/loaded from.
|
||||||
|
|
|
@ -68,9 +68,6 @@ struct MBlazeRegisterInfo : public MBlazeGenRegisterInfo {
|
||||||
|
|
||||||
void processFunctionBeforeFrameFinalized(MachineFunction &MF) const;
|
void processFunctionBeforeFrameFinalized(MachineFunction &MF) const;
|
||||||
|
|
||||||
void emitPrologue(MachineFunction &MF) const;
|
|
||||||
void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const;
|
|
||||||
|
|
||||||
/// Debug information queries.
|
/// Debug information queries.
|
||||||
unsigned getRARegister() const;
|
unsigned getRARegister() const;
|
||||||
unsigned getFrameRegister(const MachineFunction &MF) const;
|
unsigned getFrameRegister(const MachineFunction &MF) const;
|
||||||
|
@ -79,11 +76,6 @@ struct MBlazeRegisterInfo : public MBlazeGenRegisterInfo {
|
||||||
unsigned getEHExceptionRegister() const;
|
unsigned getEHExceptionRegister() const;
|
||||||
unsigned getEHHandlerRegister() const;
|
unsigned getEHHandlerRegister() const;
|
||||||
|
|
||||||
/// targetHandlesStackFrameRounding - Returns true if the target is
|
|
||||||
/// responsible for rounding up the stack frame (probably at emitPrologue
|
|
||||||
/// time).
|
|
||||||
bool targetHandlesStackFrameRounding() const { return true; }
|
|
||||||
|
|
||||||
int getDwarfRegNum(unsigned RegNum, bool isEH) const;
|
int getDwarfRegNum(unsigned RegNum, bool isEH) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -85,7 +85,7 @@ MBlazeTargetMachine(const Target &T, const std::string &TT,
|
||||||
Subtarget(TT, FS),
|
Subtarget(TT, FS),
|
||||||
DataLayout("E-p:32:32:32-i8:8:8-i16:16:16"),
|
DataLayout("E-p:32:32:32-i8:8:8-i16:16:16"),
|
||||||
InstrInfo(*this),
|
InstrInfo(*this),
|
||||||
FrameInfo(TargetFrameInfo::StackGrowsUp, 8, 0),
|
FrameInfo(Subtarget),
|
||||||
TLInfo(*this), TSInfo(*this), ELFWriterInfo(*this) {
|
TLInfo(*this), TSInfo(*this), ELFWriterInfo(*this) {
|
||||||
if (getRelocationModel() == Reloc::Default) {
|
if (getRelocationModel() == Reloc::Default) {
|
||||||
setRelocationModel(Reloc::Static);
|
setRelocationModel(Reloc::Static);
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
#include "MBlazeISelLowering.h"
|
#include "MBlazeISelLowering.h"
|
||||||
#include "MBlazeSelectionDAGInfo.h"
|
#include "MBlazeSelectionDAGInfo.h"
|
||||||
#include "MBlazeIntrinsicInfo.h"
|
#include "MBlazeIntrinsicInfo.h"
|
||||||
|
#include "MBlazeFrameInfo.h"
|
||||||
#include "MBlazeELFWriterInfo.h"
|
#include "MBlazeELFWriterInfo.h"
|
||||||
#include "llvm/MC/MCStreamer.h"
|
#include "llvm/MC/MCStreamer.h"
|
||||||
#include "llvm/Target/TargetMachine.h"
|
#include "llvm/Target/TargetMachine.h"
|
||||||
|
@ -32,7 +33,7 @@ namespace llvm {
|
||||||
MBlazeSubtarget Subtarget;
|
MBlazeSubtarget Subtarget;
|
||||||
const TargetData DataLayout; // Calculates type size & alignment
|
const TargetData DataLayout; // Calculates type size & alignment
|
||||||
MBlazeInstrInfo InstrInfo;
|
MBlazeInstrInfo InstrInfo;
|
||||||
TargetFrameInfo FrameInfo;
|
MBlazeFrameInfo FrameInfo;
|
||||||
MBlazeTargetLowering TLInfo;
|
MBlazeTargetLowering TLInfo;
|
||||||
MBlazeSelectionDAGInfo TSInfo;
|
MBlazeSelectionDAGInfo TSInfo;
|
||||||
MBlazeIntrinsicInfo IntrinsicInfo;
|
MBlazeIntrinsicInfo IntrinsicInfo;
|
||||||
|
|
|
@ -0,0 +1,168 @@
|
||||||
|
//=======- MSP430FrameInfo.cpp - MSP430 Frame Information ------*- C++ -*-====//
|
||||||
|
//
|
||||||
|
// The LLVM Compiler Infrastructure
|
||||||
|
//
|
||||||
|
// This file is distributed under the University of Illinois Open Source
|
||||||
|
// License. See LICENSE.TXT for details.
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
//
|
||||||
|
// This file contains the MSP430 implementation of TargetFrameInfo class.
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
#include "MSP430FrameInfo.h"
|
||||||
|
#include "MSP430InstrInfo.h"
|
||||||
|
#include "MSP430MachineFunctionInfo.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;
|
||||||
|
|
||||||
|
void MSP430FrameInfo::emitPrologue(MachineFunction &MF) const {
|
||||||
|
MachineBasicBlock &MBB = MF.front(); // Prolog goes in entry BB
|
||||||
|
MachineFrameInfo *MFI = MF.getFrameInfo();
|
||||||
|
MSP430MachineFunctionInfo *MSP430FI = MF.getInfo<MSP430MachineFunctionInfo>();
|
||||||
|
const MSP430RegisterInfo *RegInfo =
|
||||||
|
static_cast<const MSP430RegisterInfo*>(MF.getTarget().getRegisterInfo());
|
||||||
|
const MSP430InstrInfo &TII =
|
||||||
|
*static_cast<const MSP430InstrInfo*>(MF.getTarget().getInstrInfo());
|
||||||
|
|
||||||
|
MachineBasicBlock::iterator MBBI = MBB.begin();
|
||||||
|
DebugLoc DL = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc();
|
||||||
|
|
||||||
|
// Get the number of bytes to allocate from the FrameInfo.
|
||||||
|
uint64_t StackSize = MFI->getStackSize();
|
||||||
|
|
||||||
|
uint64_t NumBytes = 0;
|
||||||
|
if (RegInfo->hasFP(MF)) {
|
||||||
|
// Calculate required stack adjustment
|
||||||
|
uint64_t FrameSize = StackSize - 2;
|
||||||
|
NumBytes = FrameSize - MSP430FI->getCalleeSavedFrameSize();
|
||||||
|
|
||||||
|
// Get the offset of the stack slot for the EBP register... which is
|
||||||
|
// guaranteed to be the last slot by processFunctionBeforeFrameFinalized.
|
||||||
|
// Update the frame offset adjustment.
|
||||||
|
MFI->setOffsetAdjustment(-NumBytes);
|
||||||
|
|
||||||
|
// Save FPW into the appropriate stack slot...
|
||||||
|
BuildMI(MBB, MBBI, DL, TII.get(MSP430::PUSH16r))
|
||||||
|
.addReg(MSP430::FPW, RegState::Kill);
|
||||||
|
|
||||||
|
// Update FPW with the new base value...
|
||||||
|
BuildMI(MBB, MBBI, DL, TII.get(MSP430::MOV16rr), MSP430::FPW)
|
||||||
|
.addReg(MSP430::SPW);
|
||||||
|
|
||||||
|
// Mark the FramePtr as live-in in every block except the entry.
|
||||||
|
for (MachineFunction::iterator I = llvm::next(MF.begin()), E = MF.end();
|
||||||
|
I != E; ++I)
|
||||||
|
I->addLiveIn(MSP430::FPW);
|
||||||
|
|
||||||
|
} else
|
||||||
|
NumBytes = StackSize - MSP430FI->getCalleeSavedFrameSize();
|
||||||
|
|
||||||
|
// Skip the callee-saved push instructions.
|
||||||
|
while (MBBI != MBB.end() && (MBBI->getOpcode() == MSP430::PUSH16r))
|
||||||
|
++MBBI;
|
||||||
|
|
||||||
|
if (MBBI != MBB.end())
|
||||||
|
DL = MBBI->getDebugLoc();
|
||||||
|
|
||||||
|
if (NumBytes) { // adjust stack pointer: SPW -= numbytes
|
||||||
|
// If there is an SUB16ri of SPW immediately before this instruction, merge
|
||||||
|
// the two.
|
||||||
|
//NumBytes -= mergeSPUpdates(MBB, MBBI, true);
|
||||||
|
// If there is an ADD16ri or SUB16ri of SPW immediately after this
|
||||||
|
// instruction, merge the two instructions.
|
||||||
|
// mergeSPUpdatesDown(MBB, MBBI, &NumBytes);
|
||||||
|
|
||||||
|
if (NumBytes) {
|
||||||
|
MachineInstr *MI =
|
||||||
|
BuildMI(MBB, MBBI, DL, TII.get(MSP430::SUB16ri), MSP430::SPW)
|
||||||
|
.addReg(MSP430::SPW).addImm(NumBytes);
|
||||||
|
// The SRW implicit def is dead.
|
||||||
|
MI->getOperand(3).setIsDead();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MSP430FrameInfo::emitEpilogue(MachineFunction &MF,
|
||||||
|
MachineBasicBlock &MBB) const {
|
||||||
|
const MachineFrameInfo *MFI = MF.getFrameInfo();
|
||||||
|
MSP430MachineFunctionInfo *MSP430FI = MF.getInfo<MSP430MachineFunctionInfo>();
|
||||||
|
const MSP430RegisterInfo *RegInfo =
|
||||||
|
static_cast<const MSP430RegisterInfo*>(MF.getTarget().getRegisterInfo());
|
||||||
|
const MSP430InstrInfo &TII =
|
||||||
|
*static_cast<const MSP430InstrInfo*>(MF.getTarget().getInstrInfo());
|
||||||
|
|
||||||
|
MachineBasicBlock::iterator MBBI = prior(MBB.end());
|
||||||
|
unsigned RetOpcode = MBBI->getOpcode();
|
||||||
|
DebugLoc DL = MBBI->getDebugLoc();
|
||||||
|
|
||||||
|
switch (RetOpcode) {
|
||||||
|
case MSP430::RET:
|
||||||
|
case MSP430::RETI: break; // These are ok
|
||||||
|
default:
|
||||||
|
llvm_unreachable("Can only insert epilog into returning blocks");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the number of bytes to allocate from the FrameInfo
|
||||||
|
uint64_t StackSize = MFI->getStackSize();
|
||||||
|
unsigned CSSize = MSP430FI->getCalleeSavedFrameSize();
|
||||||
|
uint64_t NumBytes = 0;
|
||||||
|
|
||||||
|
if (RegInfo->hasFP(MF)) {
|
||||||
|
// Calculate required stack adjustment
|
||||||
|
uint64_t FrameSize = StackSize - 2;
|
||||||
|
NumBytes = FrameSize - CSSize;
|
||||||
|
|
||||||
|
// pop FPW.
|
||||||
|
BuildMI(MBB, MBBI, DL, TII.get(MSP430::POP16r), MSP430::FPW);
|
||||||
|
} else
|
||||||
|
NumBytes = StackSize - CSSize;
|
||||||
|
|
||||||
|
// Skip the callee-saved pop instructions.
|
||||||
|
while (MBBI != MBB.begin()) {
|
||||||
|
MachineBasicBlock::iterator PI = prior(MBBI);
|
||||||
|
unsigned Opc = PI->getOpcode();
|
||||||
|
if (Opc != MSP430::POP16r && !PI->getDesc().isTerminator())
|
||||||
|
break;
|
||||||
|
--MBBI;
|
||||||
|
}
|
||||||
|
|
||||||
|
DL = MBBI->getDebugLoc();
|
||||||
|
|
||||||
|
// If there is an ADD16ri or SUB16ri of SPW immediately before this
|
||||||
|
// instruction, merge the two instructions.
|
||||||
|
//if (NumBytes || MFI->hasVarSizedObjects())
|
||||||
|
// mergeSPUpdatesUp(MBB, MBBI, StackPtr, &NumBytes);
|
||||||
|
|
||||||
|
if (MFI->hasVarSizedObjects()) {
|
||||||
|
BuildMI(MBB, MBBI, DL,
|
||||||
|
TII.get(MSP430::MOV16rr), MSP430::SPW).addReg(MSP430::FPW);
|
||||||
|
if (CSSize) {
|
||||||
|
MachineInstr *MI =
|
||||||
|
BuildMI(MBB, MBBI, DL,
|
||||||
|
TII.get(MSP430::SUB16ri), MSP430::SPW)
|
||||||
|
.addReg(MSP430::SPW).addImm(CSSize);
|
||||||
|
// The SRW implicit def is dead.
|
||||||
|
MI->getOperand(3).setIsDead();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// adjust stack pointer back: SPW += numbytes
|
||||||
|
if (NumBytes) {
|
||||||
|
MachineInstr *MI =
|
||||||
|
BuildMI(MBB, MBBI, DL, TII.get(MSP430::ADD16ri), MSP430::SPW)
|
||||||
|
.addReg(MSP430::SPW).addImm(NumBytes);
|
||||||
|
// The SRW implicit def is dead.
|
||||||
|
MI->getOperand(3).setIsDead();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,41 @@
|
||||||
|
//===-- MSP430FrameInfo.h - Define TargetFrameInfo for MSP430 --*- C++ -*--===//
|
||||||
|
//
|
||||||
|
// The LLVM Compiler Infrastructure
|
||||||
|
//
|
||||||
|
// This file is distributed under the University of Illinois Open Source
|
||||||
|
// License. See LICENSE.TXT for details.
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
#ifndef MSP430_FRAMEINFO_H
|
||||||
|
#define MSP430_FRAMEINFO_H
|
||||||
|
|
||||||
|
#include "MSP430.h"
|
||||||
|
#include "MSP430Subtarget.h"
|
||||||
|
#include "llvm/Target/TargetFrameInfo.h"
|
||||||
|
|
||||||
|
namespace llvm {
|
||||||
|
class MSP430Subtarget;
|
||||||
|
|
||||||
|
class MSP430FrameInfo : public TargetFrameInfo {
|
||||||
|
protected:
|
||||||
|
const MSP430Subtarget &STI;
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit MSP430FrameInfo(const MSP430Subtarget &sti)
|
||||||
|
: TargetFrameInfo(TargetFrameInfo::StackGrowsDown, 2, -2), STI(sti) {
|
||||||
|
}
|
||||||
|
|
||||||
|
/// emitProlog/emitEpilog - These methods insert prolog and epilog code into
|
||||||
|
/// the function.
|
||||||
|
void emitPrologue(MachineFunction &MF) const;
|
||||||
|
void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // End llvm namespace
|
||||||
|
|
||||||
|
#endif
|
|
@ -233,138 +233,6 @@ MSP430RegisterInfo::processFunctionBeforeFrameFinalized(MachineFunction &MF)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void MSP430RegisterInfo::emitPrologue(MachineFunction &MF) const {
|
|
||||||
MachineBasicBlock &MBB = MF.front(); // Prolog goes in entry BB
|
|
||||||
MachineFrameInfo *MFI = MF.getFrameInfo();
|
|
||||||
MSP430MachineFunctionInfo *MSP430FI = MF.getInfo<MSP430MachineFunctionInfo>();
|
|
||||||
MachineBasicBlock::iterator MBBI = MBB.begin();
|
|
||||||
DebugLoc DL = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc();
|
|
||||||
|
|
||||||
// Get the number of bytes to allocate from the FrameInfo.
|
|
||||||
uint64_t StackSize = MFI->getStackSize();
|
|
||||||
|
|
||||||
uint64_t NumBytes = 0;
|
|
||||||
if (hasFP(MF)) {
|
|
||||||
// Calculate required stack adjustment
|
|
||||||
uint64_t FrameSize = StackSize - 2;
|
|
||||||
NumBytes = FrameSize - MSP430FI->getCalleeSavedFrameSize();
|
|
||||||
|
|
||||||
// Get the offset of the stack slot for the EBP register... which is
|
|
||||||
// guaranteed to be the last slot by processFunctionBeforeFrameFinalized.
|
|
||||||
// Update the frame offset adjustment.
|
|
||||||
MFI->setOffsetAdjustment(-NumBytes);
|
|
||||||
|
|
||||||
// Save FPW into the appropriate stack slot...
|
|
||||||
BuildMI(MBB, MBBI, DL, TII.get(MSP430::PUSH16r))
|
|
||||||
.addReg(MSP430::FPW, RegState::Kill);
|
|
||||||
|
|
||||||
// Update FPW with the new base value...
|
|
||||||
BuildMI(MBB, MBBI, DL, TII.get(MSP430::MOV16rr), MSP430::FPW)
|
|
||||||
.addReg(MSP430::SPW);
|
|
||||||
|
|
||||||
// Mark the FramePtr as live-in in every block except the entry.
|
|
||||||
for (MachineFunction::iterator I = llvm::next(MF.begin()), E = MF.end();
|
|
||||||
I != E; ++I)
|
|
||||||
I->addLiveIn(MSP430::FPW);
|
|
||||||
|
|
||||||
} else
|
|
||||||
NumBytes = StackSize - MSP430FI->getCalleeSavedFrameSize();
|
|
||||||
|
|
||||||
// Skip the callee-saved push instructions.
|
|
||||||
while (MBBI != MBB.end() && (MBBI->getOpcode() == MSP430::PUSH16r))
|
|
||||||
++MBBI;
|
|
||||||
|
|
||||||
if (MBBI != MBB.end())
|
|
||||||
DL = MBBI->getDebugLoc();
|
|
||||||
|
|
||||||
if (NumBytes) { // adjust stack pointer: SPW -= numbytes
|
|
||||||
// If there is an SUB16ri of SPW immediately before this instruction, merge
|
|
||||||
// the two.
|
|
||||||
//NumBytes -= mergeSPUpdates(MBB, MBBI, true);
|
|
||||||
// If there is an ADD16ri or SUB16ri of SPW immediately after this
|
|
||||||
// instruction, merge the two instructions.
|
|
||||||
// mergeSPUpdatesDown(MBB, MBBI, &NumBytes);
|
|
||||||
|
|
||||||
if (NumBytes) {
|
|
||||||
MachineInstr *MI =
|
|
||||||
BuildMI(MBB, MBBI, DL, TII.get(MSP430::SUB16ri), MSP430::SPW)
|
|
||||||
.addReg(MSP430::SPW).addImm(NumBytes);
|
|
||||||
// The SRW implicit def is dead.
|
|
||||||
MI->getOperand(3).setIsDead();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void MSP430RegisterInfo::emitEpilogue(MachineFunction &MF,
|
|
||||||
MachineBasicBlock &MBB) const {
|
|
||||||
const MachineFrameInfo *MFI = MF.getFrameInfo();
|
|
||||||
MSP430MachineFunctionInfo *MSP430FI = MF.getInfo<MSP430MachineFunctionInfo>();
|
|
||||||
MachineBasicBlock::iterator MBBI = prior(MBB.end());
|
|
||||||
unsigned RetOpcode = MBBI->getOpcode();
|
|
||||||
DebugLoc DL = MBBI->getDebugLoc();
|
|
||||||
|
|
||||||
switch (RetOpcode) {
|
|
||||||
case MSP430::RET:
|
|
||||||
case MSP430::RETI: break; // These are ok
|
|
||||||
default:
|
|
||||||
llvm_unreachable("Can only insert epilog into returning blocks");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get the number of bytes to allocate from the FrameInfo
|
|
||||||
uint64_t StackSize = MFI->getStackSize();
|
|
||||||
unsigned CSSize = MSP430FI->getCalleeSavedFrameSize();
|
|
||||||
uint64_t NumBytes = 0;
|
|
||||||
|
|
||||||
if (hasFP(MF)) {
|
|
||||||
// Calculate required stack adjustment
|
|
||||||
uint64_t FrameSize = StackSize - 2;
|
|
||||||
NumBytes = FrameSize - CSSize;
|
|
||||||
|
|
||||||
// pop FPW.
|
|
||||||
BuildMI(MBB, MBBI, DL, TII.get(MSP430::POP16r), MSP430::FPW);
|
|
||||||
} else
|
|
||||||
NumBytes = StackSize - CSSize;
|
|
||||||
|
|
||||||
// Skip the callee-saved pop instructions.
|
|
||||||
while (MBBI != MBB.begin()) {
|
|
||||||
MachineBasicBlock::iterator PI = prior(MBBI);
|
|
||||||
unsigned Opc = PI->getOpcode();
|
|
||||||
if (Opc != MSP430::POP16r && !PI->getDesc().isTerminator())
|
|
||||||
break;
|
|
||||||
--MBBI;
|
|
||||||
}
|
|
||||||
|
|
||||||
DL = MBBI->getDebugLoc();
|
|
||||||
|
|
||||||
// If there is an ADD16ri or SUB16ri of SPW immediately before this
|
|
||||||
// instruction, merge the two instructions.
|
|
||||||
//if (NumBytes || MFI->hasVarSizedObjects())
|
|
||||||
// mergeSPUpdatesUp(MBB, MBBI, StackPtr, &NumBytes);
|
|
||||||
|
|
||||||
if (MFI->hasVarSizedObjects()) {
|
|
||||||
BuildMI(MBB, MBBI, DL,
|
|
||||||
TII.get(MSP430::MOV16rr), MSP430::SPW).addReg(MSP430::FPW);
|
|
||||||
if (CSSize) {
|
|
||||||
MachineInstr *MI =
|
|
||||||
BuildMI(MBB, MBBI, DL,
|
|
||||||
TII.get(MSP430::SUB16ri), MSP430::SPW)
|
|
||||||
.addReg(MSP430::SPW).addImm(CSSize);
|
|
||||||
// The SRW implicit def is dead.
|
|
||||||
MI->getOperand(3).setIsDead();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// adjust stack pointer back: SPW += numbytes
|
|
||||||
if (NumBytes) {
|
|
||||||
MachineInstr *MI =
|
|
||||||
BuildMI(MBB, MBBI, DL, TII.get(MSP430::ADD16ri), MSP430::SPW)
|
|
||||||
.addReg(MSP430::SPW).addImm(NumBytes);
|
|
||||||
// The SRW implicit def is dead.
|
|
||||||
MI->getOperand(3).setIsDead();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned MSP430RegisterInfo::getRARegister() const {
|
unsigned MSP430RegisterInfo::getRARegister() const {
|
||||||
return MSP430::PCW;
|
return MSP430::PCW;
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,9 +49,6 @@ public:
|
||||||
void eliminateFrameIndex(MachineBasicBlock::iterator II,
|
void eliminateFrameIndex(MachineBasicBlock::iterator II,
|
||||||
int SPAdj, RegScavenger *RS = NULL) const;
|
int SPAdj, RegScavenger *RS = NULL) const;
|
||||||
|
|
||||||
void emitPrologue(MachineFunction &MF) const;
|
|
||||||
void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const;
|
|
||||||
|
|
||||||
void processFunctionBeforeFrameFinalized(MachineFunction &MF) const;
|
void processFunctionBeforeFrameFinalized(MachineFunction &MF) const;
|
||||||
|
|
||||||
// Debug information queries.
|
// Debug information queries.
|
||||||
|
|
|
@ -28,13 +28,13 @@ extern "C" void LLVMInitializeMSP430Target() {
|
||||||
|
|
||||||
MSP430TargetMachine::MSP430TargetMachine(const Target &T,
|
MSP430TargetMachine::MSP430TargetMachine(const Target &T,
|
||||||
const std::string &TT,
|
const std::string &TT,
|
||||||
const std::string &FS) :
|
const std::string &FS)
|
||||||
LLVMTargetMachine(T, TT),
|
: LLVMTargetMachine(T, TT),
|
||||||
Subtarget(TT, FS),
|
Subtarget(TT, FS),
|
||||||
// FIXME: Check TargetData string.
|
// FIXME: Check TargetData string.
|
||||||
DataLayout("e-p:16:16:16-i8:8:8-i16:16:16-i32:16:32-n8:16"),
|
DataLayout("e-p:16:16:16-i8:8:8-i16:16:16-i32:16:32-n8:16"),
|
||||||
InstrInfo(*this), TLInfo(*this), TSInfo(*this),
|
InstrInfo(*this), TLInfo(*this), TSInfo(*this),
|
||||||
FrameInfo(TargetFrameInfo::StackGrowsDown, 2, -2) { }
|
FrameInfo(Subtarget) { }
|
||||||
|
|
||||||
|
|
||||||
bool MSP430TargetMachine::addInstSelector(PassManagerBase &PM,
|
bool MSP430TargetMachine::addInstSelector(PassManagerBase &PM,
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
|
|
||||||
#include "MSP430InstrInfo.h"
|
#include "MSP430InstrInfo.h"
|
||||||
#include "MSP430ISelLowering.h"
|
#include "MSP430ISelLowering.h"
|
||||||
|
#include "MSP430FrameInfo.h"
|
||||||
#include "MSP430SelectionDAGInfo.h"
|
#include "MSP430SelectionDAGInfo.h"
|
||||||
#include "MSP430RegisterInfo.h"
|
#include "MSP430RegisterInfo.h"
|
||||||
#include "MSP430Subtarget.h"
|
#include "MSP430Subtarget.h"
|
||||||
|
@ -34,10 +35,7 @@ class MSP430TargetMachine : public LLVMTargetMachine {
|
||||||
MSP430InstrInfo InstrInfo;
|
MSP430InstrInfo InstrInfo;
|
||||||
MSP430TargetLowering TLInfo;
|
MSP430TargetLowering TLInfo;
|
||||||
MSP430SelectionDAGInfo TSInfo;
|
MSP430SelectionDAGInfo TSInfo;
|
||||||
|
MSP430FrameInfo FrameInfo;
|
||||||
// MSP430 does not have any call stack frame, therefore not having
|
|
||||||
// any MSP430 specific FrameInfo class.
|
|
||||||
TargetFrameInfo FrameInfo;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
MSP430TargetMachine(const Target &T, const std::string &TT,
|
MSP430TargetMachine(const Target &T, const std::string &TT,
|
||||||
|
|
|
@ -0,0 +1,303 @@
|
||||||
|
//=======- MipsFrameInfo.cpp - Mips Frame Information ----------*- C++ -*-====//
|
||||||
|
//
|
||||||
|
// The LLVM Compiler Infrastructure
|
||||||
|
//
|
||||||
|
// This file is distributed under the University of Illinois Open Source
|
||||||
|
// License. See LICENSE.TXT for details.
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
//
|
||||||
|
// This file contains the Mips implementation of TargetFrameInfo class.
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
#include "MipsFrameInfo.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;
|
||||||
|
|
||||||
|
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
//
|
||||||
|
// Stack Frame Processing methods
|
||||||
|
// +----------------------------+
|
||||||
|
//
|
||||||
|
// The stack is allocated decrementing the stack pointer on
|
||||||
|
// the first instruction of a function prologue. Once decremented,
|
||||||
|
// all stack references are done thought a positive offset
|
||||||
|
// from the stack/frame pointer, so the stack is considering
|
||||||
|
// to grow up! Otherwise terrible hacks would have to be made
|
||||||
|
// to get this stack ABI compliant :)
|
||||||
|
//
|
||||||
|
// The stack frame required by the ABI (after call):
|
||||||
|
// Offset
|
||||||
|
//
|
||||||
|
// 0 ----------
|
||||||
|
// 4 Args to pass
|
||||||
|
// . saved $GP (used in PIC)
|
||||||
|
// . Alloca allocations
|
||||||
|
// . Local Area
|
||||||
|
// . CPU "Callee Saved" Registers
|
||||||
|
// . saved FP
|
||||||
|
// . saved RA
|
||||||
|
// . FPU "Callee Saved" Registers
|
||||||
|
// StackSize -----------
|
||||||
|
//
|
||||||
|
// Offset - offset from sp after stack allocation on function prologue
|
||||||
|
//
|
||||||
|
// The sp is the stack pointer subtracted/added from the stack size
|
||||||
|
// at the Prologue/Epilogue
|
||||||
|
//
|
||||||
|
// References to the previous stack (to obtain arguments) are done
|
||||||
|
// with offsets that exceeds the stack size: (stacksize+(4*(num_arg-1))
|
||||||
|
//
|
||||||
|
// Examples:
|
||||||
|
// - reference to the actual stack frame
|
||||||
|
// for any local area var there is smt like : FI >= 0, StackOffset: 4
|
||||||
|
// sw REGX, 4(SP)
|
||||||
|
//
|
||||||
|
// - reference to previous stack frame
|
||||||
|
// suppose there's a load to the 5th arguments : FI < 0, StackOffset: 16.
|
||||||
|
// The emitted instruction will be something like:
|
||||||
|
// lw REGX, 16+StackSize(SP)
|
||||||
|
//
|
||||||
|
// Since the total stack size is unknown on LowerFormalArguments, all
|
||||||
|
// stack references (ObjectOffset) created to reference the function
|
||||||
|
// arguments, are negative numbers. This way, on eliminateFrameIndex it's
|
||||||
|
// possible to detect those references and the offsets are adjusted to
|
||||||
|
// their real location.
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
void MipsFrameInfo::adjustMipsStackFrame(MachineFunction &MF) const {
|
||||||
|
MachineFrameInfo *MFI = MF.getFrameInfo();
|
||||||
|
MipsFunctionInfo *MipsFI = MF.getInfo<MipsFunctionInfo>();
|
||||||
|
const MipsRegisterInfo *RegInfo =
|
||||||
|
static_cast<const MipsRegisterInfo*>(MF.getTarget().getRegisterInfo());
|
||||||
|
const std::vector<CalleeSavedInfo> &CSI = MFI->getCalleeSavedInfo();
|
||||||
|
unsigned StackAlign = MF.getTarget().getFrameInfo()->getStackAlignment();
|
||||||
|
unsigned RegSize = STI.isGP32bit() ? 4 : 8;
|
||||||
|
bool HasGP = MipsFI->needGPSaveRestore();
|
||||||
|
|
||||||
|
// Min and Max CSI FrameIndex.
|
||||||
|
int MinCSFI = -1, MaxCSFI = -1;
|
||||||
|
|
||||||
|
// See the description at MipsMachineFunction.h
|
||||||
|
int TopCPUSavedRegOff = -1, TopFPUSavedRegOff = -1;
|
||||||
|
|
||||||
|
// Replace the dummy '0' SPOffset by the negative offsets, as explained on
|
||||||
|
// LowerFormalArguments. Leaving '0' for while is necessary to avoid the
|
||||||
|
// approach done by calculateFrameObjectOffsets to the stack frame.
|
||||||
|
MipsFI->adjustLoadArgsFI(MFI);
|
||||||
|
MipsFI->adjustStoreVarArgsFI(MFI);
|
||||||
|
|
||||||
|
// It happens that the default stack frame allocation order does not directly
|
||||||
|
// map to the convention used for mips. So we must fix it. We move the callee
|
||||||
|
// save register slots after the local variables area, as described in the
|
||||||
|
// stack frame above.
|
||||||
|
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);
|
||||||
|
|
||||||
|
// Adjust local variables. They should come on the stack right
|
||||||
|
// after the arguments.
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Adjust CPU Callee Saved Registers Area. Registers RA and FP must
|
||||||
|
// be saved in this CPU Area. This whole area must be aligned to the
|
||||||
|
// default Stack Alignment requirements.
|
||||||
|
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());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Stack locations for FP and RA. If only one of them is used,
|
||||||
|
// the space must be allocated for both, otherwise no space at all.
|
||||||
|
if (RegInfo->hasFP(MF) || MFI->adjustsStack()) {
|
||||||
|
// FP stack location
|
||||||
|
MFI->setObjectOffset(MFI->CreateStackObject(RegSize, RegSize, true),
|
||||||
|
StackOffset);
|
||||||
|
MipsFI->setFPStackOffset(StackOffset);
|
||||||
|
TopCPUSavedRegOff = StackOffset;
|
||||||
|
StackOffset += RegSize;
|
||||||
|
|
||||||
|
// SP stack location
|
||||||
|
MFI->setObjectOffset(MFI->CreateStackObject(RegSize, RegSize, true),
|
||||||
|
StackOffset);
|
||||||
|
MipsFI->setRAStackOffset(StackOffset);
|
||||||
|
StackOffset += RegSize;
|
||||||
|
|
||||||
|
if (MFI->adjustsStack())
|
||||||
|
TopCPUSavedRegOff += RegSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
StackOffset = ((StackOffset+StackAlign-1)/StackAlign*StackAlign);
|
||||||
|
|
||||||
|
// Adjust FPU Callee Saved Registers Area. This Area must be
|
||||||
|
// aligned to the default Stack Alignment requirements.
|
||||||
|
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);
|
||||||
|
|
||||||
|
// Update frame info
|
||||||
|
MFI->setStackSize(StackOffset);
|
||||||
|
|
||||||
|
// Recalculate the final tops offset. The final values must be '0'
|
||||||
|
// if there isn't a callee saved register for CPU or FPU, otherwise
|
||||||
|
// a negative offset is needed.
|
||||||
|
if (TopCPUSavedRegOff >= 0)
|
||||||
|
MipsFI->setCPUTopSavedRegOff(TopCPUSavedRegOff-StackOffset);
|
||||||
|
|
||||||
|
if (TopFPUSavedRegOff >= 0)
|
||||||
|
MipsFI->setFPUTopSavedRegOff(TopFPUSavedRegOff-StackOffset);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MipsFrameInfo::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_);
|
||||||
|
|
||||||
|
// Get the right frame order for Mips.
|
||||||
|
adjustMipsStackFrame(MF);
|
||||||
|
|
||||||
|
// Get the number of bytes to allocate from the FrameInfo.
|
||||||
|
unsigned StackSize = MFI->getStackSize();
|
||||||
|
|
||||||
|
// No need to allocate space on the stack.
|
||||||
|
if (StackSize == 0 && !MFI->adjustsStack()) return;
|
||||||
|
|
||||||
|
int FPOffset = MipsFI->getFPStackOffset();
|
||||||
|
int RAOffset = MipsFI->getRAStackOffset();
|
||||||
|
|
||||||
|
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));
|
||||||
|
|
||||||
|
// Adjust stack : addi sp, sp, (-imm)
|
||||||
|
BuildMI(MBB, MBBI, dl, TII.get(Mips::ADDiu), Mips::SP)
|
||||||
|
.addReg(Mips::SP).addImm(-StackSize);
|
||||||
|
|
||||||
|
// Save the return address only if the function isnt a leaf one.
|
||||||
|
// sw $ra, stack_loc($sp)
|
||||||
|
if (MFI->adjustsStack()) {
|
||||||
|
BuildMI(MBB, MBBI, dl, TII.get(Mips::SW))
|
||||||
|
.addReg(Mips::RA).addImm(RAOffset).addReg(Mips::SP);
|
||||||
|
}
|
||||||
|
|
||||||
|
// if framepointer enabled, save it and set it
|
||||||
|
// to point to the stack pointer
|
||||||
|
if (RegInfo->hasFP(MF)) {
|
||||||
|
// sw $fp,stack_loc($sp)
|
||||||
|
BuildMI(MBB, MBBI, dl, TII.get(Mips::SW))
|
||||||
|
.addReg(Mips::FP).addImm(FPOffset).addReg(Mips::SP);
|
||||||
|
|
||||||
|
// move $fp, $sp
|
||||||
|
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(MipsFI->getGPStackOffset());
|
||||||
|
}
|
||||||
|
|
||||||
|
void MipsFrameInfo::emitEpilogue(MachineFunction &MF,
|
||||||
|
MachineBasicBlock &MBB) const {
|
||||||
|
MachineBasicBlock::iterator MBBI = prior(MBB.end());
|
||||||
|
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());
|
||||||
|
DebugLoc dl = MBBI->getDebugLoc();
|
||||||
|
|
||||||
|
// Get the number of bytes from FrameInfo
|
||||||
|
int NumBytes = (int) MFI->getStackSize();
|
||||||
|
|
||||||
|
// Get the FI's where RA and FP are saved.
|
||||||
|
int FPOffset = MipsFI->getFPStackOffset();
|
||||||
|
int RAOffset = MipsFI->getRAStackOffset();
|
||||||
|
|
||||||
|
// if framepointer enabled, restore it and restore the
|
||||||
|
// stack pointer
|
||||||
|
if (RegInfo->hasFP(MF)) {
|
||||||
|
// move $sp, $fp
|
||||||
|
BuildMI(MBB, MBBI, dl, TII.get(Mips::ADDu), Mips::SP)
|
||||||
|
.addReg(Mips::FP).addReg(Mips::ZERO);
|
||||||
|
|
||||||
|
// lw $fp,stack_loc($sp)
|
||||||
|
BuildMI(MBB, MBBI, dl, TII.get(Mips::LW), Mips::FP)
|
||||||
|
.addImm(FPOffset).addReg(Mips::SP);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Restore the return address only if the function isnt a leaf one.
|
||||||
|
// lw $ra, stack_loc($sp)
|
||||||
|
if (MFI->adjustsStack()) {
|
||||||
|
BuildMI(MBB, MBBI, dl, TII.get(Mips::LW), Mips::RA)
|
||||||
|
.addImm(RAOffset).addReg(Mips::SP);
|
||||||
|
}
|
||||||
|
|
||||||
|
// adjust stack : insert addi sp, sp, (imm)
|
||||||
|
if (NumBytes) {
|
||||||
|
BuildMI(MBB, MBBI, dl, TII.get(Mips::ADDiu), Mips::SP)
|
||||||
|
.addReg(Mips::SP).addImm(NumBytes);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,44 @@
|
||||||
|
//====--- MipsFrameInfo.h - Define TargetFrameInfo for Mips --*- C++ -*---====//
|
||||||
|
//
|
||||||
|
// The LLVM Compiler Infrastructure
|
||||||
|
//
|
||||||
|
// This file is distributed under the University of Illinois Open Source
|
||||||
|
// License. See LICENSE.TXT for details.
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
#ifndef ALPHA_FRAMEINFO_H
|
||||||
|
#define ALPHA_FRAMEINFO_H
|
||||||
|
|
||||||
|
#include "Mips.h"
|
||||||
|
#include "MipsSubtarget.h"
|
||||||
|
#include "llvm/Target/TargetFrameInfo.h"
|
||||||
|
|
||||||
|
namespace llvm {
|
||||||
|
class MipsSubtarget;
|
||||||
|
|
||||||
|
class MipsFrameInfo : public TargetFrameInfo {
|
||||||
|
protected:
|
||||||
|
const MipsSubtarget &STI;
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit MipsFrameInfo(const MipsSubtarget &sti)
|
||||||
|
// FIXME: Is this correct at all?
|
||||||
|
: TargetFrameInfo(StackGrowsUp, 8, 0), STI(sti) {
|
||||||
|
}
|
||||||
|
|
||||||
|
void adjustMipsStackFrame(MachineFunction &MF) const;
|
||||||
|
|
||||||
|
/// emitProlog/emitEpilog - These methods insert prolog and epilog code into
|
||||||
|
/// the function.
|
||||||
|
void emitPrologue(MachineFunction &MF) const;
|
||||||
|
void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // End llvm namespace
|
||||||
|
|
||||||
|
#endif
|
|
@ -137,175 +137,6 @@ getReservedRegs(const MachineFunction &MF) const
|
||||||
return Reserved;
|
return Reserved;
|
||||||
}
|
}
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
//
|
|
||||||
// Stack Frame Processing methods
|
|
||||||
// +----------------------------+
|
|
||||||
//
|
|
||||||
// The stack is allocated decrementing the stack pointer on
|
|
||||||
// the first instruction of a function prologue. Once decremented,
|
|
||||||
// all stack references are done thought a positive offset
|
|
||||||
// from the stack/frame pointer, so the stack is considering
|
|
||||||
// to grow up! Otherwise terrible hacks would have to be made
|
|
||||||
// to get this stack ABI compliant :)
|
|
||||||
//
|
|
||||||
// The stack frame required by the ABI (after call):
|
|
||||||
// Offset
|
|
||||||
//
|
|
||||||
// 0 ----------
|
|
||||||
// 4 Args to pass
|
|
||||||
// . saved $GP (used in PIC)
|
|
||||||
// . Alloca allocations
|
|
||||||
// . Local Area
|
|
||||||
// . CPU "Callee Saved" Registers
|
|
||||||
// . saved FP
|
|
||||||
// . saved RA
|
|
||||||
// . FPU "Callee Saved" Registers
|
|
||||||
// StackSize -----------
|
|
||||||
//
|
|
||||||
// Offset - offset from sp after stack allocation on function prologue
|
|
||||||
//
|
|
||||||
// The sp is the stack pointer subtracted/added from the stack size
|
|
||||||
// at the Prologue/Epilogue
|
|
||||||
//
|
|
||||||
// References to the previous stack (to obtain arguments) are done
|
|
||||||
// with offsets that exceeds the stack size: (stacksize+(4*(num_arg-1))
|
|
||||||
//
|
|
||||||
// Examples:
|
|
||||||
// - reference to the actual stack frame
|
|
||||||
// for any local area var there is smt like : FI >= 0, StackOffset: 4
|
|
||||||
// sw REGX, 4(SP)
|
|
||||||
//
|
|
||||||
// - reference to previous stack frame
|
|
||||||
// suppose there's a load to the 5th arguments : FI < 0, StackOffset: 16.
|
|
||||||
// The emitted instruction will be something like:
|
|
||||||
// lw REGX, 16+StackSize(SP)
|
|
||||||
//
|
|
||||||
// Since the total stack size is unknown on LowerFormalArguments, all
|
|
||||||
// stack references (ObjectOffset) created to reference the function
|
|
||||||
// arguments, are negative numbers. This way, on eliminateFrameIndex it's
|
|
||||||
// possible to detect those references and the offsets are adjusted to
|
|
||||||
// their real location.
|
|
||||||
//
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
|
|
||||||
void MipsRegisterInfo::adjustMipsStackFrame(MachineFunction &MF) const
|
|
||||||
{
|
|
||||||
MachineFrameInfo *MFI = MF.getFrameInfo();
|
|
||||||
MipsFunctionInfo *MipsFI = MF.getInfo<MipsFunctionInfo>();
|
|
||||||
const std::vector<CalleeSavedInfo> &CSI = MFI->getCalleeSavedInfo();
|
|
||||||
unsigned StackAlign = MF.getTarget().getFrameInfo()->getStackAlignment();
|
|
||||||
unsigned RegSize = Subtarget.isGP32bit() ? 4 : 8;
|
|
||||||
bool HasGP = MipsFI->needGPSaveRestore();
|
|
||||||
|
|
||||||
// Min and Max CSI FrameIndex.
|
|
||||||
int MinCSFI = -1, MaxCSFI = -1;
|
|
||||||
|
|
||||||
// See the description at MipsMachineFunction.h
|
|
||||||
int TopCPUSavedRegOff = -1, TopFPUSavedRegOff = -1;
|
|
||||||
|
|
||||||
// Replace the dummy '0' SPOffset by the negative offsets, as explained on
|
|
||||||
// LowerFormalArguments. Leaving '0' for while is necessary to avoid
|
|
||||||
// the approach done by calculateFrameObjectOffsets to the stack frame.
|
|
||||||
MipsFI->adjustLoadArgsFI(MFI);
|
|
||||||
MipsFI->adjustStoreVarArgsFI(MFI);
|
|
||||||
|
|
||||||
// It happens that the default stack frame allocation order does not directly
|
|
||||||
// map to the convention used for mips. So we must fix it. We move the callee
|
|
||||||
// save register slots after the local variables area, as described in the
|
|
||||||
// stack frame above.
|
|
||||||
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)
|
|
||||||
: (Subtarget.isABI_O32() ? 16 : 0);
|
|
||||||
|
|
||||||
// Adjust local variables. They should come on the stack right
|
|
||||||
// after the arguments.
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Adjust CPU Callee Saved Registers Area. Registers RA and FP must
|
|
||||||
// be saved in this CPU Area. This whole area must be aligned to the
|
|
||||||
// default Stack Alignment requirements.
|
|
||||||
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());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Stack locations for FP and RA. If only one of them is used,
|
|
||||||
// the space must be allocated for both, otherwise no space at all.
|
|
||||||
if (hasFP(MF) || MFI->adjustsStack()) {
|
|
||||||
// FP stack location
|
|
||||||
MFI->setObjectOffset(MFI->CreateStackObject(RegSize, RegSize, true),
|
|
||||||
StackOffset);
|
|
||||||
MipsFI->setFPStackOffset(StackOffset);
|
|
||||||
TopCPUSavedRegOff = StackOffset;
|
|
||||||
StackOffset += RegSize;
|
|
||||||
|
|
||||||
// SP stack location
|
|
||||||
MFI->setObjectOffset(MFI->CreateStackObject(RegSize, RegSize, true),
|
|
||||||
StackOffset);
|
|
||||||
MipsFI->setRAStackOffset(StackOffset);
|
|
||||||
StackOffset += RegSize;
|
|
||||||
|
|
||||||
if (MFI->adjustsStack())
|
|
||||||
TopCPUSavedRegOff += RegSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
StackOffset = ((StackOffset+StackAlign-1)/StackAlign*StackAlign);
|
|
||||||
|
|
||||||
// Adjust FPU Callee Saved Registers Area. This Area must be
|
|
||||||
// aligned to the default Stack Alignment requirements.
|
|
||||||
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);
|
|
||||||
|
|
||||||
// Update frame info
|
|
||||||
MFI->setStackSize(StackOffset);
|
|
||||||
|
|
||||||
// Recalculate the final tops offset. The final values must be '0'
|
|
||||||
// if there isn't a callee saved register for CPU or FPU, otherwise
|
|
||||||
// a negative offset is needed.
|
|
||||||
if (TopCPUSavedRegOff >= 0)
|
|
||||||
MipsFI->setCPUTopSavedRegOff(TopCPUSavedRegOff-StackOffset);
|
|
||||||
|
|
||||||
if (TopFPUSavedRegOff >= 0)
|
|
||||||
MipsFI->setFPUTopSavedRegOff(TopFPUSavedRegOff-StackOffset);
|
|
||||||
}
|
|
||||||
|
|
||||||
// hasFP - Return true if the specified function should have a dedicated frame
|
// 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
|
// pointer register. This is true if the function has variable sized allocas or
|
||||||
// if frame pointer elimination is disabled.
|
// if frame pointer elimination is disabled.
|
||||||
|
@ -362,106 +193,6 @@ eliminateFrameIndex(MachineBasicBlock::iterator II, int SPAdj,
|
||||||
MI.getOperand(i).ChangeToRegister(getFrameRegister(MF), false);
|
MI.getOperand(i).ChangeToRegister(getFrameRegister(MF), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MipsRegisterInfo::
|
|
||||||
emitPrologue(MachineFunction &MF) const
|
|
||||||
{
|
|
||||||
MachineBasicBlock &MBB = MF.front();
|
|
||||||
MachineFrameInfo *MFI = MF.getFrameInfo();
|
|
||||||
MipsFunctionInfo *MipsFI = MF.getInfo<MipsFunctionInfo>();
|
|
||||||
MachineBasicBlock::iterator MBBI = MBB.begin();
|
|
||||||
DebugLoc dl = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc();
|
|
||||||
bool isPIC = (MF.getTarget().getRelocationModel() == Reloc::PIC_);
|
|
||||||
|
|
||||||
// Get the right frame order for Mips.
|
|
||||||
adjustMipsStackFrame(MF);
|
|
||||||
|
|
||||||
// Get the number of bytes to allocate from the FrameInfo.
|
|
||||||
unsigned StackSize = MFI->getStackSize();
|
|
||||||
|
|
||||||
// No need to allocate space on the stack.
|
|
||||||
if (StackSize == 0 && !MFI->adjustsStack()) return;
|
|
||||||
|
|
||||||
int FPOffset = MipsFI->getFPStackOffset();
|
|
||||||
int RAOffset = MipsFI->getRAStackOffset();
|
|
||||||
|
|
||||||
BuildMI(MBB, MBBI, dl, TII.get(Mips::NOREORDER));
|
|
||||||
|
|
||||||
// TODO: check need from GP here.
|
|
||||||
if (isPIC && Subtarget.isABI_O32())
|
|
||||||
BuildMI(MBB, MBBI, dl, TII.get(Mips::CPLOAD)).addReg(getPICCallReg());
|
|
||||||
BuildMI(MBB, MBBI, dl, TII.get(Mips::NOMACRO));
|
|
||||||
|
|
||||||
// Adjust stack : addi sp, sp, (-imm)
|
|
||||||
BuildMI(MBB, MBBI, dl, TII.get(Mips::ADDiu), Mips::SP)
|
|
||||||
.addReg(Mips::SP).addImm(-StackSize);
|
|
||||||
|
|
||||||
// Save the return address only if the function isnt a leaf one.
|
|
||||||
// sw $ra, stack_loc($sp)
|
|
||||||
if (MFI->adjustsStack()) {
|
|
||||||
BuildMI(MBB, MBBI, dl, TII.get(Mips::SW))
|
|
||||||
.addReg(Mips::RA).addImm(RAOffset).addReg(Mips::SP);
|
|
||||||
}
|
|
||||||
|
|
||||||
// if framepointer enabled, save it and set it
|
|
||||||
// to point to the stack pointer
|
|
||||||
if (hasFP(MF)) {
|
|
||||||
// sw $fp,stack_loc($sp)
|
|
||||||
BuildMI(MBB, MBBI, dl, TII.get(Mips::SW))
|
|
||||||
.addReg(Mips::FP).addImm(FPOffset).addReg(Mips::SP);
|
|
||||||
|
|
||||||
// move $fp, $sp
|
|
||||||
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(MipsFI->getGPStackOffset());
|
|
||||||
}
|
|
||||||
|
|
||||||
void MipsRegisterInfo::
|
|
||||||
emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const
|
|
||||||
{
|
|
||||||
MachineBasicBlock::iterator MBBI = prior(MBB.end());
|
|
||||||
MachineFrameInfo *MFI = MF.getFrameInfo();
|
|
||||||
MipsFunctionInfo *MipsFI = MF.getInfo<MipsFunctionInfo>();
|
|
||||||
DebugLoc dl = MBBI->getDebugLoc();
|
|
||||||
|
|
||||||
// Get the number of bytes from FrameInfo
|
|
||||||
int NumBytes = (int) MFI->getStackSize();
|
|
||||||
|
|
||||||
// Get the FI's where RA and FP are saved.
|
|
||||||
int FPOffset = MipsFI->getFPStackOffset();
|
|
||||||
int RAOffset = MipsFI->getRAStackOffset();
|
|
||||||
|
|
||||||
// if framepointer enabled, restore it and restore the
|
|
||||||
// stack pointer
|
|
||||||
if (hasFP(MF)) {
|
|
||||||
// move $sp, $fp
|
|
||||||
BuildMI(MBB, MBBI, dl, TII.get(Mips::ADDu), Mips::SP)
|
|
||||||
.addReg(Mips::FP).addReg(Mips::ZERO);
|
|
||||||
|
|
||||||
// lw $fp,stack_loc($sp)
|
|
||||||
BuildMI(MBB, MBBI, dl, TII.get(Mips::LW), Mips::FP)
|
|
||||||
.addImm(FPOffset).addReg(Mips::SP);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Restore the return address only if the function isnt a leaf one.
|
|
||||||
// lw $ra, stack_loc($sp)
|
|
||||||
if (MFI->adjustsStack()) {
|
|
||||||
BuildMI(MBB, MBBI, dl, TII.get(Mips::LW), Mips::RA)
|
|
||||||
.addImm(RAOffset).addReg(Mips::SP);
|
|
||||||
}
|
|
||||||
|
|
||||||
// adjust stack : insert addi sp, sp, (imm)
|
|
||||||
if (NumBytes) {
|
|
||||||
BuildMI(MBB, MBBI, dl, TII.get(Mips::ADDiu), Mips::SP)
|
|
||||||
.addReg(Mips::SP).addImm(NumBytes);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void MipsRegisterInfo::
|
void MipsRegisterInfo::
|
||||||
processFunctionBeforeFrameFinalized(MachineFunction &MF) const {
|
processFunctionBeforeFrameFinalized(MachineFunction &MF) const {
|
||||||
// Set the stack offset where GP must be saved/loaded from.
|
// Set the stack offset where GP must be saved/loaded from.
|
||||||
|
|
|
@ -56,9 +56,6 @@ struct MipsRegisterInfo : public MipsGenRegisterInfo {
|
||||||
|
|
||||||
void processFunctionBeforeFrameFinalized(MachineFunction &MF) const;
|
void processFunctionBeforeFrameFinalized(MachineFunction &MF) const;
|
||||||
|
|
||||||
void emitPrologue(MachineFunction &MF) const;
|
|
||||||
void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const;
|
|
||||||
|
|
||||||
/// Debug information queries.
|
/// Debug information queries.
|
||||||
unsigned getRARegister() const;
|
unsigned getRARegister() const;
|
||||||
unsigned getFrameRegister(const MachineFunction &MF) const;
|
unsigned getFrameRegister(const MachineFunction &MF) const;
|
||||||
|
|
|
@ -41,7 +41,7 @@ MipsTargetMachine(const Target &T, const std::string &TT, const std::string &FS,
|
||||||
DataLayout(isLittle ? std::string("e-p:32:32:32-i8:8:32-i16:16:32-n32") :
|
DataLayout(isLittle ? std::string("e-p:32:32:32-i8:8:32-i16:16:32-n32") :
|
||||||
std::string("E-p:32:32:32-i8:8:32-i16:16:32-n32")),
|
std::string("E-p:32:32:32-i8:8:32-i16:16:32-n32")),
|
||||||
InstrInfo(*this),
|
InstrInfo(*this),
|
||||||
FrameInfo(TargetFrameInfo::StackGrowsUp, 8, 0),
|
FrameInfo(Subtarget),
|
||||||
TLInfo(*this), TSInfo(*this) {
|
TLInfo(*this), TSInfo(*this) {
|
||||||
// Abicall enables PIC by default
|
// Abicall enables PIC by default
|
||||||
if (getRelocationModel() == Reloc::Default) {
|
if (getRelocationModel() == Reloc::Default) {
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
#include "MipsSubtarget.h"
|
#include "MipsSubtarget.h"
|
||||||
#include "MipsInstrInfo.h"
|
#include "MipsInstrInfo.h"
|
||||||
#include "MipsISelLowering.h"
|
#include "MipsISelLowering.h"
|
||||||
|
#include "MipsFrameInfo.h"
|
||||||
#include "MipsSelectionDAGInfo.h"
|
#include "MipsSelectionDAGInfo.h"
|
||||||
#include "llvm/Target/TargetMachine.h"
|
#include "llvm/Target/TargetMachine.h"
|
||||||
#include "llvm/Target/TargetData.h"
|
#include "llvm/Target/TargetData.h"
|
||||||
|
@ -29,7 +30,7 @@ namespace llvm {
|
||||||
MipsSubtarget Subtarget;
|
MipsSubtarget Subtarget;
|
||||||
const TargetData DataLayout; // Calculates type size & alignment
|
const TargetData DataLayout; // Calculates type size & alignment
|
||||||
MipsInstrInfo InstrInfo;
|
MipsInstrInfo InstrInfo;
|
||||||
TargetFrameInfo FrameInfo;
|
MipsFrameInfo FrameInfo;
|
||||||
MipsTargetLowering TLInfo;
|
MipsTargetLowering TLInfo;
|
||||||
MipsSelectionDAGInfo TSInfo;
|
MipsSelectionDAGInfo TSInfo;
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -0,0 +1,24 @@
|
||||||
|
//=======- PTXFrameInfo.cpp - PTX Frame Information -----------*- C++ -*-=====//
|
||||||
|
//
|
||||||
|
// The LLVM Compiler Infrastructure
|
||||||
|
//
|
||||||
|
// This file is distributed under the University of Illinois Open Source
|
||||||
|
// License. See LICENSE.TXT for details.
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
//
|
||||||
|
// This file contains the PTX implementation of TargetFrameInfo class.
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
#include "PTXFrameInfo.h"
|
||||||
|
#include "llvm/CodeGen/MachineFunction.h"
|
||||||
|
|
||||||
|
using namespace llvm;
|
||||||
|
|
||||||
|
void PTXFrameInfo::emitPrologue(MachineFunction &MF) const {
|
||||||
|
}
|
||||||
|
|
||||||
|
void PTXFrameInfo::emitEpilogue(MachineFunction &MF,
|
||||||
|
MachineBasicBlock &MBB) const {
|
||||||
|
}
|
|
@ -0,0 +1,41 @@
|
||||||
|
//====---- PTXFrameInfo.h - Define TargetFrameInfo for PTX --*- C++ -*----====//
|
||||||
|
//
|
||||||
|
// The LLVM Compiler Infrastructure
|
||||||
|
//
|
||||||
|
// This file is distributed under the University of Illinois Open Source
|
||||||
|
// License. See LICENSE.TXT for details.
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
#ifndef PTX_FRAMEINFO_H
|
||||||
|
#define PTX_FRAMEINFO_H
|
||||||
|
|
||||||
|
#include "PTX.h"
|
||||||
|
#include "PTXSubtarget.h"
|
||||||
|
#include "llvm/Target/TargetFrameInfo.h"
|
||||||
|
|
||||||
|
namespace llvm {
|
||||||
|
class PTXSubtarget;
|
||||||
|
|
||||||
|
class PTXFrameInfo : public TargetFrameInfo {
|
||||||
|
protected:
|
||||||
|
const PTXSubtarget &STI;
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit PTXFrameInfo(const PTXSubtarget &sti)
|
||||||
|
: TargetFrameInfo(TargetFrameInfo::StackGrowsDown, 2, -2), STI(sti) {
|
||||||
|
}
|
||||||
|
|
||||||
|
/// emitProlog/emitEpilog - These methods insert prolog and epilog code into
|
||||||
|
/// the function.
|
||||||
|
void emitPrologue(MachineFunction &MF) const;
|
||||||
|
void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // End llvm namespace
|
||||||
|
|
||||||
|
#endif
|
|
@ -46,10 +46,6 @@ struct PTXRegisterInfo : public PTXGenRegisterInfo {
|
||||||
llvm_unreachable("PTX does not support general function call");
|
llvm_unreachable("PTX does not support general function call");
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void emitPrologue(MachineFunction &MF) const {}
|
|
||||||
virtual void emitEpilogue(MachineFunction &MF,
|
|
||||||
MachineBasicBlock &MBB) const {}
|
|
||||||
|
|
||||||
virtual unsigned getFrameRegister(const MachineFunction &MF) const {
|
virtual unsigned getFrameRegister(const MachineFunction &MF) const {
|
||||||
llvm_unreachable("PTX does not have a frame register");
|
llvm_unreachable("PTX does not have a frame register");
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -32,7 +32,7 @@ PTXTargetMachine::PTXTargetMachine(const Target &T,
|
||||||
const std::string &FS)
|
const std::string &FS)
|
||||||
: LLVMTargetMachine(T, TT),
|
: LLVMTargetMachine(T, TT),
|
||||||
DataLayout("e-p:32:32-i64:32:32-f64:32:32-v128:32:128-v64:32:64-n32:64"),
|
DataLayout("e-p:32:32-i64:32:32-f64:32:32-v128:32:128-v64:32:64-n32:64"),
|
||||||
FrameInfo(TargetFrameInfo::StackGrowsDown, 2, -2),
|
FrameInfo(Subtarget),
|
||||||
InstrInfo(*this),
|
InstrInfo(*this),
|
||||||
TLInfo(*this),
|
TLInfo(*this),
|
||||||
Subtarget(TT, FS) {
|
Subtarget(TT, FS) {
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
|
|
||||||
#include "PTXISelLowering.h"
|
#include "PTXISelLowering.h"
|
||||||
#include "PTXInstrInfo.h"
|
#include "PTXInstrInfo.h"
|
||||||
|
#include "PTXFrameInfo.h"
|
||||||
#include "PTXSubtarget.h"
|
#include "PTXSubtarget.h"
|
||||||
#include "llvm/Target/TargetData.h"
|
#include "llvm/Target/TargetData.h"
|
||||||
#include "llvm/Target/TargetFrameInfo.h"
|
#include "llvm/Target/TargetFrameInfo.h"
|
||||||
|
@ -25,7 +26,7 @@ namespace llvm {
|
||||||
class PTXTargetMachine : public LLVMTargetMachine {
|
class PTXTargetMachine : public LLVMTargetMachine {
|
||||||
private:
|
private:
|
||||||
const TargetData DataLayout;
|
const TargetData DataLayout;
|
||||||
TargetFrameInfo FrameInfo;
|
PTXFrameInfo FrameInfo;
|
||||||
PTXInstrInfo InstrInfo;
|
PTXInstrInfo InstrInfo;
|
||||||
PTXTargetLowering TLInfo;
|
PTXTargetLowering TLInfo;
|
||||||
PTXSubtarget Subtarget;
|
PTXSubtarget Subtarget;
|
||||||
|
|
|
@ -0,0 +1,680 @@
|
||||||
|
//=======- PPCFrameInfo.cpp - PPC Frame Information ------------*- C++ -*-====//
|
||||||
|
//
|
||||||
|
// The LLVM Compiler Infrastructure
|
||||||
|
//
|
||||||
|
// This file is distributed under the University of Illinois Open Source
|
||||||
|
// License. See LICENSE.TXT for details.
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
//
|
||||||
|
// This file contains the PPC implementation of TargetFrameInfo class.
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
#include "PPCFrameInfo.h"
|
||||||
|
#include "PPCInstrInfo.h"
|
||||||
|
#include "PPCMachineFunctionInfo.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/TargetOptions.h"
|
||||||
|
|
||||||
|
using namespace llvm;
|
||||||
|
|
||||||
|
// FIXME This disables some code that aligns the stack to a boundary bigger than
|
||||||
|
// the default (16 bytes on Darwin) when there is a stack local of greater
|
||||||
|
// alignment. This does not currently work, because the delta between old and
|
||||||
|
// new stack pointers is added to offsets that reference incoming parameters
|
||||||
|
// after the prolog is generated, and the code that does that doesn't handle a
|
||||||
|
// variable delta. You don't want to do that anyway; a better approach is to
|
||||||
|
// reserve another register that retains to the incoming stack pointer, and
|
||||||
|
// reference parameters relative to that.
|
||||||
|
#define ALIGN_STACK 0
|
||||||
|
|
||||||
|
|
||||||
|
/// VRRegNo - Map from a numbered VR register to its enum value.
|
||||||
|
///
|
||||||
|
static const unsigned short VRRegNo[] = {
|
||||||
|
PPC::V0 , PPC::V1 , PPC::V2 , PPC::V3 , PPC::V4 , PPC::V5 , PPC::V6 , PPC::V7 ,
|
||||||
|
PPC::V8 , PPC::V9 , PPC::V10, PPC::V11, PPC::V12, PPC::V13, PPC::V14, PPC::V15,
|
||||||
|
PPC::V16, PPC::V17, PPC::V18, PPC::V19, PPC::V20, PPC::V21, PPC::V22, PPC::V23,
|
||||||
|
PPC::V24, PPC::V25, PPC::V26, PPC::V27, PPC::V28, PPC::V29, PPC::V30, PPC::V31
|
||||||
|
};
|
||||||
|
|
||||||
|
/// RemoveVRSaveCode - We have found that this function does not need any code
|
||||||
|
/// to manipulate the VRSAVE register, even though it uses vector registers.
|
||||||
|
/// This can happen when the only registers used are known to be live in or out
|
||||||
|
/// of the function. Remove all of the VRSAVE related code from the function.
|
||||||
|
static void RemoveVRSaveCode(MachineInstr *MI) {
|
||||||
|
MachineBasicBlock *Entry = MI->getParent();
|
||||||
|
MachineFunction *MF = Entry->getParent();
|
||||||
|
|
||||||
|
// We know that the MTVRSAVE instruction immediately follows MI. Remove it.
|
||||||
|
MachineBasicBlock::iterator MBBI = MI;
|
||||||
|
++MBBI;
|
||||||
|
assert(MBBI != Entry->end() && MBBI->getOpcode() == PPC::MTVRSAVE);
|
||||||
|
MBBI->eraseFromParent();
|
||||||
|
|
||||||
|
bool RemovedAllMTVRSAVEs = true;
|
||||||
|
// See if we can find and remove the MTVRSAVE instruction from all of the
|
||||||
|
// epilog blocks.
|
||||||
|
for (MachineFunction::iterator I = MF->begin(), E = MF->end(); I != E; ++I) {
|
||||||
|
// If last instruction is a return instruction, add an epilogue
|
||||||
|
if (!I->empty() && I->back().getDesc().isReturn()) {
|
||||||
|
bool FoundIt = false;
|
||||||
|
for (MBBI = I->end(); MBBI != I->begin(); ) {
|
||||||
|
--MBBI;
|
||||||
|
if (MBBI->getOpcode() == PPC::MTVRSAVE) {
|
||||||
|
MBBI->eraseFromParent(); // remove it.
|
||||||
|
FoundIt = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
RemovedAllMTVRSAVEs &= FoundIt;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we found and removed all MTVRSAVE instructions, remove the read of
|
||||||
|
// VRSAVE as well.
|
||||||
|
if (RemovedAllMTVRSAVEs) {
|
||||||
|
MBBI = MI;
|
||||||
|
assert(MBBI != Entry->begin() && "UPDATE_VRSAVE is first instr in block?");
|
||||||
|
--MBBI;
|
||||||
|
assert(MBBI->getOpcode() == PPC::MFVRSAVE && "VRSAVE instrs wandered?");
|
||||||
|
MBBI->eraseFromParent();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Finally, nuke the UPDATE_VRSAVE.
|
||||||
|
MI->eraseFromParent();
|
||||||
|
}
|
||||||
|
|
||||||
|
// HandleVRSaveUpdate - MI is the UPDATE_VRSAVE instruction introduced by the
|
||||||
|
// instruction selector. Based on the vector registers that have been used,
|
||||||
|
// transform this into the appropriate ORI instruction.
|
||||||
|
static void HandleVRSaveUpdate(MachineInstr *MI, const TargetInstrInfo &TII) {
|
||||||
|
MachineFunction *MF = MI->getParent()->getParent();
|
||||||
|
DebugLoc dl = MI->getDebugLoc();
|
||||||
|
|
||||||
|
unsigned UsedRegMask = 0;
|
||||||
|
for (unsigned i = 0; i != 32; ++i)
|
||||||
|
if (MF->getRegInfo().isPhysRegUsed(VRRegNo[i]))
|
||||||
|
UsedRegMask |= 1 << (31-i);
|
||||||
|
|
||||||
|
// Live in and live out values already must be in the mask, so don't bother
|
||||||
|
// marking them.
|
||||||
|
for (MachineRegisterInfo::livein_iterator
|
||||||
|
I = MF->getRegInfo().livein_begin(),
|
||||||
|
E = MF->getRegInfo().livein_end(); I != E; ++I) {
|
||||||
|
unsigned RegNo = PPCRegisterInfo::getRegisterNumbering(I->first);
|
||||||
|
if (VRRegNo[RegNo] == I->first) // If this really is a vector reg.
|
||||||
|
UsedRegMask &= ~(1 << (31-RegNo)); // Doesn't need to be marked.
|
||||||
|
}
|
||||||
|
for (MachineRegisterInfo::liveout_iterator
|
||||||
|
I = MF->getRegInfo().liveout_begin(),
|
||||||
|
E = MF->getRegInfo().liveout_end(); I != E; ++I) {
|
||||||
|
unsigned RegNo = PPCRegisterInfo::getRegisterNumbering(*I);
|
||||||
|
if (VRRegNo[RegNo] == *I) // If this really is a vector reg.
|
||||||
|
UsedRegMask &= ~(1 << (31-RegNo)); // Doesn't need to be marked.
|
||||||
|
}
|
||||||
|
|
||||||
|
// If no registers are used, turn this into a copy.
|
||||||
|
if (UsedRegMask == 0) {
|
||||||
|
// Remove all VRSAVE code.
|
||||||
|
RemoveVRSaveCode(MI);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned SrcReg = MI->getOperand(1).getReg();
|
||||||
|
unsigned DstReg = MI->getOperand(0).getReg();
|
||||||
|
|
||||||
|
if ((UsedRegMask & 0xFFFF) == UsedRegMask) {
|
||||||
|
if (DstReg != SrcReg)
|
||||||
|
BuildMI(*MI->getParent(), MI, dl, TII.get(PPC::ORI), DstReg)
|
||||||
|
.addReg(SrcReg)
|
||||||
|
.addImm(UsedRegMask);
|
||||||
|
else
|
||||||
|
BuildMI(*MI->getParent(), MI, dl, TII.get(PPC::ORI), DstReg)
|
||||||
|
.addReg(SrcReg, RegState::Kill)
|
||||||
|
.addImm(UsedRegMask);
|
||||||
|
} else if ((UsedRegMask & 0xFFFF0000) == UsedRegMask) {
|
||||||
|
if (DstReg != SrcReg)
|
||||||
|
BuildMI(*MI->getParent(), MI, dl, TII.get(PPC::ORIS), DstReg)
|
||||||
|
.addReg(SrcReg)
|
||||||
|
.addImm(UsedRegMask >> 16);
|
||||||
|
else
|
||||||
|
BuildMI(*MI->getParent(), MI, dl, TII.get(PPC::ORIS), DstReg)
|
||||||
|
.addReg(SrcReg, RegState::Kill)
|
||||||
|
.addImm(UsedRegMask >> 16);
|
||||||
|
} else {
|
||||||
|
if (DstReg != SrcReg)
|
||||||
|
BuildMI(*MI->getParent(), MI, dl, TII.get(PPC::ORIS), DstReg)
|
||||||
|
.addReg(SrcReg)
|
||||||
|
.addImm(UsedRegMask >> 16);
|
||||||
|
else
|
||||||
|
BuildMI(*MI->getParent(), MI, dl, TII.get(PPC::ORIS), DstReg)
|
||||||
|
.addReg(SrcReg, RegState::Kill)
|
||||||
|
.addImm(UsedRegMask >> 16);
|
||||||
|
|
||||||
|
BuildMI(*MI->getParent(), MI, dl, TII.get(PPC::ORI), DstReg)
|
||||||
|
.addReg(DstReg, RegState::Kill)
|
||||||
|
.addImm(UsedRegMask & 0xFFFF);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove the old UPDATE_VRSAVE instruction.
|
||||||
|
MI->eraseFromParent();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// determineFrameLayout - Determine the size of the frame and maximum call
|
||||||
|
/// frame size.
|
||||||
|
void PPCFrameInfo::determineFrameLayout(MachineFunction &MF) const {
|
||||||
|
MachineFrameInfo *MFI = MF.getFrameInfo();
|
||||||
|
|
||||||
|
// Get the number of bytes to allocate from the FrameInfo
|
||||||
|
unsigned FrameSize = MFI->getStackSize();
|
||||||
|
|
||||||
|
// Get the alignments provided by the target, and the maximum alignment
|
||||||
|
// (if any) of the fixed frame objects.
|
||||||
|
unsigned MaxAlign = MFI->getMaxAlignment();
|
||||||
|
unsigned TargetAlign = MF.getTarget().getFrameInfo()->getStackAlignment();
|
||||||
|
unsigned AlignMask = TargetAlign - 1; //
|
||||||
|
|
||||||
|
// If we are a leaf function, and use up to 224 bytes of stack space,
|
||||||
|
// don't have a frame pointer, calls, or dynamic alloca then we do not need
|
||||||
|
// to adjust the stack pointer (we fit in the Red Zone).
|
||||||
|
bool DisableRedZone = MF.getFunction()->hasFnAttr(Attribute::NoRedZone);
|
||||||
|
// FIXME SVR4 The 32-bit SVR4 ABI has no red zone.
|
||||||
|
if (!DisableRedZone &&
|
||||||
|
FrameSize <= 224 && // Fits in red zone.
|
||||||
|
!MFI->hasVarSizedObjects() && // No dynamic alloca.
|
||||||
|
!MFI->adjustsStack() && // No calls.
|
||||||
|
(!ALIGN_STACK || MaxAlign <= TargetAlign)) { // No special alignment.
|
||||||
|
// No need for frame
|
||||||
|
MFI->setStackSize(0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the maximum call frame size of all the calls.
|
||||||
|
unsigned maxCallFrameSize = MFI->getMaxCallFrameSize();
|
||||||
|
|
||||||
|
// Maximum call frame needs to be at least big enough for linkage and 8 args.
|
||||||
|
unsigned minCallFrameSize = getMinCallFrameSize(Subtarget.isPPC64(),
|
||||||
|
Subtarget.isDarwinABI());
|
||||||
|
maxCallFrameSize = std::max(maxCallFrameSize, minCallFrameSize);
|
||||||
|
|
||||||
|
// If we have dynamic alloca then maxCallFrameSize needs to be aligned so
|
||||||
|
// that allocations will be aligned.
|
||||||
|
if (MFI->hasVarSizedObjects())
|
||||||
|
maxCallFrameSize = (maxCallFrameSize + AlignMask) & ~AlignMask;
|
||||||
|
|
||||||
|
// Update maximum call frame size.
|
||||||
|
MFI->setMaxCallFrameSize(maxCallFrameSize);
|
||||||
|
|
||||||
|
// Include call frame size in total.
|
||||||
|
FrameSize += maxCallFrameSize;
|
||||||
|
|
||||||
|
// Make sure the frame is aligned.
|
||||||
|
FrameSize = (FrameSize + AlignMask) & ~AlignMask;
|
||||||
|
|
||||||
|
// Update frame info.
|
||||||
|
MFI->setStackSize(FrameSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
void PPCFrameInfo::emitPrologue(MachineFunction &MF) const {
|
||||||
|
MachineBasicBlock &MBB = MF.front(); // Prolog goes in entry BB
|
||||||
|
MachineBasicBlock::iterator MBBI = MBB.begin();
|
||||||
|
MachineFrameInfo *MFI = MF.getFrameInfo();
|
||||||
|
const PPCRegisterInfo *RegInfo =
|
||||||
|
static_cast<const PPCRegisterInfo*>(MF.getTarget().getRegisterInfo());
|
||||||
|
const PPCInstrInfo &TII =
|
||||||
|
*static_cast<const PPCInstrInfo*>(MF.getTarget().getInstrInfo());
|
||||||
|
|
||||||
|
MachineModuleInfo &MMI = MF.getMMI();
|
||||||
|
DebugLoc dl;
|
||||||
|
bool needsFrameMoves = MMI.hasDebugInfo() ||
|
||||||
|
!MF.getFunction()->doesNotThrow() ||
|
||||||
|
UnwindTablesMandatory;
|
||||||
|
|
||||||
|
// Prepare for frame info.
|
||||||
|
MCSymbol *FrameLabel = 0;
|
||||||
|
|
||||||
|
// Scan the prolog, looking for an UPDATE_VRSAVE instruction. If we find it,
|
||||||
|
// process it.
|
||||||
|
for (unsigned i = 0; MBBI != MBB.end(); ++i, ++MBBI) {
|
||||||
|
if (MBBI->getOpcode() == PPC::UPDATE_VRSAVE) {
|
||||||
|
HandleVRSaveUpdate(MBBI, TII);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Move MBBI back to the beginning of the function.
|
||||||
|
MBBI = MBB.begin();
|
||||||
|
|
||||||
|
// Work out frame sizes.
|
||||||
|
determineFrameLayout(MF);
|
||||||
|
unsigned FrameSize = MFI->getStackSize();
|
||||||
|
|
||||||
|
int NegFrameSize = -FrameSize;
|
||||||
|
|
||||||
|
// Get processor type.
|
||||||
|
bool isPPC64 = Subtarget.isPPC64();
|
||||||
|
// Get operating system
|
||||||
|
bool isDarwinABI = Subtarget.isDarwinABI();
|
||||||
|
// Check if the link register (LR) must be saved.
|
||||||
|
PPCFunctionInfo *FI = MF.getInfo<PPCFunctionInfo>();
|
||||||
|
bool MustSaveLR = FI->mustSaveLR();
|
||||||
|
// Do we have a frame pointer for this function?
|
||||||
|
bool HasFP = RegInfo->hasFP(MF) && FrameSize;
|
||||||
|
|
||||||
|
int LROffset = PPCFrameInfo::getReturnSaveOffset(isPPC64, isDarwinABI);
|
||||||
|
|
||||||
|
int FPOffset = 0;
|
||||||
|
if (HasFP) {
|
||||||
|
if (Subtarget.isSVR4ABI()) {
|
||||||
|
MachineFrameInfo *FFI = MF.getFrameInfo();
|
||||||
|
int FPIndex = FI->getFramePointerSaveIndex();
|
||||||
|
assert(FPIndex && "No Frame Pointer Save Slot!");
|
||||||
|
FPOffset = FFI->getObjectOffset(FPIndex);
|
||||||
|
} else {
|
||||||
|
FPOffset = PPCFrameInfo::getFramePointerSaveOffset(isPPC64, isDarwinABI);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isPPC64) {
|
||||||
|
if (MustSaveLR)
|
||||||
|
BuildMI(MBB, MBBI, dl, TII.get(PPC::MFLR8), PPC::X0);
|
||||||
|
|
||||||
|
if (HasFP)
|
||||||
|
BuildMI(MBB, MBBI, dl, TII.get(PPC::STD))
|
||||||
|
.addReg(PPC::X31)
|
||||||
|
.addImm(FPOffset/4)
|
||||||
|
.addReg(PPC::X1);
|
||||||
|
|
||||||
|
if (MustSaveLR)
|
||||||
|
BuildMI(MBB, MBBI, dl, TII.get(PPC::STD))
|
||||||
|
.addReg(PPC::X0)
|
||||||
|
.addImm(LROffset / 4)
|
||||||
|
.addReg(PPC::X1);
|
||||||
|
} else {
|
||||||
|
if (MustSaveLR)
|
||||||
|
BuildMI(MBB, MBBI, dl, TII.get(PPC::MFLR), PPC::R0);
|
||||||
|
|
||||||
|
if (HasFP)
|
||||||
|
BuildMI(MBB, MBBI, dl, TII.get(PPC::STW))
|
||||||
|
.addReg(PPC::R31)
|
||||||
|
.addImm(FPOffset)
|
||||||
|
.addReg(PPC::R1);
|
||||||
|
|
||||||
|
if (MustSaveLR)
|
||||||
|
BuildMI(MBB, MBBI, dl, TII.get(PPC::STW))
|
||||||
|
.addReg(PPC::R0)
|
||||||
|
.addImm(LROffset)
|
||||||
|
.addReg(PPC::R1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Skip if a leaf routine.
|
||||||
|
if (!FrameSize) return;
|
||||||
|
|
||||||
|
// Get stack alignments.
|
||||||
|
unsigned TargetAlign = MF.getTarget().getFrameInfo()->getStackAlignment();
|
||||||
|
unsigned MaxAlign = MFI->getMaxAlignment();
|
||||||
|
|
||||||
|
// Adjust stack pointer: r1 += NegFrameSize.
|
||||||
|
// If there is a preferred stack alignment, align R1 now
|
||||||
|
if (!isPPC64) {
|
||||||
|
// PPC32.
|
||||||
|
if (ALIGN_STACK && MaxAlign > TargetAlign) {
|
||||||
|
assert(isPowerOf2_32(MaxAlign) && isInt<16>(MaxAlign) &&
|
||||||
|
"Invalid alignment!");
|
||||||
|
assert(isInt<16>(NegFrameSize) && "Unhandled stack size and alignment!");
|
||||||
|
|
||||||
|
BuildMI(MBB, MBBI, dl, TII.get(PPC::RLWINM), PPC::R0)
|
||||||
|
.addReg(PPC::R1)
|
||||||
|
.addImm(0)
|
||||||
|
.addImm(32 - Log2_32(MaxAlign))
|
||||||
|
.addImm(31);
|
||||||
|
BuildMI(MBB, MBBI, dl, TII.get(PPC::SUBFIC) ,PPC::R0)
|
||||||
|
.addReg(PPC::R0, RegState::Kill)
|
||||||
|
.addImm(NegFrameSize);
|
||||||
|
BuildMI(MBB, MBBI, dl, TII.get(PPC::STWUX))
|
||||||
|
.addReg(PPC::R1)
|
||||||
|
.addReg(PPC::R1)
|
||||||
|
.addReg(PPC::R0);
|
||||||
|
} else if (isInt<16>(NegFrameSize)) {
|
||||||
|
BuildMI(MBB, MBBI, dl, TII.get(PPC::STWU), PPC::R1)
|
||||||
|
.addReg(PPC::R1)
|
||||||
|
.addImm(NegFrameSize)
|
||||||
|
.addReg(PPC::R1);
|
||||||
|
} else {
|
||||||
|
BuildMI(MBB, MBBI, dl, TII.get(PPC::LIS), PPC::R0)
|
||||||
|
.addImm(NegFrameSize >> 16);
|
||||||
|
BuildMI(MBB, MBBI, dl, TII.get(PPC::ORI), PPC::R0)
|
||||||
|
.addReg(PPC::R0, RegState::Kill)
|
||||||
|
.addImm(NegFrameSize & 0xFFFF);
|
||||||
|
BuildMI(MBB, MBBI, dl, TII.get(PPC::STWUX))
|
||||||
|
.addReg(PPC::R1)
|
||||||
|
.addReg(PPC::R1)
|
||||||
|
.addReg(PPC::R0);
|
||||||
|
}
|
||||||
|
} else { // PPC64.
|
||||||
|
if (ALIGN_STACK && MaxAlign > TargetAlign) {
|
||||||
|
assert(isPowerOf2_32(MaxAlign) && isInt<16>(MaxAlign) &&
|
||||||
|
"Invalid alignment!");
|
||||||
|
assert(isInt<16>(NegFrameSize) && "Unhandled stack size and alignment!");
|
||||||
|
|
||||||
|
BuildMI(MBB, MBBI, dl, TII.get(PPC::RLDICL), PPC::X0)
|
||||||
|
.addReg(PPC::X1)
|
||||||
|
.addImm(0)
|
||||||
|
.addImm(64 - Log2_32(MaxAlign));
|
||||||
|
BuildMI(MBB, MBBI, dl, TII.get(PPC::SUBFIC8), PPC::X0)
|
||||||
|
.addReg(PPC::X0)
|
||||||
|
.addImm(NegFrameSize);
|
||||||
|
BuildMI(MBB, MBBI, dl, TII.get(PPC::STDUX))
|
||||||
|
.addReg(PPC::X1)
|
||||||
|
.addReg(PPC::X1)
|
||||||
|
.addReg(PPC::X0);
|
||||||
|
} else if (isInt<16>(NegFrameSize)) {
|
||||||
|
BuildMI(MBB, MBBI, dl, TII.get(PPC::STDU), PPC::X1)
|
||||||
|
.addReg(PPC::X1)
|
||||||
|
.addImm(NegFrameSize / 4)
|
||||||
|
.addReg(PPC::X1);
|
||||||
|
} else {
|
||||||
|
BuildMI(MBB, MBBI, dl, TII.get(PPC::LIS8), PPC::X0)
|
||||||
|
.addImm(NegFrameSize >> 16);
|
||||||
|
BuildMI(MBB, MBBI, dl, TII.get(PPC::ORI8), PPC::X0)
|
||||||
|
.addReg(PPC::X0, RegState::Kill)
|
||||||
|
.addImm(NegFrameSize & 0xFFFF);
|
||||||
|
BuildMI(MBB, MBBI, dl, TII.get(PPC::STDUX))
|
||||||
|
.addReg(PPC::X1)
|
||||||
|
.addReg(PPC::X1)
|
||||||
|
.addReg(PPC::X0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<MachineMove> &Moves = MMI.getFrameMoves();
|
||||||
|
|
||||||
|
// Add the "machine moves" for the instructions we generated above, but in
|
||||||
|
// reverse order.
|
||||||
|
if (needsFrameMoves) {
|
||||||
|
// Mark effective beginning of when frame pointer becomes valid.
|
||||||
|
FrameLabel = MMI.getContext().CreateTempSymbol();
|
||||||
|
BuildMI(MBB, MBBI, dl, TII.get(PPC::PROLOG_LABEL)).addSym(FrameLabel);
|
||||||
|
|
||||||
|
// Show update of SP.
|
||||||
|
if (NegFrameSize) {
|
||||||
|
MachineLocation SPDst(MachineLocation::VirtualFP);
|
||||||
|
MachineLocation SPSrc(MachineLocation::VirtualFP, NegFrameSize);
|
||||||
|
Moves.push_back(MachineMove(FrameLabel, SPDst, SPSrc));
|
||||||
|
} else {
|
||||||
|
MachineLocation SP(isPPC64 ? PPC::X31 : PPC::R31);
|
||||||
|
Moves.push_back(MachineMove(FrameLabel, SP, SP));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (HasFP) {
|
||||||
|
MachineLocation FPDst(MachineLocation::VirtualFP, FPOffset);
|
||||||
|
MachineLocation FPSrc(isPPC64 ? PPC::X31 : PPC::R31);
|
||||||
|
Moves.push_back(MachineMove(FrameLabel, FPDst, FPSrc));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (MustSaveLR) {
|
||||||
|
MachineLocation LRDst(MachineLocation::VirtualFP, LROffset);
|
||||||
|
MachineLocation LRSrc(isPPC64 ? PPC::LR8 : PPC::LR);
|
||||||
|
Moves.push_back(MachineMove(FrameLabel, LRDst, LRSrc));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MCSymbol *ReadyLabel = 0;
|
||||||
|
|
||||||
|
// If there is a frame pointer, copy R1 into R31
|
||||||
|
if (HasFP) {
|
||||||
|
if (!isPPC64) {
|
||||||
|
BuildMI(MBB, MBBI, dl, TII.get(PPC::OR), PPC::R31)
|
||||||
|
.addReg(PPC::R1)
|
||||||
|
.addReg(PPC::R1);
|
||||||
|
} else {
|
||||||
|
BuildMI(MBB, MBBI, dl, TII.get(PPC::OR8), PPC::X31)
|
||||||
|
.addReg(PPC::X1)
|
||||||
|
.addReg(PPC::X1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (needsFrameMoves) {
|
||||||
|
ReadyLabel = MMI.getContext().CreateTempSymbol();
|
||||||
|
|
||||||
|
// Mark effective beginning of when frame pointer is ready.
|
||||||
|
BuildMI(MBB, MBBI, dl, TII.get(PPC::PROLOG_LABEL)).addSym(ReadyLabel);
|
||||||
|
|
||||||
|
MachineLocation FPDst(HasFP ? (isPPC64 ? PPC::X31 : PPC::R31) :
|
||||||
|
(isPPC64 ? PPC::X1 : PPC::R1));
|
||||||
|
MachineLocation FPSrc(MachineLocation::VirtualFP);
|
||||||
|
Moves.push_back(MachineMove(ReadyLabel, FPDst, FPSrc));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (needsFrameMoves) {
|
||||||
|
MCSymbol *Label = HasFP ? ReadyLabel : FrameLabel;
|
||||||
|
|
||||||
|
// Add callee saved registers to move list.
|
||||||
|
const std::vector<CalleeSavedInfo> &CSI = MFI->getCalleeSavedInfo();
|
||||||
|
for (unsigned I = 0, E = CSI.size(); I != E; ++I) {
|
||||||
|
int Offset = MFI->getObjectOffset(CSI[I].getFrameIdx());
|
||||||
|
unsigned Reg = CSI[I].getReg();
|
||||||
|
if (Reg == PPC::LR || Reg == PPC::LR8 || Reg == PPC::RM) continue;
|
||||||
|
MachineLocation CSDst(MachineLocation::VirtualFP, Offset);
|
||||||
|
MachineLocation CSSrc(Reg);
|
||||||
|
Moves.push_back(MachineMove(Label, CSDst, CSSrc));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void PPCFrameInfo::emitEpilogue(MachineFunction &MF,
|
||||||
|
MachineBasicBlock &MBB) const {
|
||||||
|
MachineBasicBlock::iterator MBBI = prior(MBB.end());
|
||||||
|
const PPCRegisterInfo *RegInfo =
|
||||||
|
static_cast<const PPCRegisterInfo*>(MF.getTarget().getRegisterInfo());
|
||||||
|
const PPCInstrInfo &TII =
|
||||||
|
*static_cast<const PPCInstrInfo*>(MF.getTarget().getInstrInfo());
|
||||||
|
|
||||||
|
unsigned RetOpcode = MBBI->getOpcode();
|
||||||
|
DebugLoc dl;
|
||||||
|
|
||||||
|
assert( (RetOpcode == PPC::BLR ||
|
||||||
|
RetOpcode == PPC::TCRETURNri ||
|
||||||
|
RetOpcode == PPC::TCRETURNdi ||
|
||||||
|
RetOpcode == PPC::TCRETURNai ||
|
||||||
|
RetOpcode == PPC::TCRETURNri8 ||
|
||||||
|
RetOpcode == PPC::TCRETURNdi8 ||
|
||||||
|
RetOpcode == PPC::TCRETURNai8) &&
|
||||||
|
"Can only insert epilog into returning blocks");
|
||||||
|
|
||||||
|
// Get alignment info so we know how to restore r1
|
||||||
|
const MachineFrameInfo *MFI = MF.getFrameInfo();
|
||||||
|
unsigned TargetAlign = MF.getTarget().getFrameInfo()->getStackAlignment();
|
||||||
|
unsigned MaxAlign = MFI->getMaxAlignment();
|
||||||
|
|
||||||
|
// Get the number of bytes allocated from the FrameInfo.
|
||||||
|
int FrameSize = MFI->getStackSize();
|
||||||
|
|
||||||
|
// Get processor type.
|
||||||
|
bool isPPC64 = Subtarget.isPPC64();
|
||||||
|
// Get operating system
|
||||||
|
bool isDarwinABI = Subtarget.isDarwinABI();
|
||||||
|
// Check if the link register (LR) has been saved.
|
||||||
|
PPCFunctionInfo *FI = MF.getInfo<PPCFunctionInfo>();
|
||||||
|
bool MustSaveLR = FI->mustSaveLR();
|
||||||
|
// Do we have a frame pointer for this function?
|
||||||
|
bool HasFP = RegInfo->hasFP(MF) && FrameSize;
|
||||||
|
|
||||||
|
int LROffset = PPCFrameInfo::getReturnSaveOffset(isPPC64, isDarwinABI);
|
||||||
|
|
||||||
|
int FPOffset = 0;
|
||||||
|
if (HasFP) {
|
||||||
|
if (Subtarget.isSVR4ABI()) {
|
||||||
|
MachineFrameInfo *FFI = MF.getFrameInfo();
|
||||||
|
int FPIndex = FI->getFramePointerSaveIndex();
|
||||||
|
assert(FPIndex && "No Frame Pointer Save Slot!");
|
||||||
|
FPOffset = FFI->getObjectOffset(FPIndex);
|
||||||
|
} else {
|
||||||
|
FPOffset = PPCFrameInfo::getFramePointerSaveOffset(isPPC64, isDarwinABI);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool UsesTCRet = RetOpcode == PPC::TCRETURNri ||
|
||||||
|
RetOpcode == PPC::TCRETURNdi ||
|
||||||
|
RetOpcode == PPC::TCRETURNai ||
|
||||||
|
RetOpcode == PPC::TCRETURNri8 ||
|
||||||
|
RetOpcode == PPC::TCRETURNdi8 ||
|
||||||
|
RetOpcode == PPC::TCRETURNai8;
|
||||||
|
|
||||||
|
if (UsesTCRet) {
|
||||||
|
int MaxTCRetDelta = FI->getTailCallSPDelta();
|
||||||
|
MachineOperand &StackAdjust = MBBI->getOperand(1);
|
||||||
|
assert(StackAdjust.isImm() && "Expecting immediate value.");
|
||||||
|
// Adjust stack pointer.
|
||||||
|
int StackAdj = StackAdjust.getImm();
|
||||||
|
int Delta = StackAdj - MaxTCRetDelta;
|
||||||
|
assert((Delta >= 0) && "Delta must be positive");
|
||||||
|
if (MaxTCRetDelta>0)
|
||||||
|
FrameSize += (StackAdj +Delta);
|
||||||
|
else
|
||||||
|
FrameSize += StackAdj;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (FrameSize) {
|
||||||
|
// The loaded (or persistent) stack pointer value is offset by the 'stwu'
|
||||||
|
// on entry to the function. Add this offset back now.
|
||||||
|
if (!isPPC64) {
|
||||||
|
// If this function contained a fastcc call and GuaranteedTailCallOpt is
|
||||||
|
// enabled (=> hasFastCall()==true) the fastcc call might contain a tail
|
||||||
|
// call which invalidates the stack pointer value in SP(0). So we use the
|
||||||
|
// value of R31 in this case.
|
||||||
|
if (FI->hasFastCall() && isInt<16>(FrameSize)) {
|
||||||
|
assert(RegInfo->hasFP(MF) && "Expecting a valid the frame pointer.");
|
||||||
|
BuildMI(MBB, MBBI, dl, TII.get(PPC::ADDI), PPC::R1)
|
||||||
|
.addReg(PPC::R31).addImm(FrameSize);
|
||||||
|
} else if(FI->hasFastCall()) {
|
||||||
|
BuildMI(MBB, MBBI, dl, TII.get(PPC::LIS), PPC::R0)
|
||||||
|
.addImm(FrameSize >> 16);
|
||||||
|
BuildMI(MBB, MBBI, dl, TII.get(PPC::ORI), PPC::R0)
|
||||||
|
.addReg(PPC::R0, RegState::Kill)
|
||||||
|
.addImm(FrameSize & 0xFFFF);
|
||||||
|
BuildMI(MBB, MBBI, dl, TII.get(PPC::ADD4))
|
||||||
|
.addReg(PPC::R1)
|
||||||
|
.addReg(PPC::R31)
|
||||||
|
.addReg(PPC::R0);
|
||||||
|
} else if (isInt<16>(FrameSize) &&
|
||||||
|
(!ALIGN_STACK || TargetAlign >= MaxAlign) &&
|
||||||
|
!MFI->hasVarSizedObjects()) {
|
||||||
|
BuildMI(MBB, MBBI, dl, TII.get(PPC::ADDI), PPC::R1)
|
||||||
|
.addReg(PPC::R1).addImm(FrameSize);
|
||||||
|
} else {
|
||||||
|
BuildMI(MBB, MBBI, dl, TII.get(PPC::LWZ),PPC::R1)
|
||||||
|
.addImm(0).addReg(PPC::R1);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (FI->hasFastCall() && isInt<16>(FrameSize)) {
|
||||||
|
assert(RegInfo->hasFP(MF) && "Expecting a valid the frame pointer.");
|
||||||
|
BuildMI(MBB, MBBI, dl, TII.get(PPC::ADDI8), PPC::X1)
|
||||||
|
.addReg(PPC::X31).addImm(FrameSize);
|
||||||
|
} else if(FI->hasFastCall()) {
|
||||||
|
BuildMI(MBB, MBBI, dl, TII.get(PPC::LIS8), PPC::X0)
|
||||||
|
.addImm(FrameSize >> 16);
|
||||||
|
BuildMI(MBB, MBBI, dl, TII.get(PPC::ORI8), PPC::X0)
|
||||||
|
.addReg(PPC::X0, RegState::Kill)
|
||||||
|
.addImm(FrameSize & 0xFFFF);
|
||||||
|
BuildMI(MBB, MBBI, dl, TII.get(PPC::ADD8))
|
||||||
|
.addReg(PPC::X1)
|
||||||
|
.addReg(PPC::X31)
|
||||||
|
.addReg(PPC::X0);
|
||||||
|
} else if (isInt<16>(FrameSize) && TargetAlign >= MaxAlign &&
|
||||||
|
!MFI->hasVarSizedObjects()) {
|
||||||
|
BuildMI(MBB, MBBI, dl, TII.get(PPC::ADDI8), PPC::X1)
|
||||||
|
.addReg(PPC::X1).addImm(FrameSize);
|
||||||
|
} else {
|
||||||
|
BuildMI(MBB, MBBI, dl, TII.get(PPC::LD), PPC::X1)
|
||||||
|
.addImm(0).addReg(PPC::X1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isPPC64) {
|
||||||
|
if (MustSaveLR)
|
||||||
|
BuildMI(MBB, MBBI, dl, TII.get(PPC::LD), PPC::X0)
|
||||||
|
.addImm(LROffset/4).addReg(PPC::X1);
|
||||||
|
|
||||||
|
if (HasFP)
|
||||||
|
BuildMI(MBB, MBBI, dl, TII.get(PPC::LD), PPC::X31)
|
||||||
|
.addImm(FPOffset/4).addReg(PPC::X1);
|
||||||
|
|
||||||
|
if (MustSaveLR)
|
||||||
|
BuildMI(MBB, MBBI, dl, TII.get(PPC::MTLR8)).addReg(PPC::X0);
|
||||||
|
} else {
|
||||||
|
if (MustSaveLR)
|
||||||
|
BuildMI(MBB, MBBI, dl, TII.get(PPC::LWZ), PPC::R0)
|
||||||
|
.addImm(LROffset).addReg(PPC::R1);
|
||||||
|
|
||||||
|
if (HasFP)
|
||||||
|
BuildMI(MBB, MBBI, dl, TII.get(PPC::LWZ), PPC::R31)
|
||||||
|
.addImm(FPOffset).addReg(PPC::R1);
|
||||||
|
|
||||||
|
if (MustSaveLR)
|
||||||
|
BuildMI(MBB, MBBI, dl, TII.get(PPC::MTLR)).addReg(PPC::R0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Callee pop calling convention. Pop parameter/linkage area. Used for tail
|
||||||
|
// call optimization
|
||||||
|
if (GuaranteedTailCallOpt && RetOpcode == PPC::BLR &&
|
||||||
|
MF.getFunction()->getCallingConv() == CallingConv::Fast) {
|
||||||
|
PPCFunctionInfo *FI = MF.getInfo<PPCFunctionInfo>();
|
||||||
|
unsigned CallerAllocatedAmt = FI->getMinReservedArea();
|
||||||
|
unsigned StackReg = isPPC64 ? PPC::X1 : PPC::R1;
|
||||||
|
unsigned FPReg = isPPC64 ? PPC::X31 : PPC::R31;
|
||||||
|
unsigned TmpReg = isPPC64 ? PPC::X0 : PPC::R0;
|
||||||
|
unsigned ADDIInstr = isPPC64 ? PPC::ADDI8 : PPC::ADDI;
|
||||||
|
unsigned ADDInstr = isPPC64 ? PPC::ADD8 : PPC::ADD4;
|
||||||
|
unsigned LISInstr = isPPC64 ? PPC::LIS8 : PPC::LIS;
|
||||||
|
unsigned ORIInstr = isPPC64 ? PPC::ORI8 : PPC::ORI;
|
||||||
|
|
||||||
|
if (CallerAllocatedAmt && isInt<16>(CallerAllocatedAmt)) {
|
||||||
|
BuildMI(MBB, MBBI, dl, TII.get(ADDIInstr), StackReg)
|
||||||
|
.addReg(StackReg).addImm(CallerAllocatedAmt);
|
||||||
|
} else {
|
||||||
|
BuildMI(MBB, MBBI, dl, TII.get(LISInstr), TmpReg)
|
||||||
|
.addImm(CallerAllocatedAmt >> 16);
|
||||||
|
BuildMI(MBB, MBBI, dl, TII.get(ORIInstr), TmpReg)
|
||||||
|
.addReg(TmpReg, RegState::Kill)
|
||||||
|
.addImm(CallerAllocatedAmt & 0xFFFF);
|
||||||
|
BuildMI(MBB, MBBI, dl, TII.get(ADDInstr))
|
||||||
|
.addReg(StackReg)
|
||||||
|
.addReg(FPReg)
|
||||||
|
.addReg(TmpReg);
|
||||||
|
}
|
||||||
|
} else if (RetOpcode == PPC::TCRETURNdi) {
|
||||||
|
MBBI = prior(MBB.end());
|
||||||
|
MachineOperand &JumpTarget = MBBI->getOperand(0);
|
||||||
|
BuildMI(MBB, MBBI, dl, TII.get(PPC::TAILB)).
|
||||||
|
addGlobalAddress(JumpTarget.getGlobal(), JumpTarget.getOffset());
|
||||||
|
} else if (RetOpcode == PPC::TCRETURNri) {
|
||||||
|
MBBI = prior(MBB.end());
|
||||||
|
assert(MBBI->getOperand(0).isReg() && "Expecting register operand.");
|
||||||
|
BuildMI(MBB, MBBI, dl, TII.get(PPC::TAILBCTR));
|
||||||
|
} else if (RetOpcode == PPC::TCRETURNai) {
|
||||||
|
MBBI = prior(MBB.end());
|
||||||
|
MachineOperand &JumpTarget = MBBI->getOperand(0);
|
||||||
|
BuildMI(MBB, MBBI, dl, TII.get(PPC::TAILBA)).addImm(JumpTarget.getImm());
|
||||||
|
} else if (RetOpcode == PPC::TCRETURNdi8) {
|
||||||
|
MBBI = prior(MBB.end());
|
||||||
|
MachineOperand &JumpTarget = MBBI->getOperand(0);
|
||||||
|
BuildMI(MBB, MBBI, dl, TII.get(PPC::TAILB8)).
|
||||||
|
addGlobalAddress(JumpTarget.getGlobal(), JumpTarget.getOffset());
|
||||||
|
} else if (RetOpcode == PPC::TCRETURNri8) {
|
||||||
|
MBBI = prior(MBB.end());
|
||||||
|
assert(MBBI->getOperand(0).isReg() && "Expecting register operand.");
|
||||||
|
BuildMI(MBB, MBBI, dl, TII.get(PPC::TAILBCTR8));
|
||||||
|
} else if (RetOpcode == PPC::TCRETURNai8) {
|
||||||
|
MBBI = prior(MBB.end());
|
||||||
|
MachineOperand &JumpTarget = MBBI->getOperand(0);
|
||||||
|
BuildMI(MBB, MBBI, dl, TII.get(PPC::TAILBA8)).addImm(JumpTarget.getImm());
|
||||||
|
}
|
||||||
|
}
|
|
@ -20,15 +20,28 @@
|
||||||
#include "llvm/ADT/STLExtras.h"
|
#include "llvm/ADT/STLExtras.h"
|
||||||
|
|
||||||
namespace llvm {
|
namespace llvm {
|
||||||
|
class PPCSubtarget;
|
||||||
|
|
||||||
class PPCFrameInfo: public TargetFrameInfo {
|
class PPCFrameInfo: public TargetFrameInfo {
|
||||||
const TargetMachine &TM;
|
const PPCSubtarget &Subtarget;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
PPCFrameInfo(const TargetMachine &tm, bool LP64)
|
PPCFrameInfo(const PPCSubtarget &sti)
|
||||||
: TargetFrameInfo(TargetFrameInfo::StackGrowsDown, 16, 0), TM(tm) {
|
: TargetFrameInfo(TargetFrameInfo::StackGrowsDown, 16, 0), Subtarget(sti) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void determineFrameLayout(MachineFunction &MF) const;
|
||||||
|
|
||||||
|
/// emitProlog/emitEpilog - These methods insert prolog and epilog code into
|
||||||
|
/// the function.
|
||||||
|
void emitPrologue(MachineFunction &MF) const;
|
||||||
|
void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const;
|
||||||
|
|
||||||
|
/// targetHandlesStackFrameRounding - Returns true if the target is
|
||||||
|
/// responsible for rounding up the stack frame (probably at emitPrologue
|
||||||
|
/// time).
|
||||||
|
bool targetHandlesStackFrameRounding() const { return true; }
|
||||||
|
|
||||||
/// getReturnSaveOffset - Return the previous frame offset to save the
|
/// getReturnSaveOffset - Return the previous frame offset to save the
|
||||||
/// return address.
|
/// return address.
|
||||||
static unsigned getReturnSaveOffset(bool isPPC64, bool isDarwinABI) {
|
static unsigned getReturnSaveOffset(bool isPPC64, bool isDarwinABI) {
|
||||||
|
@ -91,9 +104,9 @@ public:
|
||||||
// With the SVR4 ABI, callee-saved registers have fixed offsets on the stack.
|
// With the SVR4 ABI, callee-saved registers have fixed offsets on the stack.
|
||||||
const SpillSlot *
|
const SpillSlot *
|
||||||
getCalleeSavedSpillSlots(unsigned &NumEntries) const {
|
getCalleeSavedSpillSlots(unsigned &NumEntries) const {
|
||||||
if (TM.getSubtarget<PPCSubtarget>().isDarwinABI()) {
|
if (Subtarget.isDarwinABI()) {
|
||||||
NumEntries = 1;
|
NumEntries = 1;
|
||||||
if (TM.getSubtarget<PPCSubtarget>().isPPC64()) {
|
if (Subtarget.isPPC64()) {
|
||||||
static const SpillSlot darwin64Offsets = {PPC::X31, -8};
|
static const SpillSlot darwin64Offsets = {PPC::X31, -8};
|
||||||
return &darwin64Offsets;
|
return &darwin64Offsets;
|
||||||
} else {
|
} else {
|
||||||
|
@ -103,7 +116,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
// Early exit if not using the SVR4 ABI.
|
// Early exit if not using the SVR4 ABI.
|
||||||
if (!TM.getSubtarget<PPCSubtarget>().isSVR4ABI()) {
|
if (!Subtarget.isSVR4ABI()) {
|
||||||
NumEntries = 0;
|
NumEntries = 0;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -283,7 +296,7 @@ public:
|
||||||
{PPC::V20, -192}
|
{PPC::V20, -192}
|
||||||
};
|
};
|
||||||
|
|
||||||
if (TM.getSubtarget<PPCSubtarget>().isPPC64()) {
|
if (Subtarget.isPPC64()) {
|
||||||
NumEntries = array_lengthof(Offsets64);
|
NumEntries = array_lengthof(Offsets64);
|
||||||
|
|
||||||
return Offsets64;
|
return Offsets64;
|
||||||
|
|
|
@ -44,16 +44,6 @@
|
||||||
#include "llvm/ADT/STLExtras.h"
|
#include "llvm/ADT/STLExtras.h"
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
|
|
||||||
// FIXME This disables some code that aligns the stack to a boundary
|
|
||||||
// bigger than the default (16 bytes on Darwin) when there is a stack local
|
|
||||||
// of greater alignment. This does not currently work, because the delta
|
|
||||||
// between old and new stack pointers is added to offsets that reference
|
|
||||||
// incoming parameters after the prolog is generated, and the code that
|
|
||||||
// does that doesn't handle a variable delta. You don't want to do that
|
|
||||||
// anyway; a better approach is to reserve another register that retains
|
|
||||||
// to the incoming stack pointer, and reference parameters relative to that.
|
|
||||||
#define ALIGN_STACK 0
|
|
||||||
|
|
||||||
// FIXME (64-bit): Eventually enable by default.
|
// FIXME (64-bit): Eventually enable by default.
|
||||||
namespace llvm {
|
namespace llvm {
|
||||||
cl::opt<bool> EnablePPC32RS("enable-ppc32-regscavenger",
|
cl::opt<bool> EnablePPC32RS("enable-ppc32-regscavenger",
|
||||||
|
@ -715,194 +705,6 @@ PPCRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
|
||||||
MI.getOperand(OperandBase + 1).ChangeToRegister(SReg, false);
|
MI.getOperand(OperandBase + 1).ChangeToRegister(SReg, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// VRRegNo - Map from a numbered VR register to its enum value.
|
|
||||||
///
|
|
||||||
static const unsigned short VRRegNo[] = {
|
|
||||||
PPC::V0 , PPC::V1 , PPC::V2 , PPC::V3 , PPC::V4 , PPC::V5 , PPC::V6 , PPC::V7 ,
|
|
||||||
PPC::V8 , PPC::V9 , PPC::V10, PPC::V11, PPC::V12, PPC::V13, PPC::V14, PPC::V15,
|
|
||||||
PPC::V16, PPC::V17, PPC::V18, PPC::V19, PPC::V20, PPC::V21, PPC::V22, PPC::V23,
|
|
||||||
PPC::V24, PPC::V25, PPC::V26, PPC::V27, PPC::V28, PPC::V29, PPC::V30, PPC::V31
|
|
||||||
};
|
|
||||||
|
|
||||||
/// RemoveVRSaveCode - We have found that this function does not need any code
|
|
||||||
/// to manipulate the VRSAVE register, even though it uses vector registers.
|
|
||||||
/// This can happen when the only registers used are known to be live in or out
|
|
||||||
/// of the function. Remove all of the VRSAVE related code from the function.
|
|
||||||
static void RemoveVRSaveCode(MachineInstr *MI) {
|
|
||||||
MachineBasicBlock *Entry = MI->getParent();
|
|
||||||
MachineFunction *MF = Entry->getParent();
|
|
||||||
|
|
||||||
// We know that the MTVRSAVE instruction immediately follows MI. Remove it.
|
|
||||||
MachineBasicBlock::iterator MBBI = MI;
|
|
||||||
++MBBI;
|
|
||||||
assert(MBBI != Entry->end() && MBBI->getOpcode() == PPC::MTVRSAVE);
|
|
||||||
MBBI->eraseFromParent();
|
|
||||||
|
|
||||||
bool RemovedAllMTVRSAVEs = true;
|
|
||||||
// See if we can find and remove the MTVRSAVE instruction from all of the
|
|
||||||
// epilog blocks.
|
|
||||||
for (MachineFunction::iterator I = MF->begin(), E = MF->end(); I != E; ++I) {
|
|
||||||
// If last instruction is a return instruction, add an epilogue
|
|
||||||
if (!I->empty() && I->back().getDesc().isReturn()) {
|
|
||||||
bool FoundIt = false;
|
|
||||||
for (MBBI = I->end(); MBBI != I->begin(); ) {
|
|
||||||
--MBBI;
|
|
||||||
if (MBBI->getOpcode() == PPC::MTVRSAVE) {
|
|
||||||
MBBI->eraseFromParent(); // remove it.
|
|
||||||
FoundIt = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
RemovedAllMTVRSAVEs &= FoundIt;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// If we found and removed all MTVRSAVE instructions, remove the read of
|
|
||||||
// VRSAVE as well.
|
|
||||||
if (RemovedAllMTVRSAVEs) {
|
|
||||||
MBBI = MI;
|
|
||||||
assert(MBBI != Entry->begin() && "UPDATE_VRSAVE is first instr in block?");
|
|
||||||
--MBBI;
|
|
||||||
assert(MBBI->getOpcode() == PPC::MFVRSAVE && "VRSAVE instrs wandered?");
|
|
||||||
MBBI->eraseFromParent();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Finally, nuke the UPDATE_VRSAVE.
|
|
||||||
MI->eraseFromParent();
|
|
||||||
}
|
|
||||||
|
|
||||||
// HandleVRSaveUpdate - MI is the UPDATE_VRSAVE instruction introduced by the
|
|
||||||
// instruction selector. Based on the vector registers that have been used,
|
|
||||||
// transform this into the appropriate ORI instruction.
|
|
||||||
static void HandleVRSaveUpdate(MachineInstr *MI, const TargetInstrInfo &TII) {
|
|
||||||
MachineFunction *MF = MI->getParent()->getParent();
|
|
||||||
DebugLoc dl = MI->getDebugLoc();
|
|
||||||
|
|
||||||
unsigned UsedRegMask = 0;
|
|
||||||
for (unsigned i = 0; i != 32; ++i)
|
|
||||||
if (MF->getRegInfo().isPhysRegUsed(VRRegNo[i]))
|
|
||||||
UsedRegMask |= 1 << (31-i);
|
|
||||||
|
|
||||||
// Live in and live out values already must be in the mask, so don't bother
|
|
||||||
// marking them.
|
|
||||||
for (MachineRegisterInfo::livein_iterator
|
|
||||||
I = MF->getRegInfo().livein_begin(),
|
|
||||||
E = MF->getRegInfo().livein_end(); I != E; ++I) {
|
|
||||||
unsigned RegNo = PPCRegisterInfo::getRegisterNumbering(I->first);
|
|
||||||
if (VRRegNo[RegNo] == I->first) // If this really is a vector reg.
|
|
||||||
UsedRegMask &= ~(1 << (31-RegNo)); // Doesn't need to be marked.
|
|
||||||
}
|
|
||||||
for (MachineRegisterInfo::liveout_iterator
|
|
||||||
I = MF->getRegInfo().liveout_begin(),
|
|
||||||
E = MF->getRegInfo().liveout_end(); I != E; ++I) {
|
|
||||||
unsigned RegNo = PPCRegisterInfo::getRegisterNumbering(*I);
|
|
||||||
if (VRRegNo[RegNo] == *I) // If this really is a vector reg.
|
|
||||||
UsedRegMask &= ~(1 << (31-RegNo)); // Doesn't need to be marked.
|
|
||||||
}
|
|
||||||
|
|
||||||
// If no registers are used, turn this into a copy.
|
|
||||||
if (UsedRegMask == 0) {
|
|
||||||
// Remove all VRSAVE code.
|
|
||||||
RemoveVRSaveCode(MI);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned SrcReg = MI->getOperand(1).getReg();
|
|
||||||
unsigned DstReg = MI->getOperand(0).getReg();
|
|
||||||
|
|
||||||
if ((UsedRegMask & 0xFFFF) == UsedRegMask) {
|
|
||||||
if (DstReg != SrcReg)
|
|
||||||
BuildMI(*MI->getParent(), MI, dl, TII.get(PPC::ORI), DstReg)
|
|
||||||
.addReg(SrcReg)
|
|
||||||
.addImm(UsedRegMask);
|
|
||||||
else
|
|
||||||
BuildMI(*MI->getParent(), MI, dl, TII.get(PPC::ORI), DstReg)
|
|
||||||
.addReg(SrcReg, RegState::Kill)
|
|
||||||
.addImm(UsedRegMask);
|
|
||||||
} else if ((UsedRegMask & 0xFFFF0000) == UsedRegMask) {
|
|
||||||
if (DstReg != SrcReg)
|
|
||||||
BuildMI(*MI->getParent(), MI, dl, TII.get(PPC::ORIS), DstReg)
|
|
||||||
.addReg(SrcReg)
|
|
||||||
.addImm(UsedRegMask >> 16);
|
|
||||||
else
|
|
||||||
BuildMI(*MI->getParent(), MI, dl, TII.get(PPC::ORIS), DstReg)
|
|
||||||
.addReg(SrcReg, RegState::Kill)
|
|
||||||
.addImm(UsedRegMask >> 16);
|
|
||||||
} else {
|
|
||||||
if (DstReg != SrcReg)
|
|
||||||
BuildMI(*MI->getParent(), MI, dl, TII.get(PPC::ORIS), DstReg)
|
|
||||||
.addReg(SrcReg)
|
|
||||||
.addImm(UsedRegMask >> 16);
|
|
||||||
else
|
|
||||||
BuildMI(*MI->getParent(), MI, dl, TII.get(PPC::ORIS), DstReg)
|
|
||||||
.addReg(SrcReg, RegState::Kill)
|
|
||||||
.addImm(UsedRegMask >> 16);
|
|
||||||
|
|
||||||
BuildMI(*MI->getParent(), MI, dl, TII.get(PPC::ORI), DstReg)
|
|
||||||
.addReg(DstReg, RegState::Kill)
|
|
||||||
.addImm(UsedRegMask & 0xFFFF);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Remove the old UPDATE_VRSAVE instruction.
|
|
||||||
MI->eraseFromParent();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// determineFrameLayout - Determine the size of the frame and maximum call
|
|
||||||
/// frame size.
|
|
||||||
void PPCRegisterInfo::determineFrameLayout(MachineFunction &MF) const {
|
|
||||||
MachineFrameInfo *MFI = MF.getFrameInfo();
|
|
||||||
|
|
||||||
// Get the number of bytes to allocate from the FrameInfo
|
|
||||||
unsigned FrameSize = MFI->getStackSize();
|
|
||||||
|
|
||||||
// Get the alignments provided by the target, and the maximum alignment
|
|
||||||
// (if any) of the fixed frame objects.
|
|
||||||
unsigned MaxAlign = MFI->getMaxAlignment();
|
|
||||||
unsigned TargetAlign = MF.getTarget().getFrameInfo()->getStackAlignment();
|
|
||||||
unsigned AlignMask = TargetAlign - 1; //
|
|
||||||
|
|
||||||
// If we are a leaf function, and use up to 224 bytes of stack space,
|
|
||||||
// don't have a frame pointer, calls, or dynamic alloca then we do not need
|
|
||||||
// to adjust the stack pointer (we fit in the Red Zone).
|
|
||||||
bool DisableRedZone = MF.getFunction()->hasFnAttr(Attribute::NoRedZone);
|
|
||||||
// FIXME SVR4 The 32-bit SVR4 ABI has no red zone.
|
|
||||||
if (!DisableRedZone &&
|
|
||||||
FrameSize <= 224 && // Fits in red zone.
|
|
||||||
!MFI->hasVarSizedObjects() && // No dynamic alloca.
|
|
||||||
!MFI->adjustsStack() && // No calls.
|
|
||||||
(!ALIGN_STACK || MaxAlign <= TargetAlign)) { // No special alignment.
|
|
||||||
// No need for frame
|
|
||||||
MFI->setStackSize(0);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get the maximum call frame size of all the calls.
|
|
||||||
unsigned maxCallFrameSize = MFI->getMaxCallFrameSize();
|
|
||||||
|
|
||||||
// Maximum call frame needs to be at least big enough for linkage and 8 args.
|
|
||||||
unsigned minCallFrameSize =
|
|
||||||
PPCFrameInfo::getMinCallFrameSize(Subtarget.isPPC64(),
|
|
||||||
Subtarget.isDarwinABI());
|
|
||||||
maxCallFrameSize = std::max(maxCallFrameSize, minCallFrameSize);
|
|
||||||
|
|
||||||
// If we have dynamic alloca then maxCallFrameSize needs to be aligned so
|
|
||||||
// that allocations will be aligned.
|
|
||||||
if (MFI->hasVarSizedObjects())
|
|
||||||
maxCallFrameSize = (maxCallFrameSize + AlignMask) & ~AlignMask;
|
|
||||||
|
|
||||||
// Update maximum call frame size.
|
|
||||||
MFI->setMaxCallFrameSize(maxCallFrameSize);
|
|
||||||
|
|
||||||
// Include call frame size in total.
|
|
||||||
FrameSize += maxCallFrameSize;
|
|
||||||
|
|
||||||
// Make sure the frame is aligned.
|
|
||||||
FrameSize = (FrameSize + AlignMask) & ~AlignMask;
|
|
||||||
|
|
||||||
// Update frame info.
|
|
||||||
MFI->setStackSize(FrameSize);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
PPCRegisterInfo::processFunctionBeforeCalleeSavedScan(MachineFunction &MF,
|
PPCRegisterInfo::processFunctionBeforeCalleeSavedScan(MachineFunction &MF,
|
||||||
RegScavenger *RS) const {
|
RegScavenger *RS) const {
|
||||||
|
@ -1142,454 +944,6 @@ PPCRegisterInfo::processFunctionBeforeFrameFinalized(MachineFunction &MF)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
PPCRegisterInfo::emitPrologue(MachineFunction &MF) const {
|
|
||||||
MachineBasicBlock &MBB = MF.front(); // Prolog goes in entry BB
|
|
||||||
MachineBasicBlock::iterator MBBI = MBB.begin();
|
|
||||||
MachineFrameInfo *MFI = MF.getFrameInfo();
|
|
||||||
MachineModuleInfo &MMI = MF.getMMI();
|
|
||||||
DebugLoc dl;
|
|
||||||
bool needsFrameMoves = MMI.hasDebugInfo() ||
|
|
||||||
!MF.getFunction()->doesNotThrow() ||
|
|
||||||
UnwindTablesMandatory;
|
|
||||||
|
|
||||||
// Prepare for frame info.
|
|
||||||
MCSymbol *FrameLabel = 0;
|
|
||||||
|
|
||||||
// Scan the prolog, looking for an UPDATE_VRSAVE instruction. If we find it,
|
|
||||||
// process it.
|
|
||||||
for (unsigned i = 0; MBBI != MBB.end(); ++i, ++MBBI) {
|
|
||||||
if (MBBI->getOpcode() == PPC::UPDATE_VRSAVE) {
|
|
||||||
HandleVRSaveUpdate(MBBI, TII);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Move MBBI back to the beginning of the function.
|
|
||||||
MBBI = MBB.begin();
|
|
||||||
|
|
||||||
// Work out frame sizes.
|
|
||||||
determineFrameLayout(MF);
|
|
||||||
unsigned FrameSize = MFI->getStackSize();
|
|
||||||
|
|
||||||
int NegFrameSize = -FrameSize;
|
|
||||||
|
|
||||||
// Get processor type.
|
|
||||||
bool isPPC64 = Subtarget.isPPC64();
|
|
||||||
// Get operating system
|
|
||||||
bool isDarwinABI = Subtarget.isDarwinABI();
|
|
||||||
// Check if the link register (LR) must be saved.
|
|
||||||
PPCFunctionInfo *FI = MF.getInfo<PPCFunctionInfo>();
|
|
||||||
bool MustSaveLR = FI->mustSaveLR();
|
|
||||||
// Do we have a frame pointer for this function?
|
|
||||||
bool HasFP = hasFP(MF) && FrameSize;
|
|
||||||
|
|
||||||
int LROffset = PPCFrameInfo::getReturnSaveOffset(isPPC64, isDarwinABI);
|
|
||||||
|
|
||||||
int FPOffset = 0;
|
|
||||||
if (HasFP) {
|
|
||||||
if (Subtarget.isSVR4ABI()) {
|
|
||||||
MachineFrameInfo *FFI = MF.getFrameInfo();
|
|
||||||
int FPIndex = FI->getFramePointerSaveIndex();
|
|
||||||
assert(FPIndex && "No Frame Pointer Save Slot!");
|
|
||||||
FPOffset = FFI->getObjectOffset(FPIndex);
|
|
||||||
} else {
|
|
||||||
FPOffset = PPCFrameInfo::getFramePointerSaveOffset(isPPC64, isDarwinABI);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isPPC64) {
|
|
||||||
if (MustSaveLR)
|
|
||||||
BuildMI(MBB, MBBI, dl, TII.get(PPC::MFLR8), PPC::X0);
|
|
||||||
|
|
||||||
if (HasFP)
|
|
||||||
BuildMI(MBB, MBBI, dl, TII.get(PPC::STD))
|
|
||||||
.addReg(PPC::X31)
|
|
||||||
.addImm(FPOffset/4)
|
|
||||||
.addReg(PPC::X1);
|
|
||||||
|
|
||||||
if (MustSaveLR)
|
|
||||||
BuildMI(MBB, MBBI, dl, TII.get(PPC::STD))
|
|
||||||
.addReg(PPC::X0)
|
|
||||||
.addImm(LROffset / 4)
|
|
||||||
.addReg(PPC::X1);
|
|
||||||
} else {
|
|
||||||
if (MustSaveLR)
|
|
||||||
BuildMI(MBB, MBBI, dl, TII.get(PPC::MFLR), PPC::R0);
|
|
||||||
|
|
||||||
if (HasFP)
|
|
||||||
BuildMI(MBB, MBBI, dl, TII.get(PPC::STW))
|
|
||||||
.addReg(PPC::R31)
|
|
||||||
.addImm(FPOffset)
|
|
||||||
.addReg(PPC::R1);
|
|
||||||
|
|
||||||
if (MustSaveLR)
|
|
||||||
BuildMI(MBB, MBBI, dl, TII.get(PPC::STW))
|
|
||||||
.addReg(PPC::R0)
|
|
||||||
.addImm(LROffset)
|
|
||||||
.addReg(PPC::R1);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Skip if a leaf routine.
|
|
||||||
if (!FrameSize) return;
|
|
||||||
|
|
||||||
// Get stack alignments.
|
|
||||||
unsigned TargetAlign = MF.getTarget().getFrameInfo()->getStackAlignment();
|
|
||||||
unsigned MaxAlign = MFI->getMaxAlignment();
|
|
||||||
|
|
||||||
// Adjust stack pointer: r1 += NegFrameSize.
|
|
||||||
// If there is a preferred stack alignment, align R1 now
|
|
||||||
if (!isPPC64) {
|
|
||||||
// PPC32.
|
|
||||||
if (ALIGN_STACK && MaxAlign > TargetAlign) {
|
|
||||||
assert(isPowerOf2_32(MaxAlign) && isInt<16>(MaxAlign) &&
|
|
||||||
"Invalid alignment!");
|
|
||||||
assert(isInt<16>(NegFrameSize) && "Unhandled stack size and alignment!");
|
|
||||||
|
|
||||||
BuildMI(MBB, MBBI, dl, TII.get(PPC::RLWINM), PPC::R0)
|
|
||||||
.addReg(PPC::R1)
|
|
||||||
.addImm(0)
|
|
||||||
.addImm(32 - Log2_32(MaxAlign))
|
|
||||||
.addImm(31);
|
|
||||||
BuildMI(MBB, MBBI, dl, TII.get(PPC::SUBFIC) ,PPC::R0)
|
|
||||||
.addReg(PPC::R0, RegState::Kill)
|
|
||||||
.addImm(NegFrameSize);
|
|
||||||
BuildMI(MBB, MBBI, dl, TII.get(PPC::STWUX))
|
|
||||||
.addReg(PPC::R1)
|
|
||||||
.addReg(PPC::R1)
|
|
||||||
.addReg(PPC::R0);
|
|
||||||
} else if (isInt<16>(NegFrameSize)) {
|
|
||||||
BuildMI(MBB, MBBI, dl, TII.get(PPC::STWU), PPC::R1)
|
|
||||||
.addReg(PPC::R1)
|
|
||||||
.addImm(NegFrameSize)
|
|
||||||
.addReg(PPC::R1);
|
|
||||||
} else {
|
|
||||||
BuildMI(MBB, MBBI, dl, TII.get(PPC::LIS), PPC::R0)
|
|
||||||
.addImm(NegFrameSize >> 16);
|
|
||||||
BuildMI(MBB, MBBI, dl, TII.get(PPC::ORI), PPC::R0)
|
|
||||||
.addReg(PPC::R0, RegState::Kill)
|
|
||||||
.addImm(NegFrameSize & 0xFFFF);
|
|
||||||
BuildMI(MBB, MBBI, dl, TII.get(PPC::STWUX))
|
|
||||||
.addReg(PPC::R1)
|
|
||||||
.addReg(PPC::R1)
|
|
||||||
.addReg(PPC::R0);
|
|
||||||
}
|
|
||||||
} else { // PPC64.
|
|
||||||
if (ALIGN_STACK && MaxAlign > TargetAlign) {
|
|
||||||
assert(isPowerOf2_32(MaxAlign) && isInt<16>(MaxAlign) &&
|
|
||||||
"Invalid alignment!");
|
|
||||||
assert(isInt<16>(NegFrameSize) && "Unhandled stack size and alignment!");
|
|
||||||
|
|
||||||
BuildMI(MBB, MBBI, dl, TII.get(PPC::RLDICL), PPC::X0)
|
|
||||||
.addReg(PPC::X1)
|
|
||||||
.addImm(0)
|
|
||||||
.addImm(64 - Log2_32(MaxAlign));
|
|
||||||
BuildMI(MBB, MBBI, dl, TII.get(PPC::SUBFIC8), PPC::X0)
|
|
||||||
.addReg(PPC::X0)
|
|
||||||
.addImm(NegFrameSize);
|
|
||||||
BuildMI(MBB, MBBI, dl, TII.get(PPC::STDUX))
|
|
||||||
.addReg(PPC::X1)
|
|
||||||
.addReg(PPC::X1)
|
|
||||||
.addReg(PPC::X0);
|
|
||||||
} else if (isInt<16>(NegFrameSize)) {
|
|
||||||
BuildMI(MBB, MBBI, dl, TII.get(PPC::STDU), PPC::X1)
|
|
||||||
.addReg(PPC::X1)
|
|
||||||
.addImm(NegFrameSize / 4)
|
|
||||||
.addReg(PPC::X1);
|
|
||||||
} else {
|
|
||||||
BuildMI(MBB, MBBI, dl, TII.get(PPC::LIS8), PPC::X0)
|
|
||||||
.addImm(NegFrameSize >> 16);
|
|
||||||
BuildMI(MBB, MBBI, dl, TII.get(PPC::ORI8), PPC::X0)
|
|
||||||
.addReg(PPC::X0, RegState::Kill)
|
|
||||||
.addImm(NegFrameSize & 0xFFFF);
|
|
||||||
BuildMI(MBB, MBBI, dl, TII.get(PPC::STDUX))
|
|
||||||
.addReg(PPC::X1)
|
|
||||||
.addReg(PPC::X1)
|
|
||||||
.addReg(PPC::X0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<MachineMove> &Moves = MMI.getFrameMoves();
|
|
||||||
|
|
||||||
// Add the "machine moves" for the instructions we generated above, but in
|
|
||||||
// reverse order.
|
|
||||||
if (needsFrameMoves) {
|
|
||||||
// Mark effective beginning of when frame pointer becomes valid.
|
|
||||||
FrameLabel = MMI.getContext().CreateTempSymbol();
|
|
||||||
BuildMI(MBB, MBBI, dl, TII.get(PPC::PROLOG_LABEL)).addSym(FrameLabel);
|
|
||||||
|
|
||||||
// Show update of SP.
|
|
||||||
if (NegFrameSize) {
|
|
||||||
MachineLocation SPDst(MachineLocation::VirtualFP);
|
|
||||||
MachineLocation SPSrc(MachineLocation::VirtualFP, NegFrameSize);
|
|
||||||
Moves.push_back(MachineMove(FrameLabel, SPDst, SPSrc));
|
|
||||||
} else {
|
|
||||||
MachineLocation SP(isPPC64 ? PPC::X31 : PPC::R31);
|
|
||||||
Moves.push_back(MachineMove(FrameLabel, SP, SP));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (HasFP) {
|
|
||||||
MachineLocation FPDst(MachineLocation::VirtualFP, FPOffset);
|
|
||||||
MachineLocation FPSrc(isPPC64 ? PPC::X31 : PPC::R31);
|
|
||||||
Moves.push_back(MachineMove(FrameLabel, FPDst, FPSrc));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (MustSaveLR) {
|
|
||||||
MachineLocation LRDst(MachineLocation::VirtualFP, LROffset);
|
|
||||||
MachineLocation LRSrc(isPPC64 ? PPC::LR8 : PPC::LR);
|
|
||||||
Moves.push_back(MachineMove(FrameLabel, LRDst, LRSrc));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
MCSymbol *ReadyLabel = 0;
|
|
||||||
|
|
||||||
// If there is a frame pointer, copy R1 into R31
|
|
||||||
if (HasFP) {
|
|
||||||
if (!isPPC64) {
|
|
||||||
BuildMI(MBB, MBBI, dl, TII.get(PPC::OR), PPC::R31)
|
|
||||||
.addReg(PPC::R1)
|
|
||||||
.addReg(PPC::R1);
|
|
||||||
} else {
|
|
||||||
BuildMI(MBB, MBBI, dl, TII.get(PPC::OR8), PPC::X31)
|
|
||||||
.addReg(PPC::X1)
|
|
||||||
.addReg(PPC::X1);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (needsFrameMoves) {
|
|
||||||
ReadyLabel = MMI.getContext().CreateTempSymbol();
|
|
||||||
|
|
||||||
// Mark effective beginning of when frame pointer is ready.
|
|
||||||
BuildMI(MBB, MBBI, dl, TII.get(PPC::PROLOG_LABEL)).addSym(ReadyLabel);
|
|
||||||
|
|
||||||
MachineLocation FPDst(HasFP ? (isPPC64 ? PPC::X31 : PPC::R31) :
|
|
||||||
(isPPC64 ? PPC::X1 : PPC::R1));
|
|
||||||
MachineLocation FPSrc(MachineLocation::VirtualFP);
|
|
||||||
Moves.push_back(MachineMove(ReadyLabel, FPDst, FPSrc));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (needsFrameMoves) {
|
|
||||||
MCSymbol *Label = HasFP ? ReadyLabel : FrameLabel;
|
|
||||||
|
|
||||||
// Add callee saved registers to move list.
|
|
||||||
const std::vector<CalleeSavedInfo> &CSI = MFI->getCalleeSavedInfo();
|
|
||||||
for (unsigned I = 0, E = CSI.size(); I != E; ++I) {
|
|
||||||
int Offset = MFI->getObjectOffset(CSI[I].getFrameIdx());
|
|
||||||
unsigned Reg = CSI[I].getReg();
|
|
||||||
if (Reg == PPC::LR || Reg == PPC::LR8 || Reg == PPC::RM) continue;
|
|
||||||
MachineLocation CSDst(MachineLocation::VirtualFP, Offset);
|
|
||||||
MachineLocation CSSrc(Reg);
|
|
||||||
Moves.push_back(MachineMove(Label, CSDst, CSSrc));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void PPCRegisterInfo::emitEpilogue(MachineFunction &MF,
|
|
||||||
MachineBasicBlock &MBB) const {
|
|
||||||
MachineBasicBlock::iterator MBBI = prior(MBB.end());
|
|
||||||
unsigned RetOpcode = MBBI->getOpcode();
|
|
||||||
DebugLoc dl;
|
|
||||||
|
|
||||||
assert( (RetOpcode == PPC::BLR ||
|
|
||||||
RetOpcode == PPC::TCRETURNri ||
|
|
||||||
RetOpcode == PPC::TCRETURNdi ||
|
|
||||||
RetOpcode == PPC::TCRETURNai ||
|
|
||||||
RetOpcode == PPC::TCRETURNri8 ||
|
|
||||||
RetOpcode == PPC::TCRETURNdi8 ||
|
|
||||||
RetOpcode == PPC::TCRETURNai8) &&
|
|
||||||
"Can only insert epilog into returning blocks");
|
|
||||||
|
|
||||||
// Get alignment info so we know how to restore r1
|
|
||||||
const MachineFrameInfo *MFI = MF.getFrameInfo();
|
|
||||||
unsigned TargetAlign = MF.getTarget().getFrameInfo()->getStackAlignment();
|
|
||||||
unsigned MaxAlign = MFI->getMaxAlignment();
|
|
||||||
|
|
||||||
// Get the number of bytes allocated from the FrameInfo.
|
|
||||||
int FrameSize = MFI->getStackSize();
|
|
||||||
|
|
||||||
// Get processor type.
|
|
||||||
bool isPPC64 = Subtarget.isPPC64();
|
|
||||||
// Get operating system
|
|
||||||
bool isDarwinABI = Subtarget.isDarwinABI();
|
|
||||||
// Check if the link register (LR) has been saved.
|
|
||||||
PPCFunctionInfo *FI = MF.getInfo<PPCFunctionInfo>();
|
|
||||||
bool MustSaveLR = FI->mustSaveLR();
|
|
||||||
// Do we have a frame pointer for this function?
|
|
||||||
bool HasFP = hasFP(MF) && FrameSize;
|
|
||||||
|
|
||||||
int LROffset = PPCFrameInfo::getReturnSaveOffset(isPPC64, isDarwinABI);
|
|
||||||
|
|
||||||
int FPOffset = 0;
|
|
||||||
if (HasFP) {
|
|
||||||
if (Subtarget.isSVR4ABI()) {
|
|
||||||
MachineFrameInfo *FFI = MF.getFrameInfo();
|
|
||||||
int FPIndex = FI->getFramePointerSaveIndex();
|
|
||||||
assert(FPIndex && "No Frame Pointer Save Slot!");
|
|
||||||
FPOffset = FFI->getObjectOffset(FPIndex);
|
|
||||||
} else {
|
|
||||||
FPOffset = PPCFrameInfo::getFramePointerSaveOffset(isPPC64, isDarwinABI);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool UsesTCRet = RetOpcode == PPC::TCRETURNri ||
|
|
||||||
RetOpcode == PPC::TCRETURNdi ||
|
|
||||||
RetOpcode == PPC::TCRETURNai ||
|
|
||||||
RetOpcode == PPC::TCRETURNri8 ||
|
|
||||||
RetOpcode == PPC::TCRETURNdi8 ||
|
|
||||||
RetOpcode == PPC::TCRETURNai8;
|
|
||||||
|
|
||||||
if (UsesTCRet) {
|
|
||||||
int MaxTCRetDelta = FI->getTailCallSPDelta();
|
|
||||||
MachineOperand &StackAdjust = MBBI->getOperand(1);
|
|
||||||
assert(StackAdjust.isImm() && "Expecting immediate value.");
|
|
||||||
// Adjust stack pointer.
|
|
||||||
int StackAdj = StackAdjust.getImm();
|
|
||||||
int Delta = StackAdj - MaxTCRetDelta;
|
|
||||||
assert((Delta >= 0) && "Delta must be positive");
|
|
||||||
if (MaxTCRetDelta>0)
|
|
||||||
FrameSize += (StackAdj +Delta);
|
|
||||||
else
|
|
||||||
FrameSize += StackAdj;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (FrameSize) {
|
|
||||||
// The loaded (or persistent) stack pointer value is offset by the 'stwu'
|
|
||||||
// on entry to the function. Add this offset back now.
|
|
||||||
if (!isPPC64) {
|
|
||||||
// If this function contained a fastcc call and GuaranteedTailCallOpt is
|
|
||||||
// enabled (=> hasFastCall()==true) the fastcc call might contain a tail
|
|
||||||
// call which invalidates the stack pointer value in SP(0). So we use the
|
|
||||||
// value of R31 in this case.
|
|
||||||
if (FI->hasFastCall() && isInt<16>(FrameSize)) {
|
|
||||||
assert(hasFP(MF) && "Expecting a valid the frame pointer.");
|
|
||||||
BuildMI(MBB, MBBI, dl, TII.get(PPC::ADDI), PPC::R1)
|
|
||||||
.addReg(PPC::R31).addImm(FrameSize);
|
|
||||||
} else if(FI->hasFastCall()) {
|
|
||||||
BuildMI(MBB, MBBI, dl, TII.get(PPC::LIS), PPC::R0)
|
|
||||||
.addImm(FrameSize >> 16);
|
|
||||||
BuildMI(MBB, MBBI, dl, TII.get(PPC::ORI), PPC::R0)
|
|
||||||
.addReg(PPC::R0, RegState::Kill)
|
|
||||||
.addImm(FrameSize & 0xFFFF);
|
|
||||||
BuildMI(MBB, MBBI, dl, TII.get(PPC::ADD4))
|
|
||||||
.addReg(PPC::R1)
|
|
||||||
.addReg(PPC::R31)
|
|
||||||
.addReg(PPC::R0);
|
|
||||||
} else if (isInt<16>(FrameSize) &&
|
|
||||||
(!ALIGN_STACK || TargetAlign >= MaxAlign) &&
|
|
||||||
!MFI->hasVarSizedObjects()) {
|
|
||||||
BuildMI(MBB, MBBI, dl, TII.get(PPC::ADDI), PPC::R1)
|
|
||||||
.addReg(PPC::R1).addImm(FrameSize);
|
|
||||||
} else {
|
|
||||||
BuildMI(MBB, MBBI, dl, TII.get(PPC::LWZ),PPC::R1)
|
|
||||||
.addImm(0).addReg(PPC::R1);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (FI->hasFastCall() && isInt<16>(FrameSize)) {
|
|
||||||
assert(hasFP(MF) && "Expecting a valid the frame pointer.");
|
|
||||||
BuildMI(MBB, MBBI, dl, TII.get(PPC::ADDI8), PPC::X1)
|
|
||||||
.addReg(PPC::X31).addImm(FrameSize);
|
|
||||||
} else if(FI->hasFastCall()) {
|
|
||||||
BuildMI(MBB, MBBI, dl, TII.get(PPC::LIS8), PPC::X0)
|
|
||||||
.addImm(FrameSize >> 16);
|
|
||||||
BuildMI(MBB, MBBI, dl, TII.get(PPC::ORI8), PPC::X0)
|
|
||||||
.addReg(PPC::X0, RegState::Kill)
|
|
||||||
.addImm(FrameSize & 0xFFFF);
|
|
||||||
BuildMI(MBB, MBBI, dl, TII.get(PPC::ADD8))
|
|
||||||
.addReg(PPC::X1)
|
|
||||||
.addReg(PPC::X31)
|
|
||||||
.addReg(PPC::X0);
|
|
||||||
} else if (isInt<16>(FrameSize) && TargetAlign >= MaxAlign &&
|
|
||||||
!MFI->hasVarSizedObjects()) {
|
|
||||||
BuildMI(MBB, MBBI, dl, TII.get(PPC::ADDI8), PPC::X1)
|
|
||||||
.addReg(PPC::X1).addImm(FrameSize);
|
|
||||||
} else {
|
|
||||||
BuildMI(MBB, MBBI, dl, TII.get(PPC::LD), PPC::X1)
|
|
||||||
.addImm(0).addReg(PPC::X1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isPPC64) {
|
|
||||||
if (MustSaveLR)
|
|
||||||
BuildMI(MBB, MBBI, dl, TII.get(PPC::LD), PPC::X0)
|
|
||||||
.addImm(LROffset/4).addReg(PPC::X1);
|
|
||||||
|
|
||||||
if (HasFP)
|
|
||||||
BuildMI(MBB, MBBI, dl, TII.get(PPC::LD), PPC::X31)
|
|
||||||
.addImm(FPOffset/4).addReg(PPC::X1);
|
|
||||||
|
|
||||||
if (MustSaveLR)
|
|
||||||
BuildMI(MBB, MBBI, dl, TII.get(PPC::MTLR8)).addReg(PPC::X0);
|
|
||||||
} else {
|
|
||||||
if (MustSaveLR)
|
|
||||||
BuildMI(MBB, MBBI, dl, TII.get(PPC::LWZ), PPC::R0)
|
|
||||||
.addImm(LROffset).addReg(PPC::R1);
|
|
||||||
|
|
||||||
if (HasFP)
|
|
||||||
BuildMI(MBB, MBBI, dl, TII.get(PPC::LWZ), PPC::R31)
|
|
||||||
.addImm(FPOffset).addReg(PPC::R1);
|
|
||||||
|
|
||||||
if (MustSaveLR)
|
|
||||||
BuildMI(MBB, MBBI, dl, TII.get(PPC::MTLR)).addReg(PPC::R0);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Callee pop calling convention. Pop parameter/linkage area. Used for tail
|
|
||||||
// call optimization
|
|
||||||
if (GuaranteedTailCallOpt && RetOpcode == PPC::BLR &&
|
|
||||||
MF.getFunction()->getCallingConv() == CallingConv::Fast) {
|
|
||||||
PPCFunctionInfo *FI = MF.getInfo<PPCFunctionInfo>();
|
|
||||||
unsigned CallerAllocatedAmt = FI->getMinReservedArea();
|
|
||||||
unsigned StackReg = isPPC64 ? PPC::X1 : PPC::R1;
|
|
||||||
unsigned FPReg = isPPC64 ? PPC::X31 : PPC::R31;
|
|
||||||
unsigned TmpReg = isPPC64 ? PPC::X0 : PPC::R0;
|
|
||||||
unsigned ADDIInstr = isPPC64 ? PPC::ADDI8 : PPC::ADDI;
|
|
||||||
unsigned ADDInstr = isPPC64 ? PPC::ADD8 : PPC::ADD4;
|
|
||||||
unsigned LISInstr = isPPC64 ? PPC::LIS8 : PPC::LIS;
|
|
||||||
unsigned ORIInstr = isPPC64 ? PPC::ORI8 : PPC::ORI;
|
|
||||||
|
|
||||||
if (CallerAllocatedAmt && isInt<16>(CallerAllocatedAmt)) {
|
|
||||||
BuildMI(MBB, MBBI, dl, TII.get(ADDIInstr), StackReg)
|
|
||||||
.addReg(StackReg).addImm(CallerAllocatedAmt);
|
|
||||||
} else {
|
|
||||||
BuildMI(MBB, MBBI, dl, TII.get(LISInstr), TmpReg)
|
|
||||||
.addImm(CallerAllocatedAmt >> 16);
|
|
||||||
BuildMI(MBB, MBBI, dl, TII.get(ORIInstr), TmpReg)
|
|
||||||
.addReg(TmpReg, RegState::Kill)
|
|
||||||
.addImm(CallerAllocatedAmt & 0xFFFF);
|
|
||||||
BuildMI(MBB, MBBI, dl, TII.get(ADDInstr))
|
|
||||||
.addReg(StackReg)
|
|
||||||
.addReg(FPReg)
|
|
||||||
.addReg(TmpReg);
|
|
||||||
}
|
|
||||||
} else if (RetOpcode == PPC::TCRETURNdi) {
|
|
||||||
MBBI = prior(MBB.end());
|
|
||||||
MachineOperand &JumpTarget = MBBI->getOperand(0);
|
|
||||||
BuildMI(MBB, MBBI, dl, TII.get(PPC::TAILB)).
|
|
||||||
addGlobalAddress(JumpTarget.getGlobal(), JumpTarget.getOffset());
|
|
||||||
} else if (RetOpcode == PPC::TCRETURNri) {
|
|
||||||
MBBI = prior(MBB.end());
|
|
||||||
assert(MBBI->getOperand(0).isReg() && "Expecting register operand.");
|
|
||||||
BuildMI(MBB, MBBI, dl, TII.get(PPC::TAILBCTR));
|
|
||||||
} else if (RetOpcode == PPC::TCRETURNai) {
|
|
||||||
MBBI = prior(MBB.end());
|
|
||||||
MachineOperand &JumpTarget = MBBI->getOperand(0);
|
|
||||||
BuildMI(MBB, MBBI, dl, TII.get(PPC::TAILBA)).addImm(JumpTarget.getImm());
|
|
||||||
} else if (RetOpcode == PPC::TCRETURNdi8) {
|
|
||||||
MBBI = prior(MBB.end());
|
|
||||||
MachineOperand &JumpTarget = MBBI->getOperand(0);
|
|
||||||
BuildMI(MBB, MBBI, dl, TII.get(PPC::TAILB8)).
|
|
||||||
addGlobalAddress(JumpTarget.getGlobal(), JumpTarget.getOffset());
|
|
||||||
} else if (RetOpcode == PPC::TCRETURNri8) {
|
|
||||||
MBBI = prior(MBB.end());
|
|
||||||
assert(MBBI->getOperand(0).isReg() && "Expecting register operand.");
|
|
||||||
BuildMI(MBB, MBBI, dl, TII.get(PPC::TAILBCTR8));
|
|
||||||
} else if (RetOpcode == PPC::TCRETURNai8) {
|
|
||||||
MBBI = prior(MBB.end());
|
|
||||||
MachineOperand &JumpTarget = MBBI->getOperand(0);
|
|
||||||
BuildMI(MBB, MBBI, dl, TII.get(PPC::TAILBA8)).addImm(JumpTarget.getImm());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned PPCRegisterInfo::getRARegister() const {
|
unsigned PPCRegisterInfo::getRARegister() const {
|
||||||
return !Subtarget.isPPC64() ? PPC::LR : PPC::LR8;
|
return !Subtarget.isPPC64() ? PPC::LR : PPC::LR8;
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,11 +44,6 @@ public:
|
||||||
|
|
||||||
BitVector getReservedRegs(const MachineFunction &MF) const;
|
BitVector getReservedRegs(const MachineFunction &MF) const;
|
||||||
|
|
||||||
/// targetHandlesStackFrameRounding - Returns true if the target is
|
|
||||||
/// responsible for rounding up the stack frame (probably at emitPrologue
|
|
||||||
/// time).
|
|
||||||
bool targetHandlesStackFrameRounding() const { return true; }
|
|
||||||
|
|
||||||
/// requiresRegisterScavenging - We require a register scavenger.
|
/// requiresRegisterScavenging - We require a register scavenger.
|
||||||
/// FIXME (64-bit): Should be inlined.
|
/// FIXME (64-bit): Should be inlined.
|
||||||
bool requiresRegisterScavenging(const MachineFunction &MF) const;
|
bool requiresRegisterScavenging(const MachineFunction &MF) const;
|
||||||
|
@ -66,10 +61,6 @@ public:
|
||||||
void eliminateFrameIndex(MachineBasicBlock::iterator II,
|
void eliminateFrameIndex(MachineBasicBlock::iterator II,
|
||||||
int SPAdj, RegScavenger *RS = NULL) const;
|
int SPAdj, RegScavenger *RS = NULL) const;
|
||||||
|
|
||||||
/// determineFrameLayout - Determine the size of the frame and maximum call
|
|
||||||
/// frame size.
|
|
||||||
void determineFrameLayout(MachineFunction &MF) const;
|
|
||||||
|
|
||||||
void processFunctionBeforeCalleeSavedScan(MachineFunction &MF,
|
void processFunctionBeforeCalleeSavedScan(MachineFunction &MF,
|
||||||
RegScavenger *RS = NULL) const;
|
RegScavenger *RS = NULL) const;
|
||||||
void processFunctionBeforeFrameFinalized(MachineFunction &MF) const;
|
void processFunctionBeforeFrameFinalized(MachineFunction &MF) const;
|
||||||
|
|
|
@ -44,7 +44,7 @@ PPCTargetMachine::PPCTargetMachine(const Target &T, const std::string &TT,
|
||||||
: LLVMTargetMachine(T, TT),
|
: LLVMTargetMachine(T, TT),
|
||||||
Subtarget(TT, FS, is64Bit),
|
Subtarget(TT, FS, is64Bit),
|
||||||
DataLayout(Subtarget.getTargetDataString()), InstrInfo(*this),
|
DataLayout(Subtarget.getTargetDataString()), InstrInfo(*this),
|
||||||
FrameInfo(*this, is64Bit), JITInfo(*this, is64Bit),
|
FrameInfo(Subtarget), JITInfo(*this, is64Bit),
|
||||||
TLInfo(*this), TSInfo(*this),
|
TLInfo(*this), TSInfo(*this),
|
||||||
InstrItins(Subtarget.getInstrItineraryData()) {
|
InstrItins(Subtarget.getInstrItineraryData()) {
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,80 @@
|
||||||
|
//=======- SparcFrameInfo.cpp - Sparc Frame Information --------*- C++ -*-====//
|
||||||
|
//
|
||||||
|
// The LLVM Compiler Infrastructure
|
||||||
|
//
|
||||||
|
// This file is distributed under the University of Illinois Open Source
|
||||||
|
// License. See LICENSE.TXT for details.
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
//
|
||||||
|
// This file contains the Sparc implementation of TargetFrameInfo class.
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
#include "SparcFrameInfo.h"
|
||||||
|
#include "SparcInstrInfo.h"
|
||||||
|
#include "SparcMachineFunctionInfo.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;
|
||||||
|
|
||||||
|
void SparcFrameInfo::emitPrologue(MachineFunction &MF) const {
|
||||||
|
MachineBasicBlock &MBB = MF.front();
|
||||||
|
MachineFrameInfo *MFI = MF.getFrameInfo();
|
||||||
|
const SparcInstrInfo &TII =
|
||||||
|
*static_cast<const SparcInstrInfo*>(MF.getTarget().getInstrInfo());
|
||||||
|
MachineBasicBlock::iterator MBBI = MBB.begin();
|
||||||
|
DebugLoc dl = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc();
|
||||||
|
|
||||||
|
// Get the number of bytes to allocate from the FrameInfo
|
||||||
|
int NumBytes = (int) MFI->getStackSize();
|
||||||
|
|
||||||
|
// Emit the correct save instruction based on the number of bytes in
|
||||||
|
// the frame. Minimum stack frame size according to V8 ABI is:
|
||||||
|
// 16 words for register window spill
|
||||||
|
// 1 word for address of returned aggregate-value
|
||||||
|
// + 6 words for passing parameters on the stack
|
||||||
|
// ----------
|
||||||
|
// 23 words * 4 bytes per word = 92 bytes
|
||||||
|
NumBytes += 92;
|
||||||
|
|
||||||
|
// Round up to next doubleword boundary -- a double-word boundary
|
||||||
|
// is required by the ABI.
|
||||||
|
NumBytes = (NumBytes + 7) & ~7;
|
||||||
|
NumBytes = -NumBytes;
|
||||||
|
|
||||||
|
if (NumBytes >= -4096) {
|
||||||
|
BuildMI(MBB, MBBI, dl, TII.get(SP::SAVEri), SP::O6)
|
||||||
|
.addReg(SP::O6).addImm(NumBytes);
|
||||||
|
} else {
|
||||||
|
// Emit this the hard way. This clobbers G1 which we always know is
|
||||||
|
// available here.
|
||||||
|
unsigned OffHi = (unsigned)NumBytes >> 10U;
|
||||||
|
BuildMI(MBB, MBBI, dl, TII.get(SP::SETHIi), SP::G1).addImm(OffHi);
|
||||||
|
// Emit G1 = G1 + I6
|
||||||
|
BuildMI(MBB, MBBI, dl, TII.get(SP::ORri), SP::G1)
|
||||||
|
.addReg(SP::G1).addImm(NumBytes & ((1 << 10)-1));
|
||||||
|
BuildMI(MBB, MBBI, dl, TII.get(SP::SAVErr), SP::O6)
|
||||||
|
.addReg(SP::O6).addReg(SP::G1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SparcFrameInfo::emitEpilogue(MachineFunction &MF,
|
||||||
|
MachineBasicBlock &MBB) const {
|
||||||
|
MachineBasicBlock::iterator MBBI = prior(MBB.end());
|
||||||
|
const SparcInstrInfo &TII =
|
||||||
|
*static_cast<const SparcInstrInfo*>(MF.getTarget().getInstrInfo());
|
||||||
|
DebugLoc dl = MBBI->getDebugLoc();
|
||||||
|
assert(MBBI->getOpcode() == SP::RETL &&
|
||||||
|
"Can only put epilog before 'retl' instruction!");
|
||||||
|
BuildMI(MBB, MBBI, dl, TII.get(SP::RESTORErr), SP::G0).addReg(SP::G0)
|
||||||
|
.addReg(SP::G0);
|
||||||
|
}
|
|
@ -0,0 +1,39 @@
|
||||||
|
//===--- SparcFrameInfo.h - Define TargetFrameInfo for Sparc --*- C++ -*---===//
|
||||||
|
//
|
||||||
|
// The LLVM Compiler Infrastructure
|
||||||
|
//
|
||||||
|
// This file is distributed under the University of Illinois Open Source
|
||||||
|
// License. See LICENSE.TXT for details.
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
#ifndef SPARC_FRAMEINFO_H
|
||||||
|
#define SPARC_FRAMEINFO_H
|
||||||
|
|
||||||
|
#include "Sparc.h"
|
||||||
|
#include "SparcSubtarget.h"
|
||||||
|
#include "llvm/Target/TargetFrameInfo.h"
|
||||||
|
|
||||||
|
namespace llvm {
|
||||||
|
class SparcSubtarget;
|
||||||
|
|
||||||
|
class SparcFrameInfo : public TargetFrameInfo {
|
||||||
|
const SparcSubtarget &STI;
|
||||||
|
public:
|
||||||
|
explicit SparcFrameInfo(const SparcSubtarget &sti)
|
||||||
|
: TargetFrameInfo(TargetFrameInfo::StackGrowsDown, 8, 0), STI(sti) {
|
||||||
|
}
|
||||||
|
|
||||||
|
/// emitProlog/emitEpilog - These methods insert prolog and epilog code into
|
||||||
|
/// the function.
|
||||||
|
void emitPrologue(MachineFunction &MF) const;
|
||||||
|
void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // End llvm namespace
|
||||||
|
|
||||||
|
#endif
|
|
@ -112,55 +112,6 @@ SparcRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
|
||||||
void SparcRegisterInfo::
|
void SparcRegisterInfo::
|
||||||
processFunctionBeforeFrameFinalized(MachineFunction &MF) const {}
|
processFunctionBeforeFrameFinalized(MachineFunction &MF) const {}
|
||||||
|
|
||||||
void SparcRegisterInfo::emitPrologue(MachineFunction &MF) const {
|
|
||||||
MachineBasicBlock &MBB = MF.front();
|
|
||||||
MachineFrameInfo *MFI = MF.getFrameInfo();
|
|
||||||
MachineBasicBlock::iterator MBBI = MBB.begin();
|
|
||||||
DebugLoc dl = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc();
|
|
||||||
|
|
||||||
// Get the number of bytes to allocate from the FrameInfo
|
|
||||||
int NumBytes = (int) MFI->getStackSize();
|
|
||||||
|
|
||||||
// Emit the correct save instruction based on the number of bytes in
|
|
||||||
// the frame. Minimum stack frame size according to V8 ABI is:
|
|
||||||
// 16 words for register window spill
|
|
||||||
// 1 word for address of returned aggregate-value
|
|
||||||
// + 6 words for passing parameters on the stack
|
|
||||||
// ----------
|
|
||||||
// 23 words * 4 bytes per word = 92 bytes
|
|
||||||
NumBytes += 92;
|
|
||||||
|
|
||||||
// Round up to next doubleword boundary -- a double-word boundary
|
|
||||||
// is required by the ABI.
|
|
||||||
NumBytes = (NumBytes + 7) & ~7;
|
|
||||||
NumBytes = -NumBytes;
|
|
||||||
|
|
||||||
if (NumBytes >= -4096) {
|
|
||||||
BuildMI(MBB, MBBI, dl, TII.get(SP::SAVEri), SP::O6)
|
|
||||||
.addReg(SP::O6).addImm(NumBytes);
|
|
||||||
} else {
|
|
||||||
// Emit this the hard way. This clobbers G1 which we always know is
|
|
||||||
// available here.
|
|
||||||
unsigned OffHi = (unsigned)NumBytes >> 10U;
|
|
||||||
BuildMI(MBB, MBBI, dl, TII.get(SP::SETHIi), SP::G1).addImm(OffHi);
|
|
||||||
// Emit G1 = G1 + I6
|
|
||||||
BuildMI(MBB, MBBI, dl, TII.get(SP::ORri), SP::G1)
|
|
||||||
.addReg(SP::G1).addImm(NumBytes & ((1 << 10)-1));
|
|
||||||
BuildMI(MBB, MBBI, dl, TII.get(SP::SAVErr), SP::O6)
|
|
||||||
.addReg(SP::O6).addReg(SP::G1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void SparcRegisterInfo::emitEpilogue(MachineFunction &MF,
|
|
||||||
MachineBasicBlock &MBB) const {
|
|
||||||
MachineBasicBlock::iterator MBBI = prior(MBB.end());
|
|
||||||
DebugLoc dl = MBBI->getDebugLoc();
|
|
||||||
assert(MBBI->getOpcode() == SP::RETL &&
|
|
||||||
"Can only put epilog before 'retl' instruction!");
|
|
||||||
BuildMI(MBB, MBBI, dl, TII.get(SP::RESTORErr), SP::G0).addReg(SP::G0)
|
|
||||||
.addReg(SP::G0);
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned SparcRegisterInfo::getRARegister() const {
|
unsigned SparcRegisterInfo::getRARegister() const {
|
||||||
return SP::I7;
|
return SP::I7;
|
||||||
}
|
}
|
||||||
|
|
|
@ -45,9 +45,6 @@ struct SparcRegisterInfo : public SparcGenRegisterInfo {
|
||||||
|
|
||||||
void processFunctionBeforeFrameFinalized(MachineFunction &MF) const;
|
void processFunctionBeforeFrameFinalized(MachineFunction &MF) const;
|
||||||
|
|
||||||
void emitPrologue(MachineFunction &MF) const;
|
|
||||||
void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const;
|
|
||||||
|
|
||||||
// Debug information queries.
|
// Debug information queries.
|
||||||
unsigned getRARegister() const;
|
unsigned getRARegister() const;
|
||||||
unsigned getFrameRegister(const MachineFunction &MF) const;
|
unsigned getFrameRegister(const MachineFunction &MF) const;
|
||||||
|
|
|
@ -10,9 +10,9 @@
|
||||||
//
|
//
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
#include "Sparc.h"
|
||||||
#include "SparcMCAsmInfo.h"
|
#include "SparcMCAsmInfo.h"
|
||||||
#include "SparcTargetMachine.h"
|
#include "SparcTargetMachine.h"
|
||||||
#include "Sparc.h"
|
|
||||||
#include "llvm/PassManager.h"
|
#include "llvm/PassManager.h"
|
||||||
#include "llvm/Target/TargetRegistry.h"
|
#include "llvm/Target/TargetRegistry.h"
|
||||||
using namespace llvm;
|
using namespace llvm;
|
||||||
|
@ -34,8 +34,8 @@ SparcTargetMachine::SparcTargetMachine(const Target &T, const std::string &TT,
|
||||||
: LLVMTargetMachine(T, TT),
|
: LLVMTargetMachine(T, TT),
|
||||||
Subtarget(TT, FS, is64bit),
|
Subtarget(TT, FS, is64bit),
|
||||||
DataLayout(Subtarget.getDataLayout()),
|
DataLayout(Subtarget.getDataLayout()),
|
||||||
TLInfo(*this), TSInfo(*this), InstrInfo(Subtarget),
|
TLInfo(*this), TSInfo(*this), InstrInfo(Subtarget),
|
||||||
FrameInfo(TargetFrameInfo::StackGrowsDown, 8, 0) {
|
FrameInfo(Subtarget) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SparcTargetMachine::addInstSelector(PassManagerBase &PM,
|
bool SparcTargetMachine::addInstSelector(PassManagerBase &PM,
|
||||||
|
|
|
@ -14,13 +14,14 @@
|
||||||
#ifndef SPARCTARGETMACHINE_H
|
#ifndef SPARCTARGETMACHINE_H
|
||||||
#define SPARCTARGETMACHINE_H
|
#define SPARCTARGETMACHINE_H
|
||||||
|
|
||||||
|
#include "SparcInstrInfo.h"
|
||||||
|
#include "SparcISelLowering.h"
|
||||||
|
#include "SparcFrameInfo.h"
|
||||||
|
#include "SparcSelectionDAGInfo.h"
|
||||||
|
#include "SparcSubtarget.h"
|
||||||
#include "llvm/Target/TargetMachine.h"
|
#include "llvm/Target/TargetMachine.h"
|
||||||
#include "llvm/Target/TargetData.h"
|
#include "llvm/Target/TargetData.h"
|
||||||
#include "llvm/Target/TargetFrameInfo.h"
|
#include "llvm/Target/TargetFrameInfo.h"
|
||||||
#include "SparcInstrInfo.h"
|
|
||||||
#include "SparcSubtarget.h"
|
|
||||||
#include "SparcISelLowering.h"
|
|
||||||
#include "SparcSelectionDAGInfo.h"
|
|
||||||
|
|
||||||
namespace llvm {
|
namespace llvm {
|
||||||
|
|
||||||
|
@ -30,7 +31,7 @@ class SparcTargetMachine : public LLVMTargetMachine {
|
||||||
SparcTargetLowering TLInfo;
|
SparcTargetLowering TLInfo;
|
||||||
SparcSelectionDAGInfo TSInfo;
|
SparcSelectionDAGInfo TSInfo;
|
||||||
SparcInstrInfo InstrInfo;
|
SparcInstrInfo InstrInfo;
|
||||||
TargetFrameInfo FrameInfo;
|
SparcFrameInfo FrameInfo;
|
||||||
public:
|
public:
|
||||||
SparcTargetMachine(const Target &T, const std::string &TT,
|
SparcTargetMachine(const Target &T, const std::string &TT,
|
||||||
const std::string &FS, bool is64bit);
|
const std::string &FS, bool is64bit);
|
||||||
|
|
|
@ -0,0 +1,171 @@
|
||||||
|
//=====- SystemZFrameInfo.cpp - SystemZ Frame Information ------*- C++ -*-====//
|
||||||
|
//
|
||||||
|
// The LLVM Compiler Infrastructure
|
||||||
|
//
|
||||||
|
// This file is distributed under the University of Illinois Open Source
|
||||||
|
// License. See LICENSE.TXT for details.
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
//
|
||||||
|
// This file contains the SystemZ implementation of TargetFrameInfo class.
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
#include "SystemZFrameInfo.h"
|
||||||
|
#include "SystemZInstrBuilder.h"
|
||||||
|
#include "SystemZInstrInfo.h"
|
||||||
|
#include "SystemZMachineFunctionInfo.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;
|
||||||
|
|
||||||
|
/// emitSPUpdate - Emit a series of instructions to increment / decrement the
|
||||||
|
/// stack pointer by a constant value.
|
||||||
|
static
|
||||||
|
void emitSPUpdate(MachineBasicBlock &MBB, MachineBasicBlock::iterator &MBBI,
|
||||||
|
int64_t NumBytes, const TargetInstrInfo &TII) {
|
||||||
|
unsigned Opc; uint64_t Chunk;
|
||||||
|
bool isSub = NumBytes < 0;
|
||||||
|
uint64_t Offset = isSub ? -NumBytes : NumBytes;
|
||||||
|
|
||||||
|
if (Offset >= (1LL << 15) - 1) {
|
||||||
|
Opc = SystemZ::ADD64ri32;
|
||||||
|
Chunk = (1LL << 31) - 1;
|
||||||
|
} else {
|
||||||
|
Opc = SystemZ::ADD64ri16;
|
||||||
|
Chunk = (1LL << 15) - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
DebugLoc DL = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc();
|
||||||
|
|
||||||
|
while (Offset) {
|
||||||
|
uint64_t ThisVal = (Offset > Chunk) ? Chunk : Offset;
|
||||||
|
MachineInstr *MI =
|
||||||
|
BuildMI(MBB, MBBI, DL, TII.get(Opc), SystemZ::R15D)
|
||||||
|
.addReg(SystemZ::R15D).addImm(isSub ? -ThisVal : ThisVal);
|
||||||
|
// The PSW implicit def is dead.
|
||||||
|
MI->getOperand(3).setIsDead();
|
||||||
|
Offset -= ThisVal;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SystemZFrameInfo::emitPrologue(MachineFunction &MF) const {
|
||||||
|
MachineBasicBlock &MBB = MF.front(); // Prolog goes in entry BB
|
||||||
|
const TargetFrameInfo &TFI = *MF.getTarget().getFrameInfo();
|
||||||
|
MachineFrameInfo *MFI = MF.getFrameInfo();
|
||||||
|
const SystemZRegisterInfo *RegInfo =
|
||||||
|
static_cast<const SystemZRegisterInfo*>(MF.getTarget().getRegisterInfo());
|
||||||
|
const SystemZInstrInfo &TII =
|
||||||
|
*static_cast<const SystemZInstrInfo*>(MF.getTarget().getInstrInfo());
|
||||||
|
SystemZMachineFunctionInfo *SystemZMFI =
|
||||||
|
MF.getInfo<SystemZMachineFunctionInfo>();
|
||||||
|
MachineBasicBlock::iterator MBBI = MBB.begin();
|
||||||
|
DebugLoc DL = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc();
|
||||||
|
|
||||||
|
// Get the number of bytes to allocate from the FrameInfo.
|
||||||
|
// Note that area for callee-saved stuff is already allocated, thus we need to
|
||||||
|
// 'undo' the stack movement.
|
||||||
|
uint64_t StackSize = MFI->getStackSize();
|
||||||
|
StackSize -= SystemZMFI->getCalleeSavedFrameSize();
|
||||||
|
|
||||||
|
uint64_t NumBytes = StackSize - TFI.getOffsetOfLocalArea();
|
||||||
|
|
||||||
|
// Skip the callee-saved push instructions.
|
||||||
|
while (MBBI != MBB.end() &&
|
||||||
|
(MBBI->getOpcode() == SystemZ::MOV64mr ||
|
||||||
|
MBBI->getOpcode() == SystemZ::MOV64mrm))
|
||||||
|
++MBBI;
|
||||||
|
|
||||||
|
if (MBBI != MBB.end())
|
||||||
|
DL = MBBI->getDebugLoc();
|
||||||
|
|
||||||
|
// adjust stack pointer: R15 -= numbytes
|
||||||
|
if (StackSize || MFI->hasCalls()) {
|
||||||
|
assert(MF.getRegInfo().isPhysRegUsed(SystemZ::R15D) &&
|
||||||
|
"Invalid stack frame calculation!");
|
||||||
|
emitSPUpdate(MBB, MBBI, -(int64_t)NumBytes, TII);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (RegInfo->hasFP(MF)) {
|
||||||
|
// Update R11 with the new base value...
|
||||||
|
BuildMI(MBB, MBBI, DL, TII.get(SystemZ::MOV64rr), SystemZ::R11D)
|
||||||
|
.addReg(SystemZ::R15D);
|
||||||
|
|
||||||
|
// Mark the FramePtr as live-in in every block except the entry.
|
||||||
|
for (MachineFunction::iterator I = llvm::next(MF.begin()), E = MF.end();
|
||||||
|
I != E; ++I)
|
||||||
|
I->addLiveIn(SystemZ::R11D);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SystemZFrameInfo::emitEpilogue(MachineFunction &MF,
|
||||||
|
MachineBasicBlock &MBB) const {
|
||||||
|
const MachineFrameInfo *MFI = MF.getFrameInfo();
|
||||||
|
const TargetFrameInfo &TFI = *MF.getTarget().getFrameInfo();
|
||||||
|
MachineBasicBlock::iterator MBBI = prior(MBB.end());
|
||||||
|
const SystemZInstrInfo &TII =
|
||||||
|
*static_cast<const SystemZInstrInfo*>(MF.getTarget().getInstrInfo());
|
||||||
|
SystemZMachineFunctionInfo *SystemZMFI =
|
||||||
|
MF.getInfo<SystemZMachineFunctionInfo>();
|
||||||
|
unsigned RetOpcode = MBBI->getOpcode();
|
||||||
|
|
||||||
|
switch (RetOpcode) {
|
||||||
|
case SystemZ::RET: break; // These are ok
|
||||||
|
default:
|
||||||
|
assert(0 && "Can only insert epilog into returning blocks");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the number of bytes to allocate from the FrameInfo
|
||||||
|
// Note that area for callee-saved stuff is already allocated, thus we need to
|
||||||
|
// 'undo' the stack movement.
|
||||||
|
uint64_t StackSize =
|
||||||
|
MFI->getStackSize() - SystemZMFI->getCalleeSavedFrameSize();
|
||||||
|
uint64_t NumBytes = StackSize - TFI.getOffsetOfLocalArea();
|
||||||
|
|
||||||
|
// Skip the final terminator instruction.
|
||||||
|
while (MBBI != MBB.begin()) {
|
||||||
|
MachineBasicBlock::iterator PI = prior(MBBI);
|
||||||
|
--MBBI;
|
||||||
|
if (!PI->getDesc().isTerminator())
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// During callee-saved restores emission stack frame was not yet finialized
|
||||||
|
// (and thus - the stack size was unknown). Tune the offset having full stack
|
||||||
|
// size in hands.
|
||||||
|
if (StackSize || MFI->hasCalls()) {
|
||||||
|
assert((MBBI->getOpcode() == SystemZ::MOV64rmm ||
|
||||||
|
MBBI->getOpcode() == SystemZ::MOV64rm) &&
|
||||||
|
"Expected to see callee-save register restore code");
|
||||||
|
assert(MF.getRegInfo().isPhysRegUsed(SystemZ::R15D) &&
|
||||||
|
"Invalid stack frame calculation!");
|
||||||
|
|
||||||
|
unsigned i = 0;
|
||||||
|
MachineInstr &MI = *MBBI;
|
||||||
|
while (!MI.getOperand(i).isImm()) {
|
||||||
|
++i;
|
||||||
|
assert(i < MI.getNumOperands() && "Unexpected restore code!");
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t Offset = NumBytes + MI.getOperand(i).getImm();
|
||||||
|
// If Offset does not fit into 20-bit signed displacement field we need to
|
||||||
|
// emit some additional code...
|
||||||
|
if (Offset > 524287) {
|
||||||
|
// Fold the displacement into load instruction as much as possible.
|
||||||
|
NumBytes = Offset - 524287;
|
||||||
|
Offset = 524287;
|
||||||
|
emitSPUpdate(MBB, MBBI, NumBytes, TII);
|
||||||
|
}
|
||||||
|
|
||||||
|
MI.getOperand(i).ChangeToImmediate(Offset);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,41 @@
|
||||||
|
//==- SystemZFrameInfo.h - Define TargetFrameInfo for z/System --*- C++ -*--==//
|
||||||
|
//
|
||||||
|
// The LLVM Compiler Infrastructure
|
||||||
|
//
|
||||||
|
// This file is distributed under the University of Illinois Open Source
|
||||||
|
// License. See LICENSE.TXT for details.
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
#ifndef SYSTEMZ_FRAMEINFO_H
|
||||||
|
#define SYSTEMZ_FRAMEINFO_H
|
||||||
|
|
||||||
|
#include "SystemZ.h"
|
||||||
|
#include "SystemZSubtarget.h"
|
||||||
|
#include "llvm/Target/TargetFrameInfo.h"
|
||||||
|
|
||||||
|
namespace llvm {
|
||||||
|
class SystemZSubtarget;
|
||||||
|
|
||||||
|
class SystemZFrameInfo : public TargetFrameInfo {
|
||||||
|
protected:
|
||||||
|
const SystemZSubtarget &STI;
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit SystemZFrameInfo(const SystemZSubtarget &sti)
|
||||||
|
: TargetFrameInfo(TargetFrameInfo::StackGrowsDown, 8, -160), STI(sti) {
|
||||||
|
}
|
||||||
|
|
||||||
|
/// emitProlog/emitEpilog - These methods insert prolog and epilog code into
|
||||||
|
/// the function.
|
||||||
|
void emitPrologue(MachineFunction &MF) const;
|
||||||
|
void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // End llvm namespace
|
||||||
|
|
||||||
|
#endif
|
|
@ -160,143 +160,6 @@ SystemZRegisterInfo::processFunctionBeforeCalleeSavedScan(MachineFunction &MF,
|
||||||
MRI.setPhysRegUsed(SystemZ::R15D);
|
MRI.setPhysRegUsed(SystemZ::R15D);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// emitSPUpdate - Emit a series of instructions to increment / decrement the
|
|
||||||
/// stack pointer by a constant value.
|
|
||||||
static
|
|
||||||
void emitSPUpdate(MachineBasicBlock &MBB, MachineBasicBlock::iterator &MBBI,
|
|
||||||
int64_t NumBytes, const TargetInstrInfo &TII) {
|
|
||||||
unsigned Opc; uint64_t Chunk;
|
|
||||||
bool isSub = NumBytes < 0;
|
|
||||||
uint64_t Offset = isSub ? -NumBytes : NumBytes;
|
|
||||||
|
|
||||||
if (Offset >= (1LL << 15) - 1) {
|
|
||||||
Opc = SystemZ::ADD64ri32;
|
|
||||||
Chunk = (1LL << 31) - 1;
|
|
||||||
} else {
|
|
||||||
Opc = SystemZ::ADD64ri16;
|
|
||||||
Chunk = (1LL << 15) - 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
DebugLoc DL = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc();
|
|
||||||
|
|
||||||
while (Offset) {
|
|
||||||
uint64_t ThisVal = (Offset > Chunk) ? Chunk : Offset;
|
|
||||||
MachineInstr *MI =
|
|
||||||
BuildMI(MBB, MBBI, DL, TII.get(Opc), SystemZ::R15D)
|
|
||||||
.addReg(SystemZ::R15D).addImm(isSub ? -ThisVal : ThisVal);
|
|
||||||
// The PSW implicit def is dead.
|
|
||||||
MI->getOperand(3).setIsDead();
|
|
||||||
Offset -= ThisVal;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void SystemZRegisterInfo::emitPrologue(MachineFunction &MF) const {
|
|
||||||
MachineBasicBlock &MBB = MF.front(); // Prolog goes in entry BB
|
|
||||||
const TargetFrameInfo &TFI = *MF.getTarget().getFrameInfo();
|
|
||||||
MachineFrameInfo *MFI = MF.getFrameInfo();
|
|
||||||
SystemZMachineFunctionInfo *SystemZMFI =
|
|
||||||
MF.getInfo<SystemZMachineFunctionInfo>();
|
|
||||||
MachineBasicBlock::iterator MBBI = MBB.begin();
|
|
||||||
DebugLoc DL = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc();
|
|
||||||
|
|
||||||
// Get the number of bytes to allocate from the FrameInfo.
|
|
||||||
// Note that area for callee-saved stuff is already allocated, thus we need to
|
|
||||||
// 'undo' the stack movement.
|
|
||||||
uint64_t StackSize = MFI->getStackSize();
|
|
||||||
StackSize -= SystemZMFI->getCalleeSavedFrameSize();
|
|
||||||
|
|
||||||
uint64_t NumBytes = StackSize - TFI.getOffsetOfLocalArea();
|
|
||||||
|
|
||||||
// Skip the callee-saved push instructions.
|
|
||||||
while (MBBI != MBB.end() &&
|
|
||||||
(MBBI->getOpcode() == SystemZ::MOV64mr ||
|
|
||||||
MBBI->getOpcode() == SystemZ::MOV64mrm))
|
|
||||||
++MBBI;
|
|
||||||
|
|
||||||
if (MBBI != MBB.end())
|
|
||||||
DL = MBBI->getDebugLoc();
|
|
||||||
|
|
||||||
// adjust stack pointer: R15 -= numbytes
|
|
||||||
if (StackSize || MFI->hasCalls()) {
|
|
||||||
assert(MF.getRegInfo().isPhysRegUsed(SystemZ::R15D) &&
|
|
||||||
"Invalid stack frame calculation!");
|
|
||||||
emitSPUpdate(MBB, MBBI, -(int64_t)NumBytes, TII);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (hasFP(MF)) {
|
|
||||||
// Update R11 with the new base value...
|
|
||||||
BuildMI(MBB, MBBI, DL, TII.get(SystemZ::MOV64rr), SystemZ::R11D)
|
|
||||||
.addReg(SystemZ::R15D);
|
|
||||||
|
|
||||||
// Mark the FramePtr as live-in in every block except the entry.
|
|
||||||
for (MachineFunction::iterator I = llvm::next(MF.begin()), E = MF.end();
|
|
||||||
I != E; ++I)
|
|
||||||
I->addLiveIn(SystemZ::R11D);
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void SystemZRegisterInfo::emitEpilogue(MachineFunction &MF,
|
|
||||||
MachineBasicBlock &MBB) const {
|
|
||||||
const MachineFrameInfo *MFI = MF.getFrameInfo();
|
|
||||||
const TargetFrameInfo &TFI = *MF.getTarget().getFrameInfo();
|
|
||||||
MachineBasicBlock::iterator MBBI = prior(MBB.end());
|
|
||||||
SystemZMachineFunctionInfo *SystemZMFI =
|
|
||||||
MF.getInfo<SystemZMachineFunctionInfo>();
|
|
||||||
unsigned RetOpcode = MBBI->getOpcode();
|
|
||||||
|
|
||||||
switch (RetOpcode) {
|
|
||||||
case SystemZ::RET: break; // These are ok
|
|
||||||
default:
|
|
||||||
assert(0 && "Can only insert epilog into returning blocks");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get the number of bytes to allocate from the FrameInfo
|
|
||||||
// Note that area for callee-saved stuff is already allocated, thus we need to
|
|
||||||
// 'undo' the stack movement.
|
|
||||||
uint64_t StackSize =
|
|
||||||
MFI->getStackSize() - SystemZMFI->getCalleeSavedFrameSize();
|
|
||||||
uint64_t NumBytes = StackSize - TFI.getOffsetOfLocalArea();
|
|
||||||
|
|
||||||
// Skip the final terminator instruction.
|
|
||||||
while (MBBI != MBB.begin()) {
|
|
||||||
MachineBasicBlock::iterator PI = prior(MBBI);
|
|
||||||
--MBBI;
|
|
||||||
if (!PI->getDesc().isTerminator())
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// During callee-saved restores emission stack frame was not yet finialized
|
|
||||||
// (and thus - the stack size was unknown). Tune the offset having full stack
|
|
||||||
// size in hands.
|
|
||||||
if (StackSize || MFI->hasCalls()) {
|
|
||||||
assert((MBBI->getOpcode() == SystemZ::MOV64rmm ||
|
|
||||||
MBBI->getOpcode() == SystemZ::MOV64rm) &&
|
|
||||||
"Expected to see callee-save register restore code");
|
|
||||||
assert(MF.getRegInfo().isPhysRegUsed(SystemZ::R15D) &&
|
|
||||||
"Invalid stack frame calculation!");
|
|
||||||
|
|
||||||
unsigned i = 0;
|
|
||||||
MachineInstr &MI = *MBBI;
|
|
||||||
while (!MI.getOperand(i).isImm()) {
|
|
||||||
++i;
|
|
||||||
assert(i < MI.getNumOperands() && "Unexpected restore code!");
|
|
||||||
}
|
|
||||||
|
|
||||||
uint64_t Offset = NumBytes + MI.getOperand(i).getImm();
|
|
||||||
// If Offset does not fit into 20-bit signed displacement field we need to
|
|
||||||
// emit some additional code...
|
|
||||||
if (Offset > 524287) {
|
|
||||||
// Fold the displacement into load instruction as much as possible.
|
|
||||||
NumBytes = Offset - 524287;
|
|
||||||
Offset = 524287;
|
|
||||||
emitSPUpdate(MBB, MBBI, NumBytes, TII);
|
|
||||||
}
|
|
||||||
|
|
||||||
MI.getOperand(i).ChangeToImmediate(Offset);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned SystemZRegisterInfo::getRARegister() const {
|
unsigned SystemZRegisterInfo::getRARegister() const {
|
||||||
assert(0 && "What is the return address register");
|
assert(0 && "What is the return address register");
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -50,9 +50,6 @@ struct SystemZRegisterInfo : public SystemZGenRegisterInfo {
|
||||||
void processFunctionBeforeCalleeSavedScan(MachineFunction &MF,
|
void processFunctionBeforeCalleeSavedScan(MachineFunction &MF,
|
||||||
RegScavenger *RS) const;
|
RegScavenger *RS) const;
|
||||||
|
|
||||||
void emitPrologue(MachineFunction &MF) const;
|
|
||||||
void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const;
|
|
||||||
|
|
||||||
// Debug information queries.
|
// Debug information queries.
|
||||||
unsigned getRARegister() const;
|
unsigned getRARegister() const;
|
||||||
unsigned getFrameRegister(const MachineFunction &MF) const;
|
unsigned getFrameRegister(const MachineFunction &MF) const;
|
||||||
|
|
|
@ -30,7 +30,7 @@ SystemZTargetMachine::SystemZTargetMachine(const Target &T,
|
||||||
DataLayout("E-p:64:64:64-i8:8:16-i16:16:16-i32:32:32-i64:64:64-f32:32:32"
|
DataLayout("E-p:64:64:64-i8:8:16-i16:16:16-i32:32:32-i64:64:64-f32:32:32"
|
||||||
"-f64:64:64-f128:128:128-a0:16:16-n32:64"),
|
"-f64:64:64-f128:128:128-a0:16:16-n32:64"),
|
||||||
InstrInfo(*this), TLInfo(*this), TSInfo(*this),
|
InstrInfo(*this), TLInfo(*this), TSInfo(*this),
|
||||||
FrameInfo(TargetFrameInfo::StackGrowsDown, 8, -160) {
|
FrameInfo(Subtarget) {
|
||||||
|
|
||||||
if (getRelocationModel() == Reloc::Default)
|
if (getRelocationModel() == Reloc::Default)
|
||||||
setRelocationModel(Reloc::Static);
|
setRelocationModel(Reloc::Static);
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
|
|
||||||
#include "SystemZInstrInfo.h"
|
#include "SystemZInstrInfo.h"
|
||||||
#include "SystemZISelLowering.h"
|
#include "SystemZISelLowering.h"
|
||||||
|
#include "SystemZFrameInfo.h"
|
||||||
#include "SystemZSelectionDAGInfo.h"
|
#include "SystemZSelectionDAGInfo.h"
|
||||||
#include "SystemZRegisterInfo.h"
|
#include "SystemZRegisterInfo.h"
|
||||||
#include "SystemZSubtarget.h"
|
#include "SystemZSubtarget.h"
|
||||||
|
@ -34,10 +35,7 @@ class SystemZTargetMachine : public LLVMTargetMachine {
|
||||||
SystemZInstrInfo InstrInfo;
|
SystemZInstrInfo InstrInfo;
|
||||||
SystemZTargetLowering TLInfo;
|
SystemZTargetLowering TLInfo;
|
||||||
SystemZSelectionDAGInfo TSInfo;
|
SystemZSelectionDAGInfo TSInfo;
|
||||||
|
SystemZFrameInfo FrameInfo;
|
||||||
// SystemZ does not have any call stack frame, therefore not having
|
|
||||||
// any SystemZ specific FrameInfo class.
|
|
||||||
TargetFrameInfo FrameInfo;
|
|
||||||
public:
|
public:
|
||||||
SystemZTargetMachine(const Target &T, const std::string &TT,
|
SystemZTargetMachine(const Target &T, const std::string &TT,
|
||||||
const std::string &FS);
|
const std::string &FS);
|
||||||
|
|
|
@ -0,0 +1,736 @@
|
||||||
|
//=======- X86FrameInfo.cpp - X86 Frame Information ------------*- C++ -*-====//
|
||||||
|
//
|
||||||
|
// The LLVM Compiler Infrastructure
|
||||||
|
//
|
||||||
|
// This file is distributed under the University of Illinois Open Source
|
||||||
|
// License. See LICENSE.TXT for details.
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
//
|
||||||
|
// This file contains the X86 implementation of TargetFrameInfo class.
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
#include "X86FrameInfo.h"
|
||||||
|
#include "X86InstrBuilder.h"
|
||||||
|
#include "X86InstrInfo.h"
|
||||||
|
#include "X86MachineFunctionInfo.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;
|
||||||
|
|
||||||
|
// FIXME: completely move here.
|
||||||
|
extern cl::opt<bool> ForceStackAlign;
|
||||||
|
|
||||||
|
static unsigned getSUBriOpcode(unsigned is64Bit, int64_t Imm) {
|
||||||
|
if (is64Bit) {
|
||||||
|
if (isInt<8>(Imm))
|
||||||
|
return X86::SUB64ri8;
|
||||||
|
return X86::SUB64ri32;
|
||||||
|
} else {
|
||||||
|
if (isInt<8>(Imm))
|
||||||
|
return X86::SUB32ri8;
|
||||||
|
return X86::SUB32ri;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static unsigned getADDriOpcode(unsigned is64Bit, int64_t Imm) {
|
||||||
|
if (is64Bit) {
|
||||||
|
if (isInt<8>(Imm))
|
||||||
|
return X86::ADD64ri8;
|
||||||
|
return X86::ADD64ri32;
|
||||||
|
} else {
|
||||||
|
if (isInt<8>(Imm))
|
||||||
|
return X86::ADD32ri8;
|
||||||
|
return X86::ADD32ri;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// emitSPUpdate - Emit a series of instructions to increment / decrement the
|
||||||
|
/// stack pointer by a constant value.
|
||||||
|
static
|
||||||
|
void emitSPUpdate(MachineBasicBlock &MBB, MachineBasicBlock::iterator &MBBI,
|
||||||
|
unsigned StackPtr, int64_t NumBytes, bool Is64Bit,
|
||||||
|
const TargetInstrInfo &TII) {
|
||||||
|
bool isSub = NumBytes < 0;
|
||||||
|
uint64_t Offset = isSub ? -NumBytes : NumBytes;
|
||||||
|
unsigned Opc = isSub ?
|
||||||
|
getSUBriOpcode(Is64Bit, Offset) :
|
||||||
|
getADDriOpcode(Is64Bit, Offset);
|
||||||
|
uint64_t Chunk = (1LL << 31) - 1;
|
||||||
|
DebugLoc DL = MBB.findDebugLoc(MBBI);
|
||||||
|
|
||||||
|
while (Offset) {
|
||||||
|
uint64_t ThisVal = (Offset > Chunk) ? Chunk : Offset;
|
||||||
|
MachineInstr *MI =
|
||||||
|
BuildMI(MBB, MBBI, DL, TII.get(Opc), StackPtr)
|
||||||
|
.addReg(StackPtr)
|
||||||
|
.addImm(ThisVal);
|
||||||
|
MI->getOperand(3).setIsDead(); // The EFLAGS implicit def is dead.
|
||||||
|
Offset -= ThisVal;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// mergeSPUpdatesUp - Merge two stack-manipulating instructions upper iterator.
|
||||||
|
static
|
||||||
|
void mergeSPUpdatesUp(MachineBasicBlock &MBB, MachineBasicBlock::iterator &MBBI,
|
||||||
|
unsigned StackPtr, uint64_t *NumBytes = NULL) {
|
||||||
|
if (MBBI == MBB.begin()) return;
|
||||||
|
|
||||||
|
MachineBasicBlock::iterator PI = prior(MBBI);
|
||||||
|
unsigned Opc = PI->getOpcode();
|
||||||
|
if ((Opc == X86::ADD64ri32 || Opc == X86::ADD64ri8 ||
|
||||||
|
Opc == X86::ADD32ri || Opc == X86::ADD32ri8) &&
|
||||||
|
PI->getOperand(0).getReg() == StackPtr) {
|
||||||
|
if (NumBytes)
|
||||||
|
*NumBytes += PI->getOperand(2).getImm();
|
||||||
|
MBB.erase(PI);
|
||||||
|
} else if ((Opc == X86::SUB64ri32 || Opc == X86::SUB64ri8 ||
|
||||||
|
Opc == X86::SUB32ri || Opc == X86::SUB32ri8) &&
|
||||||
|
PI->getOperand(0).getReg() == StackPtr) {
|
||||||
|
if (NumBytes)
|
||||||
|
*NumBytes -= PI->getOperand(2).getImm();
|
||||||
|
MBB.erase(PI);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// mergeSPUpdatesDown - Merge two stack-manipulating instructions lower iterator.
|
||||||
|
static
|
||||||
|
void mergeSPUpdatesDown(MachineBasicBlock &MBB,
|
||||||
|
MachineBasicBlock::iterator &MBBI,
|
||||||
|
unsigned StackPtr, uint64_t *NumBytes = NULL) {
|
||||||
|
// FIXME: THIS ISN'T RUN!!!
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (MBBI == MBB.end()) return;
|
||||||
|
|
||||||
|
MachineBasicBlock::iterator NI = llvm::next(MBBI);
|
||||||
|
if (NI == MBB.end()) return;
|
||||||
|
|
||||||
|
unsigned Opc = NI->getOpcode();
|
||||||
|
if ((Opc == X86::ADD64ri32 || Opc == X86::ADD64ri8 ||
|
||||||
|
Opc == X86::ADD32ri || Opc == X86::ADD32ri8) &&
|
||||||
|
NI->getOperand(0).getReg() == StackPtr) {
|
||||||
|
if (NumBytes)
|
||||||
|
*NumBytes -= NI->getOperand(2).getImm();
|
||||||
|
MBB.erase(NI);
|
||||||
|
MBBI = NI;
|
||||||
|
} else if ((Opc == X86::SUB64ri32 || Opc == X86::SUB64ri8 ||
|
||||||
|
Opc == X86::SUB32ri || Opc == X86::SUB32ri8) &&
|
||||||
|
NI->getOperand(0).getReg() == StackPtr) {
|
||||||
|
if (NumBytes)
|
||||||
|
*NumBytes += NI->getOperand(2).getImm();
|
||||||
|
MBB.erase(NI);
|
||||||
|
MBBI = NI;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// mergeSPUpdates - Checks the instruction before/after the passed
|
||||||
|
/// instruction. If it is an ADD/SUB instruction it is deleted argument and the
|
||||||
|
/// stack adjustment is returned as a positive value for ADD and a negative for
|
||||||
|
/// SUB.
|
||||||
|
static int mergeSPUpdates(MachineBasicBlock &MBB,
|
||||||
|
MachineBasicBlock::iterator &MBBI,
|
||||||
|
unsigned StackPtr,
|
||||||
|
bool doMergeWithPrevious) {
|
||||||
|
if ((doMergeWithPrevious && MBBI == MBB.begin()) ||
|
||||||
|
(!doMergeWithPrevious && MBBI == MBB.end()))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
MachineBasicBlock::iterator PI = doMergeWithPrevious ? prior(MBBI) : MBBI;
|
||||||
|
MachineBasicBlock::iterator NI = doMergeWithPrevious ? 0 : llvm::next(MBBI);
|
||||||
|
unsigned Opc = PI->getOpcode();
|
||||||
|
int Offset = 0;
|
||||||
|
|
||||||
|
if ((Opc == X86::ADD64ri32 || Opc == X86::ADD64ri8 ||
|
||||||
|
Opc == X86::ADD32ri || Opc == X86::ADD32ri8) &&
|
||||||
|
PI->getOperand(0).getReg() == StackPtr){
|
||||||
|
Offset += PI->getOperand(2).getImm();
|
||||||
|
MBB.erase(PI);
|
||||||
|
if (!doMergeWithPrevious) MBBI = NI;
|
||||||
|
} else if ((Opc == X86::SUB64ri32 || Opc == X86::SUB64ri8 ||
|
||||||
|
Opc == X86::SUB32ri || Opc == X86::SUB32ri8) &&
|
||||||
|
PI->getOperand(0).getReg() == StackPtr) {
|
||||||
|
Offset -= PI->getOperand(2).getImm();
|
||||||
|
MBB.erase(PI);
|
||||||
|
if (!doMergeWithPrevious) MBBI = NI;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool isEAXLiveIn(MachineFunction &MF) {
|
||||||
|
for (MachineRegisterInfo::livein_iterator II = MF.getRegInfo().livein_begin(),
|
||||||
|
EE = MF.getRegInfo().livein_end(); II != EE; ++II) {
|
||||||
|
unsigned Reg = II->first;
|
||||||
|
|
||||||
|
if (Reg == X86::EAX || Reg == X86::AX ||
|
||||||
|
Reg == X86::AH || Reg == X86::AL)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void X86FrameInfo::emitCalleeSavedFrameMoves(MachineFunction &MF,
|
||||||
|
MCSymbol *Label,
|
||||||
|
unsigned FramePtr) const {
|
||||||
|
MachineFrameInfo *MFI = MF.getFrameInfo();
|
||||||
|
const X86RegisterInfo *RegInfo =
|
||||||
|
static_cast<const X86RegisterInfo*>(MF.getTarget().getRegisterInfo());
|
||||||
|
MachineModuleInfo &MMI = MF.getMMI();
|
||||||
|
|
||||||
|
// Add callee saved registers to move list.
|
||||||
|
const std::vector<CalleeSavedInfo> &CSI = MFI->getCalleeSavedInfo();
|
||||||
|
if (CSI.empty()) return;
|
||||||
|
|
||||||
|
std::vector<MachineMove> &Moves = MMI.getFrameMoves();
|
||||||
|
const TargetData *TD = MF.getTarget().getTargetData();
|
||||||
|
bool HasFP = RegInfo->hasFP(MF);
|
||||||
|
|
||||||
|
// Calculate amount of bytes used for return address storing.
|
||||||
|
int stackGrowth =
|
||||||
|
(MF.getTarget().getFrameInfo()->getStackGrowthDirection() ==
|
||||||
|
TargetFrameInfo::StackGrowsUp ?
|
||||||
|
TD->getPointerSize() : -TD->getPointerSize());
|
||||||
|
|
||||||
|
// FIXME: This is dirty hack. The code itself is pretty mess right now.
|
||||||
|
// It should be rewritten from scratch and generalized sometimes.
|
||||||
|
|
||||||
|
// Determine maximum offset (minumum due to stack growth).
|
||||||
|
int64_t MaxOffset = 0;
|
||||||
|
for (std::vector<CalleeSavedInfo>::const_iterator
|
||||||
|
I = CSI.begin(), E = CSI.end(); I != E; ++I)
|
||||||
|
MaxOffset = std::min(MaxOffset,
|
||||||
|
MFI->getObjectOffset(I->getFrameIdx()));
|
||||||
|
|
||||||
|
// Calculate offsets.
|
||||||
|
int64_t saveAreaOffset = (HasFP ? 3 : 2) * stackGrowth;
|
||||||
|
for (std::vector<CalleeSavedInfo>::const_iterator
|
||||||
|
I = CSI.begin(), E = CSI.end(); I != E; ++I) {
|
||||||
|
int64_t Offset = MFI->getObjectOffset(I->getFrameIdx());
|
||||||
|
unsigned Reg = I->getReg();
|
||||||
|
Offset = MaxOffset - Offset + saveAreaOffset;
|
||||||
|
|
||||||
|
// Don't output a new machine move if we're re-saving the frame
|
||||||
|
// pointer. This happens when the PrologEpilogInserter has inserted an extra
|
||||||
|
// "PUSH" of the frame pointer -- the "emitPrologue" method automatically
|
||||||
|
// generates one when frame pointers are used. If we generate a "machine
|
||||||
|
// move" for this extra "PUSH", the linker will lose track of the fact that
|
||||||
|
// the frame pointer should have the value of the first "PUSH" when it's
|
||||||
|
// trying to unwind.
|
||||||
|
//
|
||||||
|
// FIXME: This looks inelegant. It's possibly correct, but it's covering up
|
||||||
|
// another bug. I.e., one where we generate a prolog like this:
|
||||||
|
//
|
||||||
|
// pushl %ebp
|
||||||
|
// movl %esp, %ebp
|
||||||
|
// pushl %ebp
|
||||||
|
// pushl %esi
|
||||||
|
// ...
|
||||||
|
//
|
||||||
|
// The immediate re-push of EBP is unnecessary. At the least, it's an
|
||||||
|
// optimization bug. EBP can be used as a scratch register in certain
|
||||||
|
// cases, but probably not when we have a frame pointer.
|
||||||
|
if (HasFP && FramePtr == Reg)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
MachineLocation CSDst(MachineLocation::VirtualFP, Offset);
|
||||||
|
MachineLocation CSSrc(Reg);
|
||||||
|
Moves.push_back(MachineMove(Label, CSDst, CSSrc));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// emitPrologue - Push callee-saved registers onto the stack, which
|
||||||
|
/// automatically adjust the stack pointer. Adjust the stack pointer to allocate
|
||||||
|
/// space for local variables. Also emit labels used by the exception handler to
|
||||||
|
/// generate the exception handling frames.
|
||||||
|
void X86FrameInfo::emitPrologue(MachineFunction &MF) const {
|
||||||
|
MachineBasicBlock &MBB = MF.front(); // Prologue goes in entry BB.
|
||||||
|
MachineBasicBlock::iterator MBBI = MBB.begin();
|
||||||
|
MachineFrameInfo *MFI = MF.getFrameInfo();
|
||||||
|
const Function *Fn = MF.getFunction();
|
||||||
|
const X86Subtarget *Subtarget = &MF.getTarget().getSubtarget<X86Subtarget>();
|
||||||
|
const X86RegisterInfo *RegInfo =
|
||||||
|
static_cast<const X86RegisterInfo*>(MF.getTarget().getRegisterInfo());
|
||||||
|
const X86InstrInfo &TII =
|
||||||
|
*static_cast<const X86InstrInfo*>(MF.getTarget().getInstrInfo());
|
||||||
|
MachineModuleInfo &MMI = MF.getMMI();
|
||||||
|
X86MachineFunctionInfo *X86FI = MF.getInfo<X86MachineFunctionInfo>();
|
||||||
|
bool needsFrameMoves = MMI.hasDebugInfo() ||
|
||||||
|
!Fn->doesNotThrow() || UnwindTablesMandatory;
|
||||||
|
uint64_t MaxAlign = MFI->getMaxAlignment(); // Desired stack alignment.
|
||||||
|
uint64_t StackSize = MFI->getStackSize(); // Number of bytes to allocate.
|
||||||
|
bool HasFP = RegInfo->hasFP(MF);
|
||||||
|
bool Is64Bit = STI.is64Bit();
|
||||||
|
bool IsWin64 = STI.isTargetWin64();
|
||||||
|
unsigned StackAlign = getStackAlignment();
|
||||||
|
unsigned SlotSize = RegInfo->getSlotSize();
|
||||||
|
unsigned FramePtr = RegInfo->getFrameRegister(MF);
|
||||||
|
unsigned StackPtr = RegInfo->getStackRegister();
|
||||||
|
|
||||||
|
DebugLoc DL;
|
||||||
|
|
||||||
|
// If we're forcing a stack realignment we can't rely on just the frame
|
||||||
|
// info, we need to know the ABI stack alignment as well in case we
|
||||||
|
// have a call out. Otherwise just make sure we have some alignment - we'll
|
||||||
|
// go with the minimum SlotSize.
|
||||||
|
if (ForceStackAlign) {
|
||||||
|
if (MFI->hasCalls())
|
||||||
|
MaxAlign = (StackAlign > MaxAlign) ? StackAlign : MaxAlign;
|
||||||
|
else if (MaxAlign < SlotSize)
|
||||||
|
MaxAlign = SlotSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add RETADDR move area to callee saved frame size.
|
||||||
|
int TailCallReturnAddrDelta = X86FI->getTCReturnAddrDelta();
|
||||||
|
if (TailCallReturnAddrDelta < 0)
|
||||||
|
X86FI->setCalleeSavedFrameSize(
|
||||||
|
X86FI->getCalleeSavedFrameSize() - TailCallReturnAddrDelta);
|
||||||
|
|
||||||
|
// If this is x86-64 and the Red Zone is not disabled, if we are a leaf
|
||||||
|
// function, and use up to 128 bytes of stack space, don't have a frame
|
||||||
|
// pointer, calls, or dynamic alloca then we do not need to adjust the
|
||||||
|
// stack pointer (we fit in the Red Zone).
|
||||||
|
if (Is64Bit && !Fn->hasFnAttr(Attribute::NoRedZone) &&
|
||||||
|
!RegInfo->needsStackRealignment(MF) &&
|
||||||
|
!MFI->hasVarSizedObjects() && // No dynamic alloca.
|
||||||
|
!MFI->adjustsStack() && // No calls.
|
||||||
|
!IsWin64) { // Win64 has no Red Zone
|
||||||
|
uint64_t MinSize = X86FI->getCalleeSavedFrameSize();
|
||||||
|
if (HasFP) MinSize += SlotSize;
|
||||||
|
StackSize = std::max(MinSize, StackSize > 128 ? StackSize - 128 : 0);
|
||||||
|
MFI->setStackSize(StackSize);
|
||||||
|
} else if (IsWin64) {
|
||||||
|
// We need to always allocate 32 bytes as register spill area.
|
||||||
|
// FIXME: We might reuse these 32 bytes for leaf functions.
|
||||||
|
StackSize += 32;
|
||||||
|
MFI->setStackSize(StackSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Insert stack pointer adjustment for later moving of return addr. Only
|
||||||
|
// applies to tail call optimized functions where the callee argument stack
|
||||||
|
// size is bigger than the callers.
|
||||||
|
if (TailCallReturnAddrDelta < 0) {
|
||||||
|
MachineInstr *MI =
|
||||||
|
BuildMI(MBB, MBBI, DL,
|
||||||
|
TII.get(getSUBriOpcode(Is64Bit, -TailCallReturnAddrDelta)),
|
||||||
|
StackPtr)
|
||||||
|
.addReg(StackPtr)
|
||||||
|
.addImm(-TailCallReturnAddrDelta);
|
||||||
|
MI->getOperand(3).setIsDead(); // The EFLAGS implicit def is dead.
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mapping for machine moves:
|
||||||
|
//
|
||||||
|
// DST: VirtualFP AND
|
||||||
|
// SRC: VirtualFP => DW_CFA_def_cfa_offset
|
||||||
|
// ELSE => DW_CFA_def_cfa
|
||||||
|
//
|
||||||
|
// SRC: VirtualFP AND
|
||||||
|
// DST: Register => DW_CFA_def_cfa_register
|
||||||
|
//
|
||||||
|
// ELSE
|
||||||
|
// OFFSET < 0 => DW_CFA_offset_extended_sf
|
||||||
|
// REG < 64 => DW_CFA_offset + Reg
|
||||||
|
// ELSE => DW_CFA_offset_extended
|
||||||
|
|
||||||
|
std::vector<MachineMove> &Moves = MMI.getFrameMoves();
|
||||||
|
const TargetData *TD = MF.getTarget().getTargetData();
|
||||||
|
uint64_t NumBytes = 0;
|
||||||
|
int stackGrowth = -TD->getPointerSize();
|
||||||
|
|
||||||
|
if (HasFP) {
|
||||||
|
// Calculate required stack adjustment.
|
||||||
|
uint64_t FrameSize = StackSize - SlotSize;
|
||||||
|
if (RegInfo->needsStackRealignment(MF))
|
||||||
|
FrameSize = (FrameSize + MaxAlign - 1) / MaxAlign * MaxAlign;
|
||||||
|
|
||||||
|
NumBytes = FrameSize - X86FI->getCalleeSavedFrameSize();
|
||||||
|
|
||||||
|
// Get the offset of the stack slot for the EBP register, which is
|
||||||
|
// guaranteed to be the last slot by processFunctionBeforeFrameFinalized.
|
||||||
|
// Update the frame offset adjustment.
|
||||||
|
MFI->setOffsetAdjustment(-NumBytes);
|
||||||
|
|
||||||
|
// Save EBP/RBP into the appropriate stack slot.
|
||||||
|
BuildMI(MBB, MBBI, DL, TII.get(Is64Bit ? X86::PUSH64r : X86::PUSH32r))
|
||||||
|
.addReg(FramePtr, RegState::Kill);
|
||||||
|
|
||||||
|
if (needsFrameMoves) {
|
||||||
|
// Mark the place where EBP/RBP was saved.
|
||||||
|
MCSymbol *FrameLabel = MMI.getContext().CreateTempSymbol();
|
||||||
|
BuildMI(MBB, MBBI, DL, TII.get(X86::PROLOG_LABEL)).addSym(FrameLabel);
|
||||||
|
|
||||||
|
// Define the current CFA rule to use the provided offset.
|
||||||
|
if (StackSize) {
|
||||||
|
MachineLocation SPDst(MachineLocation::VirtualFP);
|
||||||
|
MachineLocation SPSrc(MachineLocation::VirtualFP, 2 * stackGrowth);
|
||||||
|
Moves.push_back(MachineMove(FrameLabel, SPDst, SPSrc));
|
||||||
|
} else {
|
||||||
|
// FIXME: Verify & implement for FP
|
||||||
|
MachineLocation SPDst(StackPtr);
|
||||||
|
MachineLocation SPSrc(StackPtr, stackGrowth);
|
||||||
|
Moves.push_back(MachineMove(FrameLabel, SPDst, SPSrc));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Change the rule for the FramePtr to be an "offset" rule.
|
||||||
|
MachineLocation FPDst(MachineLocation::VirtualFP, 2 * stackGrowth);
|
||||||
|
MachineLocation FPSrc(FramePtr);
|
||||||
|
Moves.push_back(MachineMove(FrameLabel, FPDst, FPSrc));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update EBP with the new base value...
|
||||||
|
BuildMI(MBB, MBBI, DL,
|
||||||
|
TII.get(Is64Bit ? X86::MOV64rr : X86::MOV32rr), FramePtr)
|
||||||
|
.addReg(StackPtr);
|
||||||
|
|
||||||
|
if (needsFrameMoves) {
|
||||||
|
// Mark effective beginning of when frame pointer becomes valid.
|
||||||
|
MCSymbol *FrameLabel = MMI.getContext().CreateTempSymbol();
|
||||||
|
BuildMI(MBB, MBBI, DL, TII.get(X86::PROLOG_LABEL)).addSym(FrameLabel);
|
||||||
|
|
||||||
|
// Define the current CFA to use the EBP/RBP register.
|
||||||
|
MachineLocation FPDst(FramePtr);
|
||||||
|
MachineLocation FPSrc(MachineLocation::VirtualFP);
|
||||||
|
Moves.push_back(MachineMove(FrameLabel, FPDst, FPSrc));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mark the FramePtr as live-in in every block except the entry.
|
||||||
|
for (MachineFunction::iterator I = llvm::next(MF.begin()), E = MF.end();
|
||||||
|
I != E; ++I)
|
||||||
|
I->addLiveIn(FramePtr);
|
||||||
|
|
||||||
|
// Realign stack
|
||||||
|
if (RegInfo->needsStackRealignment(MF)) {
|
||||||
|
MachineInstr *MI =
|
||||||
|
BuildMI(MBB, MBBI, DL,
|
||||||
|
TII.get(Is64Bit ? X86::AND64ri32 : X86::AND32ri),
|
||||||
|
StackPtr).addReg(StackPtr).addImm(-MaxAlign);
|
||||||
|
|
||||||
|
// The EFLAGS implicit def is dead.
|
||||||
|
MI->getOperand(3).setIsDead();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
NumBytes = StackSize - X86FI->getCalleeSavedFrameSize();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Skip the callee-saved push instructions.
|
||||||
|
bool PushedRegs = false;
|
||||||
|
int StackOffset = 2 * stackGrowth;
|
||||||
|
|
||||||
|
while (MBBI != MBB.end() &&
|
||||||
|
(MBBI->getOpcode() == X86::PUSH32r ||
|
||||||
|
MBBI->getOpcode() == X86::PUSH64r)) {
|
||||||
|
PushedRegs = true;
|
||||||
|
++MBBI;
|
||||||
|
|
||||||
|
if (!HasFP && needsFrameMoves) {
|
||||||
|
// Mark callee-saved push instruction.
|
||||||
|
MCSymbol *Label = MMI.getContext().CreateTempSymbol();
|
||||||
|
BuildMI(MBB, MBBI, DL, TII.get(X86::PROLOG_LABEL)).addSym(Label);
|
||||||
|
|
||||||
|
// Define the current CFA rule to use the provided offset.
|
||||||
|
unsigned Ptr = StackSize ?
|
||||||
|
MachineLocation::VirtualFP : StackPtr;
|
||||||
|
MachineLocation SPDst(Ptr);
|
||||||
|
MachineLocation SPSrc(Ptr, StackOffset);
|
||||||
|
Moves.push_back(MachineMove(Label, SPDst, SPSrc));
|
||||||
|
StackOffset += stackGrowth;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DL = MBB.findDebugLoc(MBBI);
|
||||||
|
|
||||||
|
// If there is an SUB32ri of ESP immediately before this instruction, merge
|
||||||
|
// the two. This can be the case when tail call elimination is enabled and
|
||||||
|
// the callee has more arguments then the caller.
|
||||||
|
NumBytes -= mergeSPUpdates(MBB, MBBI, StackPtr, true);
|
||||||
|
|
||||||
|
// If there is an ADD32ri or SUB32ri of ESP immediately after this
|
||||||
|
// instruction, merge the two instructions.
|
||||||
|
mergeSPUpdatesDown(MBB, MBBI, StackPtr, &NumBytes);
|
||||||
|
|
||||||
|
// Adjust stack pointer: ESP -= numbytes.
|
||||||
|
|
||||||
|
// Windows and cygwin/mingw require a prologue helper routine when allocating
|
||||||
|
// more than 4K bytes on the stack. Windows uses __chkstk and cygwin/mingw
|
||||||
|
// uses __alloca. __alloca and the 32-bit version of __chkstk will probe the
|
||||||
|
// stack and adjust the stack pointer in one go. The 64-bit version of
|
||||||
|
// __chkstk is only responsible for probing the stack. The 64-bit prologue is
|
||||||
|
// responsible for adjusting the stack pointer. Touching the stack at 4K
|
||||||
|
// increments is necessary to ensure that the guard pages used by the OS
|
||||||
|
// virtual memory manager are allocated in correct sequence.
|
||||||
|
if (NumBytes >= 4096 &&
|
||||||
|
(Subtarget->isTargetCygMing() || Subtarget->isTargetWin32())) {
|
||||||
|
// Check whether EAX is livein for this function.
|
||||||
|
bool isEAXAlive = isEAXLiveIn(MF);
|
||||||
|
|
||||||
|
const char *StackProbeSymbol =
|
||||||
|
Subtarget->isTargetWindows() ? "_chkstk" : "_alloca";
|
||||||
|
unsigned CallOp = Is64Bit ? X86::CALL64pcrel32 : X86::CALLpcrel32;
|
||||||
|
if (!isEAXAlive) {
|
||||||
|
BuildMI(MBB, MBBI, DL, TII.get(X86::MOV32ri), X86::EAX)
|
||||||
|
.addImm(NumBytes);
|
||||||
|
BuildMI(MBB, MBBI, DL, TII.get(CallOp))
|
||||||
|
.addExternalSymbol(StackProbeSymbol)
|
||||||
|
.addReg(StackPtr, RegState::Define | RegState::Implicit)
|
||||||
|
.addReg(X86::EFLAGS, RegState::Define | RegState::Implicit);
|
||||||
|
} else {
|
||||||
|
// Save EAX
|
||||||
|
BuildMI(MBB, MBBI, DL, TII.get(X86::PUSH32r))
|
||||||
|
.addReg(X86::EAX, RegState::Kill);
|
||||||
|
|
||||||
|
// Allocate NumBytes-4 bytes on stack. We'll also use 4 already
|
||||||
|
// allocated bytes for EAX.
|
||||||
|
BuildMI(MBB, MBBI, DL, TII.get(X86::MOV32ri), X86::EAX)
|
||||||
|
.addImm(NumBytes - 4);
|
||||||
|
BuildMI(MBB, MBBI, DL, TII.get(CallOp))
|
||||||
|
.addExternalSymbol(StackProbeSymbol)
|
||||||
|
.addReg(StackPtr, RegState::Define | RegState::Implicit)
|
||||||
|
.addReg(X86::EFLAGS, RegState::Define | RegState::Implicit);
|
||||||
|
|
||||||
|
// Restore EAX
|
||||||
|
MachineInstr *MI = addRegOffset(BuildMI(MF, DL, TII.get(X86::MOV32rm),
|
||||||
|
X86::EAX),
|
||||||
|
StackPtr, false, NumBytes - 4);
|
||||||
|
MBB.insert(MBBI, MI);
|
||||||
|
}
|
||||||
|
} else if (NumBytes >= 4096 && Subtarget->isTargetWin64()) {
|
||||||
|
// Sanity check that EAX is not livein for this function. It should
|
||||||
|
// should not be, so throw an assert.
|
||||||
|
assert(!isEAXLiveIn(MF) && "EAX is livein in the Win64 case!");
|
||||||
|
|
||||||
|
// Handle the 64-bit Windows ABI case where we need to call __chkstk.
|
||||||
|
// Function prologue is responsible for adjusting the stack pointer.
|
||||||
|
BuildMI(MBB, MBBI, DL, TII.get(X86::MOV32ri), X86::EAX)
|
||||||
|
.addImm(NumBytes);
|
||||||
|
BuildMI(MBB, MBBI, DL, TII.get(X86::WINCALL64pcrel32))
|
||||||
|
.addExternalSymbol("__chkstk")
|
||||||
|
.addReg(StackPtr, RegState::Define | RegState::Implicit);
|
||||||
|
emitSPUpdate(MBB, MBBI, StackPtr, -(int64_t)NumBytes, Is64Bit, TII);
|
||||||
|
} else if (NumBytes)
|
||||||
|
emitSPUpdate(MBB, MBBI, StackPtr, -(int64_t)NumBytes, Is64Bit, TII);
|
||||||
|
|
||||||
|
if ((NumBytes || PushedRegs) && needsFrameMoves) {
|
||||||
|
// Mark end of stack pointer adjustment.
|
||||||
|
MCSymbol *Label = MMI.getContext().CreateTempSymbol();
|
||||||
|
BuildMI(MBB, MBBI, DL, TII.get(X86::PROLOG_LABEL)).addSym(Label);
|
||||||
|
|
||||||
|
if (!HasFP && NumBytes) {
|
||||||
|
// Define the current CFA rule to use the provided offset.
|
||||||
|
if (StackSize) {
|
||||||
|
MachineLocation SPDst(MachineLocation::VirtualFP);
|
||||||
|
MachineLocation SPSrc(MachineLocation::VirtualFP,
|
||||||
|
-StackSize + stackGrowth);
|
||||||
|
Moves.push_back(MachineMove(Label, SPDst, SPSrc));
|
||||||
|
} else {
|
||||||
|
// FIXME: Verify & implement for FP
|
||||||
|
MachineLocation SPDst(StackPtr);
|
||||||
|
MachineLocation SPSrc(StackPtr, stackGrowth);
|
||||||
|
Moves.push_back(MachineMove(Label, SPDst, SPSrc));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Emit DWARF info specifying the offsets of the callee-saved registers.
|
||||||
|
if (PushedRegs)
|
||||||
|
emitCalleeSavedFrameMoves(MF, Label, HasFP ? FramePtr : StackPtr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void X86FrameInfo::emitEpilogue(MachineFunction &MF,
|
||||||
|
MachineBasicBlock &MBB) const {
|
||||||
|
const MachineFrameInfo *MFI = MF.getFrameInfo();
|
||||||
|
X86MachineFunctionInfo *X86FI = MF.getInfo<X86MachineFunctionInfo>();
|
||||||
|
const X86RegisterInfo *RegInfo =
|
||||||
|
static_cast<const X86RegisterInfo*>(MF.getTarget().getRegisterInfo());
|
||||||
|
const X86InstrInfo &TII =
|
||||||
|
*static_cast<const X86InstrInfo*>(MF.getTarget().getInstrInfo());
|
||||||
|
MachineBasicBlock::iterator MBBI = prior(MBB.end());
|
||||||
|
unsigned RetOpcode = MBBI->getOpcode();
|
||||||
|
DebugLoc DL = MBBI->getDebugLoc();
|
||||||
|
bool Is64Bit = STI.is64Bit();
|
||||||
|
unsigned StackAlign = getStackAlignment();
|
||||||
|
unsigned SlotSize = RegInfo->getSlotSize();
|
||||||
|
unsigned FramePtr = RegInfo->getFrameRegister(MF);
|
||||||
|
unsigned StackPtr = RegInfo->getStackRegister();
|
||||||
|
|
||||||
|
switch (RetOpcode) {
|
||||||
|
default:
|
||||||
|
llvm_unreachable("Can only insert epilog into returning blocks");
|
||||||
|
case X86::RET:
|
||||||
|
case X86::RETI:
|
||||||
|
case X86::TCRETURNdi:
|
||||||
|
case X86::TCRETURNri:
|
||||||
|
case X86::TCRETURNmi:
|
||||||
|
case X86::TCRETURNdi64:
|
||||||
|
case X86::TCRETURNri64:
|
||||||
|
case X86::TCRETURNmi64:
|
||||||
|
case X86::EH_RETURN:
|
||||||
|
case X86::EH_RETURN64:
|
||||||
|
break; // These are ok
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the number of bytes to allocate from the FrameInfo.
|
||||||
|
uint64_t StackSize = MFI->getStackSize();
|
||||||
|
uint64_t MaxAlign = MFI->getMaxAlignment();
|
||||||
|
unsigned CSSize = X86FI->getCalleeSavedFrameSize();
|
||||||
|
uint64_t NumBytes = 0;
|
||||||
|
|
||||||
|
// If we're forcing a stack realignment we can't rely on just the frame
|
||||||
|
// info, we need to know the ABI stack alignment as well in case we
|
||||||
|
// have a call out. Otherwise just make sure we have some alignment - we'll
|
||||||
|
// go with the minimum.
|
||||||
|
if (ForceStackAlign) {
|
||||||
|
if (MFI->hasCalls())
|
||||||
|
MaxAlign = (StackAlign > MaxAlign) ? StackAlign : MaxAlign;
|
||||||
|
else
|
||||||
|
MaxAlign = MaxAlign ? MaxAlign : 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (RegInfo->hasFP(MF)) {
|
||||||
|
// Calculate required stack adjustment.
|
||||||
|
uint64_t FrameSize = StackSize - SlotSize;
|
||||||
|
if (RegInfo->needsStackRealignment(MF))
|
||||||
|
FrameSize = (FrameSize + MaxAlign - 1)/MaxAlign*MaxAlign;
|
||||||
|
|
||||||
|
NumBytes = FrameSize - CSSize;
|
||||||
|
|
||||||
|
// Pop EBP.
|
||||||
|
BuildMI(MBB, MBBI, DL,
|
||||||
|
TII.get(Is64Bit ? X86::POP64r : X86::POP32r), FramePtr);
|
||||||
|
} else {
|
||||||
|
NumBytes = StackSize - CSSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Skip the callee-saved pop instructions.
|
||||||
|
MachineBasicBlock::iterator LastCSPop = MBBI;
|
||||||
|
while (MBBI != MBB.begin()) {
|
||||||
|
MachineBasicBlock::iterator PI = prior(MBBI);
|
||||||
|
unsigned Opc = PI->getOpcode();
|
||||||
|
|
||||||
|
if (Opc != X86::POP32r && Opc != X86::POP64r &&
|
||||||
|
!PI->getDesc().isTerminator())
|
||||||
|
break;
|
||||||
|
|
||||||
|
--MBBI;
|
||||||
|
}
|
||||||
|
|
||||||
|
DL = MBBI->getDebugLoc();
|
||||||
|
|
||||||
|
// If there is an ADD32ri or SUB32ri of ESP immediately before this
|
||||||
|
// instruction, merge the two instructions.
|
||||||
|
if (NumBytes || MFI->hasVarSizedObjects())
|
||||||
|
mergeSPUpdatesUp(MBB, MBBI, StackPtr, &NumBytes);
|
||||||
|
|
||||||
|
// If dynamic alloca is used, then reset esp to point to the last callee-saved
|
||||||
|
// slot before popping them off! Same applies for the case, when stack was
|
||||||
|
// realigned.
|
||||||
|
if (RegInfo->needsStackRealignment(MF)) {
|
||||||
|
// We cannot use LEA here, because stack pointer was realigned. We need to
|
||||||
|
// deallocate local frame back.
|
||||||
|
if (CSSize) {
|
||||||
|
emitSPUpdate(MBB, MBBI, StackPtr, NumBytes, Is64Bit, TII);
|
||||||
|
MBBI = prior(LastCSPop);
|
||||||
|
}
|
||||||
|
|
||||||
|
BuildMI(MBB, MBBI, DL,
|
||||||
|
TII.get(Is64Bit ? X86::MOV64rr : X86::MOV32rr),
|
||||||
|
StackPtr).addReg(FramePtr);
|
||||||
|
} else if (MFI->hasVarSizedObjects()) {
|
||||||
|
if (CSSize) {
|
||||||
|
unsigned Opc = Is64Bit ? X86::LEA64r : X86::LEA32r;
|
||||||
|
MachineInstr *MI =
|
||||||
|
addRegOffset(BuildMI(MF, DL, TII.get(Opc), StackPtr),
|
||||||
|
FramePtr, false, -CSSize);
|
||||||
|
MBB.insert(MBBI, MI);
|
||||||
|
} else {
|
||||||
|
BuildMI(MBB, MBBI, DL,
|
||||||
|
TII.get(Is64Bit ? X86::MOV64rr : X86::MOV32rr), StackPtr)
|
||||||
|
.addReg(FramePtr);
|
||||||
|
}
|
||||||
|
} else if (NumBytes) {
|
||||||
|
// Adjust stack pointer back: ESP += numbytes.
|
||||||
|
emitSPUpdate(MBB, MBBI, StackPtr, NumBytes, Is64Bit, TII);
|
||||||
|
}
|
||||||
|
|
||||||
|
// We're returning from function via eh_return.
|
||||||
|
if (RetOpcode == X86::EH_RETURN || RetOpcode == X86::EH_RETURN64) {
|
||||||
|
MBBI = prior(MBB.end());
|
||||||
|
MachineOperand &DestAddr = MBBI->getOperand(0);
|
||||||
|
assert(DestAddr.isReg() && "Offset should be in register!");
|
||||||
|
BuildMI(MBB, MBBI, DL,
|
||||||
|
TII.get(Is64Bit ? X86::MOV64rr : X86::MOV32rr),
|
||||||
|
StackPtr).addReg(DestAddr.getReg());
|
||||||
|
} else if (RetOpcode == X86::TCRETURNri || RetOpcode == X86::TCRETURNdi ||
|
||||||
|
RetOpcode == X86::TCRETURNmi ||
|
||||||
|
RetOpcode == X86::TCRETURNri64 || RetOpcode == X86::TCRETURNdi64 ||
|
||||||
|
RetOpcode == X86::TCRETURNmi64) {
|
||||||
|
bool isMem = RetOpcode == X86::TCRETURNmi || RetOpcode == X86::TCRETURNmi64;
|
||||||
|
// Tail call return: adjust the stack pointer and jump to callee.
|
||||||
|
MBBI = prior(MBB.end());
|
||||||
|
MachineOperand &JumpTarget = MBBI->getOperand(0);
|
||||||
|
MachineOperand &StackAdjust = MBBI->getOperand(isMem ? 5 : 1);
|
||||||
|
assert(StackAdjust.isImm() && "Expecting immediate value.");
|
||||||
|
|
||||||
|
// Adjust stack pointer.
|
||||||
|
int StackAdj = StackAdjust.getImm();
|
||||||
|
int MaxTCDelta = X86FI->getTCReturnAddrDelta();
|
||||||
|
int Offset = 0;
|
||||||
|
assert(MaxTCDelta <= 0 && "MaxTCDelta should never be positive");
|
||||||
|
|
||||||
|
// Incoporate the retaddr area.
|
||||||
|
Offset = StackAdj-MaxTCDelta;
|
||||||
|
assert(Offset >= 0 && "Offset should never be negative");
|
||||||
|
|
||||||
|
if (Offset) {
|
||||||
|
// Check for possible merge with preceeding ADD instruction.
|
||||||
|
Offset += mergeSPUpdates(MBB, MBBI, StackPtr, true);
|
||||||
|
emitSPUpdate(MBB, MBBI, StackPtr, Offset, Is64Bit, TII);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Jump to label or value in register.
|
||||||
|
if (RetOpcode == X86::TCRETURNdi || RetOpcode == X86::TCRETURNdi64) {
|
||||||
|
BuildMI(MBB, MBBI, DL, TII.get((RetOpcode == X86::TCRETURNdi)
|
||||||
|
? X86::TAILJMPd : X86::TAILJMPd64)).
|
||||||
|
addGlobalAddress(JumpTarget.getGlobal(), JumpTarget.getOffset(),
|
||||||
|
JumpTarget.getTargetFlags());
|
||||||
|
} else if (RetOpcode == X86::TCRETURNmi || RetOpcode == X86::TCRETURNmi64) {
|
||||||
|
MachineInstrBuilder MIB =
|
||||||
|
BuildMI(MBB, MBBI, DL, TII.get((RetOpcode == X86::TCRETURNmi)
|
||||||
|
? X86::TAILJMPm : X86::TAILJMPm64));
|
||||||
|
for (unsigned i = 0; i != 5; ++i)
|
||||||
|
MIB.addOperand(MBBI->getOperand(i));
|
||||||
|
} else if (RetOpcode == X86::TCRETURNri64) {
|
||||||
|
BuildMI(MBB, MBBI, DL, TII.get(X86::TAILJMPr64)).
|
||||||
|
addReg(JumpTarget.getReg(), RegState::Kill);
|
||||||
|
} else {
|
||||||
|
BuildMI(MBB, MBBI, DL, TII.get(X86::TAILJMPr)).
|
||||||
|
addReg(JumpTarget.getReg(), RegState::Kill);
|
||||||
|
}
|
||||||
|
|
||||||
|
MachineInstr *NewMI = prior(MBBI);
|
||||||
|
for (unsigned i = 2, e = MBBI->getNumOperands(); i != e; ++i)
|
||||||
|
NewMI->addOperand(MBBI->getOperand(i));
|
||||||
|
|
||||||
|
// Delete the pseudo instruction TCRETURN.
|
||||||
|
MBB.erase(MBBI);
|
||||||
|
} else if ((RetOpcode == X86::RET || RetOpcode == X86::RETI) &&
|
||||||
|
(X86FI->getTCReturnAddrDelta() < 0)) {
|
||||||
|
// Add the return addr area delta back since we are not tail calling.
|
||||||
|
int delta = -1*X86FI->getTCReturnAddrDelta();
|
||||||
|
MBBI = prior(MBB.end());
|
||||||
|
|
||||||
|
// Check for possible merge with preceeding ADD instruction.
|
||||||
|
delta += mergeSPUpdates(MBB, MBBI, StackPtr, true);
|
||||||
|
emitSPUpdate(MBB, MBBI, StackPtr, delta, Is64Bit, TII);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,46 @@
|
||||||
|
//===-- X86TargetFrameInfo.h - Define TargetFrameInfo for X86 ---*- C++ -*-===//
|
||||||
|
//
|
||||||
|
// The LLVM Compiler Infrastructure
|
||||||
|
//
|
||||||
|
// This file is distributed under the University of Illinois Open Source
|
||||||
|
// License. See LICENSE.TXT for details.
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
#ifndef X86_FRAMEINFO_H
|
||||||
|
#define X86_FRAMEINFO_H
|
||||||
|
|
||||||
|
#include "X86Subtarget.h"
|
||||||
|
#include "llvm/Target/TargetFrameInfo.h"
|
||||||
|
|
||||||
|
namespace llvm {
|
||||||
|
class MCSymbol;
|
||||||
|
|
||||||
|
class X86FrameInfo : public TargetFrameInfo {
|
||||||
|
protected:
|
||||||
|
const X86Subtarget &STI;
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit X86FrameInfo(const X86Subtarget &sti)
|
||||||
|
: TargetFrameInfo(StackGrowsDown,
|
||||||
|
sti.getStackAlignment(),
|
||||||
|
(sti.isTargetWin64() ? -40 : (sti.is64Bit() ? -8 : -4))),
|
||||||
|
STI(sti) {
|
||||||
|
}
|
||||||
|
|
||||||
|
void emitCalleeSavedFrameMoves(MachineFunction &MF, MCSymbol *Label,
|
||||||
|
unsigned FramePtr) const;
|
||||||
|
|
||||||
|
/// emitProlog/emitEpilog - These methods insert prolog and epilog code into
|
||||||
|
/// the function.
|
||||||
|
void emitPrologue(MachineFunction &MF) const;
|
||||||
|
void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // End llvm namespace
|
||||||
|
|
||||||
|
#endif
|
|
@ -41,7 +41,7 @@
|
||||||
#include "llvm/Support/CommandLine.h"
|
#include "llvm/Support/CommandLine.h"
|
||||||
using namespace llvm;
|
using namespace llvm;
|
||||||
|
|
||||||
static cl::opt<bool>
|
cl::opt<bool>
|
||||||
ForceStackAlign("force-align-stack",
|
ForceStackAlign("force-align-stack",
|
||||||
cl::desc("Force align the stack to the minimum alignment"
|
cl::desc("Force align the stack to the minimum alignment"
|
||||||
" needed for the function."),
|
" needed for the function."),
|
||||||
|
@ -696,665 +696,6 @@ X86RegisterInfo::processFunctionBeforeCalleeSavedScan(MachineFunction &MF,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// emitSPUpdate - Emit a series of instructions to increment / decrement the
|
|
||||||
/// stack pointer by a constant value.
|
|
||||||
static
|
|
||||||
void emitSPUpdate(MachineBasicBlock &MBB, MachineBasicBlock::iterator &MBBI,
|
|
||||||
unsigned StackPtr, int64_t NumBytes, bool Is64Bit,
|
|
||||||
const TargetInstrInfo &TII) {
|
|
||||||
bool isSub = NumBytes < 0;
|
|
||||||
uint64_t Offset = isSub ? -NumBytes : NumBytes;
|
|
||||||
unsigned Opc = isSub ?
|
|
||||||
getSUBriOpcode(Is64Bit, Offset) :
|
|
||||||
getADDriOpcode(Is64Bit, Offset);
|
|
||||||
uint64_t Chunk = (1LL << 31) - 1;
|
|
||||||
DebugLoc DL = MBB.findDebugLoc(MBBI);
|
|
||||||
|
|
||||||
while (Offset) {
|
|
||||||
uint64_t ThisVal = (Offset > Chunk) ? Chunk : Offset;
|
|
||||||
MachineInstr *MI =
|
|
||||||
BuildMI(MBB, MBBI, DL, TII.get(Opc), StackPtr)
|
|
||||||
.addReg(StackPtr)
|
|
||||||
.addImm(ThisVal);
|
|
||||||
MI->getOperand(3).setIsDead(); // The EFLAGS implicit def is dead.
|
|
||||||
Offset -= ThisVal;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// mergeSPUpdatesUp - Merge two stack-manipulating instructions upper iterator.
|
|
||||||
static
|
|
||||||
void mergeSPUpdatesUp(MachineBasicBlock &MBB, MachineBasicBlock::iterator &MBBI,
|
|
||||||
unsigned StackPtr, uint64_t *NumBytes = NULL) {
|
|
||||||
if (MBBI == MBB.begin()) return;
|
|
||||||
|
|
||||||
MachineBasicBlock::iterator PI = prior(MBBI);
|
|
||||||
unsigned Opc = PI->getOpcode();
|
|
||||||
if ((Opc == X86::ADD64ri32 || Opc == X86::ADD64ri8 ||
|
|
||||||
Opc == X86::ADD32ri || Opc == X86::ADD32ri8) &&
|
|
||||||
PI->getOperand(0).getReg() == StackPtr) {
|
|
||||||
if (NumBytes)
|
|
||||||
*NumBytes += PI->getOperand(2).getImm();
|
|
||||||
MBB.erase(PI);
|
|
||||||
} else if ((Opc == X86::SUB64ri32 || Opc == X86::SUB64ri8 ||
|
|
||||||
Opc == X86::SUB32ri || Opc == X86::SUB32ri8) &&
|
|
||||||
PI->getOperand(0).getReg() == StackPtr) {
|
|
||||||
if (NumBytes)
|
|
||||||
*NumBytes -= PI->getOperand(2).getImm();
|
|
||||||
MBB.erase(PI);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// mergeSPUpdatesDown - Merge two stack-manipulating instructions lower iterator.
|
|
||||||
static
|
|
||||||
void mergeSPUpdatesDown(MachineBasicBlock &MBB,
|
|
||||||
MachineBasicBlock::iterator &MBBI,
|
|
||||||
unsigned StackPtr, uint64_t *NumBytes = NULL) {
|
|
||||||
// FIXME: THIS ISN'T RUN!!!
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (MBBI == MBB.end()) return;
|
|
||||||
|
|
||||||
MachineBasicBlock::iterator NI = llvm::next(MBBI);
|
|
||||||
if (NI == MBB.end()) return;
|
|
||||||
|
|
||||||
unsigned Opc = NI->getOpcode();
|
|
||||||
if ((Opc == X86::ADD64ri32 || Opc == X86::ADD64ri8 ||
|
|
||||||
Opc == X86::ADD32ri || Opc == X86::ADD32ri8) &&
|
|
||||||
NI->getOperand(0).getReg() == StackPtr) {
|
|
||||||
if (NumBytes)
|
|
||||||
*NumBytes -= NI->getOperand(2).getImm();
|
|
||||||
MBB.erase(NI);
|
|
||||||
MBBI = NI;
|
|
||||||
} else if ((Opc == X86::SUB64ri32 || Opc == X86::SUB64ri8 ||
|
|
||||||
Opc == X86::SUB32ri || Opc == X86::SUB32ri8) &&
|
|
||||||
NI->getOperand(0).getReg() == StackPtr) {
|
|
||||||
if (NumBytes)
|
|
||||||
*NumBytes += NI->getOperand(2).getImm();
|
|
||||||
MBB.erase(NI);
|
|
||||||
MBBI = NI;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// mergeSPUpdates - Checks the instruction before/after the passed
|
|
||||||
/// instruction. If it is an ADD/SUB instruction it is deleted argument and the
|
|
||||||
/// stack adjustment is returned as a positive value for ADD and a negative for
|
|
||||||
/// SUB.
|
|
||||||
static int mergeSPUpdates(MachineBasicBlock &MBB,
|
|
||||||
MachineBasicBlock::iterator &MBBI,
|
|
||||||
unsigned StackPtr,
|
|
||||||
bool doMergeWithPrevious) {
|
|
||||||
if ((doMergeWithPrevious && MBBI == MBB.begin()) ||
|
|
||||||
(!doMergeWithPrevious && MBBI == MBB.end()))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
MachineBasicBlock::iterator PI = doMergeWithPrevious ? prior(MBBI) : MBBI;
|
|
||||||
MachineBasicBlock::iterator NI = doMergeWithPrevious ? 0 : llvm::next(MBBI);
|
|
||||||
unsigned Opc = PI->getOpcode();
|
|
||||||
int Offset = 0;
|
|
||||||
|
|
||||||
if ((Opc == X86::ADD64ri32 || Opc == X86::ADD64ri8 ||
|
|
||||||
Opc == X86::ADD32ri || Opc == X86::ADD32ri8) &&
|
|
||||||
PI->getOperand(0).getReg() == StackPtr){
|
|
||||||
Offset += PI->getOperand(2).getImm();
|
|
||||||
MBB.erase(PI);
|
|
||||||
if (!doMergeWithPrevious) MBBI = NI;
|
|
||||||
} else if ((Opc == X86::SUB64ri32 || Opc == X86::SUB64ri8 ||
|
|
||||||
Opc == X86::SUB32ri || Opc == X86::SUB32ri8) &&
|
|
||||||
PI->getOperand(0).getReg() == StackPtr) {
|
|
||||||
Offset -= PI->getOperand(2).getImm();
|
|
||||||
MBB.erase(PI);
|
|
||||||
if (!doMergeWithPrevious) MBBI = NI;
|
|
||||||
}
|
|
||||||
|
|
||||||
return Offset;
|
|
||||||
}
|
|
||||||
|
|
||||||
void X86RegisterInfo::emitCalleeSavedFrameMoves(MachineFunction &MF,
|
|
||||||
MCSymbol *Label,
|
|
||||||
unsigned FramePtr) const {
|
|
||||||
MachineFrameInfo *MFI = MF.getFrameInfo();
|
|
||||||
MachineModuleInfo &MMI = MF.getMMI();
|
|
||||||
|
|
||||||
// Add callee saved registers to move list.
|
|
||||||
const std::vector<CalleeSavedInfo> &CSI = MFI->getCalleeSavedInfo();
|
|
||||||
if (CSI.empty()) return;
|
|
||||||
|
|
||||||
std::vector<MachineMove> &Moves = MMI.getFrameMoves();
|
|
||||||
const TargetData *TD = MF.getTarget().getTargetData();
|
|
||||||
bool HasFP = hasFP(MF);
|
|
||||||
|
|
||||||
// Calculate amount of bytes used for return address storing.
|
|
||||||
int stackGrowth =
|
|
||||||
(MF.getTarget().getFrameInfo()->getStackGrowthDirection() ==
|
|
||||||
TargetFrameInfo::StackGrowsUp ?
|
|
||||||
TD->getPointerSize() : -TD->getPointerSize());
|
|
||||||
|
|
||||||
// FIXME: This is dirty hack. The code itself is pretty mess right now.
|
|
||||||
// It should be rewritten from scratch and generalized sometimes.
|
|
||||||
|
|
||||||
// Determine maximum offset (minumum due to stack growth).
|
|
||||||
int64_t MaxOffset = 0;
|
|
||||||
for (std::vector<CalleeSavedInfo>::const_iterator
|
|
||||||
I = CSI.begin(), E = CSI.end(); I != E; ++I)
|
|
||||||
MaxOffset = std::min(MaxOffset,
|
|
||||||
MFI->getObjectOffset(I->getFrameIdx()));
|
|
||||||
|
|
||||||
// Calculate offsets.
|
|
||||||
int64_t saveAreaOffset = (HasFP ? 3 : 2) * stackGrowth;
|
|
||||||
for (std::vector<CalleeSavedInfo>::const_iterator
|
|
||||||
I = CSI.begin(), E = CSI.end(); I != E; ++I) {
|
|
||||||
int64_t Offset = MFI->getObjectOffset(I->getFrameIdx());
|
|
||||||
unsigned Reg = I->getReg();
|
|
||||||
Offset = MaxOffset - Offset + saveAreaOffset;
|
|
||||||
|
|
||||||
// Don't output a new machine move if we're re-saving the frame
|
|
||||||
// pointer. This happens when the PrologEpilogInserter has inserted an extra
|
|
||||||
// "PUSH" of the frame pointer -- the "emitPrologue" method automatically
|
|
||||||
// generates one when frame pointers are used. If we generate a "machine
|
|
||||||
// move" for this extra "PUSH", the linker will lose track of the fact that
|
|
||||||
// the frame pointer should have the value of the first "PUSH" when it's
|
|
||||||
// trying to unwind.
|
|
||||||
//
|
|
||||||
// FIXME: This looks inelegant. It's possibly correct, but it's covering up
|
|
||||||
// another bug. I.e., one where we generate a prolog like this:
|
|
||||||
//
|
|
||||||
// pushl %ebp
|
|
||||||
// movl %esp, %ebp
|
|
||||||
// pushl %ebp
|
|
||||||
// pushl %esi
|
|
||||||
// ...
|
|
||||||
//
|
|
||||||
// The immediate re-push of EBP is unnecessary. At the least, it's an
|
|
||||||
// optimization bug. EBP can be used as a scratch register in certain
|
|
||||||
// cases, but probably not when we have a frame pointer.
|
|
||||||
if (HasFP && FramePtr == Reg)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
MachineLocation CSDst(MachineLocation::VirtualFP, Offset);
|
|
||||||
MachineLocation CSSrc(Reg);
|
|
||||||
Moves.push_back(MachineMove(Label, CSDst, CSSrc));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool isEAXLiveIn(MachineFunction &MF) {
|
|
||||||
for (MachineRegisterInfo::livein_iterator II = MF.getRegInfo().livein_begin(),
|
|
||||||
EE = MF.getRegInfo().livein_end(); II != EE; ++II) {
|
|
||||||
unsigned Reg = II->first;
|
|
||||||
|
|
||||||
if (Reg == X86::EAX || Reg == X86::AX ||
|
|
||||||
Reg == X86::AH || Reg == X86::AL)
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// emitPrologue - Push callee-saved registers onto the stack, which
|
|
||||||
/// automatically adjust the stack pointer. Adjust the stack pointer to allocate
|
|
||||||
/// space for local variables. Also emit labels used by the exception handler to
|
|
||||||
/// generate the exception handling frames.
|
|
||||||
void X86RegisterInfo::emitPrologue(MachineFunction &MF) const {
|
|
||||||
MachineBasicBlock &MBB = MF.front(); // Prologue goes in entry BB.
|
|
||||||
MachineBasicBlock::iterator MBBI = MBB.begin();
|
|
||||||
MachineFrameInfo *MFI = MF.getFrameInfo();
|
|
||||||
const Function *Fn = MF.getFunction();
|
|
||||||
const X86Subtarget *Subtarget = &MF.getTarget().getSubtarget<X86Subtarget>();
|
|
||||||
MachineModuleInfo &MMI = MF.getMMI();
|
|
||||||
X86MachineFunctionInfo *X86FI = MF.getInfo<X86MachineFunctionInfo>();
|
|
||||||
bool needsFrameMoves = MMI.hasDebugInfo() ||
|
|
||||||
!Fn->doesNotThrow() || UnwindTablesMandatory;
|
|
||||||
uint64_t MaxAlign = MFI->getMaxAlignment(); // Desired stack alignment.
|
|
||||||
uint64_t StackSize = MFI->getStackSize(); // Number of bytes to allocate.
|
|
||||||
bool HasFP = hasFP(MF);
|
|
||||||
DebugLoc DL;
|
|
||||||
|
|
||||||
// If we're forcing a stack realignment we can't rely on just the frame
|
|
||||||
// info, we need to know the ABI stack alignment as well in case we
|
|
||||||
// have a call out. Otherwise just make sure we have some alignment - we'll
|
|
||||||
// go with the minimum SlotSize.
|
|
||||||
if (ForceStackAlign) {
|
|
||||||
if (MFI->hasCalls())
|
|
||||||
MaxAlign = (StackAlign > MaxAlign) ? StackAlign : MaxAlign;
|
|
||||||
else if (MaxAlign < SlotSize)
|
|
||||||
MaxAlign = SlotSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add RETADDR move area to callee saved frame size.
|
|
||||||
int TailCallReturnAddrDelta = X86FI->getTCReturnAddrDelta();
|
|
||||||
if (TailCallReturnAddrDelta < 0)
|
|
||||||
X86FI->setCalleeSavedFrameSize(
|
|
||||||
X86FI->getCalleeSavedFrameSize() - TailCallReturnAddrDelta);
|
|
||||||
|
|
||||||
// If this is x86-64 and the Red Zone is not disabled, if we are a leaf
|
|
||||||
// function, and use up to 128 bytes of stack space, don't have a frame
|
|
||||||
// pointer, calls, or dynamic alloca then we do not need to adjust the
|
|
||||||
// stack pointer (we fit in the Red Zone).
|
|
||||||
if (Is64Bit && !Fn->hasFnAttr(Attribute::NoRedZone) &&
|
|
||||||
!needsStackRealignment(MF) &&
|
|
||||||
!MFI->hasVarSizedObjects() && // No dynamic alloca.
|
|
||||||
!MFI->adjustsStack() && // No calls.
|
|
||||||
!IsWin64) { // Win64 has no Red Zone
|
|
||||||
uint64_t MinSize = X86FI->getCalleeSavedFrameSize();
|
|
||||||
if (HasFP) MinSize += SlotSize;
|
|
||||||
StackSize = std::max(MinSize, StackSize > 128 ? StackSize - 128 : 0);
|
|
||||||
MFI->setStackSize(StackSize);
|
|
||||||
} else if (IsWin64) {
|
|
||||||
// We need to always allocate 32 bytes as register spill area.
|
|
||||||
// FIXME: We might reuse these 32 bytes for leaf functions.
|
|
||||||
StackSize += 32;
|
|
||||||
MFI->setStackSize(StackSize);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Insert stack pointer adjustment for later moving of return addr. Only
|
|
||||||
// applies to tail call optimized functions where the callee argument stack
|
|
||||||
// size is bigger than the callers.
|
|
||||||
if (TailCallReturnAddrDelta < 0) {
|
|
||||||
MachineInstr *MI =
|
|
||||||
BuildMI(MBB, MBBI, DL,
|
|
||||||
TII.get(getSUBriOpcode(Is64Bit, -TailCallReturnAddrDelta)),
|
|
||||||
StackPtr)
|
|
||||||
.addReg(StackPtr)
|
|
||||||
.addImm(-TailCallReturnAddrDelta);
|
|
||||||
MI->getOperand(3).setIsDead(); // The EFLAGS implicit def is dead.
|
|
||||||
}
|
|
||||||
|
|
||||||
// Mapping for machine moves:
|
|
||||||
//
|
|
||||||
// DST: VirtualFP AND
|
|
||||||
// SRC: VirtualFP => DW_CFA_def_cfa_offset
|
|
||||||
// ELSE => DW_CFA_def_cfa
|
|
||||||
//
|
|
||||||
// SRC: VirtualFP AND
|
|
||||||
// DST: Register => DW_CFA_def_cfa_register
|
|
||||||
//
|
|
||||||
// ELSE
|
|
||||||
// OFFSET < 0 => DW_CFA_offset_extended_sf
|
|
||||||
// REG < 64 => DW_CFA_offset + Reg
|
|
||||||
// ELSE => DW_CFA_offset_extended
|
|
||||||
|
|
||||||
std::vector<MachineMove> &Moves = MMI.getFrameMoves();
|
|
||||||
const TargetData *TD = MF.getTarget().getTargetData();
|
|
||||||
uint64_t NumBytes = 0;
|
|
||||||
int stackGrowth = -TD->getPointerSize();
|
|
||||||
|
|
||||||
if (HasFP) {
|
|
||||||
// Calculate required stack adjustment.
|
|
||||||
uint64_t FrameSize = StackSize - SlotSize;
|
|
||||||
if (needsStackRealignment(MF))
|
|
||||||
FrameSize = (FrameSize + MaxAlign - 1) / MaxAlign * MaxAlign;
|
|
||||||
|
|
||||||
NumBytes = FrameSize - X86FI->getCalleeSavedFrameSize();
|
|
||||||
|
|
||||||
// Get the offset of the stack slot for the EBP register, which is
|
|
||||||
// guaranteed to be the last slot by processFunctionBeforeFrameFinalized.
|
|
||||||
// Update the frame offset adjustment.
|
|
||||||
MFI->setOffsetAdjustment(-NumBytes);
|
|
||||||
|
|
||||||
// Save EBP/RBP into the appropriate stack slot.
|
|
||||||
BuildMI(MBB, MBBI, DL, TII.get(Is64Bit ? X86::PUSH64r : X86::PUSH32r))
|
|
||||||
.addReg(FramePtr, RegState::Kill);
|
|
||||||
|
|
||||||
if (needsFrameMoves) {
|
|
||||||
// Mark the place where EBP/RBP was saved.
|
|
||||||
MCSymbol *FrameLabel = MMI.getContext().CreateTempSymbol();
|
|
||||||
BuildMI(MBB, MBBI, DL, TII.get(X86::PROLOG_LABEL)).addSym(FrameLabel);
|
|
||||||
|
|
||||||
// Define the current CFA rule to use the provided offset.
|
|
||||||
if (StackSize) {
|
|
||||||
MachineLocation SPDst(MachineLocation::VirtualFP);
|
|
||||||
MachineLocation SPSrc(MachineLocation::VirtualFP, 2 * stackGrowth);
|
|
||||||
Moves.push_back(MachineMove(FrameLabel, SPDst, SPSrc));
|
|
||||||
} else {
|
|
||||||
// FIXME: Verify & implement for FP
|
|
||||||
MachineLocation SPDst(StackPtr);
|
|
||||||
MachineLocation SPSrc(StackPtr, stackGrowth);
|
|
||||||
Moves.push_back(MachineMove(FrameLabel, SPDst, SPSrc));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Change the rule for the FramePtr to be an "offset" rule.
|
|
||||||
MachineLocation FPDst(MachineLocation::VirtualFP, 2 * stackGrowth);
|
|
||||||
MachineLocation FPSrc(FramePtr);
|
|
||||||
Moves.push_back(MachineMove(FrameLabel, FPDst, FPSrc));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update EBP with the new base value...
|
|
||||||
BuildMI(MBB, MBBI, DL,
|
|
||||||
TII.get(Is64Bit ? X86::MOV64rr : X86::MOV32rr), FramePtr)
|
|
||||||
.addReg(StackPtr);
|
|
||||||
|
|
||||||
if (needsFrameMoves) {
|
|
||||||
// Mark effective beginning of when frame pointer becomes valid.
|
|
||||||
MCSymbol *FrameLabel = MMI.getContext().CreateTempSymbol();
|
|
||||||
BuildMI(MBB, MBBI, DL, TII.get(X86::PROLOG_LABEL)).addSym(FrameLabel);
|
|
||||||
|
|
||||||
// Define the current CFA to use the EBP/RBP register.
|
|
||||||
MachineLocation FPDst(FramePtr);
|
|
||||||
MachineLocation FPSrc(MachineLocation::VirtualFP);
|
|
||||||
Moves.push_back(MachineMove(FrameLabel, FPDst, FPSrc));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Mark the FramePtr as live-in in every block except the entry.
|
|
||||||
for (MachineFunction::iterator I = llvm::next(MF.begin()), E = MF.end();
|
|
||||||
I != E; ++I)
|
|
||||||
I->addLiveIn(FramePtr);
|
|
||||||
|
|
||||||
// Realign stack
|
|
||||||
if (needsStackRealignment(MF)) {
|
|
||||||
MachineInstr *MI =
|
|
||||||
BuildMI(MBB, MBBI, DL,
|
|
||||||
TII.get(Is64Bit ? X86::AND64ri32 : X86::AND32ri),
|
|
||||||
StackPtr).addReg(StackPtr).addImm(-MaxAlign);
|
|
||||||
|
|
||||||
// The EFLAGS implicit def is dead.
|
|
||||||
MI->getOperand(3).setIsDead();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
NumBytes = StackSize - X86FI->getCalleeSavedFrameSize();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Skip the callee-saved push instructions.
|
|
||||||
bool PushedRegs = false;
|
|
||||||
int StackOffset = 2 * stackGrowth;
|
|
||||||
|
|
||||||
while (MBBI != MBB.end() &&
|
|
||||||
(MBBI->getOpcode() == X86::PUSH32r ||
|
|
||||||
MBBI->getOpcode() == X86::PUSH64r)) {
|
|
||||||
PushedRegs = true;
|
|
||||||
++MBBI;
|
|
||||||
|
|
||||||
if (!HasFP && needsFrameMoves) {
|
|
||||||
// Mark callee-saved push instruction.
|
|
||||||
MCSymbol *Label = MMI.getContext().CreateTempSymbol();
|
|
||||||
BuildMI(MBB, MBBI, DL, TII.get(X86::PROLOG_LABEL)).addSym(Label);
|
|
||||||
|
|
||||||
// Define the current CFA rule to use the provided offset.
|
|
||||||
unsigned Ptr = StackSize ?
|
|
||||||
MachineLocation::VirtualFP : StackPtr;
|
|
||||||
MachineLocation SPDst(Ptr);
|
|
||||||
MachineLocation SPSrc(Ptr, StackOffset);
|
|
||||||
Moves.push_back(MachineMove(Label, SPDst, SPSrc));
|
|
||||||
StackOffset += stackGrowth;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
DL = MBB.findDebugLoc(MBBI);
|
|
||||||
|
|
||||||
// If there is an SUB32ri of ESP immediately before this instruction, merge
|
|
||||||
// the two. This can be the case when tail call elimination is enabled and
|
|
||||||
// the callee has more arguments then the caller.
|
|
||||||
NumBytes -= mergeSPUpdates(MBB, MBBI, StackPtr, true);
|
|
||||||
|
|
||||||
// If there is an ADD32ri or SUB32ri of ESP immediately after this
|
|
||||||
// instruction, merge the two instructions.
|
|
||||||
mergeSPUpdatesDown(MBB, MBBI, StackPtr, &NumBytes);
|
|
||||||
|
|
||||||
// Adjust stack pointer: ESP -= numbytes.
|
|
||||||
|
|
||||||
// Windows and cygwin/mingw require a prologue helper routine when allocating
|
|
||||||
// more than 4K bytes on the stack. Windows uses __chkstk and cygwin/mingw
|
|
||||||
// uses __alloca. __alloca and the 32-bit version of __chkstk will probe the
|
|
||||||
// stack and adjust the stack pointer in one go. The 64-bit version of
|
|
||||||
// __chkstk is only responsible for probing the stack. The 64-bit prologue is
|
|
||||||
// responsible for adjusting the stack pointer. Touching the stack at 4K
|
|
||||||
// increments is necessary to ensure that the guard pages used by the OS
|
|
||||||
// virtual memory manager are allocated in correct sequence.
|
|
||||||
if (NumBytes >= 4096 &&
|
|
||||||
(Subtarget->isTargetCygMing() || Subtarget->isTargetWin32())) {
|
|
||||||
// Check whether EAX is livein for this function.
|
|
||||||
bool isEAXAlive = isEAXLiveIn(MF);
|
|
||||||
|
|
||||||
const char *StackProbeSymbol =
|
|
||||||
Subtarget->isTargetWindows() ? "_chkstk" : "_alloca";
|
|
||||||
unsigned CallOp = Is64Bit ? X86::CALL64pcrel32 : X86::CALLpcrel32;
|
|
||||||
if (!isEAXAlive) {
|
|
||||||
BuildMI(MBB, MBBI, DL, TII.get(X86::MOV32ri), X86::EAX)
|
|
||||||
.addImm(NumBytes);
|
|
||||||
BuildMI(MBB, MBBI, DL, TII.get(CallOp))
|
|
||||||
.addExternalSymbol(StackProbeSymbol)
|
|
||||||
.addReg(StackPtr, RegState::Define | RegState::Implicit)
|
|
||||||
.addReg(X86::EFLAGS, RegState::Define | RegState::Implicit);
|
|
||||||
} else {
|
|
||||||
// Save EAX
|
|
||||||
BuildMI(MBB, MBBI, DL, TII.get(X86::PUSH32r))
|
|
||||||
.addReg(X86::EAX, RegState::Kill);
|
|
||||||
|
|
||||||
// Allocate NumBytes-4 bytes on stack. We'll also use 4 already
|
|
||||||
// allocated bytes for EAX.
|
|
||||||
BuildMI(MBB, MBBI, DL, TII.get(X86::MOV32ri), X86::EAX)
|
|
||||||
.addImm(NumBytes - 4);
|
|
||||||
BuildMI(MBB, MBBI, DL, TII.get(CallOp))
|
|
||||||
.addExternalSymbol(StackProbeSymbol)
|
|
||||||
.addReg(StackPtr, RegState::Define | RegState::Implicit)
|
|
||||||
.addReg(X86::EFLAGS, RegState::Define | RegState::Implicit);
|
|
||||||
|
|
||||||
// Restore EAX
|
|
||||||
MachineInstr *MI = addRegOffset(BuildMI(MF, DL, TII.get(X86::MOV32rm),
|
|
||||||
X86::EAX),
|
|
||||||
StackPtr, false, NumBytes - 4);
|
|
||||||
MBB.insert(MBBI, MI);
|
|
||||||
}
|
|
||||||
} else if (NumBytes >= 4096 && Subtarget->isTargetWin64()) {
|
|
||||||
// Sanity check that EAX is not livein for this function. It should
|
|
||||||
// should not be, so throw an assert.
|
|
||||||
assert(!isEAXLiveIn(MF) && "EAX is livein in the Win64 case!");
|
|
||||||
|
|
||||||
// Handle the 64-bit Windows ABI case where we need to call __chkstk.
|
|
||||||
// Function prologue is responsible for adjusting the stack pointer.
|
|
||||||
BuildMI(MBB, MBBI, DL, TII.get(X86::MOV32ri), X86::EAX)
|
|
||||||
.addImm(NumBytes);
|
|
||||||
BuildMI(MBB, MBBI, DL, TII.get(X86::WINCALL64pcrel32))
|
|
||||||
.addExternalSymbol("__chkstk")
|
|
||||||
.addReg(StackPtr, RegState::Define | RegState::Implicit);
|
|
||||||
emitSPUpdate(MBB, MBBI, StackPtr, -(int64_t)NumBytes, Is64Bit, TII);
|
|
||||||
} else if (NumBytes)
|
|
||||||
emitSPUpdate(MBB, MBBI, StackPtr, -(int64_t)NumBytes, Is64Bit, TII);
|
|
||||||
|
|
||||||
if ((NumBytes || PushedRegs) && needsFrameMoves) {
|
|
||||||
// Mark end of stack pointer adjustment.
|
|
||||||
MCSymbol *Label = MMI.getContext().CreateTempSymbol();
|
|
||||||
BuildMI(MBB, MBBI, DL, TII.get(X86::PROLOG_LABEL)).addSym(Label);
|
|
||||||
|
|
||||||
if (!HasFP && NumBytes) {
|
|
||||||
// Define the current CFA rule to use the provided offset.
|
|
||||||
if (StackSize) {
|
|
||||||
MachineLocation SPDst(MachineLocation::VirtualFP);
|
|
||||||
MachineLocation SPSrc(MachineLocation::VirtualFP,
|
|
||||||
-StackSize + stackGrowth);
|
|
||||||
Moves.push_back(MachineMove(Label, SPDst, SPSrc));
|
|
||||||
} else {
|
|
||||||
// FIXME: Verify & implement for FP
|
|
||||||
MachineLocation SPDst(StackPtr);
|
|
||||||
MachineLocation SPSrc(StackPtr, stackGrowth);
|
|
||||||
Moves.push_back(MachineMove(Label, SPDst, SPSrc));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Emit DWARF info specifying the offsets of the callee-saved registers.
|
|
||||||
if (PushedRegs)
|
|
||||||
emitCalleeSavedFrameMoves(MF, Label, HasFP ? FramePtr : StackPtr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void X86RegisterInfo::emitEpilogue(MachineFunction &MF,
|
|
||||||
MachineBasicBlock &MBB) const {
|
|
||||||
const MachineFrameInfo *MFI = MF.getFrameInfo();
|
|
||||||
X86MachineFunctionInfo *X86FI = MF.getInfo<X86MachineFunctionInfo>();
|
|
||||||
MachineBasicBlock::iterator MBBI = prior(MBB.end());
|
|
||||||
unsigned RetOpcode = MBBI->getOpcode();
|
|
||||||
DebugLoc DL = MBBI->getDebugLoc();
|
|
||||||
|
|
||||||
switch (RetOpcode) {
|
|
||||||
default:
|
|
||||||
llvm_unreachable("Can only insert epilog into returning blocks");
|
|
||||||
case X86::RET:
|
|
||||||
case X86::RETI:
|
|
||||||
case X86::TCRETURNdi:
|
|
||||||
case X86::TCRETURNri:
|
|
||||||
case X86::TCRETURNmi:
|
|
||||||
case X86::TCRETURNdi64:
|
|
||||||
case X86::TCRETURNri64:
|
|
||||||
case X86::TCRETURNmi64:
|
|
||||||
case X86::EH_RETURN:
|
|
||||||
case X86::EH_RETURN64:
|
|
||||||
break; // These are ok
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get the number of bytes to allocate from the FrameInfo.
|
|
||||||
uint64_t StackSize = MFI->getStackSize();
|
|
||||||
uint64_t MaxAlign = MFI->getMaxAlignment();
|
|
||||||
unsigned CSSize = X86FI->getCalleeSavedFrameSize();
|
|
||||||
uint64_t NumBytes = 0;
|
|
||||||
|
|
||||||
// If we're forcing a stack realignment we can't rely on just the frame
|
|
||||||
// info, we need to know the ABI stack alignment as well in case we
|
|
||||||
// have a call out. Otherwise just make sure we have some alignment - we'll
|
|
||||||
// go with the minimum.
|
|
||||||
if (ForceStackAlign) {
|
|
||||||
if (MFI->hasCalls())
|
|
||||||
MaxAlign = (StackAlign > MaxAlign) ? StackAlign : MaxAlign;
|
|
||||||
else
|
|
||||||
MaxAlign = MaxAlign ? MaxAlign : 4;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (hasFP(MF)) {
|
|
||||||
// Calculate required stack adjustment.
|
|
||||||
uint64_t FrameSize = StackSize - SlotSize;
|
|
||||||
if (needsStackRealignment(MF))
|
|
||||||
FrameSize = (FrameSize + MaxAlign - 1)/MaxAlign*MaxAlign;
|
|
||||||
|
|
||||||
NumBytes = FrameSize - CSSize;
|
|
||||||
|
|
||||||
// Pop EBP.
|
|
||||||
BuildMI(MBB, MBBI, DL,
|
|
||||||
TII.get(Is64Bit ? X86::POP64r : X86::POP32r), FramePtr);
|
|
||||||
} else {
|
|
||||||
NumBytes = StackSize - CSSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Skip the callee-saved pop instructions.
|
|
||||||
MachineBasicBlock::iterator LastCSPop = MBBI;
|
|
||||||
while (MBBI != MBB.begin()) {
|
|
||||||
MachineBasicBlock::iterator PI = prior(MBBI);
|
|
||||||
unsigned Opc = PI->getOpcode();
|
|
||||||
|
|
||||||
if (Opc != X86::POP32r && Opc != X86::POP64r &&
|
|
||||||
!PI->getDesc().isTerminator())
|
|
||||||
break;
|
|
||||||
|
|
||||||
--MBBI;
|
|
||||||
}
|
|
||||||
|
|
||||||
DL = MBBI->getDebugLoc();
|
|
||||||
|
|
||||||
// If there is an ADD32ri or SUB32ri of ESP immediately before this
|
|
||||||
// instruction, merge the two instructions.
|
|
||||||
if (NumBytes || MFI->hasVarSizedObjects())
|
|
||||||
mergeSPUpdatesUp(MBB, MBBI, StackPtr, &NumBytes);
|
|
||||||
|
|
||||||
// If dynamic alloca is used, then reset esp to point to the last callee-saved
|
|
||||||
// slot before popping them off! Same applies for the case, when stack was
|
|
||||||
// realigned.
|
|
||||||
if (needsStackRealignment(MF)) {
|
|
||||||
// We cannot use LEA here, because stack pointer was realigned. We need to
|
|
||||||
// deallocate local frame back.
|
|
||||||
if (CSSize) {
|
|
||||||
emitSPUpdate(MBB, MBBI, StackPtr, NumBytes, Is64Bit, TII);
|
|
||||||
MBBI = prior(LastCSPop);
|
|
||||||
}
|
|
||||||
|
|
||||||
BuildMI(MBB, MBBI, DL,
|
|
||||||
TII.get(Is64Bit ? X86::MOV64rr : X86::MOV32rr),
|
|
||||||
StackPtr).addReg(FramePtr);
|
|
||||||
} else if (MFI->hasVarSizedObjects()) {
|
|
||||||
if (CSSize) {
|
|
||||||
unsigned Opc = Is64Bit ? X86::LEA64r : X86::LEA32r;
|
|
||||||
MachineInstr *MI =
|
|
||||||
addRegOffset(BuildMI(MF, DL, TII.get(Opc), StackPtr),
|
|
||||||
FramePtr, false, -CSSize);
|
|
||||||
MBB.insert(MBBI, MI);
|
|
||||||
} else {
|
|
||||||
BuildMI(MBB, MBBI, DL,
|
|
||||||
TII.get(Is64Bit ? X86::MOV64rr : X86::MOV32rr), StackPtr)
|
|
||||||
.addReg(FramePtr);
|
|
||||||
}
|
|
||||||
} else if (NumBytes) {
|
|
||||||
// Adjust stack pointer back: ESP += numbytes.
|
|
||||||
emitSPUpdate(MBB, MBBI, StackPtr, NumBytes, Is64Bit, TII);
|
|
||||||
}
|
|
||||||
|
|
||||||
// We're returning from function via eh_return.
|
|
||||||
if (RetOpcode == X86::EH_RETURN || RetOpcode == X86::EH_RETURN64) {
|
|
||||||
MBBI = prior(MBB.end());
|
|
||||||
MachineOperand &DestAddr = MBBI->getOperand(0);
|
|
||||||
assert(DestAddr.isReg() && "Offset should be in register!");
|
|
||||||
BuildMI(MBB, MBBI, DL,
|
|
||||||
TII.get(Is64Bit ? X86::MOV64rr : X86::MOV32rr),
|
|
||||||
StackPtr).addReg(DestAddr.getReg());
|
|
||||||
} else if (RetOpcode == X86::TCRETURNri || RetOpcode == X86::TCRETURNdi ||
|
|
||||||
RetOpcode == X86::TCRETURNmi ||
|
|
||||||
RetOpcode == X86::TCRETURNri64 || RetOpcode == X86::TCRETURNdi64 ||
|
|
||||||
RetOpcode == X86::TCRETURNmi64) {
|
|
||||||
bool isMem = RetOpcode == X86::TCRETURNmi || RetOpcode == X86::TCRETURNmi64;
|
|
||||||
// Tail call return: adjust the stack pointer and jump to callee.
|
|
||||||
MBBI = prior(MBB.end());
|
|
||||||
MachineOperand &JumpTarget = MBBI->getOperand(0);
|
|
||||||
MachineOperand &StackAdjust = MBBI->getOperand(isMem ? 5 : 1);
|
|
||||||
assert(StackAdjust.isImm() && "Expecting immediate value.");
|
|
||||||
|
|
||||||
// Adjust stack pointer.
|
|
||||||
int StackAdj = StackAdjust.getImm();
|
|
||||||
int MaxTCDelta = X86FI->getTCReturnAddrDelta();
|
|
||||||
int Offset = 0;
|
|
||||||
assert(MaxTCDelta <= 0 && "MaxTCDelta should never be positive");
|
|
||||||
|
|
||||||
// Incoporate the retaddr area.
|
|
||||||
Offset = StackAdj-MaxTCDelta;
|
|
||||||
assert(Offset >= 0 && "Offset should never be negative");
|
|
||||||
|
|
||||||
if (Offset) {
|
|
||||||
// Check for possible merge with preceeding ADD instruction.
|
|
||||||
Offset += mergeSPUpdates(MBB, MBBI, StackPtr, true);
|
|
||||||
emitSPUpdate(MBB, MBBI, StackPtr, Offset, Is64Bit, TII);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Jump to label or value in register.
|
|
||||||
if (RetOpcode == X86::TCRETURNdi || RetOpcode == X86::TCRETURNdi64) {
|
|
||||||
BuildMI(MBB, MBBI, DL, TII.get((RetOpcode == X86::TCRETURNdi)
|
|
||||||
? X86::TAILJMPd : X86::TAILJMPd64)).
|
|
||||||
addGlobalAddress(JumpTarget.getGlobal(), JumpTarget.getOffset(),
|
|
||||||
JumpTarget.getTargetFlags());
|
|
||||||
} else if (RetOpcode == X86::TCRETURNmi || RetOpcode == X86::TCRETURNmi64) {
|
|
||||||
MachineInstrBuilder MIB =
|
|
||||||
BuildMI(MBB, MBBI, DL, TII.get((RetOpcode == X86::TCRETURNmi)
|
|
||||||
? X86::TAILJMPm : X86::TAILJMPm64));
|
|
||||||
for (unsigned i = 0; i != 5; ++i)
|
|
||||||
MIB.addOperand(MBBI->getOperand(i));
|
|
||||||
} else if (RetOpcode == X86::TCRETURNri64) {
|
|
||||||
BuildMI(MBB, MBBI, DL, TII.get(X86::TAILJMPr64)).
|
|
||||||
addReg(JumpTarget.getReg(), RegState::Kill);
|
|
||||||
} else {
|
|
||||||
BuildMI(MBB, MBBI, DL, TII.get(X86::TAILJMPr)).
|
|
||||||
addReg(JumpTarget.getReg(), RegState::Kill);
|
|
||||||
}
|
|
||||||
|
|
||||||
MachineInstr *NewMI = prior(MBBI);
|
|
||||||
for (unsigned i = 2, e = MBBI->getNumOperands(); i != e; ++i)
|
|
||||||
NewMI->addOperand(MBBI->getOperand(i));
|
|
||||||
|
|
||||||
// Delete the pseudo instruction TCRETURN.
|
|
||||||
MBB.erase(MBBI);
|
|
||||||
} else if ((RetOpcode == X86::RET || RetOpcode == X86::RETI) &&
|
|
||||||
(X86FI->getTCReturnAddrDelta() < 0)) {
|
|
||||||
// Add the return addr area delta back since we are not tail calling.
|
|
||||||
int delta = -1*X86FI->getTCReturnAddrDelta();
|
|
||||||
MBBI = prior(MBB.end());
|
|
||||||
|
|
||||||
// Check for possible merge with preceeding ADD instruction.
|
|
||||||
delta += mergeSPUpdates(MBB, MBBI, StackPtr, true);
|
|
||||||
emitSPUpdate(MBB, MBBI, StackPtr, delta, Is64Bit, TII);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned X86RegisterInfo::getRARegister() const {
|
unsigned X86RegisterInfo::getRARegister() const {
|
||||||
return Is64Bit ? X86::RIP // Should have dwarf #16.
|
return Is64Bit ? X86::RIP // Should have dwarf #16.
|
||||||
: X86::EIP; // Should have dwarf #8.
|
: X86::EIP; // Should have dwarf #8.
|
||||||
|
|
|
@ -132,14 +132,13 @@ public:
|
||||||
void processFunctionBeforeCalleeSavedScan(MachineFunction &MF,
|
void processFunctionBeforeCalleeSavedScan(MachineFunction &MF,
|
||||||
RegScavenger *RS = NULL) const;
|
RegScavenger *RS = NULL) const;
|
||||||
|
|
||||||
void emitCalleeSavedFrameMoves(MachineFunction &MF, MCSymbol *Label,
|
|
||||||
unsigned FramePtr) const;
|
|
||||||
void emitPrologue(MachineFunction &MF) const;
|
|
||||||
void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const;
|
|
||||||
|
|
||||||
// Debug information queries.
|
// Debug information queries.
|
||||||
unsigned getRARegister() const;
|
unsigned getRARegister() const;
|
||||||
unsigned getFrameRegister(const MachineFunction &MF) const;
|
unsigned getFrameRegister(const MachineFunction &MF) const;
|
||||||
|
unsigned getStackRegister() const { return StackPtr; }
|
||||||
|
// FIXME: Move to FrameInfok
|
||||||
|
unsigned getSlotSize() const { return SlotSize; }
|
||||||
|
|
||||||
int getFrameIndexOffset(const MachineFunction &MF, int FI) const;
|
int getFrameIndexOffset(const MachineFunction &MF, int FI) const;
|
||||||
void getInitialFrameState(std::vector<MachineMove> &Moves) const;
|
void getInitialFrameState(std::vector<MachineMove> &Moves) const;
|
||||||
|
|
||||||
|
|
|
@ -119,10 +119,7 @@ X86TargetMachine::X86TargetMachine(const Target &T, const std::string &TT,
|
||||||
const std::string &FS, bool is64Bit)
|
const std::string &FS, bool is64Bit)
|
||||||
: LLVMTargetMachine(T, TT),
|
: LLVMTargetMachine(T, TT),
|
||||||
Subtarget(TT, FS, is64Bit),
|
Subtarget(TT, FS, is64Bit),
|
||||||
FrameInfo(TargetFrameInfo::StackGrowsDown,
|
FrameInfo(Subtarget),
|
||||||
Subtarget.getStackAlignment(),
|
|
||||||
(Subtarget.isTargetWin64() ? -40 :
|
|
||||||
(Subtarget.is64Bit() ? -8 : -4))),
|
|
||||||
ELFWriterInfo(is64Bit, true) {
|
ELFWriterInfo(is64Bit, true) {
|
||||||
DefRelocModel = getRelocationModel();
|
DefRelocModel = getRelocationModel();
|
||||||
|
|
||||||
|
|
|
@ -14,16 +14,17 @@
|
||||||
#ifndef X86TARGETMACHINE_H
|
#ifndef X86TARGETMACHINE_H
|
||||||
#define X86TARGETMACHINE_H
|
#define X86TARGETMACHINE_H
|
||||||
|
|
||||||
#include "llvm/Target/TargetMachine.h"
|
|
||||||
#include "llvm/Target/TargetData.h"
|
|
||||||
#include "llvm/Target/TargetFrameInfo.h"
|
|
||||||
#include "X86.h"
|
#include "X86.h"
|
||||||
#include "X86ELFWriterInfo.h"
|
#include "X86ELFWriterInfo.h"
|
||||||
#include "X86InstrInfo.h"
|
#include "X86InstrInfo.h"
|
||||||
#include "X86JITInfo.h"
|
|
||||||
#include "X86Subtarget.h"
|
|
||||||
#include "X86ISelLowering.h"
|
#include "X86ISelLowering.h"
|
||||||
|
#include "X86FrameInfo.h"
|
||||||
|
#include "X86JITInfo.h"
|
||||||
#include "X86SelectionDAGInfo.h"
|
#include "X86SelectionDAGInfo.h"
|
||||||
|
#include "X86Subtarget.h"
|
||||||
|
#include "llvm/Target/TargetMachine.h"
|
||||||
|
#include "llvm/Target/TargetData.h"
|
||||||
|
#include "llvm/Target/TargetFrameInfo.h"
|
||||||
|
|
||||||
namespace llvm {
|
namespace llvm {
|
||||||
|
|
||||||
|
@ -31,7 +32,7 @@ class formatted_raw_ostream;
|
||||||
|
|
||||||
class X86TargetMachine : public LLVMTargetMachine {
|
class X86TargetMachine : public LLVMTargetMachine {
|
||||||
X86Subtarget Subtarget;
|
X86Subtarget Subtarget;
|
||||||
TargetFrameInfo FrameInfo;
|
X86FrameInfo FrameInfo;
|
||||||
X86ELFWriterInfo ELFWriterInfo;
|
X86ELFWriterInfo ELFWriterInfo;
|
||||||
Reloc::Model DefRelocModel; // Reloc model before it's overridden.
|
Reloc::Model DefRelocModel; // Reloc model before it's overridden.
|
||||||
|
|
||||||
|
|
|
@ -14,14 +14,251 @@
|
||||||
|
|
||||||
#include "XCore.h"
|
#include "XCore.h"
|
||||||
#include "XCoreFrameInfo.h"
|
#include "XCoreFrameInfo.h"
|
||||||
|
#include "XCoreInstrInfo.h"
|
||||||
|
#include "XCoreMachineFunctionInfo.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/ErrorHandling.h"
|
||||||
|
|
||||||
using namespace llvm;
|
using namespace llvm;
|
||||||
|
|
||||||
|
// helper functions. FIXME: Eliminate.
|
||||||
|
static inline bool isImmUs(unsigned val) {
|
||||||
|
return val <= 11;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline bool isImmU6(unsigned val) {
|
||||||
|
return val < (1 << 6);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline bool isImmU16(unsigned val) {
|
||||||
|
return val < (1 << 16);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void loadFromStack(MachineBasicBlock &MBB,
|
||||||
|
MachineBasicBlock::iterator I,
|
||||||
|
unsigned DstReg, int Offset, DebugLoc dl,
|
||||||
|
const TargetInstrInfo &TII) {
|
||||||
|
assert(Offset%4 == 0 && "Misaligned stack offset");
|
||||||
|
Offset/=4;
|
||||||
|
bool isU6 = isImmU6(Offset);
|
||||||
|
if (!isU6 && !isImmU16(Offset))
|
||||||
|
report_fatal_error("loadFromStack offset too big " + Twine(Offset));
|
||||||
|
int Opcode = isU6 ? XCore::LDWSP_ru6 : XCore::LDWSP_lru6;
|
||||||
|
BuildMI(MBB, I, dl, TII.get(Opcode), DstReg)
|
||||||
|
.addImm(Offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void storeToStack(MachineBasicBlock &MBB,
|
||||||
|
MachineBasicBlock::iterator I,
|
||||||
|
unsigned SrcReg, int Offset, DebugLoc dl,
|
||||||
|
const TargetInstrInfo &TII) {
|
||||||
|
assert(Offset%4 == 0 && "Misaligned stack offset");
|
||||||
|
Offset/=4;
|
||||||
|
bool isU6 = isImmU6(Offset);
|
||||||
|
if (!isU6 && !isImmU16(Offset))
|
||||||
|
report_fatal_error("storeToStack offset too big " + Twine(Offset));
|
||||||
|
int Opcode = isU6 ? XCore::STWSP_ru6 : XCore::STWSP_lru6;
|
||||||
|
BuildMI(MBB, I, dl, TII.get(Opcode))
|
||||||
|
.addReg(SrcReg)
|
||||||
|
.addImm(Offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
// XCoreFrameInfo:
|
// XCoreFrameInfo:
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
XCoreFrameInfo::XCoreFrameInfo(const TargetMachine &tm):
|
XCoreFrameInfo::XCoreFrameInfo(const XCoreSubtarget &sti)
|
||||||
TargetFrameInfo(TargetFrameInfo::StackGrowsDown, 4, 0)
|
: TargetFrameInfo(TargetFrameInfo::StackGrowsDown, 4, 0),
|
||||||
{
|
STI(sti) {
|
||||||
// Do nothing
|
// Do nothing
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void XCoreFrameInfo::emitPrologue(MachineFunction &MF) const {
|
||||||
|
MachineBasicBlock &MBB = MF.front(); // Prolog goes in entry BB
|
||||||
|
MachineBasicBlock::iterator MBBI = MBB.begin();
|
||||||
|
MachineFrameInfo *MFI = MF.getFrameInfo();
|
||||||
|
MachineModuleInfo *MMI = &MF.getMMI();
|
||||||
|
const XCoreRegisterInfo *RegInfo =
|
||||||
|
static_cast<const XCoreRegisterInfo*>(MF.getTarget().getRegisterInfo());
|
||||||
|
const XCoreInstrInfo &TII =
|
||||||
|
*static_cast<const XCoreInstrInfo*>(MF.getTarget().getInstrInfo());
|
||||||
|
XCoreFunctionInfo *XFI = MF.getInfo<XCoreFunctionInfo>();
|
||||||
|
DebugLoc dl = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc();
|
||||||
|
|
||||||
|
bool FP = RegInfo->hasFP(MF);
|
||||||
|
|
||||||
|
// Work out frame sizes.
|
||||||
|
int FrameSize = MFI->getStackSize();
|
||||||
|
assert(FrameSize%4 == 0 && "Misaligned frame size");
|
||||||
|
FrameSize/=4;
|
||||||
|
|
||||||
|
bool isU6 = isImmU6(FrameSize);
|
||||||
|
|
||||||
|
if (!isU6 && !isImmU16(FrameSize)) {
|
||||||
|
// FIXME could emit multiple instructions.
|
||||||
|
report_fatal_error("emitPrologue Frame size too big: " + Twine(FrameSize));
|
||||||
|
}
|
||||||
|
bool emitFrameMoves = RegInfo->needsFrameMoves(MF);
|
||||||
|
|
||||||
|
// Do we need to allocate space on the stack?
|
||||||
|
if (FrameSize) {
|
||||||
|
bool saveLR = XFI->getUsesLR();
|
||||||
|
bool LRSavedOnEntry = false;
|
||||||
|
int Opcode;
|
||||||
|
if (saveLR && (MFI->getObjectOffset(XFI->getLRSpillSlot()) == 0)) {
|
||||||
|
Opcode = (isU6) ? XCore::ENTSP_u6 : XCore::ENTSP_lu6;
|
||||||
|
MBB.addLiveIn(XCore::LR);
|
||||||
|
saveLR = false;
|
||||||
|
LRSavedOnEntry = true;
|
||||||
|
} else {
|
||||||
|
Opcode = (isU6) ? XCore::EXTSP_u6 : XCore::EXTSP_lu6;
|
||||||
|
}
|
||||||
|
BuildMI(MBB, MBBI, dl, TII.get(Opcode)).addImm(FrameSize);
|
||||||
|
|
||||||
|
if (emitFrameMoves) {
|
||||||
|
std::vector<MachineMove> &Moves = MMI->getFrameMoves();
|
||||||
|
|
||||||
|
// Show update of SP.
|
||||||
|
MCSymbol *FrameLabel = MMI->getContext().CreateTempSymbol();
|
||||||
|
BuildMI(MBB, MBBI, dl, TII.get(XCore::PROLOG_LABEL)).addSym(FrameLabel);
|
||||||
|
|
||||||
|
MachineLocation SPDst(MachineLocation::VirtualFP);
|
||||||
|
MachineLocation SPSrc(MachineLocation::VirtualFP, -FrameSize * 4);
|
||||||
|
Moves.push_back(MachineMove(FrameLabel, SPDst, SPSrc));
|
||||||
|
|
||||||
|
if (LRSavedOnEntry) {
|
||||||
|
MachineLocation CSDst(MachineLocation::VirtualFP, 0);
|
||||||
|
MachineLocation CSSrc(XCore::LR);
|
||||||
|
Moves.push_back(MachineMove(FrameLabel, CSDst, CSSrc));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (saveLR) {
|
||||||
|
int LRSpillOffset = MFI->getObjectOffset(XFI->getLRSpillSlot());
|
||||||
|
storeToStack(MBB, MBBI, XCore::LR, LRSpillOffset + FrameSize*4, dl, TII);
|
||||||
|
MBB.addLiveIn(XCore::LR);
|
||||||
|
|
||||||
|
if (emitFrameMoves) {
|
||||||
|
MCSymbol *SaveLRLabel = MMI->getContext().CreateTempSymbol();
|
||||||
|
BuildMI(MBB, MBBI, dl, TII.get(XCore::PROLOG_LABEL)).addSym(SaveLRLabel);
|
||||||
|
MachineLocation CSDst(MachineLocation::VirtualFP, LRSpillOffset);
|
||||||
|
MachineLocation CSSrc(XCore::LR);
|
||||||
|
MMI->getFrameMoves().push_back(MachineMove(SaveLRLabel, CSDst, CSSrc));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (FP) {
|
||||||
|
// Save R10 to the stack.
|
||||||
|
int FPSpillOffset = MFI->getObjectOffset(XFI->getFPSpillSlot());
|
||||||
|
storeToStack(MBB, MBBI, XCore::R10, FPSpillOffset + FrameSize*4, dl, TII);
|
||||||
|
// R10 is live-in. It is killed at the spill.
|
||||||
|
MBB.addLiveIn(XCore::R10);
|
||||||
|
if (emitFrameMoves) {
|
||||||
|
MCSymbol *SaveR10Label = MMI->getContext().CreateTempSymbol();
|
||||||
|
BuildMI(MBB, MBBI, dl, TII.get(XCore::PROLOG_LABEL)).addSym(SaveR10Label);
|
||||||
|
MachineLocation CSDst(MachineLocation::VirtualFP, FPSpillOffset);
|
||||||
|
MachineLocation CSSrc(XCore::R10);
|
||||||
|
MMI->getFrameMoves().push_back(MachineMove(SaveR10Label, CSDst, CSSrc));
|
||||||
|
}
|
||||||
|
// Set the FP from the SP.
|
||||||
|
unsigned FramePtr = XCore::R10;
|
||||||
|
BuildMI(MBB, MBBI, dl, TII.get(XCore::LDAWSP_ru6), FramePtr)
|
||||||
|
.addImm(0);
|
||||||
|
if (emitFrameMoves) {
|
||||||
|
// Show FP is now valid.
|
||||||
|
MCSymbol *FrameLabel = MMI->getContext().CreateTempSymbol();
|
||||||
|
BuildMI(MBB, MBBI, dl, TII.get(XCore::PROLOG_LABEL)).addSym(FrameLabel);
|
||||||
|
MachineLocation SPDst(FramePtr);
|
||||||
|
MachineLocation SPSrc(MachineLocation::VirtualFP);
|
||||||
|
MMI->getFrameMoves().push_back(MachineMove(FrameLabel, SPDst, SPSrc));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (emitFrameMoves) {
|
||||||
|
// Frame moves for callee saved.
|
||||||
|
std::vector<MachineMove> &Moves = MMI->getFrameMoves();
|
||||||
|
std::vector<std::pair<MCSymbol*, CalleeSavedInfo> >&SpillLabels =
|
||||||
|
XFI->getSpillLabels();
|
||||||
|
for (unsigned I = 0, E = SpillLabels.size(); I != E; ++I) {
|
||||||
|
MCSymbol *SpillLabel = SpillLabels[I].first;
|
||||||
|
CalleeSavedInfo &CSI = SpillLabels[I].second;
|
||||||
|
int Offset = MFI->getObjectOffset(CSI.getFrameIdx());
|
||||||
|
unsigned Reg = CSI.getReg();
|
||||||
|
MachineLocation CSDst(MachineLocation::VirtualFP, Offset);
|
||||||
|
MachineLocation CSSrc(Reg);
|
||||||
|
Moves.push_back(MachineMove(SpillLabel, CSDst, CSSrc));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void XCoreFrameInfo::emitEpilogue(MachineFunction &MF,
|
||||||
|
MachineBasicBlock &MBB) const {
|
||||||
|
MachineFrameInfo *MFI = MF.getFrameInfo();
|
||||||
|
MachineBasicBlock::iterator MBBI = prior(MBB.end());
|
||||||
|
const XCoreRegisterInfo *RegInfo =
|
||||||
|
static_cast<const XCoreRegisterInfo*>(MF.getTarget().getRegisterInfo());
|
||||||
|
const XCoreInstrInfo &TII =
|
||||||
|
*static_cast<const XCoreInstrInfo*>(MF.getTarget().getInstrInfo());
|
||||||
|
DebugLoc dl = MBBI->getDebugLoc();
|
||||||
|
|
||||||
|
bool FP = RegInfo->hasFP(MF);
|
||||||
|
|
||||||
|
if (FP) {
|
||||||
|
// Restore the stack pointer.
|
||||||
|
unsigned FramePtr = XCore::R10;
|
||||||
|
BuildMI(MBB, MBBI, dl, TII.get(XCore::SETSP_1r))
|
||||||
|
.addReg(FramePtr);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Work out frame sizes.
|
||||||
|
int FrameSize = MFI->getStackSize();
|
||||||
|
|
||||||
|
assert(FrameSize%4 == 0 && "Misaligned frame size");
|
||||||
|
|
||||||
|
FrameSize/=4;
|
||||||
|
|
||||||
|
bool isU6 = isImmU6(FrameSize);
|
||||||
|
|
||||||
|
if (!isU6 && !isImmU16(FrameSize)) {
|
||||||
|
// FIXME could emit multiple instructions.
|
||||||
|
report_fatal_error("emitEpilogue Frame size too big: " + Twine(FrameSize));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (FrameSize) {
|
||||||
|
XCoreFunctionInfo *XFI = MF.getInfo<XCoreFunctionInfo>();
|
||||||
|
|
||||||
|
if (FP) {
|
||||||
|
// Restore R10
|
||||||
|
int FPSpillOffset = MFI->getObjectOffset(XFI->getFPSpillSlot());
|
||||||
|
FPSpillOffset += FrameSize*4;
|
||||||
|
loadFromStack(MBB, MBBI, XCore::R10, FPSpillOffset, dl, TII);
|
||||||
|
}
|
||||||
|
bool restoreLR = XFI->getUsesLR();
|
||||||
|
if (restoreLR && MFI->getObjectOffset(XFI->getLRSpillSlot()) != 0) {
|
||||||
|
int LRSpillOffset = MFI->getObjectOffset(XFI->getLRSpillSlot());
|
||||||
|
LRSpillOffset += FrameSize*4;
|
||||||
|
loadFromStack(MBB, MBBI, XCore::LR, LRSpillOffset, dl, TII);
|
||||||
|
restoreLR = false;
|
||||||
|
}
|
||||||
|
if (restoreLR) {
|
||||||
|
// Fold prologue into return instruction
|
||||||
|
assert(MBBI->getOpcode() == XCore::RETSP_u6
|
||||||
|
|| MBBI->getOpcode() == XCore::RETSP_lu6);
|
||||||
|
int Opcode = (isU6) ? XCore::RETSP_u6 : XCore::RETSP_lu6;
|
||||||
|
BuildMI(MBB, MBBI, dl, TII.get(Opcode)).addImm(FrameSize);
|
||||||
|
MBB.erase(MBBI);
|
||||||
|
} else {
|
||||||
|
int Opcode = (isU6) ? XCore::LDAWSP_ru6_RRegs : XCore::LDAWSP_lru6_RRegs;
|
||||||
|
BuildMI(MBB, MBBI, dl, TII.get(Opcode), XCore::SP).addImm(FrameSize);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -19,10 +19,17 @@
|
||||||
#include "llvm/Target/TargetMachine.h"
|
#include "llvm/Target/TargetMachine.h"
|
||||||
|
|
||||||
namespace llvm {
|
namespace llvm {
|
||||||
class XCoreFrameInfo: public TargetFrameInfo {
|
class XCoreSubtarget;
|
||||||
|
|
||||||
|
class XCoreFrameInfo: public TargetFrameInfo {
|
||||||
|
const XCoreSubtarget &STI;
|
||||||
public:
|
public:
|
||||||
XCoreFrameInfo(const TargetMachine &tm);
|
XCoreFrameInfo(const XCoreSubtarget &STI);
|
||||||
|
|
||||||
|
/// emitProlog/emitEpilog - These methods insert prolog and epilog code into
|
||||||
|
/// the function.
|
||||||
|
void emitPrologue(MachineFunction &MF) const;
|
||||||
|
void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const;
|
||||||
|
|
||||||
//! Stack slot size (4 bytes)
|
//! Stack slot size (4 bytes)
|
||||||
static int stackSlotSize() {
|
static int stackSlotSize() {
|
||||||
|
|
|
@ -346,208 +346,6 @@ loadConstant(MachineBasicBlock &MBB, MachineBasicBlock::iterator I,
|
||||||
BuildMI(MBB, I, dl, TII.get(Opcode), DstReg).addImm(Value);
|
BuildMI(MBB, I, dl, TII.get(Opcode), DstReg).addImm(Value);
|
||||||
}
|
}
|
||||||
|
|
||||||
void XCoreRegisterInfo::
|
|
||||||
storeToStack(MachineBasicBlock &MBB, MachineBasicBlock::iterator I,
|
|
||||||
unsigned SrcReg, int Offset, DebugLoc dl) const {
|
|
||||||
assert(Offset%4 == 0 && "Misaligned stack offset");
|
|
||||||
Offset/=4;
|
|
||||||
bool isU6 = isImmU6(Offset);
|
|
||||||
if (!isU6 && !isImmU16(Offset))
|
|
||||||
report_fatal_error("storeToStack offset too big " + Twine(Offset));
|
|
||||||
int Opcode = isU6 ? XCore::STWSP_ru6 : XCore::STWSP_lru6;
|
|
||||||
BuildMI(MBB, I, dl, TII.get(Opcode))
|
|
||||||
.addReg(SrcReg)
|
|
||||||
.addImm(Offset);
|
|
||||||
}
|
|
||||||
|
|
||||||
void XCoreRegisterInfo::
|
|
||||||
loadFromStack(MachineBasicBlock &MBB, MachineBasicBlock::iterator I,
|
|
||||||
unsigned DstReg, int Offset, DebugLoc dl) const {
|
|
||||||
assert(Offset%4 == 0 && "Misaligned stack offset");
|
|
||||||
Offset/=4;
|
|
||||||
bool isU6 = isImmU6(Offset);
|
|
||||||
if (!isU6 && !isImmU16(Offset))
|
|
||||||
report_fatal_error("loadFromStack offset too big " + Twine(Offset));
|
|
||||||
int Opcode = isU6 ? XCore::LDWSP_ru6 : XCore::LDWSP_lru6;
|
|
||||||
BuildMI(MBB, I, dl, TII.get(Opcode), DstReg)
|
|
||||||
.addImm(Offset);
|
|
||||||
}
|
|
||||||
|
|
||||||
void XCoreRegisterInfo::emitPrologue(MachineFunction &MF) const {
|
|
||||||
MachineBasicBlock &MBB = MF.front(); // Prolog goes in entry BB
|
|
||||||
MachineBasicBlock::iterator MBBI = MBB.begin();
|
|
||||||
MachineFrameInfo *MFI = MF.getFrameInfo();
|
|
||||||
MachineModuleInfo *MMI = &MF.getMMI();
|
|
||||||
XCoreFunctionInfo *XFI = MF.getInfo<XCoreFunctionInfo>();
|
|
||||||
DebugLoc dl = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc();
|
|
||||||
|
|
||||||
bool FP = hasFP(MF);
|
|
||||||
|
|
||||||
// Work out frame sizes.
|
|
||||||
int FrameSize = MFI->getStackSize();
|
|
||||||
|
|
||||||
assert(FrameSize%4 == 0 && "Misaligned frame size");
|
|
||||||
|
|
||||||
FrameSize/=4;
|
|
||||||
|
|
||||||
bool isU6 = isImmU6(FrameSize);
|
|
||||||
|
|
||||||
if (!isU6 && !isImmU16(FrameSize)) {
|
|
||||||
// FIXME could emit multiple instructions.
|
|
||||||
report_fatal_error("emitPrologue Frame size too big: " + Twine(FrameSize));
|
|
||||||
}
|
|
||||||
bool emitFrameMoves = needsFrameMoves(MF);
|
|
||||||
|
|
||||||
// Do we need to allocate space on the stack?
|
|
||||||
if (FrameSize) {
|
|
||||||
bool saveLR = XFI->getUsesLR();
|
|
||||||
bool LRSavedOnEntry = false;
|
|
||||||
int Opcode;
|
|
||||||
if (saveLR && (MFI->getObjectOffset(XFI->getLRSpillSlot()) == 0)) {
|
|
||||||
Opcode = (isU6) ? XCore::ENTSP_u6 : XCore::ENTSP_lu6;
|
|
||||||
MBB.addLiveIn(XCore::LR);
|
|
||||||
saveLR = false;
|
|
||||||
LRSavedOnEntry = true;
|
|
||||||
} else {
|
|
||||||
Opcode = (isU6) ? XCore::EXTSP_u6 : XCore::EXTSP_lu6;
|
|
||||||
}
|
|
||||||
BuildMI(MBB, MBBI, dl, TII.get(Opcode)).addImm(FrameSize);
|
|
||||||
|
|
||||||
if (emitFrameMoves) {
|
|
||||||
std::vector<MachineMove> &Moves = MMI->getFrameMoves();
|
|
||||||
|
|
||||||
// Show update of SP.
|
|
||||||
MCSymbol *FrameLabel = MMI->getContext().CreateTempSymbol();
|
|
||||||
BuildMI(MBB, MBBI, dl, TII.get(XCore::PROLOG_LABEL)).addSym(FrameLabel);
|
|
||||||
|
|
||||||
MachineLocation SPDst(MachineLocation::VirtualFP);
|
|
||||||
MachineLocation SPSrc(MachineLocation::VirtualFP, -FrameSize * 4);
|
|
||||||
Moves.push_back(MachineMove(FrameLabel, SPDst, SPSrc));
|
|
||||||
|
|
||||||
if (LRSavedOnEntry) {
|
|
||||||
MachineLocation CSDst(MachineLocation::VirtualFP, 0);
|
|
||||||
MachineLocation CSSrc(XCore::LR);
|
|
||||||
Moves.push_back(MachineMove(FrameLabel, CSDst, CSSrc));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (saveLR) {
|
|
||||||
int LRSpillOffset = MFI->getObjectOffset(XFI->getLRSpillSlot());
|
|
||||||
storeToStack(MBB, MBBI, XCore::LR, LRSpillOffset + FrameSize*4, dl);
|
|
||||||
MBB.addLiveIn(XCore::LR);
|
|
||||||
|
|
||||||
if (emitFrameMoves) {
|
|
||||||
MCSymbol *SaveLRLabel = MMI->getContext().CreateTempSymbol();
|
|
||||||
BuildMI(MBB, MBBI, dl, TII.get(XCore::PROLOG_LABEL)).addSym(SaveLRLabel);
|
|
||||||
MachineLocation CSDst(MachineLocation::VirtualFP, LRSpillOffset);
|
|
||||||
MachineLocation CSSrc(XCore::LR);
|
|
||||||
MMI->getFrameMoves().push_back(MachineMove(SaveLRLabel, CSDst, CSSrc));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (FP) {
|
|
||||||
// Save R10 to the stack.
|
|
||||||
int FPSpillOffset = MFI->getObjectOffset(XFI->getFPSpillSlot());
|
|
||||||
storeToStack(MBB, MBBI, XCore::R10, FPSpillOffset + FrameSize*4, dl);
|
|
||||||
// R10 is live-in. It is killed at the spill.
|
|
||||||
MBB.addLiveIn(XCore::R10);
|
|
||||||
if (emitFrameMoves) {
|
|
||||||
MCSymbol *SaveR10Label = MMI->getContext().CreateTempSymbol();
|
|
||||||
BuildMI(MBB, MBBI, dl, TII.get(XCore::PROLOG_LABEL)).addSym(SaveR10Label);
|
|
||||||
MachineLocation CSDst(MachineLocation::VirtualFP, FPSpillOffset);
|
|
||||||
MachineLocation CSSrc(XCore::R10);
|
|
||||||
MMI->getFrameMoves().push_back(MachineMove(SaveR10Label, CSDst, CSSrc));
|
|
||||||
}
|
|
||||||
// Set the FP from the SP.
|
|
||||||
unsigned FramePtr = XCore::R10;
|
|
||||||
BuildMI(MBB, MBBI, dl, TII.get(XCore::LDAWSP_ru6), FramePtr)
|
|
||||||
.addImm(0);
|
|
||||||
if (emitFrameMoves) {
|
|
||||||
// Show FP is now valid.
|
|
||||||
MCSymbol *FrameLabel = MMI->getContext().CreateTempSymbol();
|
|
||||||
BuildMI(MBB, MBBI, dl, TII.get(XCore::PROLOG_LABEL)).addSym(FrameLabel);
|
|
||||||
MachineLocation SPDst(FramePtr);
|
|
||||||
MachineLocation SPSrc(MachineLocation::VirtualFP);
|
|
||||||
MMI->getFrameMoves().push_back(MachineMove(FrameLabel, SPDst, SPSrc));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (emitFrameMoves) {
|
|
||||||
// Frame moves for callee saved.
|
|
||||||
std::vector<MachineMove> &Moves = MMI->getFrameMoves();
|
|
||||||
std::vector<std::pair<MCSymbol*, CalleeSavedInfo> >&SpillLabels =
|
|
||||||
XFI->getSpillLabels();
|
|
||||||
for (unsigned I = 0, E = SpillLabels.size(); I != E; ++I) {
|
|
||||||
MCSymbol *SpillLabel = SpillLabels[I].first;
|
|
||||||
CalleeSavedInfo &CSI = SpillLabels[I].second;
|
|
||||||
int Offset = MFI->getObjectOffset(CSI.getFrameIdx());
|
|
||||||
unsigned Reg = CSI.getReg();
|
|
||||||
MachineLocation CSDst(MachineLocation::VirtualFP, Offset);
|
|
||||||
MachineLocation CSSrc(Reg);
|
|
||||||
Moves.push_back(MachineMove(SpillLabel, CSDst, CSSrc));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void XCoreRegisterInfo::emitEpilogue(MachineFunction &MF,
|
|
||||||
MachineBasicBlock &MBB) const {
|
|
||||||
MachineFrameInfo *MFI = MF.getFrameInfo();
|
|
||||||
MachineBasicBlock::iterator MBBI = prior(MBB.end());
|
|
||||||
DebugLoc dl = MBBI->getDebugLoc();
|
|
||||||
|
|
||||||
bool FP = hasFP(MF);
|
|
||||||
|
|
||||||
if (FP) {
|
|
||||||
// Restore the stack pointer.
|
|
||||||
unsigned FramePtr = XCore::R10;
|
|
||||||
BuildMI(MBB, MBBI, dl, TII.get(XCore::SETSP_1r))
|
|
||||||
.addReg(FramePtr);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Work out frame sizes.
|
|
||||||
int FrameSize = MFI->getStackSize();
|
|
||||||
|
|
||||||
assert(FrameSize%4 == 0 && "Misaligned frame size");
|
|
||||||
|
|
||||||
FrameSize/=4;
|
|
||||||
|
|
||||||
bool isU6 = isImmU6(FrameSize);
|
|
||||||
|
|
||||||
if (!isU6 && !isImmU16(FrameSize)) {
|
|
||||||
// FIXME could emit multiple instructions.
|
|
||||||
report_fatal_error("emitEpilogue Frame size too big: " + Twine(FrameSize));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (FrameSize) {
|
|
||||||
XCoreFunctionInfo *XFI = MF.getInfo<XCoreFunctionInfo>();
|
|
||||||
|
|
||||||
if (FP) {
|
|
||||||
// Restore R10
|
|
||||||
int FPSpillOffset = MFI->getObjectOffset(XFI->getFPSpillSlot());
|
|
||||||
FPSpillOffset += FrameSize*4;
|
|
||||||
loadFromStack(MBB, MBBI, XCore::R10, FPSpillOffset, dl);
|
|
||||||
}
|
|
||||||
bool restoreLR = XFI->getUsesLR();
|
|
||||||
if (restoreLR && MFI->getObjectOffset(XFI->getLRSpillSlot()) != 0) {
|
|
||||||
int LRSpillOffset = MFI->getObjectOffset(XFI->getLRSpillSlot());
|
|
||||||
LRSpillOffset += FrameSize*4;
|
|
||||||
loadFromStack(MBB, MBBI, XCore::LR, LRSpillOffset, dl);
|
|
||||||
restoreLR = false;
|
|
||||||
}
|
|
||||||
if (restoreLR) {
|
|
||||||
// Fold prologue into return instruction
|
|
||||||
assert(MBBI->getOpcode() == XCore::RETSP_u6
|
|
||||||
|| MBBI->getOpcode() == XCore::RETSP_lu6);
|
|
||||||
int Opcode = (isU6) ? XCore::RETSP_u6 : XCore::RETSP_lu6;
|
|
||||||
BuildMI(MBB, MBBI, dl, TII.get(Opcode)).addImm(FrameSize);
|
|
||||||
MBB.erase(MBBI);
|
|
||||||
} else {
|
|
||||||
int Opcode = (isU6) ? XCore::LDAWSP_ru6_RRegs : XCore::LDAWSP_lru6_RRegs;
|
|
||||||
BuildMI(MBB, MBBI, dl, TII.get(Opcode), XCore::SP).addImm(FrameSize);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int XCoreRegisterInfo::getDwarfRegNum(unsigned RegNum, bool isEH) const {
|
int XCoreRegisterInfo::getDwarfRegNum(unsigned RegNum, bool isEH) const {
|
||||||
return XCoreGenRegisterInfo::getDwarfRegNumFull(RegNum, 0);
|
return XCoreGenRegisterInfo::getDwarfRegNumFull(RegNum, 0);
|
||||||
}
|
}
|
||||||
|
|
|
@ -62,9 +62,6 @@ public:
|
||||||
|
|
||||||
void processFunctionBeforeFrameFinalized(MachineFunction &MF) const;
|
void processFunctionBeforeFrameFinalized(MachineFunction &MF) const;
|
||||||
|
|
||||||
void emitPrologue(MachineFunction &MF) const;
|
|
||||||
void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const;
|
|
||||||
|
|
||||||
// Debug information queries.
|
// Debug information queries.
|
||||||
unsigned getRARegister() const;
|
unsigned getRARegister() const;
|
||||||
unsigned getFrameRegister(const MachineFunction &MF) const;
|
unsigned getFrameRegister(const MachineFunction &MF) const;
|
||||||
|
|
|
@ -27,7 +27,7 @@ XCoreTargetMachine::XCoreTargetMachine(const Target &T, const std::string &TT,
|
||||||
DataLayout("e-p:32:32:32-a0:0:32-f32:32:32-f64:32:32-i1:8:32-i8:8:32-"
|
DataLayout("e-p:32:32:32-a0:0:32-f32:32:32-f64:32:32-i1:8:32-i8:8:32-"
|
||||||
"i16:16:32-i32:32:32-i64:32:32-n32"),
|
"i16:16:32-i32:32:32-i64:32:32-n32"),
|
||||||
InstrInfo(),
|
InstrInfo(),
|
||||||
FrameInfo(*this),
|
FrameInfo(Subtarget),
|
||||||
TLInfo(*this),
|
TLInfo(*this),
|
||||||
TSInfo(*this) {
|
TSInfo(*this) {
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue