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 | 9409825b57cec078a2a90910978622073d31813d (patch) | |
tree | a02b7f584547e9b4390f79c43657786a11bf0154 /lib | |
parent | eb720cc3a118f4bc397981f4487cd5894072f9aa (diff) | |
download | llvm-9409825b57cec078a2a90910978622073d31813d.tar.gz llvm-9409825b57cec078a2a90910978622073d31813d.tar.bz2 llvm-9409825b57cec078a2a90910978622073d31813d.tar.xz |
XCore target: Fix llvm.eh.return and EH info register handling
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@201561 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib')
-rw-r--r-- | lib/Target/XCore/XCoreFrameLowering.cpp | 137 | ||||
-rw-r--r-- | lib/Target/XCore/XCoreMachineFunctionInfo.cpp | 12 | ||||
-rw-r--r-- | lib/Target/XCore/XCoreMachineFunctionInfo.h | 19 | ||||
-rw-r--r-- | lib/Target/XCore/XCoreRegisterInfo.cpp | 2 |
4 files changed, 123 insertions, 47 deletions
diff --git a/lib/Target/XCore/XCoreFrameLowering.cpp b/lib/Target/XCore/XCoreFrameLowering.cpp index 9950d78b50..8ea9788b1a 100644 --- a/lib/Target/XCore/XCoreFrameLowering.cpp +++ b/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); } diff --git a/lib/Target/XCore/XCoreMachineFunctionInfo.cpp b/lib/Target/XCore/XCoreMachineFunctionInfo.cpp index c41a3d5f92..9ef9752d0a 100644 --- a/lib/Target/XCore/XCoreMachineFunctionInfo.cpp +++ b/lib/Target/XCore/XCoreMachineFunctionInfo.cpp @@ -58,3 +58,15 @@ int XCoreFunctionInfo::createFPSpillSlot(MachineFunction &MF) { return FPSpillSlot; } +const int* XCoreFunctionInfo::createEHSpillSlot(MachineFunction &MF) { + if (EHSpillSlotSet) { + return EHSpillSlot; + } + const TargetRegisterClass *RC = &XCore::GRRegsRegClass; + MachineFrameInfo *MFI = MF.getFrameInfo(); + EHSpillSlot[0] = MFI->CreateStackObject(RC->getSize(), RC->getAlignment(), true); + EHSpillSlot[1] = MFI->CreateStackObject(RC->getSize(), RC->getAlignment(), true); + EHSpillSlotSet = true; + return EHSpillSlot; +} + diff --git a/lib/Target/XCore/XCoreMachineFunctionInfo.h b/lib/Target/XCore/XCoreMachineFunctionInfo.h index 6419c2fd65..f1777a87e1 100644 --- a/lib/Target/XCore/XCoreMachineFunctionInfo.h +++ b/lib/Target/XCore/XCoreMachineFunctionInfo.h @@ -31,6 +31,8 @@ class XCoreFunctionInfo : public MachineFunctionInfo { int LRSpillSlot; bool FPSpillSlotSet; int FPSpillSlot; + bool EHSpillSlotSet; + int EHSpillSlot[2]; int VarArgsFrameIndex; mutable int CachedEStackSize; std::vector<std::pair<MCSymbol*, CalleeSavedInfo> > SpillLabels; @@ -38,17 +40,15 @@ class XCoreFunctionInfo : public MachineFunctionInfo { public: XCoreFunctionInfo() : LRSpillSlotSet(false), - LRSpillSlot(0), FPSpillSlotSet(false), - FPSpillSlot(0), + EHSpillSlotSet(false), VarArgsFrameIndex(0), CachedEStackSize(-1) {} explicit XCoreFunctionInfo(MachineFunction &MF) : LRSpillSlotSet(false), - LRSpillSlot(0), FPSpillSlotSet(false), - FPSpillSlot(0), + EHSpillSlotSet(false), VarArgsFrameIndex(0), CachedEStackSize(-1) {} @@ -60,17 +60,24 @@ public: int createLRSpillSlot(MachineFunction &MF); bool hasLRSpillSlot() { return LRSpillSlotSet; } int getLRSpillSlot() const { - assert(LRSpillSlotSet && "LR Spill slot no set"); + assert(LRSpillSlotSet && "LR Spill slot not set"); return LRSpillSlot; } int createFPSpillSlot(MachineFunction &MF); bool hasFPSpillSlot() { return FPSpillSlotSet; } int getFPSpillSlot() const { - assert(FPSpillSlotSet && "FP Spill slot no set"); + assert(FPSpillSlotSet && "FP Spill slot not set"); return FPSpillSlot; } + const int* createEHSpillSlot(MachineFunction &MF); + bool hasEHSpillSlot() { return EHSpillSlotSet; } + const int* getEHSpillSlot() const { + assert(EHSpillSlotSet && "EH Spill slot not set"); + return EHSpillSlot; + } + bool isLargeFrame(const MachineFunction &MF) const; std::vector<std::pair<MCSymbol*, CalleeSavedInfo> > &getSpillLabels() { diff --git a/lib/Target/XCore/XCoreRegisterInfo.cpp b/lib/Target/XCore/XCoreRegisterInfo.cpp index 367c79cc13..d5a96d70b5 100644 --- a/lib/Target/XCore/XCoreRegisterInfo.cpp +++ b/lib/Target/XCore/XCoreRegisterInfo.cpp @@ -200,7 +200,7 @@ bool XCoreRegisterInfo::needsFrameMoves(const MachineFunction &MF) { const uint16_t* XCoreRegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const { // The callee saved registers LR & FP are explicitly handled during - // emitPrologue & emitEpilogue and releated functions. + // emitPrologue & emitEpilogue and related functions. static const uint16_t CalleeSavedRegs[] = { XCore::R4, XCore::R5, XCore::R6, XCore::R7, XCore::R8, XCore::R9, XCore::R10, |