diff options
author | Robert Lytton <robert@xmos.com> | 2014-02-18 11:21:48 +0000 |
---|---|---|
committer | Robert Lytton <robert@xmos.com> | 2014-02-18 11:21:48 +0000 |
commit | af6c256c348fab7d12222d0e71475d116493ff23 (patch) | |
tree | a44fd4c6f270d2f520db0b58895a97c2829c9e9b /llvm/lib/Target/XCore/XCoreFrameLowering.cpp | |
parent | d5fe8ce005e628de5fcbdace9f7dfec225676d8b (diff) | |
download | bcm5719-llvm-af6c256c348fab7d12222d0e71475d116493ff23.tar.gz bcm5719-llvm-af6c256c348fab7d12222d0e71475d116493ff23.zip |
XCore target: Fix llvm.eh.return and EH info register handling
llvm-svn: 201561
Diffstat (limited to 'llvm/lib/Target/XCore/XCoreFrameLowering.cpp')
-rw-r--r-- | llvm/lib/Target/XCore/XCoreFrameLowering.cpp | 137 |
1 files changed, 97 insertions, 40 deletions
diff --git a/llvm/lib/Target/XCore/XCoreFrameLowering.cpp b/llvm/lib/Target/XCore/XCoreFrameLowering.cpp index 9950d78b50f..8ea9788b1a8 100644 --- a/llvm/lib/Target/XCore/XCoreFrameLowering.cpp +++ b/llvm/lib/Target/XCore/XCoreFrameLowering.cpp @@ -25,8 +25,11 @@ #include "llvm/IR/DataLayout.h" #include "llvm/IR/Function.h" #include "llvm/Support/ErrorHandling.h" +#include "llvm/Target/TargetLowering.h" #include "llvm/Target/TargetOptions.h" +#include <algorithm> // std::sort + using namespace llvm; static const unsigned FramePtr = XCore::R10; @@ -115,21 +118,58 @@ static void IfNeededLDAWSP(MachineBasicBlock &MBB, /// Creates an ordered list of registers that are spilled /// during the emitPrologue/emitEpilogue. /// Registers are ordered according to their frame offset. -static void GetSpillList(SmallVectorImpl<std::pair<unsigned,int> > &SpillList, +/// As offsets are negative, the largest offsets will be first. +static void GetSpillList(SmallVectorImpl<std::pair<int,unsigned> > &SpillList, MachineFrameInfo *MFI, XCoreFunctionInfo *XFI, bool fetchLR, bool fetchFP) { - int LRSpillOffset = fetchLR? MFI->getObjectOffset(XFI->getLRSpillSlot()) : 0; - int FPSpillOffset = fetchFP? MFI->getObjectOffset(XFI->getFPSpillSlot()) : 0; - if (fetchLR && fetchFP && LRSpillOffset > FPSpillOffset) { - SpillList.push_back(std::pair<unsigned, int>(XCore::LR, LRSpillOffset)); - fetchLR = false; + if (fetchLR) { + int Offset = MFI->getObjectOffset(XFI->getLRSpillSlot()); + SpillList.push_back(std::pair<int,unsigned>(Offset, XCore::LR)); + } + if (fetchFP) { + int Offset = MFI->getObjectOffset(XFI->getFPSpillSlot()); + SpillList.push_back(std::pair<int,unsigned>(Offset, FramePtr)); } - if (fetchFP) - SpillList.push_back(std::pair<unsigned, int>(FramePtr, FPSpillOffset)); - if (fetchLR) - SpillList.push_back(std::pair<unsigned, int>(XCore::LR, LRSpillOffset)); + std::sort(SpillList.begin(), SpillList.end()); +} + +/// Creates an ordered list of EH info register 'spills'. +/// These slots are only used by the unwinder and calls to llvm.eh.return(). +/// Registers are ordered according to their frame offset. +/// As offsets are negative, the largest offsets will be first. +static void GetEHSpillList(SmallVectorImpl<std::pair<int,unsigned> > &SpillList, + MachineFrameInfo *MFI, XCoreFunctionInfo *XFI, + const TargetLowering *TL) { + assert(XFI->hasEHSpillSlot() && "There are no EH register spill slots"); + const int* EHSlot = XFI->getEHSpillSlot(); + SpillList.push_back( + std::pair<int,unsigned>(MFI->getObjectOffset(EHSlot[0]), + TL->getExceptionPointerRegister())); + SpillList.push_back( + std::pair<int,unsigned>(MFI->getObjectOffset(EHSlot[1]), + TL->getExceptionSelectorRegister())); + std::sort(SpillList.begin(), SpillList.end()); } +/// Restore clobbered registers with their spill slot value. +/// The SP will be adjusted at the same time, thus the SpillList must be ordered +/// with the largest (negative) offsets first. +static void +RestoreSpillList(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, + DebugLoc dl, const TargetInstrInfo &TII, int &RemainingAdj, + SmallVectorImpl<std::pair<int,unsigned> > &SpillList) { + for (unsigned i = 0, e = SpillList.size(); i != e; ++i) { + unsigned SpilledReg = SpillList[i].second; + int SpillOffset = SpillList[i].first; + assert(SpillOffset % 4 == 0 && "Misaligned stack offset"); + assert(SpillOffset <= 0 && "Unexpected positive stack offset"); + int OffsetFromTop = - SpillOffset/4; + IfNeededLDAWSP(MBB, MBBI, dl, TII, OffsetFromTop, RemainingAdj); + int Offset = RemainingAdj - OffsetFromTop; + int Opcode = isImmU6(Offset) ? XCore::LDWSP_ru6 : XCore::LDWSP_lru6; + BuildMI(MBB, MBBI, dl, TII.get(Opcode), SpilledReg).addImm(Offset); + } +} //===----------------------------------------------------------------------===// // XCoreFrameLowering: @@ -194,11 +234,13 @@ void XCoreFrameLowering::emitPrologue(MachineFunction &MF) const { } // If necessary, save LR and FP to the stack, as we EXTSP. - SmallVector<std::pair<unsigned,int>,2> SpillList; + SmallVector<std::pair<int,unsigned>,2> SpillList; GetSpillList(SpillList, MFI, XFI, saveLR, FP); + // We want the nearest (negative) offsets first, so reverse list. + std::reverse(SpillList.begin(),SpillList.end()); for (unsigned i = 0, e = SpillList.size(); i != e; ++i) { - unsigned SpillReg = SpillList[i].first; - int SpillOffset = SpillList[i].second; + unsigned SpillReg = SpillList[i].second; + int SpillOffset = SpillList[i].first; assert(SpillOffset % 4 == 0 && "Misaligned stack offset"); assert(SpillOffset <= 0 && "Unexpected positive stack offset"); int OffsetFromTop = - SpillOffset/4; @@ -239,6 +281,19 @@ void XCoreFrameLowering::emitPrologue(MachineFunction &MF) const { unsigned DRegNum = MRI->getDwarfRegNum(CSI.getReg(), true); EmitCfiOffset(MBB, MBBI, dl, TII, MMI, DRegNum, Offset, SpillLabel); } + if (XFI->hasEHSpillSlot()) { + // The unwinder requires stack slot & CFI offsets for the exception info. + // We do not save/spill these registers. + SmallVector<std::pair<int,unsigned>,2> SpillList; + GetEHSpillList(SpillList, MFI, XFI, MF.getTarget().getTargetLowering()); + assert(SpillList.size()==2 && "Unexpected SpillList size"); + EmitCfiOffset(MBB, MBBI, dl, TII, MMI, + MRI->getDwarfRegNum(SpillList[0].second,true), + SpillList[0].first, NULL); + EmitCfiOffset(MBB, MBBI, dl, TII, MMI, + MRI->getDwarfRegNum(SpillList[1].second,true), + SpillList[1].first, NULL); + } } } @@ -252,7 +307,19 @@ void XCoreFrameLowering::emitEpilogue(MachineFunction &MF, DebugLoc dl = MBBI->getDebugLoc(); unsigned RetOpcode = MBBI->getOpcode(); + // Work out frame sizes. + // We will adjust the SP in stages towards the final FrameSize. + int RemainingAdj = MFI->getStackSize(); + assert(RemainingAdj%4 == 0 && "Misaligned frame size"); + RemainingAdj /= 4; + if (RetOpcode == XCore::EH_RETURN) { + // 'Restore' the exception info the unwinder has placed into the stack slots. + SmallVector<std::pair<int,unsigned>,2> SpillList; + GetEHSpillList(SpillList, MFI, XFI, MF.getTarget().getTargetLowering()); + RestoreSpillList(MBB, MBBI, dl, TII, RemainingAdj, SpillList); + + // Return to the landing pad. unsigned EhStackReg = MBBI->getOperand(0).getReg(); unsigned EhHandlerReg = MBBI->getOperand(1).getReg(); BuildMI(MBB, MBBI, dl, TII.get(XCore::SETSP_1r)).addReg(EhStackReg); @@ -261,12 +328,6 @@ void XCoreFrameLowering::emitEpilogue(MachineFunction &MF, return; } - // Work out frame sizes. - // We will adjust the SP in stages towards the final FrameSize. - int RemainingAdj = MFI->getStackSize(); - assert(RemainingAdj%4 == 0 && "Misaligned frame size"); - RemainingAdj /= 4; - bool restoreLR = XFI->hasLRSpillSlot(); bool UseRETSP = restoreLR && RemainingAdj && (MFI->getObjectOffset(XFI->getLRSpillSlot()) == 0); @@ -278,20 +339,9 @@ void XCoreFrameLowering::emitEpilogue(MachineFunction &MF, BuildMI(MBB, MBBI, dl, TII.get(XCore::SETSP_1r)).addReg(FramePtr); // If necessary, restore LR and FP from the stack, as we EXTSP. - SmallVector<std::pair<unsigned,int>,2> SpillList; + SmallVector<std::pair<int,unsigned>,2> SpillList; GetSpillList(SpillList, MFI, XFI, restoreLR, FP); - unsigned i = SpillList.size(); - while (i--) { - unsigned SpilledReg = SpillList[i].first; - int SpillOffset = SpillList[i].second; - assert(SpillOffset % 4 == 0 && "Misaligned stack offset"); - assert(SpillOffset <= 0 && "Unexpected positive stack offset"); - int OffsetFromTop = - SpillOffset/4; - IfNeededLDAWSP(MBB, MBBI, dl, TII, OffsetFromTop, RemainingAdj); - int Offset = RemainingAdj - OffsetFromTop; - int Opcode = isImmU6(Offset) ? XCore::LDWSP_ru6 : XCore::LDWSP_lru6; - BuildMI(MBB, MBBI, dl, TII.get(Opcode), SpilledReg).addImm(Offset); - } + RestoreSpillList(MBB, MBBI, dl, TII, RemainingAdj, SpillList); if (RemainingAdj) { // Complete all but one of the remaining Stack adjustments. @@ -442,25 +492,32 @@ processFunctionBeforeCalleeSavedScan(MachineFunction &MF, XCoreFunctionInfo *XFI = MF.getInfo<XCoreFunctionInfo>(); bool LRUsed = MF.getRegInfo().isPhysRegUsed(XCore::LR); - // If we need to extend the stack it is more efficient to use entsp / retsp. - // We force the LR to be saved so these instructions are used. + if (!LRUsed && !MF.getFunction()->isVarArg() && MF.getFrameInfo()->estimateStackSize(MF)) + // If we need to extend the stack it is more efficient to use entsp / retsp. + // We force the LR to be saved so these instructions are used. LRUsed = true; - // We will be spilling all callee saved registers in case of unwinding. - if (MF.getMMI().callsUnwindInit()) + + if (MF.getMMI().callsUnwindInit() || MF.getMMI().callsEHReturn()) { + // The unwinder expects to find spill slots for the exception info regs R0 + // & R1. These are used during llvm.eh.return() to 'restore' the exception + // info. N.B. we do not spill or restore R0, R1 during normal operation. + XFI->createEHSpillSlot(MF); + // As we will have a stack, we force the LR to be saved. LRUsed = true; + } - // We will handling LR in the prologue/epilogue - // and space on the stack ourselves. if (LRUsed) { + // We will handle the LR in the prologue/epilogue + // and allocate space on the stack ourselves. MF.getRegInfo().setPhysRegUnused(XCore::LR); XFI->createLRSpillSlot(MF); } - // A callee save register is used to hold the FP. - // This needs saving / restoring in the epilogue / prologue. if (hasFP(MF)) + // A callee save register is used to hold the FP. + // This needs saving / restoring in the epilogue / prologue. XFI->createFPSpillSlot(MF); } |