#include "llvm/Target/MRegisterInfo.h"
#include "llvm/Target/TargetFrameInfo.h"
#include "llvm/Target/TargetInstrInfo.h"
+#include "llvm/Support/Compiler.h"
+#include <climits>
using namespace llvm;
namespace {
- struct PEI : public MachineFunctionPass {
+ struct VISIBILITY_HIDDEN PEI : public MachineFunctionPass {
const char *getPassName() const {
return "Prolog/Epilog Insertion & Frame Finalization";
}
/// frame indexes with appropriate references.
///
bool runOnMachineFunction(MachineFunction &Fn) {
- // Scan the function for modified caller saved registers and insert spill
- // code for any caller saved registers that are modified. Also calculate
+ // Get MachineDebugInfo so that we can track the construction of the
+ // frame.
+ if (MachineDebugInfo *DI = getAnalysisToUpdate<MachineDebugInfo>()) {
+ Fn.getFrameInfo()->setMachineDebugInfo(DI);
+ }
+
+ // Allow the target machine to make some adjustments to the function
+ // e.g. UsedPhysRegs before calculateCalleeSavedRegisters.
+ Fn.getTarget().getRegisterInfo()->processFunctionBeforeCalleeSaveScan(Fn);
+
+ // Scan the function for modified callee saved registers and insert spill
+ // code for any callee saved registers that are modified. Also calculate
// the MaxCallFrameSize and HasCalls variables for the function's frame
// information and eliminates call frame pseudo instructions.
- calculateCallerSavedRegisters(Fn);
+ calculateCalleeSavedRegisters(Fn);
- // Add the code to save and restore the caller saved registers
- saveCallerSavedRegisters(Fn);
+ // Add the code to save and restore the callee saved registers
+ saveCalleeSavedRegisters(Fn);
// Allow the target machine to make final modifications to the function
// before the frame layout is finalized.
// Add prolog and epilog code to the function. This function is required
// to align the stack frame as necessary for any stack variables or
- // called functions. Because of this, calculateCallerSavedRegisters
+ // called functions. Because of this, calculateCalleeSavedRegisters
// must be called before this function in order to set the HasCalls
// and MaxCallFrameSize variables.
insertPrologEpilogCode(Fn);
//
replaceFrameIndices(Fn);
- RegsToSave.clear();
- StackSlots.clear();
return true;
}
-
+
private:
- std::vector<std::pair<unsigned, const TargetRegisterClass*> > RegsToSave;
- std::vector<int> StackSlots;
+ // MinCSFrameIndex, MaxCSFrameIndex - Keeps the range of callee save
+ // stack frame indexes.
+ unsigned MinCSFrameIndex, MaxCSFrameIndex;
- void calculateCallerSavedRegisters(MachineFunction &Fn);
- void saveCallerSavedRegisters(MachineFunction &Fn);
+ void calculateCalleeSavedRegisters(MachineFunction &Fn);
+ void saveCalleeSavedRegisters(MachineFunction &Fn);
void calculateFrameObjectOffsets(MachineFunction &Fn);
void replaceFrameIndices(MachineFunction &Fn);
void insertPrologEpilogCode(MachineFunction &Fn);
FunctionPass *llvm::createPrologEpilogCodeInserter() { return new PEI(); }
-/// calculateCallerSavedRegisters - Scan the function for modified caller saved
+/// calculateCalleeSavedRegisters - Scan the function for modified callee saved
/// registers. Also calculate the MaxCallFrameSize and HasCalls variables for
/// the function's frame information and eliminates call frame pseudo
/// instructions.
///
-void PEI::calculateCallerSavedRegisters(MachineFunction &Fn) {
+void PEI::calculateCalleeSavedRegisters(MachineFunction &Fn) {
const MRegisterInfo *RegInfo = Fn.getTarget().getRegisterInfo();
const TargetFrameInfo *TFI = Fn.getTarget().getFrameInfo();
- const TargetInstrInfo &TII = *Fn.getTarget().getInstrInfo();
// Get the callee saved register list...
const unsigned *CSRegs = RegInfo->getCalleeSaveRegs();
const bool *PhysRegsUsed = Fn.getUsedPhysregs();
const TargetRegisterClass* const *CSRegClasses =
RegInfo->getCalleeSaveRegClasses();
+ std::vector<CalleeSavedInfo> CSI;
for (unsigned i = 0; CSRegs[i]; ++i) {
unsigned Reg = CSRegs[i];
if (PhysRegsUsed[Reg]) {
// If the reg is modified, save it!
- RegsToSave.push_back(std::make_pair(Reg, CSRegClasses[i]));
+ CSI.push_back(CalleeSavedInfo(Reg, CSRegClasses[i]));
} else {
for (const unsigned *AliasSet = RegInfo->getAliasSet(Reg);
*AliasSet; ++AliasSet) { // Check alias registers too.
if (PhysRegsUsed[*AliasSet]) {
- RegsToSave.push_back(std::make_pair(Reg, CSRegClasses[i]));
+ CSI.push_back(CalleeSavedInfo(Reg, CSRegClasses[i]));
break;
}
}
}
}
- if (RegsToSave.empty())
- return; // Early exit if no caller saved registers are modified!
+ if (CSI.empty())
+ return; // Early exit if no callee saved registers are modified!
unsigned NumFixedSpillSlots;
const std::pair<unsigned,int> *FixedSpillSlots =
// Now that we know which registers need to be saved and restored, allocate
// stack slots for them.
- for (unsigned i = 0, e = RegsToSave.size(); i != e; ++i) {
- unsigned Reg = RegsToSave[i].first;
- const TargetRegisterClass *RC = RegsToSave[i].second;
+ MinCSFrameIndex = INT_MAX;
+ MaxCSFrameIndex = 0;
+ for (unsigned i = 0, e = CSI.size(); i != e; ++i) {
+ unsigned Reg = CSI[i].getReg();
+ const TargetRegisterClass *RC = CSI[i].getRegClass();
// Check to see if this physreg must be spilled to a particular stack slot
// on this target.
int FrameIdx;
if (FixedSlot == FixedSpillSlots+NumFixedSpillSlots) {
// Nope, just spill it anywhere convenient.
- FrameIdx = FFI->CreateStackObject(RC->getSize(), RC->getAlignment());
+ unsigned Align = RC->getAlignment();
+ unsigned StackAlign = TFI->getStackAlignment();
+ // We may not be able to sastify the desired alignment specification of
+ // the TargetRegisterClass if the stack alignment is smaller. Use the min.
+ Align = std::min(Align, StackAlign);
+ FrameIdx = FFI->CreateStackObject(RC->getSize(), Align);
+ if ((unsigned)FrameIdx < MinCSFrameIndex) MinCSFrameIndex = FrameIdx;
+ if ((unsigned)FrameIdx > MaxCSFrameIndex) MaxCSFrameIndex = FrameIdx;
} else {
// Spill it to the stack where we must.
FrameIdx = FFI->CreateFixedObject(RC->getSize(), FixedSlot->second);
}
- StackSlots.push_back(FrameIdx);
+ CSI[i].setFrameIdx(FrameIdx);
}
+
+ FFI->setCalleeSavedInfo(CSI);
}
-/// saveCallerSavedRegisters - Insert spill code for any caller saved registers
+/// saveCalleeSavedRegisters - Insert spill code for any callee saved registers
/// that are modified in the function.
///
-void PEI::saveCallerSavedRegisters(MachineFunction &Fn) {
- // Early exit if no caller saved registers are modified!
- if (RegsToSave.empty())
+void PEI::saveCalleeSavedRegisters(MachineFunction &Fn) {
+ // Get callee saved register information.
+ MachineFrameInfo *FFI = Fn.getFrameInfo();
+ const std::vector<CalleeSavedInfo> &CSI = FFI->getCalleeSavedInfo();
+
+ // Early exit if no callee saved registers are modified!
+ if (CSI.empty())
return;
const MRegisterInfo *RegInfo = Fn.getTarget().getRegisterInfo();
// code into the entry block.
MachineBasicBlock *MBB = Fn.begin();
MachineBasicBlock::iterator I = MBB->begin();
- for (unsigned i = 0, e = RegsToSave.size(); i != e; ++i) {
+ for (unsigned i = 0, e = CSI.size(); i != e; ++i) {
// Insert the spill to the stack frame.
- RegInfo->storeRegToStackSlot(*MBB, I, RegsToSave[i].first, StackSlots[i],
- RegsToSave[i].second);
+ RegInfo->storeRegToStackSlot(*MBB, I, CSI[i].getReg(), CSI[i].getFrameIdx(),
+ CSI[i].getRegClass());
}
// Add code to restore the callee-save registers in each exiting block.
// Restore all registers immediately before the return and any terminators
// that preceed it.
- for (unsigned i = 0, e = RegsToSave.size(); i != e; ++i) {
- RegInfo->loadRegFromStackSlot(*MBB, I, RegsToSave[i].first,
- StackSlots[i], RegsToSave[i].second);
+ for (unsigned i = 0, e = CSI.size(); i != e; ++i) {
+ RegInfo->loadRegFromStackSlot(*MBB, I, CSI[i].getReg(),
+ CSI[i].getFrameIdx(),
+ CSI[i].getRegClass());
assert(I != MBB->begin() &&
"loadRegFromStackSlot didn't insert any code!");
// Insert in reverse order. loadRegFromStackSlot can insert multiple
if (FixedOff > Offset) Offset = FixedOff;
}
+ // First assign frame offsets to stack objects that are used to spill
+ // callee save registers.
+ if (StackGrowsDown) {
+ for (unsigned i = 0, e = FFI->getObjectIndexEnd(); i != e; ++i) {
+ if (i < MinCSFrameIndex || i > MaxCSFrameIndex)
+ continue;
+
+ // If stack grows down, we need to add size of find the lowest
+ // address of the object.
+ Offset += FFI->getObjectSize(i);
+
+ unsigned Align = FFI->getObjectAlignment(i);
+ // If the alignment of this object is greater than that of the stack, then
+ // increase the stack alignment to match.
+ MaxAlign = std::max(MaxAlign, Align);
+ // Adjust to alignment boundary
+ Offset = (Offset+Align-1)/Align*Align;
+
+ FFI->setObjectOffset(i, -Offset); // Set the computed offset
+ }
+ } else {
+ for (int i = FFI->getObjectIndexEnd()-1; i >= 0; --i) {
+ if ((unsigned)i < MinCSFrameIndex || (unsigned)i > MaxCSFrameIndex)
+ continue;
+
+ unsigned Align = FFI->getObjectAlignment(i);
+ // If the alignment of this object is greater than that of the stack, then
+ // increase the stack alignment to match.
+ MaxAlign = std::max(MaxAlign, Align);
+ // Adjust to alignment boundary
+ Offset = (Offset+Align-1)/Align*Align;
+
+ FFI->setObjectOffset(i, Offset);
+ Offset += FFI->getObjectSize(i);
+ }
+ }
+
+ // Then assign frame offsets to stack objects that are not used to spill
+ // callee save registers.
for (unsigned i = 0, e = FFI->getObjectIndexEnd(); i != e; ++i) {
+ if (i >= MinCSFrameIndex && i <= MaxCSFrameIndex)
+ continue;
+
// If stack grows down, we need to add size of find the lowest
// address of the object.
if (StackGrowsDown)
}
}
+
// Align the final stack pointer offset, but only if there are calls in the
// function. This ensures that any calls to subroutines have their stack
// frames suitable aligned.
// Remember the required stack alignment in case targets need it to perform
// dynamic stack alignment.
- FFI->setMaxAlignment(MaxAlign);
+ assert(FFI->getMaxAlignment() == MaxAlign &&
+ "Stack alignment calculation broken!");
}
-/// insertPrologEpilogCode - Scan the function for modified caller saved
-/// registers, insert spill code for these caller saved registers, then add
+/// insertPrologEpilogCode - Scan the function for modified callee saved
+/// registers, insert spill code for these callee saved registers, then add
/// prolog and epilog code to the function.
///
void PEI::insertPrologEpilogCode(MachineFunction &Fn) {