mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-03-18 12:31:26 +00:00
First step of huge frame-related refactoring: move emit{Prologue,Epilogue} out of TargetRegisterInfo to TargetFrameInfo, which is definitely much better suitable place
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@119097 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
78b4fee8fd
commit
3346491223
@ -17,6 +17,8 @@
|
||||
#include <utility>
|
||||
|
||||
namespace llvm {
|
||||
class MachineFunction;
|
||||
class MachineBasicBlock;
|
||||
|
||||
/// 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
|
||||
@ -90,6 +92,19 @@ public:
|
||||
NumEntries = 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
|
||||
|
@ -577,13 +577,6 @@ public:
|
||||
// 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
|
||||
/// make use of) the register scavenger.
|
||||
virtual bool requiresRegisterScavenging(const MachineFunction &MF) const {
|
||||
@ -749,12 +742,6 @@ public:
|
||||
virtual void eliminateFrameIndex(MachineBasicBlock::iterator MI,
|
||||
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.
|
||||
|
||||
|
@ -641,7 +641,7 @@ void PEI::calculateFrameObjectOffsets(MachineFunction &Fn) {
|
||||
AdjustStackOffset(MFI, SFI, StackGrowsDown, Offset, MaxAlign);
|
||||
}
|
||||
|
||||
if (!RegInfo->targetHandlesStackFrameRounding()) {
|
||||
if (!TFI.targetHandlesStackFrameRounding()) {
|
||||
// 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
|
||||
// overall stack size.
|
||||
@ -676,16 +676,16 @@ void PEI::calculateFrameObjectOffsets(MachineFunction &Fn) {
|
||||
/// prolog and epilog code to the function.
|
||||
///
|
||||
void PEI::insertPrologEpilogCode(MachineFunction &Fn) {
|
||||
const TargetRegisterInfo *TRI = Fn.getTarget().getRegisterInfo();
|
||||
const TargetFrameInfo &TFI = *Fn.getTarget().getFrameInfo();
|
||||
|
||||
// Add prologue to the function...
|
||||
TRI->emitPrologue(Fn);
|
||||
TFI.emitPrologue(Fn);
|
||||
|
||||
// Add epilogue to restore the callee-save registers in each exiting block
|
||||
for (MachineFunction::iterator I = Fn.begin(), E = Fn.end(); I != E; ++I) {
|
||||
// If last instruction is a return instruction, add an epilogue
|
||||
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"
|
||||
|
@ -122,6 +122,7 @@ public:
|
||||
// Debug information queries.
|
||||
unsigned getRARegister() const;
|
||||
unsigned getFrameRegister(const MachineFunction &MF) const;
|
||||
unsigned getBaseRegister() const { return BasePtr; };
|
||||
int getFrameIndexReference(const MachineFunction &MF, int FI,
|
||||
unsigned &FrameReg) const;
|
||||
int ResolveFrameIndexReference(const MachineFunction &MF, int FI,
|
||||
@ -166,9 +167,6 @@ public:
|
||||
virtual void eliminateFrameIndex(MachineBasicBlock::iterator II,
|
||||
int SPAdj, RegScavenger *RS = NULL) const;
|
||||
|
||||
virtual void emitPrologue(MachineFunction &MF) const;
|
||||
virtual void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const;
|
||||
|
||||
private:
|
||||
unsigned estimateRSStackSizeLimit(MachineFunction &MF) const;
|
||||
|
||||
|
376
lib/Target/ARM/ARMFrameInfo.cpp
Normal file
376
lib/Target/ARM/ARMFrameInfo.cpp
Normal file
@ -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"
|
||||
|
||||
namespace llvm {
|
||||
class ARMSubtarget;
|
||||
|
||||
class ARMFrameInfo : public TargetFrameInfo {
|
||||
protected:
|
||||
const ARMSubtarget &STI;
|
||||
|
||||
public:
|
||||
explicit ARMFrameInfo(const ARMSubtarget &ST)
|
||||
: TargetFrameInfo(StackGrowsDown, ST.getStackAlignment(), 0, 4) {
|
||||
explicit ARMFrameInfo(const ARMSubtarget &sti)
|
||||
: 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
|
||||
|
@ -89,7 +89,6 @@ ARMBaseTargetMachine::ARMBaseTargetMachine(const Target &T,
|
||||
bool isThumb)
|
||||
: LLVMTargetMachine(T, TT),
|
||||
Subtarget(TT, FS, isThumb),
|
||||
FrameInfo(Subtarget),
|
||||
JITInfo(),
|
||||
InstrItins(Subtarget.getInstrItineraryData())
|
||||
{
|
||||
@ -106,7 +105,8 @@ ARMTargetMachine::ARMTargetMachine(const Target &T, const std::string &TT,
|
||||
"v128:64:128-v64:64:64-n32")),
|
||||
ELFWriterInfo(*this),
|
||||
TLInfo(*this),
|
||||
TSInfo(*this) {
|
||||
TSInfo(*this),
|
||||
FrameInfo(Subtarget) {
|
||||
if (!Subtarget.hasARMOps())
|
||||
report_fatal_error("CPU: '" + Subtarget.getCPUString() + "' does not "
|
||||
"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")),
|
||||
ELFWriterInfo(*this),
|
||||
TLInfo(*this),
|
||||
TSInfo(*this) {
|
||||
TSInfo(*this),
|
||||
FrameInfo(Subtarget.hasThumb2()
|
||||
? new ARMFrameInfo(Subtarget)
|
||||
: (ARMFrameInfo*)new Thumb1FrameInfo(Subtarget)) {
|
||||
}
|
||||
|
||||
// Pass Pipeline Configuration
|
||||
|
@ -14,9 +14,6 @@
|
||||
#ifndef ARMTARGETMACHINE_H
|
||||
#define ARMTARGETMACHINE_H
|
||||
|
||||
#include "llvm/Target/TargetMachine.h"
|
||||
#include "llvm/Target/TargetData.h"
|
||||
#include "llvm/MC/MCStreamer.h"
|
||||
#include "ARMInstrInfo.h"
|
||||
#include "ARMELFWriterInfo.h"
|
||||
#include "ARMFrameInfo.h"
|
||||
@ -25,7 +22,11 @@
|
||||
#include "ARMISelLowering.h"
|
||||
#include "ARMSelectionDAGInfo.h"
|
||||
#include "Thumb1InstrInfo.h"
|
||||
#include "Thumb1FrameInfo.h"
|
||||
#include "Thumb2InstrInfo.h"
|
||||
#include "llvm/Target/TargetMachine.h"
|
||||
#include "llvm/Target/TargetData.h"
|
||||
#include "llvm/MC/MCStreamer.h"
|
||||
#include "llvm/ADT/OwningPtr.h"
|
||||
|
||||
namespace llvm {
|
||||
@ -33,9 +34,7 @@ namespace llvm {
|
||||
class ARMBaseTargetMachine : public LLVMTargetMachine {
|
||||
protected:
|
||||
ARMSubtarget Subtarget;
|
||||
|
||||
private:
|
||||
ARMFrameInfo FrameInfo;
|
||||
ARMJITInfo JITInfo;
|
||||
InstrItineraryData InstrItins;
|
||||
Reloc::Model DefRelocModel; // Reloc model before it's overridden.
|
||||
@ -44,7 +43,6 @@ public:
|
||||
ARMBaseTargetMachine(const Target &T, const std::string &TT,
|
||||
const std::string &FS, bool isThumb);
|
||||
|
||||
virtual const ARMFrameInfo *getFrameInfo() const { return &FrameInfo; }
|
||||
virtual ARMJITInfo *getJITInfo() { return &JITInfo; }
|
||||
virtual const ARMSubtarget *getSubtargetImpl() const { return &Subtarget; }
|
||||
virtual const InstrItineraryData *getInstrItineraryData() const {
|
||||
@ -69,7 +67,8 @@ class ARMTargetMachine : public ARMBaseTargetMachine {
|
||||
ARMELFWriterInfo ELFWriterInfo;
|
||||
ARMTargetLowering TLInfo;
|
||||
ARMSelectionDAGInfo TSInfo;
|
||||
public:
|
||||
ARMFrameInfo FrameInfo;
|
||||
public:
|
||||
ARMTargetMachine(const Target &T, const std::string &TT,
|
||||
const std::string &FS);
|
||||
|
||||
@ -84,6 +83,7 @@ public:
|
||||
virtual const ARMSelectionDAGInfo* getSelectionDAGInfo() const {
|
||||
return &TSInfo;
|
||||
}
|
||||
virtual const ARMFrameInfo *getFrameInfo() const { return &FrameInfo; }
|
||||
|
||||
virtual const ARMInstrInfo *getInstrInfo() const { return &InstrInfo; }
|
||||
virtual const TargetData *getTargetData() const { return &DataLayout; }
|
||||
@ -103,6 +103,8 @@ class ThumbTargetMachine : public ARMBaseTargetMachine {
|
||||
ARMELFWriterInfo ELFWriterInfo;
|
||||
ARMTargetLowering TLInfo;
|
||||
ARMSelectionDAGInfo TSInfo;
|
||||
// Either Thumb1FrameInfo or ARMFrameInfo.
|
||||
OwningPtr<ARMFrameInfo> FrameInfo;
|
||||
public:
|
||||
ThumbTargetMachine(const Target &T, const std::string &TT,
|
||||
const std::string &FS);
|
||||
@ -124,6 +126,10 @@ public:
|
||||
virtual const ARMBaseInstrInfo *getInstrInfo() const {
|
||||
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 ARMELFWriterInfo *getELFWriterInfo() const {
|
||||
return Subtarget.isTargetELF() ? &ELFWriterInfo : 0;
|
||||
|
246
lib/Target/ARM/Thumb1FrameInfo.cpp
Normal file
246
lib/Target/ARM/Thumb1FrameInfo.cpp
Normal file
@ -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);
|
||||
}
|
||||
}
|
41
lib/Target/ARM/Thumb1FrameInfo.h
Normal file
41
lib/Target/ARM/Thumb1FrameInfo.h
Normal file
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
void eliminateFrameIndex(MachineBasicBlock::iterator II,
|
||||
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"
|
||||
|
||||
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 FunctionPass;
|
||||
|
140
lib/Target/Alpha/AlphaFrameInfo.cpp
Normal file
140
lib/Target/Alpha/AlphaFrameInfo.cpp
Normal file
@ -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));
|
||||
}
|
||||
}
|
||||
}
|
41
lib/Target/Alpha/AlphaFrameInfo.h
Normal file
41
lib/Target/Alpha/AlphaFrameInfo.h
Normal file
@ -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>
|
||||
using namespace llvm;
|
||||
|
||||
//These describe LDAx
|
||||
static const int IMM_LOW = -32768;
|
||||
static const int IMM_HIGH = 32767;
|
||||
static const int IMM_MULT = 65536;
|
||||
AlphaRegisterInfo::AlphaRegisterInfo(const TargetInstrInfo &tii)
|
||||
: AlphaGenRegisterInfo(Alpha::ADJUSTSTACKDOWN, Alpha::ADJUSTSTACKUP),
|
||||
TII(tii) {
|
||||
}
|
||||
|
||||
static long getUpper16(long l)
|
||||
{
|
||||
long y = l / IMM_MULT;
|
||||
if (l % IMM_MULT > IMM_HIGH)
|
||||
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)
|
||||
{
|
||||
static long getLower16(long l) {
|
||||
long h = getUpper16(l);
|
||||
return l - h * IMM_MULT;
|
||||
}
|
||||
|
||||
AlphaRegisterInfo::AlphaRegisterInfo(const TargetInstrInfo &tii)
|
||||
: AlphaGenRegisterInfo(Alpha::ADJUSTSTACKDOWN, Alpha::ADJUSTSTACKUP),
|
||||
TII(tii), curgpdist(0)
|
||||
{
|
||||
return l - h * Alpha::IMM_MULT;
|
||||
}
|
||||
|
||||
const unsigned* AlphaRegisterInfo::getCalleeSavedRegs(const MachineFunction *MF)
|
||||
@ -168,7 +160,7 @@ AlphaRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
|
||||
DEBUG(errs() << "Corrected Offset " << Offset
|
||||
<< " 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: "
|
||||
<< Offset << "\n");
|
||||
//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 {
|
||||
return Alpha::R26;
|
||||
}
|
||||
|
@ -41,11 +41,6 @@ struct AlphaRegisterInfo : public AlphaGenRegisterInfo {
|
||||
void eliminateFrameIndex(MachineBasicBlock::iterator II,
|
||||
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.
|
||||
unsigned getRARegister() const;
|
||||
unsigned getFrameRegister(const MachineFunction &MF) const;
|
||||
@ -57,9 +52,6 @@ struct AlphaRegisterInfo : public AlphaGenRegisterInfo {
|
||||
int getDwarfRegNum(unsigned RegNum, bool isEH) const;
|
||||
|
||||
static std::string getPrettyName(unsigned reg);
|
||||
|
||||
private:
|
||||
mutable int curgpdist;
|
||||
};
|
||||
|
||||
} // end namespace llvm
|
||||
|
@ -28,7 +28,7 @@ AlphaTargetMachine::AlphaTargetMachine(const Target &T, const std::string &TT,
|
||||
const std::string &FS)
|
||||
: LLVMTargetMachine(T, TT),
|
||||
DataLayout("e-f128:128:128-n64"),
|
||||
FrameInfo(TargetFrameInfo::StackGrowsDown, 16, 0),
|
||||
FrameInfo(Subtarget),
|
||||
Subtarget(TT, FS),
|
||||
TLInfo(*this),
|
||||
TSInfo(*this) {
|
||||
|
@ -14,13 +14,14 @@
|
||||
#ifndef 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/TargetData.h"
|
||||
#include "llvm/Target/TargetFrameInfo.h"
|
||||
#include "AlphaInstrInfo.h"
|
||||
#include "AlphaISelLowering.h"
|
||||
#include "AlphaSelectionDAGInfo.h"
|
||||
#include "AlphaSubtarget.h"
|
||||
|
||||
namespace llvm {
|
||||
|
||||
@ -29,7 +30,7 @@ class GlobalValue;
|
||||
class AlphaTargetMachine : public LLVMTargetMachine {
|
||||
const TargetData DataLayout; // Calculates type size & alignment
|
||||
AlphaInstrInfo InstrInfo;
|
||||
TargetFrameInfo FrameInfo;
|
||||
AlphaFrameInfo FrameInfo;
|
||||
AlphaSubtarget Subtarget;
|
||||
AlphaTargetLowering TLInfo;
|
||||
AlphaSelectionDAGInfo TSInfo;
|
||||
|
97
lib/Target/Blackfin/BlackfinFrameInfo.cpp
Normal file
97
lib/Target/Blackfin/BlackfinFrameInfo.cpp
Normal file
@ -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));
|
||||
}
|
41
lib/Target/Blackfin/BlackfinFrameInfo.h
Normal file
41
lib/Target/Blackfin/BlackfinFrameInfo.h
Normal file
@ -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 {
|
||||
return BF::RETS;
|
||||
}
|
||||
|
@ -57,9 +57,6 @@ namespace llvm {
|
||||
void processFunctionBeforeCalleeSavedScan(MachineFunction &MF,
|
||||
RegScavenger *RS) const;
|
||||
|
||||
void emitPrologue(MachineFunction &MF) const;
|
||||
void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const;
|
||||
|
||||
unsigned getFrameRegister(const MachineFunction &MF) const;
|
||||
unsigned getRARegister() const;
|
||||
|
||||
|
@ -33,7 +33,7 @@ BlackfinTargetMachine::BlackfinTargetMachine(const Target &T,
|
||||
TLInfo(*this),
|
||||
TSInfo(*this),
|
||||
InstrInfo(Subtarget),
|
||||
FrameInfo(TargetFrameInfo::StackGrowsDown, 4, 0) {
|
||||
FrameInfo(Subtarget) {
|
||||
}
|
||||
|
||||
bool BlackfinTargetMachine::addInstSelector(PassManagerBase &PM,
|
||||
|
@ -14,14 +14,15 @@
|
||||
#ifndef 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/TargetData.h"
|
||||
#include "llvm/Target/TargetFrameInfo.h"
|
||||
#include "BlackfinInstrInfo.h"
|
||||
#include "BlackfinSubtarget.h"
|
||||
#include "BlackfinISelLowering.h"
|
||||
#include "BlackfinSelectionDAGInfo.h"
|
||||
#include "BlackfinIntrinsicInfo.h"
|
||||
|
||||
namespace llvm {
|
||||
|
||||
@ -31,7 +32,7 @@ namespace llvm {
|
||||
BlackfinTargetLowering TLInfo;
|
||||
BlackfinSelectionDAGInfo TSInfo;
|
||||
BlackfinInstrInfo InstrInfo;
|
||||
TargetFrameInfo FrameInfo;
|
||||
BlackfinFrameInfo FrameInfo;
|
||||
BlackfinIntrinsicInfo IntrinsicInfo;
|
||||
public:
|
||||
BlackfinTargetMachine(const Target &T, const std::string &TT,
|
||||
|
@ -14,16 +14,225 @@
|
||||
#include "SPU.h"
|
||||
#include "SPUFrameInfo.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;
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// SPUFrameInfo:
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
SPUFrameInfo::SPUFrameInfo(const TargetMachine &tm):
|
||||
TargetFrameInfo(TargetFrameInfo::StackGrowsDown, 16, 0),
|
||||
TM(tm)
|
||||
{
|
||||
SPUFrameInfo::SPUFrameInfo(const SPUSubtarget &sti)
|
||||
: TargetFrameInfo(TargetFrameInfo::StackGrowsDown, 16, 0),
|
||||
Subtarget(sti) {
|
||||
LR[0].first = SPU::R0;
|
||||
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/TargetMachine.h"
|
||||
#include "SPURegisterInfo.h"
|
||||
|
||||
namespace llvm {
|
||||
class SPUSubtarget;
|
||||
|
||||
class SPUFrameInfo: public TargetFrameInfo {
|
||||
const TargetMachine &TM;
|
||||
const SPUSubtarget &Subtarget;
|
||||
std::pair<unsigned, int> LR[1];
|
||||
|
||||
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
|
||||
/*!
|
||||
@ -71,5 +82,4 @@ namespace llvm {
|
||||
};
|
||||
}
|
||||
|
||||
#define SPUFRAMEINFO_H 1
|
||||
#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,
|
||||
RegScavenger *RS)
|
||||
const {
|
||||
@ -378,174 +340,11 @@ void SPURegisterInfo::processFunctionBeforeCalleeSavedScan(MachineFunction &MF,
|
||||
MF.getRegInfo().setPhysRegUnused(SPU::R1);
|
||||
MF.getRegInfo().setPhysRegUnused(SPU::R2);
|
||||
|
||||
MachineFrameInfo *MFI = MF.getFrameInfo();
|
||||
MachineFrameInfo *MFI = MF.getFrameInfo();
|
||||
const TargetRegisterClass *RC = &SPU::R32CRegClass;
|
||||
RS->setScavengingFrameIndex(MFI->CreateStackObject(RC->getSize(),
|
||||
RC->getAlignment(),
|
||||
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
|
||||
@ -576,10 +375,10 @@ SPURegisterInfo::getDwarfRegNum(unsigned RegNum, bool isEH) const {
|
||||
return SPUGenRegisterInfo::getDwarfRegNumFull(RegNum, 0);
|
||||
}
|
||||
|
||||
int
|
||||
int
|
||||
SPURegisterInfo::convertDFormToXForm(int dFormOpcode) const
|
||||
{
|
||||
switch(dFormOpcode)
|
||||
switch(dFormOpcode)
|
||||
{
|
||||
case SPU::AIr32: return SPU::Ar32;
|
||||
case SPU::LQDr32: return SPU::LQXr32;
|
||||
@ -602,10 +401,10 @@ SPURegisterInfo::convertDFormToXForm(int dFormOpcode) const
|
||||
|
||||
// TODO this is already copied from PPC. Could this convenience function
|
||||
// be moved to the RegScavenger class?
|
||||
unsigned
|
||||
SPURegisterInfo::findScratchRegister(MachineBasicBlock::iterator II,
|
||||
unsigned
|
||||
SPURegisterInfo::findScratchRegister(MachineBasicBlock::iterator II,
|
||||
RegScavenger *RS,
|
||||
const TargetRegisterClass *RC,
|
||||
const TargetRegisterClass *RC,
|
||||
int SPAdj) const
|
||||
{
|
||||
assert(RS && "Register scavenging must be on");
|
||||
|
@ -33,7 +33,7 @@ namespace llvm {
|
||||
|
||||
public:
|
||||
SPURegisterInfo(const SPUSubtarget &subtarget, const TargetInstrInfo &tii);
|
||||
|
||||
|
||||
//! Translate a register's enum value to a register number
|
||||
/*!
|
||||
This method translates a register's enum value to it's regiser number,
|
||||
@ -65,15 +65,10 @@ namespace llvm {
|
||||
//! Convert frame indicies into machine operands
|
||||
void eliminateFrameIndex(MachineBasicBlock::iterator II, int SPAdj,
|
||||
RegScavenger *RS = NULL) const;
|
||||
//! Determine the frame's layour
|
||||
void determineFrameLayout(MachineFunction &MF) const;
|
||||
|
||||
void processFunctionBeforeCalleeSavedScan(MachineFunction &MF,
|
||||
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)
|
||||
unsigned getRARegister() const;
|
||||
//! Get the stack frame register (SP, aka R1)
|
||||
|
@ -40,7 +40,7 @@ SPUTargetMachine::SPUTargetMachine(const Target &T, const std::string &TT,
|
||||
Subtarget(TT, FS),
|
||||
DataLayout(Subtarget.getTargetDataString()),
|
||||
InstrInfo(*this),
|
||||
FrameInfo(*this),
|
||||
FrameInfo(Subtarget),
|
||||
TLInfo(*this),
|
||||
TSInfo(*this),
|
||||
InstrItins(Subtarget.getInstrItineraryData()) {
|
||||
|
183
lib/Target/MBlaze/MBlazeFrameInfo.cpp
Normal file
183
lib/Target/MBlaze/MBlazeFrameInfo.cpp
Normal file
@ -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);
|
||||
}
|
||||
}
|
48
lib/Target/MBlaze/MBlazeFrameInfo.h
Normal file
48
lib/Target/MBlaze/MBlazeFrameInfo.h
Normal file
@ -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;
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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
|
||||
// pointer register. This is true if the function has variable sized allocas or
|
||||
// if frame pointer elimination is disabled.
|
||||
@ -279,94 +221,6 @@ eliminateFrameIndex(MachineBasicBlock::iterator II, int SPAdj,
|
||||
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::
|
||||
processFunctionBeforeFrameFinalized(MachineFunction &MF) const {
|
||||
// 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 emitPrologue(MachineFunction &MF) const;
|
||||
void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const;
|
||||
|
||||
/// Debug information queries.
|
||||
unsigned getRARegister() const;
|
||||
unsigned getFrameRegister(const MachineFunction &MF) const;
|
||||
@ -79,11 +76,6 @@ struct MBlazeRegisterInfo : public MBlazeGenRegisterInfo {
|
||||
unsigned getEHExceptionRegister() 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;
|
||||
};
|
||||
|
||||
|
@ -85,7 +85,7 @@ MBlazeTargetMachine(const Target &T, const std::string &TT,
|
||||
Subtarget(TT, FS),
|
||||
DataLayout("E-p:32:32:32-i8:8:8-i16:16:16"),
|
||||
InstrInfo(*this),
|
||||
FrameInfo(TargetFrameInfo::StackGrowsUp, 8, 0),
|
||||
FrameInfo(Subtarget),
|
||||
TLInfo(*this), TSInfo(*this), ELFWriterInfo(*this) {
|
||||
if (getRelocationModel() == Reloc::Default) {
|
||||
setRelocationModel(Reloc::Static);
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include "MBlazeISelLowering.h"
|
||||
#include "MBlazeSelectionDAGInfo.h"
|
||||
#include "MBlazeIntrinsicInfo.h"
|
||||
#include "MBlazeFrameInfo.h"
|
||||
#include "MBlazeELFWriterInfo.h"
|
||||
#include "llvm/MC/MCStreamer.h"
|
||||
#include "llvm/Target/TargetMachine.h"
|
||||
@ -32,7 +33,7 @@ namespace llvm {
|
||||
MBlazeSubtarget Subtarget;
|
||||
const TargetData DataLayout; // Calculates type size & alignment
|
||||
MBlazeInstrInfo InstrInfo;
|
||||
TargetFrameInfo FrameInfo;
|
||||
MBlazeFrameInfo FrameInfo;
|
||||
MBlazeTargetLowering TLInfo;
|
||||
MBlazeSelectionDAGInfo TSInfo;
|
||||
MBlazeIntrinsicInfo IntrinsicInfo;
|
||||
|
168
lib/Target/MSP430/MSP430FrameInfo.cpp
Normal file
168
lib/Target/MSP430/MSP430FrameInfo.cpp
Normal file
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
41
lib/Target/MSP430/MSP430FrameInfo.h
Normal file
41
lib/Target/MSP430/MSP430FrameInfo.h
Normal file
@ -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 {
|
||||
return MSP430::PCW;
|
||||
}
|
||||
|
@ -49,9 +49,6 @@ public:
|
||||
void eliminateFrameIndex(MachineBasicBlock::iterator II,
|
||||
int SPAdj, RegScavenger *RS = NULL) const;
|
||||
|
||||
void emitPrologue(MachineFunction &MF) const;
|
||||
void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const;
|
||||
|
||||
void processFunctionBeforeFrameFinalized(MachineFunction &MF) const;
|
||||
|
||||
// Debug information queries.
|
||||
|
@ -28,13 +28,13 @@ extern "C" void LLVMInitializeMSP430Target() {
|
||||
|
||||
MSP430TargetMachine::MSP430TargetMachine(const Target &T,
|
||||
const std::string &TT,
|
||||
const std::string &FS) :
|
||||
LLVMTargetMachine(T, TT),
|
||||
Subtarget(TT, FS),
|
||||
// FIXME: Check TargetData string.
|
||||
DataLayout("e-p:16:16:16-i8:8:8-i16:16:16-i32:16:32-n8:16"),
|
||||
InstrInfo(*this), TLInfo(*this), TSInfo(*this),
|
||||
FrameInfo(TargetFrameInfo::StackGrowsDown, 2, -2) { }
|
||||
const std::string &FS)
|
||||
: LLVMTargetMachine(T, TT),
|
||||
Subtarget(TT, FS),
|
||||
// FIXME: Check TargetData string.
|
||||
DataLayout("e-p:16:16:16-i8:8:8-i16:16:16-i32:16:32-n8:16"),
|
||||
InstrInfo(*this), TLInfo(*this), TSInfo(*this),
|
||||
FrameInfo(Subtarget) { }
|
||||
|
||||
|
||||
bool MSP430TargetMachine::addInstSelector(PassManagerBase &PM,
|
||||
|
@ -17,6 +17,7 @@
|
||||
|
||||
#include "MSP430InstrInfo.h"
|
||||
#include "MSP430ISelLowering.h"
|
||||
#include "MSP430FrameInfo.h"
|
||||
#include "MSP430SelectionDAGInfo.h"
|
||||
#include "MSP430RegisterInfo.h"
|
||||
#include "MSP430Subtarget.h"
|
||||
@ -34,10 +35,7 @@ class MSP430TargetMachine : public LLVMTargetMachine {
|
||||
MSP430InstrInfo InstrInfo;
|
||||
MSP430TargetLowering TLInfo;
|
||||
MSP430SelectionDAGInfo TSInfo;
|
||||
|
||||
// MSP430 does not have any call stack frame, therefore not having
|
||||
// any MSP430 specific FrameInfo class.
|
||||
TargetFrameInfo FrameInfo;
|
||||
MSP430FrameInfo FrameInfo;
|
||||
|
||||
public:
|
||||
MSP430TargetMachine(const Target &T, const std::string &TT,
|
||||
|
303
lib/Target/Mips/MipsFrameInfo.cpp
Normal file
303
lib/Target/Mips/MipsFrameInfo.cpp
Normal file
@ -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);
|
||||
}
|
||||
}
|
44
lib/Target/Mips/MipsFrameInfo.h
Normal file
44
lib/Target/Mips/MipsFrameInfo.h
Normal file
@ -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;
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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
|
||||
// pointer register. This is true if the function has variable sized allocas or
|
||||
// if frame pointer elimination is disabled.
|
||||
@ -362,106 +193,6 @@ eliminateFrameIndex(MachineBasicBlock::iterator II, int SPAdj,
|
||||
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::
|
||||
processFunctionBeforeFrameFinalized(MachineFunction &MF) const {
|
||||
// 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 emitPrologue(MachineFunction &MF) const;
|
||||
void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const;
|
||||
|
||||
/// Debug information queries.
|
||||
unsigned getRARegister() const;
|
||||
unsigned getFrameRegister(const MachineFunction &MF) const;
|
||||
|
@ -30,18 +30,18 @@ extern "C" void LLVMInitializeMipsTarget() {
|
||||
// The stack is always 8 byte aligned
|
||||
// On function prologue, the stack is created by decrementing
|
||||
// its pointer. Once decremented, all references are done with positive
|
||||
// offset from the stack/frame pointer, using StackGrowsUp enables
|
||||
// offset from the stack/frame pointer, using StackGrowsUp enables
|
||||
// an easier handling.
|
||||
// Using CodeModel::Large enables different CALL behavior.
|
||||
MipsTargetMachine::
|
||||
MipsTargetMachine(const Target &T, const std::string &TT, const std::string &FS,
|
||||
bool isLittle=false):
|
||||
LLVMTargetMachine(T, TT),
|
||||
Subtarget(TT, FS, isLittle),
|
||||
Subtarget(TT, FS, isLittle),
|
||||
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")),
|
||||
InstrInfo(*this),
|
||||
FrameInfo(TargetFrameInfo::StackGrowsUp, 8, 0),
|
||||
std::string("E-p:32:32:32-i8:8:32-i16:16:32-n32")),
|
||||
InstrInfo(*this),
|
||||
FrameInfo(Subtarget),
|
||||
TLInfo(*this), TSInfo(*this) {
|
||||
// Abicall enables PIC by default
|
||||
if (getRelocationModel() == Reloc::Default) {
|
||||
@ -57,20 +57,20 @@ MipselTargetMachine(const Target &T, const std::string &TT,
|
||||
const std::string &FS) :
|
||||
MipsTargetMachine(T, TT, FS, true) {}
|
||||
|
||||
// Install an instruction selector pass using
|
||||
// Install an instruction selector pass using
|
||||
// the ISelDag to gen Mips code.
|
||||
bool MipsTargetMachine::
|
||||
addInstSelector(PassManagerBase &PM, CodeGenOpt::Level OptLevel)
|
||||
addInstSelector(PassManagerBase &PM, CodeGenOpt::Level OptLevel)
|
||||
{
|
||||
PM.add(createMipsISelDag(*this));
|
||||
return false;
|
||||
}
|
||||
|
||||
// Implemented by targets that want to run passes immediately before
|
||||
// machine code is emitted. return true if -print-machineinstrs should
|
||||
// Implemented by targets that want to run passes immediately before
|
||||
// machine code is emitted. return true if -print-machineinstrs should
|
||||
// print out the code after the passes.
|
||||
bool MipsTargetMachine::
|
||||
addPreEmitPass(PassManagerBase &PM, CodeGenOpt::Level OptLevel)
|
||||
addPreEmitPass(PassManagerBase &PM, CodeGenOpt::Level OptLevel)
|
||||
{
|
||||
PM.add(createMipsDelaySlotFillerPass(*this));
|
||||
return true;
|
||||
|
@ -17,6 +17,7 @@
|
||||
#include "MipsSubtarget.h"
|
||||
#include "MipsInstrInfo.h"
|
||||
#include "MipsISelLowering.h"
|
||||
#include "MipsFrameInfo.h"
|
||||
#include "MipsSelectionDAGInfo.h"
|
||||
#include "llvm/Target/TargetMachine.h"
|
||||
#include "llvm/Target/TargetData.h"
|
||||
@ -24,32 +25,32 @@
|
||||
|
||||
namespace llvm {
|
||||
class formatted_raw_ostream;
|
||||
|
||||
|
||||
class MipsTargetMachine : public LLVMTargetMachine {
|
||||
MipsSubtarget Subtarget;
|
||||
const TargetData DataLayout; // Calculates type size & alignment
|
||||
MipsInstrInfo InstrInfo;
|
||||
TargetFrameInfo FrameInfo;
|
||||
MipsFrameInfo FrameInfo;
|
||||
MipsTargetLowering TLInfo;
|
||||
MipsSelectionDAGInfo TSInfo;
|
||||
public:
|
||||
MipsTargetMachine(const Target &T, const std::string &TT,
|
||||
const std::string &FS, bool isLittle);
|
||||
|
||||
virtual const MipsInstrInfo *getInstrInfo() const
|
||||
|
||||
virtual const MipsInstrInfo *getInstrInfo() const
|
||||
{ return &InstrInfo; }
|
||||
virtual const TargetFrameInfo *getFrameInfo() const
|
||||
virtual const TargetFrameInfo *getFrameInfo() const
|
||||
{ return &FrameInfo; }
|
||||
virtual const MipsSubtarget *getSubtargetImpl() const
|
||||
virtual const MipsSubtarget *getSubtargetImpl() const
|
||||
{ return &Subtarget; }
|
||||
virtual const TargetData *getTargetData() const
|
||||
virtual const TargetData *getTargetData() const
|
||||
{ return &DataLayout;}
|
||||
|
||||
virtual const MipsRegisterInfo *getRegisterInfo() const {
|
||||
return &InstrInfo.getRegisterInfo();
|
||||
}
|
||||
|
||||
virtual const MipsTargetLowering *getTargetLowering() const {
|
||||
virtual const MipsTargetLowering *getTargetLowering() const {
|
||||
return &TLInfo;
|
||||
}
|
||||
|
||||
|
24
lib/Target/PTX/PTXFrameInfo.cpp
Normal file
24
lib/Target/PTX/PTXFrameInfo.cpp
Normal file
@ -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 {
|
||||
}
|
41
lib/Target/PTX/PTXFrameInfo.h
Normal file
41
lib/Target/PTX/PTXFrameInfo.h
Normal file
@ -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");
|
||||
}
|
||||
|
||||
virtual void emitPrologue(MachineFunction &MF) const {}
|
||||
virtual void emitEpilogue(MachineFunction &MF,
|
||||
MachineBasicBlock &MBB) const {}
|
||||
|
||||
virtual unsigned getFrameRegister(const MachineFunction &MF) const {
|
||||
llvm_unreachable("PTX does not have a frame register");
|
||||
return 0;
|
||||
|
@ -32,7 +32,7 @@ PTXTargetMachine::PTXTargetMachine(const Target &T,
|
||||
const std::string &FS)
|
||||
: LLVMTargetMachine(T, TT),
|
||||
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),
|
||||
TLInfo(*this),
|
||||
Subtarget(TT, FS) {
|
||||
|
@ -16,6 +16,7 @@
|
||||
|
||||
#include "PTXISelLowering.h"
|
||||
#include "PTXInstrInfo.h"
|
||||
#include "PTXFrameInfo.h"
|
||||
#include "PTXSubtarget.h"
|
||||
#include "llvm/Target/TargetData.h"
|
||||
#include "llvm/Target/TargetFrameInfo.h"
|
||||
@ -25,7 +26,7 @@ namespace llvm {
|
||||
class PTXTargetMachine : public LLVMTargetMachine {
|
||||
private:
|
||||
const TargetData DataLayout;
|
||||
TargetFrameInfo FrameInfo;
|
||||
PTXFrameInfo FrameInfo;
|
||||
PTXInstrInfo InstrInfo;
|
||||
PTXTargetLowering TLInfo;
|
||||
PTXSubtarget Subtarget;
|
||||
|
680
lib/Target/PowerPC/PPCFrameInfo.cpp
Normal file
680
lib/Target/PowerPC/PPCFrameInfo.cpp
Normal file
@ -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"
|
||||
|
||||
namespace llvm {
|
||||
class PPCSubtarget;
|
||||
|
||||
class PPCFrameInfo: public TargetFrameInfo {
|
||||
const TargetMachine &TM;
|
||||
const PPCSubtarget &Subtarget;
|
||||
|
||||
public:
|
||||
PPCFrameInfo(const TargetMachine &tm, bool LP64)
|
||||
: TargetFrameInfo(TargetFrameInfo::StackGrowsDown, 16, 0), TM(tm) {
|
||||
PPCFrameInfo(const PPCSubtarget &sti)
|
||||
: 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
|
||||
/// return address.
|
||||
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.
|
||||
const SpillSlot *
|
||||
getCalleeSavedSpillSlots(unsigned &NumEntries) const {
|
||||
if (TM.getSubtarget<PPCSubtarget>().isDarwinABI()) {
|
||||
if (Subtarget.isDarwinABI()) {
|
||||
NumEntries = 1;
|
||||
if (TM.getSubtarget<PPCSubtarget>().isPPC64()) {
|
||||
if (Subtarget.isPPC64()) {
|
||||
static const SpillSlot darwin64Offsets = {PPC::X31, -8};
|
||||
return &darwin64Offsets;
|
||||
} else {
|
||||
@ -103,7 +116,7 @@ public:
|
||||
}
|
||||
|
||||
// Early exit if not using the SVR4 ABI.
|
||||
if (!TM.getSubtarget<PPCSubtarget>().isSVR4ABI()) {
|
||||
if (!Subtarget.isSVR4ABI()) {
|
||||
NumEntries = 0;
|
||||
return 0;
|
||||
}
|
||||
@ -283,7 +296,7 @@ public:
|
||||
{PPC::V20, -192}
|
||||
};
|
||||
|
||||
if (TM.getSubtarget<PPCSubtarget>().isPPC64()) {
|
||||
if (Subtarget.isPPC64()) {
|
||||
NumEntries = array_lengthof(Offsets64);
|
||||
|
||||
return Offsets64;
|
||||
|
@ -44,16 +44,6 @@
|
||||
#include "llvm/ADT/STLExtras.h"
|
||||
#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.
|
||||
namespace llvm {
|
||||
cl::opt<bool> EnablePPC32RS("enable-ppc32-regscavenger",
|
||||
@ -715,194 +705,6 @@ PPCRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
|
||||
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
|
||||
PPCRegisterInfo::processFunctionBeforeCalleeSavedScan(MachineFunction &MF,
|
||||
RegScavenger *RS) const {
|
||||
@ -926,7 +728,7 @@ PPCRegisterInfo::processFunctionBeforeCalleeSavedScan(MachineFunction &MF,
|
||||
// Allocate the frame index for frame pointer save area.
|
||||
FPSI = MF.getFrameInfo()->CreateFixedObject(isPPC64? 8 : 4, FPOffset, true);
|
||||
// Save the result.
|
||||
FI->setFramePointerSaveIndex(FPSI);
|
||||
FI->setFramePointerSaveIndex(FPSI);
|
||||
}
|
||||
|
||||
// Reserve stack space to move the linkage area to in case of a tail call.
|
||||
@ -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 {
|
||||
return !Subtarget.isPPC64() ? PPC::LR : PPC::LR8;
|
||||
}
|
||||
|
@ -44,11 +44,6 @@ public:
|
||||
|
||||
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.
|
||||
/// FIXME (64-bit): Should be inlined.
|
||||
bool requiresRegisterScavenging(const MachineFunction &MF) const;
|
||||
@ -66,10 +61,6 @@ public:
|
||||
void eliminateFrameIndex(MachineBasicBlock::iterator II,
|
||||
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,
|
||||
RegScavenger *RS = NULL) const;
|
||||
void processFunctionBeforeFrameFinalized(MachineFunction &MF) const;
|
||||
|
@ -44,7 +44,7 @@ PPCTargetMachine::PPCTargetMachine(const Target &T, const std::string &TT,
|
||||
: LLVMTargetMachine(T, TT),
|
||||
Subtarget(TT, FS, is64Bit),
|
||||
DataLayout(Subtarget.getTargetDataString()), InstrInfo(*this),
|
||||
FrameInfo(*this, is64Bit), JITInfo(*this, is64Bit),
|
||||
FrameInfo(Subtarget), JITInfo(*this, is64Bit),
|
||||
TLInfo(*this), TSInfo(*this),
|
||||
InstrItins(Subtarget.getInstrItineraryData()) {
|
||||
|
||||
|
80
lib/Target/Sparc/SparcFrameInfo.cpp
Normal file
80
lib/Target/Sparc/SparcFrameInfo.cpp
Normal file
@ -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);
|
||||
}
|
39
lib/Target/Sparc/SparcFrameInfo.h
Normal file
39
lib/Target/Sparc/SparcFrameInfo.h
Normal file
@ -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::
|
||||
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 {
|
||||
return SP::I7;
|
||||
}
|
||||
|
@ -26,10 +26,10 @@ class Type;
|
||||
struct SparcRegisterInfo : public SparcGenRegisterInfo {
|
||||
SparcSubtarget &Subtarget;
|
||||
const TargetInstrInfo &TII;
|
||||
|
||||
|
||||
SparcRegisterInfo(SparcSubtarget &st, const TargetInstrInfo &tii);
|
||||
|
||||
/// Code Generation virtual methods...
|
||||
/// Code Generation virtual methods...
|
||||
const unsigned *getCalleeSavedRegs(const MachineFunction *MF = 0) const;
|
||||
|
||||
BitVector getReservedRegs(const MachineFunction &MF) const;
|
||||
@ -45,9 +45,6 @@ struct SparcRegisterInfo : public SparcGenRegisterInfo {
|
||||
|
||||
void processFunctionBeforeFrameFinalized(MachineFunction &MF) const;
|
||||
|
||||
void emitPrologue(MachineFunction &MF) const;
|
||||
void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const;
|
||||
|
||||
// Debug information queries.
|
||||
unsigned getRARegister() const;
|
||||
unsigned getFrameRegister(const MachineFunction &MF) const;
|
||||
|
@ -10,9 +10,9 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "Sparc.h"
|
||||
#include "SparcMCAsmInfo.h"
|
||||
#include "SparcTargetMachine.h"
|
||||
#include "Sparc.h"
|
||||
#include "llvm/PassManager.h"
|
||||
#include "llvm/Target/TargetRegistry.h"
|
||||
using namespace llvm;
|
||||
@ -34,8 +34,8 @@ SparcTargetMachine::SparcTargetMachine(const Target &T, const std::string &TT,
|
||||
: LLVMTargetMachine(T, TT),
|
||||
Subtarget(TT, FS, is64bit),
|
||||
DataLayout(Subtarget.getDataLayout()),
|
||||
TLInfo(*this), TSInfo(*this), InstrInfo(Subtarget),
|
||||
FrameInfo(TargetFrameInfo::StackGrowsDown, 8, 0) {
|
||||
TLInfo(*this), TSInfo(*this), InstrInfo(Subtarget),
|
||||
FrameInfo(Subtarget) {
|
||||
}
|
||||
|
||||
bool SparcTargetMachine::addInstSelector(PassManagerBase &PM,
|
||||
|
@ -14,13 +14,14 @@
|
||||
#ifndef 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/TargetData.h"
|
||||
#include "llvm/Target/TargetFrameInfo.h"
|
||||
#include "SparcInstrInfo.h"
|
||||
#include "SparcSubtarget.h"
|
||||
#include "SparcISelLowering.h"
|
||||
#include "SparcSelectionDAGInfo.h"
|
||||
|
||||
namespace llvm {
|
||||
|
||||
@ -30,7 +31,7 @@ class SparcTargetMachine : public LLVMTargetMachine {
|
||||
SparcTargetLowering TLInfo;
|
||||
SparcSelectionDAGInfo TSInfo;
|
||||
SparcInstrInfo InstrInfo;
|
||||
TargetFrameInfo FrameInfo;
|
||||
SparcFrameInfo FrameInfo;
|
||||
public:
|
||||
SparcTargetMachine(const Target &T, const std::string &TT,
|
||||
const std::string &FS, bool is64bit);
|
||||
|
171
lib/Target/SystemZ/SystemZFrameInfo.cpp
Normal file
171
lib/Target/SystemZ/SystemZFrameInfo.cpp
Normal file
@ -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);
|
||||
}
|
||||
}
|
41
lib/Target/SystemZ/SystemZFrameInfo.h
Normal file
41
lib/Target/SystemZ/SystemZFrameInfo.h
Normal file
@ -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);
|
||||
}
|
||||
|
||||
/// 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 {
|
||||
assert(0 && "What is the return address register");
|
||||
return 0;
|
||||
|
@ -50,9 +50,6 @@ struct SystemZRegisterInfo : public SystemZGenRegisterInfo {
|
||||
void processFunctionBeforeCalleeSavedScan(MachineFunction &MF,
|
||||
RegScavenger *RS) const;
|
||||
|
||||
void emitPrologue(MachineFunction &MF) const;
|
||||
void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const;
|
||||
|
||||
// Debug information queries.
|
||||
unsigned getRARegister() 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"
|
||||
"-f64:64:64-f128:128:128-a0:16:16-n32:64"),
|
||||
InstrInfo(*this), TLInfo(*this), TSInfo(*this),
|
||||
FrameInfo(TargetFrameInfo::StackGrowsDown, 8, -160) {
|
||||
FrameInfo(Subtarget) {
|
||||
|
||||
if (getRelocationModel() == Reloc::Default)
|
||||
setRelocationModel(Reloc::Static);
|
||||
|
@ -17,6 +17,7 @@
|
||||
|
||||
#include "SystemZInstrInfo.h"
|
||||
#include "SystemZISelLowering.h"
|
||||
#include "SystemZFrameInfo.h"
|
||||
#include "SystemZSelectionDAGInfo.h"
|
||||
#include "SystemZRegisterInfo.h"
|
||||
#include "SystemZSubtarget.h"
|
||||
@ -34,10 +35,7 @@ class SystemZTargetMachine : public LLVMTargetMachine {
|
||||
SystemZInstrInfo InstrInfo;
|
||||
SystemZTargetLowering TLInfo;
|
||||
SystemZSelectionDAGInfo TSInfo;
|
||||
|
||||
// SystemZ does not have any call stack frame, therefore not having
|
||||
// any SystemZ specific FrameInfo class.
|
||||
TargetFrameInfo FrameInfo;
|
||||
SystemZFrameInfo FrameInfo;
|
||||
public:
|
||||
SystemZTargetMachine(const Target &T, const std::string &TT,
|
||||
const std::string &FS);
|
||||
|
736
lib/Target/X86/X86FrameInfo.cpp
Normal file
736
lib/Target/X86/X86FrameInfo.cpp
Normal file
@ -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);
|
||||
}
|
||||
}
|
46
lib/Target/X86/X86FrameInfo.h
Normal file
46
lib/Target/X86/X86FrameInfo.h
Normal file
@ -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"
|
||||
using namespace llvm;
|
||||
|
||||
static cl::opt<bool>
|
||||
cl::opt<bool>
|
||||
ForceStackAlign("force-align-stack",
|
||||
cl::desc("Force align the stack to the minimum alignment"
|
||||
" 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 {
|
||||
return Is64Bit ? X86::RIP // Should have dwarf #16.
|
||||
: X86::EIP; // Should have dwarf #8.
|
||||
|
@ -132,14 +132,13 @@ public:
|
||||
void processFunctionBeforeCalleeSavedScan(MachineFunction &MF,
|
||||
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.
|
||||
unsigned getRARegister() 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;
|
||||
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)
|
||||
: LLVMTargetMachine(T, TT),
|
||||
Subtarget(TT, FS, is64Bit),
|
||||
FrameInfo(TargetFrameInfo::StackGrowsDown,
|
||||
Subtarget.getStackAlignment(),
|
||||
(Subtarget.isTargetWin64() ? -40 :
|
||||
(Subtarget.is64Bit() ? -8 : -4))),
|
||||
FrameInfo(Subtarget),
|
||||
ELFWriterInfo(is64Bit, true) {
|
||||
DefRelocModel = getRelocationModel();
|
||||
|
||||
|
@ -14,16 +14,17 @@
|
||||
#ifndef X86TARGETMACHINE_H
|
||||
#define X86TARGETMACHINE_H
|
||||
|
||||
#include "llvm/Target/TargetMachine.h"
|
||||
#include "llvm/Target/TargetData.h"
|
||||
#include "llvm/Target/TargetFrameInfo.h"
|
||||
#include "X86.h"
|
||||
#include "X86ELFWriterInfo.h"
|
||||
#include "X86InstrInfo.h"
|
||||
#include "X86JITInfo.h"
|
||||
#include "X86Subtarget.h"
|
||||
#include "X86ISelLowering.h"
|
||||
#include "X86FrameInfo.h"
|
||||
#include "X86JITInfo.h"
|
||||
#include "X86SelectionDAGInfo.h"
|
||||
#include "X86Subtarget.h"
|
||||
#include "llvm/Target/TargetMachine.h"
|
||||
#include "llvm/Target/TargetData.h"
|
||||
#include "llvm/Target/TargetFrameInfo.h"
|
||||
|
||||
namespace llvm {
|
||||
|
||||
@ -31,7 +32,7 @@ class formatted_raw_ostream;
|
||||
|
||||
class X86TargetMachine : public LLVMTargetMachine {
|
||||
X86Subtarget Subtarget;
|
||||
TargetFrameInfo FrameInfo;
|
||||
X86FrameInfo FrameInfo;
|
||||
X86ELFWriterInfo ELFWriterInfo;
|
||||
Reloc::Model DefRelocModel; // Reloc model before it's overridden.
|
||||
|
||||
|
@ -14,14 +14,251 @@
|
||||
|
||||
#include "XCore.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;
|
||||
|
||||
// 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(const TargetMachine &tm):
|
||||
TargetFrameInfo(TargetFrameInfo::StackGrowsDown, 4, 0)
|
||||
{
|
||||
XCoreFrameInfo::XCoreFrameInfo(const XCoreSubtarget &sti)
|
||||
: TargetFrameInfo(TargetFrameInfo::StackGrowsDown, 4, 0),
|
||||
STI(sti) {
|
||||
// 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"
|
||||
|
||||
namespace llvm {
|
||||
class XCoreFrameInfo: public TargetFrameInfo {
|
||||
class XCoreSubtarget;
|
||||
|
||||
class XCoreFrameInfo: public TargetFrameInfo {
|
||||
const XCoreSubtarget &STI;
|
||||
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)
|
||||
static int stackSlotSize() {
|
||||
|
@ -346,215 +346,13 @@ loadConstant(MachineBasicBlock &MBB, MachineBasicBlock::iterator I,
|
||||
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 {
|
||||
return XCoreGenRegisterInfo::getDwarfRegNumFull(RegNum, 0);
|
||||
}
|
||||
|
||||
unsigned XCoreRegisterInfo::getFrameRegister(const MachineFunction &MF) const {
|
||||
bool FP = hasFP(MF);
|
||||
|
||||
|
||||
return FP ? XCore::R10 : XCore::SP;
|
||||
}
|
||||
|
||||
|
@ -62,9 +62,6 @@ public:
|
||||
|
||||
void processFunctionBeforeFrameFinalized(MachineFunction &MF) const;
|
||||
|
||||
void emitPrologue(MachineFunction &MF) const;
|
||||
void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const;
|
||||
|
||||
// Debug information queries.
|
||||
unsigned getRARegister() 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-"
|
||||
"i16:16:32-i32:32:32-i64:32:32-n32"),
|
||||
InstrInfo(),
|
||||
FrameInfo(*this),
|
||||
FrameInfo(Subtarget),
|
||||
TLInfo(*this),
|
||||
TSInfo(*this) {
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user