1dff0c46cSDimitry Andric //===-- XCoreFrameLowering.cpp - Frame info for XCore Target --------------===//
22754fe60SDimitry Andric //
32754fe60SDimitry Andric //                     The LLVM Compiler Infrastructure
42754fe60SDimitry Andric //
52754fe60SDimitry Andric // This file is distributed under the University of Illinois Open Source
62754fe60SDimitry Andric // License. See LICENSE.TXT for details.
72754fe60SDimitry Andric //
82754fe60SDimitry Andric //===----------------------------------------------------------------------===//
92754fe60SDimitry Andric //
102754fe60SDimitry Andric // This file contains XCore frame information that doesn't fit anywhere else
112754fe60SDimitry Andric // cleanly...
122754fe60SDimitry Andric //
132754fe60SDimitry Andric //===----------------------------------------------------------------------===//
142754fe60SDimitry Andric 
152754fe60SDimitry Andric #include "XCoreFrameLowering.h"
16dff0c46cSDimitry Andric #include "XCore.h"
172754fe60SDimitry Andric #include "XCoreInstrInfo.h"
182754fe60SDimitry Andric #include "XCoreMachineFunctionInfo.h"
1939d628a0SDimitry Andric #include "XCoreSubtarget.h"
202754fe60SDimitry Andric #include "llvm/CodeGen/MachineFrameInfo.h"
212754fe60SDimitry Andric #include "llvm/CodeGen/MachineFunction.h"
222754fe60SDimitry Andric #include "llvm/CodeGen/MachineInstrBuilder.h"
232754fe60SDimitry Andric #include "llvm/CodeGen/MachineModuleInfo.h"
242754fe60SDimitry Andric #include "llvm/CodeGen/MachineRegisterInfo.h"
252754fe60SDimitry Andric #include "llvm/CodeGen/RegisterScavenging.h"
262cab237bSDimitry Andric #include "llvm/CodeGen/TargetLowering.h"
27139f7f9bSDimitry Andric #include "llvm/IR/DataLayout.h"
28139f7f9bSDimitry Andric #include "llvm/IR/Function.h"
292754fe60SDimitry Andric #include "llvm/Support/ErrorHandling.h"
30139f7f9bSDimitry Andric #include "llvm/Target/TargetOptions.h"
3191bc56edSDimitry Andric #include <algorithm> // std::sort
322754fe60SDimitry Andric 
332754fe60SDimitry Andric using namespace llvm;
342754fe60SDimitry Andric 
3591bc56edSDimitry Andric static const unsigned FramePtr = XCore::R10;
3691bc56edSDimitry Andric static const int MaxImmU16 = (1<<16) - 1;
3791bc56edSDimitry Andric 
382754fe60SDimitry Andric // helper functions. FIXME: Eliminate.
isImmU6(unsigned val)392754fe60SDimitry Andric static inline bool isImmU6(unsigned val) {
402754fe60SDimitry Andric   return val < (1 << 6);
412754fe60SDimitry Andric }
422754fe60SDimitry Andric 
isImmU16(unsigned val)432754fe60SDimitry Andric static inline bool isImmU16(unsigned val) {
442754fe60SDimitry Andric   return val < (1 << 16);
452754fe60SDimitry Andric }
462754fe60SDimitry Andric 
4791bc56edSDimitry Andric // Helper structure with compare function for handling stack slots.
4891bc56edSDimitry Andric namespace {
4991bc56edSDimitry Andric struct StackSlotInfo {
5091bc56edSDimitry Andric   int FI;
5191bc56edSDimitry Andric   int Offset;
5291bc56edSDimitry Andric   unsigned Reg;
StackSlotInfo__anonc00228ce0111::StackSlotInfo5391bc56edSDimitry Andric   StackSlotInfo(int f, int o, int r) : FI(f), Offset(o), Reg(r){};
5491bc56edSDimitry Andric };
5591bc56edSDimitry Andric }  // end anonymous namespace
5691bc56edSDimitry Andric 
CompareSSIOffset(const StackSlotInfo & a,const StackSlotInfo & b)5791bc56edSDimitry Andric static bool CompareSSIOffset(const StackSlotInfo& a, const StackSlotInfo& b) {
5891bc56edSDimitry Andric   return a.Offset < b.Offset;
592754fe60SDimitry Andric }
602754fe60SDimitry Andric 
EmitDefCfaRegister(MachineBasicBlock & MBB,MachineBasicBlock::iterator MBBI,const DebugLoc & dl,const TargetInstrInfo & TII,MachineFunction & MF,unsigned DRegNum)6191bc56edSDimitry Andric static void EmitDefCfaRegister(MachineBasicBlock &MBB,
623ca95b02SDimitry Andric                                MachineBasicBlock::iterator MBBI,
633ca95b02SDimitry Andric                                const DebugLoc &dl, const TargetInstrInfo &TII,
64d88c1a5aSDimitry Andric                                MachineFunction &MF, unsigned DRegNum) {
65d88c1a5aSDimitry Andric   unsigned CFIIndex = MF.addFrameInst(
6691bc56edSDimitry Andric       MCCFIInstruction::createDefCfaRegister(nullptr, DRegNum));
6791bc56edSDimitry Andric   BuildMI(MBB, MBBI, dl, TII.get(TargetOpcode::CFI_INSTRUCTION))
6891bc56edSDimitry Andric       .addCFIIndex(CFIIndex);
692754fe60SDimitry Andric }
702754fe60SDimitry Andric 
EmitDefCfaOffset(MachineBasicBlock & MBB,MachineBasicBlock::iterator MBBI,const DebugLoc & dl,const TargetInstrInfo & TII,int Offset)7191bc56edSDimitry Andric static void EmitDefCfaOffset(MachineBasicBlock &MBB,
723ca95b02SDimitry Andric                              MachineBasicBlock::iterator MBBI,
733ca95b02SDimitry Andric                              const DebugLoc &dl, const TargetInstrInfo &TII,
74d88c1a5aSDimitry Andric                              int Offset) {
75d88c1a5aSDimitry Andric   MachineFunction &MF = *MBB.getParent();
7691bc56edSDimitry Andric   unsigned CFIIndex =
77d88c1a5aSDimitry Andric       MF.addFrameInst(MCCFIInstruction::createDefCfaOffset(nullptr, -Offset));
7891bc56edSDimitry Andric   BuildMI(MBB, MBBI, dl, TII.get(TargetOpcode::CFI_INSTRUCTION))
7991bc56edSDimitry Andric       .addCFIIndex(CFIIndex);
8091bc56edSDimitry Andric }
8191bc56edSDimitry Andric 
EmitCfiOffset(MachineBasicBlock & MBB,MachineBasicBlock::iterator MBBI,const DebugLoc & dl,const TargetInstrInfo & TII,unsigned DRegNum,int Offset)8291bc56edSDimitry Andric static void EmitCfiOffset(MachineBasicBlock &MBB,
833ca95b02SDimitry Andric                           MachineBasicBlock::iterator MBBI, const DebugLoc &dl,
84d88c1a5aSDimitry Andric                           const TargetInstrInfo &TII, unsigned DRegNum,
85d88c1a5aSDimitry Andric                           int Offset) {
86d88c1a5aSDimitry Andric   MachineFunction &MF = *MBB.getParent();
87d88c1a5aSDimitry Andric   unsigned CFIIndex = MF.addFrameInst(
8891bc56edSDimitry Andric       MCCFIInstruction::createOffset(nullptr, DRegNum, Offset));
8991bc56edSDimitry Andric   BuildMI(MBB, MBBI, dl, TII.get(TargetOpcode::CFI_INSTRUCTION))
9091bc56edSDimitry Andric       .addCFIIndex(CFIIndex);
9191bc56edSDimitry Andric }
9291bc56edSDimitry Andric 
9391bc56edSDimitry Andric /// The SP register is moved in steps of 'MaxImmU16' towards the bottom of the
9491bc56edSDimitry Andric /// frame. During these steps, it may be necessary to spill registers.
9591bc56edSDimitry Andric /// IfNeededExtSP emits the necessary EXTSP instructions to move the SP only
9691bc56edSDimitry Andric /// as far as to make 'OffsetFromBottom' reachable using an STWSP_lru6.
9791bc56edSDimitry Andric /// \param OffsetFromTop the spill offset from the top of the frame.
9891bc56edSDimitry Andric /// \param [in,out] Adjusted the current SP offset from the top of the frame.
IfNeededExtSP(MachineBasicBlock & MBB,MachineBasicBlock::iterator MBBI,const DebugLoc & dl,const TargetInstrInfo & TII,int OffsetFromTop,int & Adjusted,int FrameSize,bool emitFrameMoves)9991bc56edSDimitry Andric static void IfNeededExtSP(MachineBasicBlock &MBB,
1003ca95b02SDimitry Andric                           MachineBasicBlock::iterator MBBI, const DebugLoc &dl,
101d88c1a5aSDimitry Andric                           const TargetInstrInfo &TII, int OffsetFromTop,
102d88c1a5aSDimitry Andric                           int &Adjusted, int FrameSize, bool emitFrameMoves) {
10391bc56edSDimitry Andric   while (OffsetFromTop > Adjusted) {
10491bc56edSDimitry Andric     assert(Adjusted < FrameSize && "OffsetFromTop is beyond FrameSize");
10591bc56edSDimitry Andric     int remaining = FrameSize - Adjusted;
10691bc56edSDimitry Andric     int OpImm = (remaining > MaxImmU16) ? MaxImmU16 : remaining;
10791bc56edSDimitry Andric     int Opcode = isImmU6(OpImm) ? XCore::EXTSP_u6 : XCore::EXTSP_lu6;
10891bc56edSDimitry Andric     BuildMI(MBB, MBBI, dl, TII.get(Opcode)).addImm(OpImm);
10991bc56edSDimitry Andric     Adjusted += OpImm;
11091bc56edSDimitry Andric     if (emitFrameMoves)
111d88c1a5aSDimitry Andric       EmitDefCfaOffset(MBB, MBBI, dl, TII, Adjusted*4);
11291bc56edSDimitry Andric   }
11391bc56edSDimitry Andric }
11491bc56edSDimitry Andric 
11591bc56edSDimitry Andric /// The SP register is moved in steps of 'MaxImmU16' towards the top of the
11691bc56edSDimitry Andric /// frame. During these steps, it may be necessary to re-load registers.
11791bc56edSDimitry Andric /// IfNeededLDAWSP emits the necessary LDAWSP instructions to move the SP only
11891bc56edSDimitry Andric /// as far as to make 'OffsetFromTop' reachable using an LDAWSP_lru6.
11991bc56edSDimitry Andric /// \param OffsetFromTop the spill offset from the top of the frame.
12091bc56edSDimitry Andric /// \param [in,out] RemainingAdj the current SP offset from the top of the
12191bc56edSDimitry Andric /// frame.
IfNeededLDAWSP(MachineBasicBlock & MBB,MachineBasicBlock::iterator MBBI,const DebugLoc & dl,const TargetInstrInfo & TII,int OffsetFromTop,int & RemainingAdj)12291bc56edSDimitry Andric static void IfNeededLDAWSP(MachineBasicBlock &MBB,
1233ca95b02SDimitry Andric                            MachineBasicBlock::iterator MBBI, const DebugLoc &dl,
12491bc56edSDimitry Andric                            const TargetInstrInfo &TII, int OffsetFromTop,
12591bc56edSDimitry Andric                            int &RemainingAdj) {
12691bc56edSDimitry Andric   while (OffsetFromTop < RemainingAdj - MaxImmU16) {
12791bc56edSDimitry Andric     assert(RemainingAdj && "OffsetFromTop is beyond FrameSize");
12891bc56edSDimitry Andric     int OpImm = (RemainingAdj > MaxImmU16) ? MaxImmU16 : RemainingAdj;
12991bc56edSDimitry Andric     int Opcode = isImmU6(OpImm) ? XCore::LDAWSP_ru6 : XCore::LDAWSP_lru6;
13091bc56edSDimitry Andric     BuildMI(MBB, MBBI, dl, TII.get(Opcode), XCore::SP).addImm(OpImm);
13191bc56edSDimitry Andric     RemainingAdj -= OpImm;
13291bc56edSDimitry Andric   }
13391bc56edSDimitry Andric }
13491bc56edSDimitry Andric 
13591bc56edSDimitry Andric /// Creates an ordered list of registers that are spilled
13691bc56edSDimitry Andric /// during the emitPrologue/emitEpilogue.
13791bc56edSDimitry Andric /// Registers are ordered according to their frame offset.
13891bc56edSDimitry Andric /// As offsets are negative, the largest offsets will be first.
GetSpillList(SmallVectorImpl<StackSlotInfo> & SpillList,MachineFrameInfo & MFI,XCoreFunctionInfo * XFI,bool fetchLR,bool fetchFP)13991bc56edSDimitry Andric static void GetSpillList(SmallVectorImpl<StackSlotInfo> &SpillList,
140d88c1a5aSDimitry Andric                          MachineFrameInfo &MFI, XCoreFunctionInfo *XFI,
14191bc56edSDimitry Andric                          bool fetchLR, bool fetchFP) {
14291bc56edSDimitry Andric   if (fetchLR) {
143d88c1a5aSDimitry Andric     int Offset = MFI.getObjectOffset(XFI->getLRSpillSlot());
14491bc56edSDimitry Andric     SpillList.push_back(StackSlotInfo(XFI->getLRSpillSlot(),
14591bc56edSDimitry Andric                                       Offset,
14691bc56edSDimitry Andric                                       XCore::LR));
14791bc56edSDimitry Andric   }
14891bc56edSDimitry Andric   if (fetchFP) {
149d88c1a5aSDimitry Andric     int Offset = MFI.getObjectOffset(XFI->getFPSpillSlot());
15091bc56edSDimitry Andric     SpillList.push_back(StackSlotInfo(XFI->getFPSpillSlot(),
15191bc56edSDimitry Andric                                       Offset,
15291bc56edSDimitry Andric                                       FramePtr));
15391bc56edSDimitry Andric   }
154*b5893f02SDimitry Andric   llvm::sort(SpillList, CompareSSIOffset);
15591bc56edSDimitry Andric }
15691bc56edSDimitry Andric 
15791bc56edSDimitry Andric /// Creates an ordered list of EH info register 'spills'.
15891bc56edSDimitry Andric /// These slots are only used by the unwinder and calls to llvm.eh.return().
15991bc56edSDimitry Andric /// Registers are ordered according to their frame offset.
16091bc56edSDimitry Andric /// As offsets are negative, the largest offsets will be first.
GetEHSpillList(SmallVectorImpl<StackSlotInfo> & SpillList,MachineFrameInfo & MFI,XCoreFunctionInfo * XFI,const Constant * PersonalityFn,const TargetLowering * TL)16191bc56edSDimitry Andric static void GetEHSpillList(SmallVectorImpl<StackSlotInfo> &SpillList,
162d88c1a5aSDimitry Andric                            MachineFrameInfo &MFI, XCoreFunctionInfo *XFI,
1637d523365SDimitry Andric                            const Constant *PersonalityFn,
16491bc56edSDimitry Andric                            const TargetLowering *TL) {
16591bc56edSDimitry Andric   assert(XFI->hasEHSpillSlot() && "There are no EH register spill slots");
16691bc56edSDimitry Andric   const int *EHSlot = XFI->getEHSpillSlot();
1677d523365SDimitry Andric   SpillList.push_back(
168d88c1a5aSDimitry Andric       StackSlotInfo(EHSlot[0], MFI.getObjectOffset(EHSlot[0]),
1697d523365SDimitry Andric                     TL->getExceptionPointerRegister(PersonalityFn)));
1707d523365SDimitry Andric   SpillList.push_back(
171d88c1a5aSDimitry Andric       StackSlotInfo(EHSlot[0], MFI.getObjectOffset(EHSlot[1]),
1727d523365SDimitry Andric                     TL->getExceptionSelectorRegister(PersonalityFn)));
173*b5893f02SDimitry Andric   llvm::sort(SpillList, CompareSSIOffset);
17491bc56edSDimitry Andric }
17591bc56edSDimitry Andric 
getFrameIndexMMO(MachineBasicBlock & MBB,int FrameIndex,MachineMemOperand::Flags flags)1763ca95b02SDimitry Andric static MachineMemOperand *getFrameIndexMMO(MachineBasicBlock &MBB,
1773ca95b02SDimitry Andric                                            int FrameIndex,
1783ca95b02SDimitry Andric                                            MachineMemOperand::Flags flags) {
17991bc56edSDimitry Andric   MachineFunction *MF = MBB.getParent();
180d88c1a5aSDimitry Andric   const MachineFrameInfo &MFI = MF->getFrameInfo();
1817d523365SDimitry Andric   MachineMemOperand *MMO = MF->getMachineMemOperand(
1827d523365SDimitry Andric       MachinePointerInfo::getFixedStack(*MF, FrameIndex), flags,
1837d523365SDimitry Andric       MFI.getObjectSize(FrameIndex), MFI.getObjectAlignment(FrameIndex));
18491bc56edSDimitry Andric   return MMO;
18591bc56edSDimitry Andric }
18691bc56edSDimitry Andric 
18791bc56edSDimitry Andric 
18891bc56edSDimitry Andric /// Restore clobbered registers with their spill slot value.
18991bc56edSDimitry Andric /// The SP will be adjusted at the same time, thus the SpillList must be ordered
19091bc56edSDimitry Andric /// with the largest (negative) offsets first.
RestoreSpillList(MachineBasicBlock & MBB,MachineBasicBlock::iterator MBBI,const DebugLoc & dl,const TargetInstrInfo & TII,int & RemainingAdj,SmallVectorImpl<StackSlotInfo> & SpillList)1913ca95b02SDimitry Andric static void RestoreSpillList(MachineBasicBlock &MBB,
1923ca95b02SDimitry Andric                              MachineBasicBlock::iterator MBBI,
1933ca95b02SDimitry Andric                              const DebugLoc &dl, const TargetInstrInfo &TII,
1943ca95b02SDimitry Andric                              int &RemainingAdj,
19591bc56edSDimitry Andric                              SmallVectorImpl<StackSlotInfo> &SpillList) {
19691bc56edSDimitry Andric   for (unsigned i = 0, e = SpillList.size(); i != e; ++i) {
19791bc56edSDimitry Andric     assert(SpillList[i].Offset % 4 == 0 && "Misaligned stack offset");
19891bc56edSDimitry Andric     assert(SpillList[i].Offset <= 0 && "Unexpected positive stack offset");
19991bc56edSDimitry Andric     int OffsetFromTop = - SpillList[i].Offset/4;
20091bc56edSDimitry Andric     IfNeededLDAWSP(MBB, MBBI, dl, TII, OffsetFromTop, RemainingAdj);
20191bc56edSDimitry Andric     int Offset = RemainingAdj - OffsetFromTop;
20291bc56edSDimitry Andric     int Opcode = isImmU6(Offset) ? XCore::LDWSP_ru6 : XCore::LDWSP_lru6;
20391bc56edSDimitry Andric     BuildMI(MBB, MBBI, dl, TII.get(Opcode), SpillList[i].Reg)
20491bc56edSDimitry Andric       .addImm(Offset)
20591bc56edSDimitry Andric       .addMemOperand(getFrameIndexMMO(MBB, SpillList[i].FI,
20691bc56edSDimitry Andric                                       MachineMemOperand::MOLoad));
20791bc56edSDimitry Andric   }
20891bc56edSDimitry Andric }
2092754fe60SDimitry Andric 
2102754fe60SDimitry Andric //===----------------------------------------------------------------------===//
2112754fe60SDimitry Andric // XCoreFrameLowering:
2122754fe60SDimitry Andric //===----------------------------------------------------------------------===//
2132754fe60SDimitry Andric 
XCoreFrameLowering(const XCoreSubtarget & sti)2142754fe60SDimitry Andric XCoreFrameLowering::XCoreFrameLowering(const XCoreSubtarget &sti)
2157ae0e2c9SDimitry Andric   : TargetFrameLowering(TargetFrameLowering::StackGrowsDown, 4, 0) {
2162754fe60SDimitry Andric   // Do nothing
2172754fe60SDimitry Andric }
2182754fe60SDimitry Andric 
hasFP(const MachineFunction & MF) const2192754fe60SDimitry Andric bool XCoreFrameLowering::hasFP(const MachineFunction &MF) const {
220dff0c46cSDimitry Andric   return MF.getTarget().Options.DisableFramePointerElim(MF) ||
221d88c1a5aSDimitry Andric          MF.getFrameInfo().hasVarSizedObjects();
2222754fe60SDimitry Andric }
2232754fe60SDimitry Andric 
emitPrologue(MachineFunction & MF,MachineBasicBlock & MBB) const224ff0cc061SDimitry Andric void XCoreFrameLowering::emitPrologue(MachineFunction &MF,
225ff0cc061SDimitry Andric                                       MachineBasicBlock &MBB) const {
226ff0cc061SDimitry Andric   assert(&MF.front() == &MBB && "Shrink-wrapping not yet supported");
2272754fe60SDimitry Andric   MachineBasicBlock::iterator MBBI = MBB.begin();
228d88c1a5aSDimitry Andric   MachineFrameInfo &MFI = MF.getFrameInfo();
2292754fe60SDimitry Andric   MachineModuleInfo *MMI = &MF.getMMI();
230f785676fSDimitry Andric   const MCRegisterInfo *MRI = MMI->getContext().getRegisterInfo();
231ff0cc061SDimitry Andric   const XCoreInstrInfo &TII = *MF.getSubtarget<XCoreSubtarget>().getInstrInfo();
2322754fe60SDimitry Andric   XCoreFunctionInfo *XFI = MF.getInfo<XCoreFunctionInfo>();
23391bc56edSDimitry Andric   // Debug location must be unknown since the first debug location is used
23491bc56edSDimitry Andric   // to determine the end of the prologue.
23591bc56edSDimitry Andric   DebugLoc dl;
2362754fe60SDimitry Andric 
237d88c1a5aSDimitry Andric   if (MFI.getMaxAlignment() > getStackAlignment())
238f785676fSDimitry Andric     report_fatal_error("emitPrologue unsupported alignment: "
239d88c1a5aSDimitry Andric                        + Twine(MFI.getMaxAlignment()));
240f785676fSDimitry Andric 
2412cab237bSDimitry Andric   const AttributeList &PAL = MF.getFunction().getAttributes();
242139f7f9bSDimitry Andric   if (PAL.hasAttrSomewhere(Attribute::Nest))
24391bc56edSDimitry Andric     BuildMI(MBB, MBBI, dl, TII.get(XCore::LDWSP_ru6), XCore::R11).addImm(0);
24491bc56edSDimitry Andric     // FIX: Needs addMemOperand() but can't use getFixedStack() or getStack().
2452754fe60SDimitry Andric 
2462754fe60SDimitry Andric   // Work out frame sizes.
24791bc56edSDimitry Andric   // We will adjust the SP in stages towards the final FrameSize.
248d88c1a5aSDimitry Andric   assert(MFI.getStackSize()%4 == 0 && "Misaligned frame size");
249d88c1a5aSDimitry Andric   const int FrameSize = MFI.getStackSize() / 4;
25091bc56edSDimitry Andric   int Adjusted = 0;
2512754fe60SDimitry Andric 
25291bc56edSDimitry Andric   bool saveLR = XFI->hasLRSpillSlot();
25391bc56edSDimitry Andric   bool UseENTSP = saveLR && FrameSize
254d88c1a5aSDimitry Andric                   && (MFI.getObjectOffset(XFI->getLRSpillSlot()) == 0);
25591bc56edSDimitry Andric   if (UseENTSP)
25691bc56edSDimitry Andric     saveLR = false;
25791bc56edSDimitry Andric   bool FP = hasFP(MF);
258dff0c46cSDimitry Andric   bool emitFrameMoves = XCoreRegisterInfo::needsFrameMoves(MF);
2592754fe60SDimitry Andric 
26091bc56edSDimitry Andric   if (UseENTSP) {
26191bc56edSDimitry Andric     // Allocate space on the stack at the same time as saving LR.
26291bc56edSDimitry Andric     Adjusted = (FrameSize > MaxImmU16) ? MaxImmU16 : FrameSize;
26391bc56edSDimitry Andric     int Opcode = isImmU6(Adjusted) ? XCore::ENTSP_u6 : XCore::ENTSP_lu6;
2642754fe60SDimitry Andric     MBB.addLiveIn(XCore::LR);
26591bc56edSDimitry Andric     MachineInstrBuilder MIB = BuildMI(MBB, MBBI, dl, TII.get(Opcode));
26691bc56edSDimitry Andric     MIB.addImm(Adjusted);
26739d628a0SDimitry Andric     MIB->addRegisterKilled(XCore::LR, MF.getSubtarget().getRegisterInfo(),
26839d628a0SDimitry Andric                            true);
2692754fe60SDimitry Andric     if (emitFrameMoves) {
270d88c1a5aSDimitry Andric       EmitDefCfaOffset(MBB, MBBI, dl, TII, Adjusted*4);
27191bc56edSDimitry Andric       unsigned DRegNum = MRI->getDwarfRegNum(XCore::LR, true);
272d88c1a5aSDimitry Andric       EmitCfiOffset(MBB, MBBI, dl, TII, DRegNum, 0);
273f785676fSDimitry Andric     }
2742754fe60SDimitry Andric   }
2752754fe60SDimitry Andric 
27691bc56edSDimitry Andric   // If necessary, save LR and FP to the stack, as we EXTSP.
27791bc56edSDimitry Andric   SmallVector<StackSlotInfo,2> SpillList;
27891bc56edSDimitry Andric   GetSpillList(SpillList, MFI, XFI, saveLR, FP);
27991bc56edSDimitry Andric   // We want the nearest (negative) offsets first, so reverse list.
28091bc56edSDimitry Andric   std::reverse(SpillList.begin(), SpillList.end());
28191bc56edSDimitry Andric   for (unsigned i = 0, e = SpillList.size(); i != e; ++i) {
28291bc56edSDimitry Andric     assert(SpillList[i].Offset % 4 == 0 && "Misaligned stack offset");
28391bc56edSDimitry Andric     assert(SpillList[i].Offset <= 0 && "Unexpected positive stack offset");
28491bc56edSDimitry Andric     int OffsetFromTop = - SpillList[i].Offset/4;
285d88c1a5aSDimitry Andric     IfNeededExtSP(MBB, MBBI, dl, TII, OffsetFromTop, Adjusted, FrameSize,
28691bc56edSDimitry Andric                   emitFrameMoves);
28791bc56edSDimitry Andric     int Offset = Adjusted - OffsetFromTop;
28891bc56edSDimitry Andric     int Opcode = isImmU6(Offset) ? XCore::STWSP_ru6 : XCore::STWSP_lru6;
28991bc56edSDimitry Andric     MBB.addLiveIn(SpillList[i].Reg);
29091bc56edSDimitry Andric     BuildMI(MBB, MBBI, dl, TII.get(Opcode))
29191bc56edSDimitry Andric       .addReg(SpillList[i].Reg, RegState::Kill)
29291bc56edSDimitry Andric       .addImm(Offset)
29391bc56edSDimitry Andric       .addMemOperand(getFrameIndexMMO(MBB, SpillList[i].FI,
29491bc56edSDimitry Andric                                       MachineMemOperand::MOStore));
2952754fe60SDimitry Andric     if (emitFrameMoves) {
29691bc56edSDimitry Andric       unsigned DRegNum = MRI->getDwarfRegNum(SpillList[i].Reg, true);
297d88c1a5aSDimitry Andric       EmitCfiOffset(MBB, MBBI, dl, TII, DRegNum, SpillList[i].Offset);
2982754fe60SDimitry Andric     }
2992754fe60SDimitry Andric   }
3002754fe60SDimitry Andric 
30191bc56edSDimitry Andric   // Complete any remaining Stack adjustment.
302d88c1a5aSDimitry Andric   IfNeededExtSP(MBB, MBBI, dl, TII, FrameSize, Adjusted, FrameSize,
30391bc56edSDimitry Andric                 emitFrameMoves);
30491bc56edSDimitry Andric   assert(Adjusted==FrameSize && "IfNeededExtSP has not completed adjustment");
30591bc56edSDimitry Andric 
3062754fe60SDimitry Andric   if (FP) {
3072754fe60SDimitry Andric     // Set the FP from the SP.
308f785676fSDimitry Andric     BuildMI(MBB, MBBI, dl, TII.get(XCore::LDAWSP_ru6), FramePtr).addImm(0);
30991bc56edSDimitry Andric     if (emitFrameMoves)
310d88c1a5aSDimitry Andric       EmitDefCfaRegister(MBB, MBBI, dl, TII, MF,
31191bc56edSDimitry Andric                          MRI->getDwarfRegNum(FramePtr, true));
3122754fe60SDimitry Andric   }
3132754fe60SDimitry Andric 
3142754fe60SDimitry Andric   if (emitFrameMoves) {
3152754fe60SDimitry Andric     // Frame moves for callee saved.
31639d628a0SDimitry Andric     for (const auto &SpillLabel : XFI->getSpillLabels()) {
31739d628a0SDimitry Andric       MachineBasicBlock::iterator Pos = SpillLabel.first;
31891bc56edSDimitry Andric       ++Pos;
31939d628a0SDimitry Andric       const CalleeSavedInfo &CSI = SpillLabel.second;
320d88c1a5aSDimitry Andric       int Offset = MFI.getObjectOffset(CSI.getFrameIdx());
32191bc56edSDimitry Andric       unsigned DRegNum = MRI->getDwarfRegNum(CSI.getReg(), true);
322d88c1a5aSDimitry Andric       EmitCfiOffset(MBB, Pos, dl, TII, DRegNum, Offset);
32391bc56edSDimitry Andric     }
32491bc56edSDimitry Andric     if (XFI->hasEHSpillSlot()) {
32591bc56edSDimitry Andric       // The unwinder requires stack slot & CFI offsets for the exception info.
32691bc56edSDimitry Andric       // We do not save/spill these registers.
3272cab237bSDimitry Andric       const Function *Fn = &MF.getFunction();
3287d523365SDimitry Andric       const Constant *PersonalityFn =
3297d523365SDimitry Andric           Fn->hasPersonalityFn() ? Fn->getPersonalityFn() : nullptr;
33091bc56edSDimitry Andric       SmallVector<StackSlotInfo, 2> SpillList;
3317d523365SDimitry Andric       GetEHSpillList(SpillList, MFI, XFI, PersonalityFn,
33239d628a0SDimitry Andric                      MF.getSubtarget().getTargetLowering());
33391bc56edSDimitry Andric       assert(SpillList.size()==2 && "Unexpected SpillList size");
334d88c1a5aSDimitry Andric       EmitCfiOffset(MBB, MBBI, dl, TII,
33591bc56edSDimitry Andric                     MRI->getDwarfRegNum(SpillList[0].Reg, true),
33691bc56edSDimitry Andric                     SpillList[0].Offset);
337d88c1a5aSDimitry Andric       EmitCfiOffset(MBB, MBBI, dl, TII,
33891bc56edSDimitry Andric                     MRI->getDwarfRegNum(SpillList[1].Reg, true),
33991bc56edSDimitry Andric                     SpillList[1].Offset);
3402754fe60SDimitry Andric     }
3412754fe60SDimitry Andric   }
3422754fe60SDimitry Andric }
3432754fe60SDimitry Andric 
emitEpilogue(MachineFunction & MF,MachineBasicBlock & MBB) const3442754fe60SDimitry Andric void XCoreFrameLowering::emitEpilogue(MachineFunction &MF,
3452754fe60SDimitry Andric                                      MachineBasicBlock &MBB) const {
346d88c1a5aSDimitry Andric   MachineFrameInfo &MFI = MF.getFrameInfo();
3472754fe60SDimitry Andric   MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr();
348ff0cc061SDimitry Andric   const XCoreInstrInfo &TII = *MF.getSubtarget<XCoreSubtarget>().getInstrInfo();
349f785676fSDimitry Andric   XCoreFunctionInfo *XFI = MF.getInfo<XCoreFunctionInfo>();
3502754fe60SDimitry Andric   DebugLoc dl = MBBI->getDebugLoc();
35191bc56edSDimitry Andric   unsigned RetOpcode = MBBI->getOpcode();
3522754fe60SDimitry Andric 
3532754fe60SDimitry Andric   // Work out frame sizes.
35491bc56edSDimitry Andric   // We will adjust the SP in stages towards the final FrameSize.
355d88c1a5aSDimitry Andric   int RemainingAdj = MFI.getStackSize();
35691bc56edSDimitry Andric   assert(RemainingAdj%4 == 0 && "Misaligned frame size");
35791bc56edSDimitry Andric   RemainingAdj /= 4;
3582754fe60SDimitry Andric 
35991bc56edSDimitry Andric   if (RetOpcode == XCore::EH_RETURN) {
36091bc56edSDimitry Andric     // 'Restore' the exception info the unwinder has placed into the stack
36191bc56edSDimitry Andric     // slots.
3622cab237bSDimitry Andric     const Function *Fn = &MF.getFunction();
3637d523365SDimitry Andric     const Constant *PersonalityFn =
3647d523365SDimitry Andric         Fn->hasPersonalityFn() ? Fn->getPersonalityFn() : nullptr;
36591bc56edSDimitry Andric     SmallVector<StackSlotInfo, 2> SpillList;
3667d523365SDimitry Andric     GetEHSpillList(SpillList, MFI, XFI, PersonalityFn,
3677d523365SDimitry Andric                    MF.getSubtarget().getTargetLowering());
36891bc56edSDimitry Andric     RestoreSpillList(MBB, MBBI, dl, TII, RemainingAdj, SpillList);
3692754fe60SDimitry Andric 
37091bc56edSDimitry Andric     // Return to the landing pad.
37191bc56edSDimitry Andric     unsigned EhStackReg = MBBI->getOperand(0).getReg();
37291bc56edSDimitry Andric     unsigned EhHandlerReg = MBBI->getOperand(1).getReg();
37391bc56edSDimitry Andric     BuildMI(MBB, MBBI, dl, TII.get(XCore::SETSP_1r)).addReg(EhStackReg);
37491bc56edSDimitry Andric     BuildMI(MBB, MBBI, dl, TII.get(XCore::BAU_1r)).addReg(EhHandlerReg);
37591bc56edSDimitry Andric     MBB.erase(MBBI);  // Erase the previous return instruction.
37691bc56edSDimitry Andric     return;
3772754fe60SDimitry Andric   }
3782754fe60SDimitry Andric 
37991bc56edSDimitry Andric   bool restoreLR = XFI->hasLRSpillSlot();
38091bc56edSDimitry Andric   bool UseRETSP = restoreLR && RemainingAdj
381d88c1a5aSDimitry Andric                   && (MFI.getObjectOffset(XFI->getLRSpillSlot()) == 0);
38291bc56edSDimitry Andric   if (UseRETSP)
3832754fe60SDimitry Andric     restoreLR = false;
38491bc56edSDimitry Andric   bool FP = hasFP(MF);
385f785676fSDimitry Andric 
38691bc56edSDimitry Andric   if (FP) // Restore the stack pointer.
38791bc56edSDimitry Andric     BuildMI(MBB, MBBI, dl, TII.get(XCore::SETSP_1r)).addReg(FramePtr);
38891bc56edSDimitry Andric 
38991bc56edSDimitry Andric   // If necessary, restore LR and FP from the stack, as we EXTSP.
39091bc56edSDimitry Andric   SmallVector<StackSlotInfo,2> SpillList;
39191bc56edSDimitry Andric   GetSpillList(SpillList, MFI, XFI, restoreLR, FP);
39291bc56edSDimitry Andric   RestoreSpillList(MBB, MBBI, dl, TII, RemainingAdj, SpillList);
39391bc56edSDimitry Andric 
39491bc56edSDimitry Andric   if (RemainingAdj) {
39591bc56edSDimitry Andric     // Complete all but one of the remaining Stack adjustments.
39691bc56edSDimitry Andric     IfNeededLDAWSP(MBB, MBBI, dl, TII, 0, RemainingAdj);
39791bc56edSDimitry Andric     if (UseRETSP) {
3982754fe60SDimitry Andric       // Fold prologue into return instruction
39991bc56edSDimitry Andric       assert(RetOpcode == XCore::RETSP_u6
40091bc56edSDimitry Andric              || RetOpcode == XCore::RETSP_lu6);
40191bc56edSDimitry Andric       int Opcode = isImmU6(RemainingAdj) ? XCore::RETSP_u6 : XCore::RETSP_lu6;
40291bc56edSDimitry Andric       MachineInstrBuilder MIB = BuildMI(MBB, MBBI, dl, TII.get(Opcode))
40391bc56edSDimitry Andric                                   .addImm(RemainingAdj);
404f785676fSDimitry Andric       for (unsigned i = 3, e = MBBI->getNumOperands(); i < e; ++i)
405f785676fSDimitry Andric         MIB->addOperand(MBBI->getOperand(i)); // copy any variadic operands
40691bc56edSDimitry Andric       MBB.erase(MBBI);  // Erase the previous return instruction.
4072754fe60SDimitry Andric     } else {
40891bc56edSDimitry Andric       int Opcode = isImmU6(RemainingAdj) ? XCore::LDAWSP_ru6 :
40991bc56edSDimitry Andric                                            XCore::LDAWSP_lru6;
41091bc56edSDimitry Andric       BuildMI(MBB, MBBI, dl, TII.get(Opcode), XCore::SP).addImm(RemainingAdj);
41191bc56edSDimitry Andric       // Don't erase the return instruction.
4122754fe60SDimitry Andric     }
41391bc56edSDimitry Andric   } // else Don't erase the return instruction.
4142754fe60SDimitry Andric }
4152754fe60SDimitry Andric 
41691bc56edSDimitry Andric bool XCoreFrameLowering::
spillCalleeSavedRegisters(MachineBasicBlock & MBB,MachineBasicBlock::iterator MI,const std::vector<CalleeSavedInfo> & CSI,const TargetRegisterInfo * TRI) const41791bc56edSDimitry Andric spillCalleeSavedRegisters(MachineBasicBlock &MBB,
4182754fe60SDimitry Andric                           MachineBasicBlock::iterator MI,
4192754fe60SDimitry Andric                           const std::vector<CalleeSavedInfo> &CSI,
4202754fe60SDimitry Andric                           const TargetRegisterInfo *TRI) const {
4212754fe60SDimitry Andric   if (CSI.empty())
4222754fe60SDimitry Andric     return true;
4232754fe60SDimitry Andric 
4242754fe60SDimitry Andric   MachineFunction *MF = MBB.getParent();
42539d628a0SDimitry Andric   const TargetInstrInfo &TII = *MF->getSubtarget().getInstrInfo();
4262754fe60SDimitry Andric   XCoreFunctionInfo *XFI = MF->getInfo<XCoreFunctionInfo>();
4272754fe60SDimitry Andric   bool emitFrameMoves = XCoreRegisterInfo::needsFrameMoves(*MF);
4282754fe60SDimitry Andric 
4292754fe60SDimitry Andric   DebugLoc DL;
4304ba319b5SDimitry Andric   if (MI != MBB.end() && !MI->isDebugInstr())
43191bc56edSDimitry Andric     DL = MI->getDebugLoc();
4322754fe60SDimitry Andric 
4332754fe60SDimitry Andric   for (std::vector<CalleeSavedInfo>::const_iterator it = CSI.begin();
4342754fe60SDimitry Andric                                                     it != CSI.end(); ++it) {
4352754fe60SDimitry Andric     unsigned Reg = it->getReg();
43691bc56edSDimitry Andric     assert(Reg != XCore::LR && !(Reg == XCore::R10 && hasFP(*MF)) &&
43791bc56edSDimitry Andric            "LR & FP are always handled in emitPrologue");
43891bc56edSDimitry Andric 
43991bc56edSDimitry Andric     // Add the callee-saved register as live-in. It's killed at the spill.
44091bc56edSDimitry Andric     MBB.addLiveIn(Reg);
4412754fe60SDimitry Andric     const TargetRegisterClass *RC = TRI->getMinimalPhysRegClass(Reg);
44291bc56edSDimitry Andric     TII.storeRegToStackSlot(MBB, MI, Reg, true, it->getFrameIdx(), RC, TRI);
4432754fe60SDimitry Andric     if (emitFrameMoves) {
44491bc56edSDimitry Andric       auto Store = MI;
44591bc56edSDimitry Andric       --Store;
44691bc56edSDimitry Andric       XFI->getSpillLabels().push_back(std::make_pair(Store, *it));
4472754fe60SDimitry Andric     }
4482754fe60SDimitry Andric   }
4492754fe60SDimitry Andric   return true;
4502754fe60SDimitry Andric }
4512754fe60SDimitry Andric 
45291bc56edSDimitry Andric bool XCoreFrameLowering::
restoreCalleeSavedRegisters(MachineBasicBlock & MBB,MachineBasicBlock::iterator MI,std::vector<CalleeSavedInfo> & CSI,const TargetRegisterInfo * TRI) const45391bc56edSDimitry Andric restoreCalleeSavedRegisters(MachineBasicBlock &MBB,
4542754fe60SDimitry Andric                             MachineBasicBlock::iterator MI,
4552cab237bSDimitry Andric                             std::vector<CalleeSavedInfo> &CSI,
4562754fe60SDimitry Andric                             const TargetRegisterInfo *TRI) const{
4572754fe60SDimitry Andric   MachineFunction *MF = MBB.getParent();
45839d628a0SDimitry Andric   const TargetInstrInfo &TII = *MF->getSubtarget().getInstrInfo();
4592754fe60SDimitry Andric   bool AtStart = MI == MBB.begin();
4602754fe60SDimitry Andric   MachineBasicBlock::iterator BeforeI = MI;
4612754fe60SDimitry Andric   if (!AtStart)
4622754fe60SDimitry Andric     --BeforeI;
4632754fe60SDimitry Andric   for (std::vector<CalleeSavedInfo>::const_iterator it = CSI.begin();
4642754fe60SDimitry Andric                                                     it != CSI.end(); ++it) {
4652754fe60SDimitry Andric     unsigned Reg = it->getReg();
46691bc56edSDimitry Andric     assert(Reg != XCore::LR && !(Reg == XCore::R10 && hasFP(*MF)) &&
46791bc56edSDimitry Andric            "LR & FP are always handled in emitEpilogue");
46891bc56edSDimitry Andric 
4692754fe60SDimitry Andric     const TargetRegisterClass *RC = TRI->getMinimalPhysRegClass(Reg);
47091bc56edSDimitry Andric     TII.loadRegFromStackSlot(MBB, MI, Reg, it->getFrameIdx(), RC, TRI);
4712754fe60SDimitry Andric     assert(MI != MBB.begin() &&
4722754fe60SDimitry Andric            "loadRegFromStackSlot didn't insert any code!");
4732754fe60SDimitry Andric     // Insert in reverse order.  loadRegFromStackSlot can insert multiple
4742754fe60SDimitry Andric     // instructions.
4752754fe60SDimitry Andric     if (AtStart)
4762754fe60SDimitry Andric       MI = MBB.begin();
4772754fe60SDimitry Andric     else {
4782754fe60SDimitry Andric       MI = BeforeI;
4792754fe60SDimitry Andric       ++MI;
4802754fe60SDimitry Andric     }
4812754fe60SDimitry Andric   }
4822754fe60SDimitry Andric   return true;
4832754fe60SDimitry Andric }
4842754fe60SDimitry Andric 
485139f7f9bSDimitry Andric // This function eliminates ADJCALLSTACKDOWN,
486139f7f9bSDimitry Andric // ADJCALLSTACKUP pseudo instructions
eliminateCallFramePseudoInstr(MachineFunction & MF,MachineBasicBlock & MBB,MachineBasicBlock::iterator I) const4873ca95b02SDimitry Andric MachineBasicBlock::iterator XCoreFrameLowering::eliminateCallFramePseudoInstr(
4883ca95b02SDimitry Andric     MachineFunction &MF, MachineBasicBlock &MBB,
489139f7f9bSDimitry Andric     MachineBasicBlock::iterator I) const {
490ff0cc061SDimitry Andric   const XCoreInstrInfo &TII = *MF.getSubtarget<XCoreSubtarget>().getInstrInfo();
491139f7f9bSDimitry Andric   if (!hasReservedCallFrame(MF)) {
492139f7f9bSDimitry Andric     // Turn the adjcallstackdown instruction into 'extsp <amt>' and the
493139f7f9bSDimitry Andric     // adjcallstackup instruction into 'ldaw sp, sp[<amt>]'
494d88c1a5aSDimitry Andric     MachineInstr &Old = *I;
495d88c1a5aSDimitry Andric     uint64_t Amount = Old.getOperand(0).getImm();
496139f7f9bSDimitry Andric     if (Amount != 0) {
497139f7f9bSDimitry Andric       // We need to keep the stack aligned properly.  To do this, we round the
498139f7f9bSDimitry Andric       // amount of space needed for the outgoing arguments up to the next
499139f7f9bSDimitry Andric       // alignment boundary.
500139f7f9bSDimitry Andric       unsigned Align = getStackAlignment();
501139f7f9bSDimitry Andric       Amount = (Amount+Align-1)/Align*Align;
502139f7f9bSDimitry Andric 
503139f7f9bSDimitry Andric       assert(Amount%4 == 0);
504139f7f9bSDimitry Andric       Amount /= 4;
505139f7f9bSDimitry Andric 
506139f7f9bSDimitry Andric       bool isU6 = isImmU6(Amount);
507139f7f9bSDimitry Andric       if (!isU6 && !isImmU16(Amount)) {
508139f7f9bSDimitry Andric         // FIX could emit multiple instructions in this case.
509139f7f9bSDimitry Andric #ifndef NDEBUG
510139f7f9bSDimitry Andric         errs() << "eliminateCallFramePseudoInstr size too big: "
511139f7f9bSDimitry Andric                << Amount << "\n";
512139f7f9bSDimitry Andric #endif
51391bc56edSDimitry Andric         llvm_unreachable(nullptr);
514139f7f9bSDimitry Andric       }
515139f7f9bSDimitry Andric 
516139f7f9bSDimitry Andric       MachineInstr *New;
517d88c1a5aSDimitry Andric       if (Old.getOpcode() == XCore::ADJCALLSTACKDOWN) {
518139f7f9bSDimitry Andric         int Opcode = isU6 ? XCore::EXTSP_u6 : XCore::EXTSP_lu6;
519d88c1a5aSDimitry Andric         New = BuildMI(MF, Old.getDebugLoc(), TII.get(Opcode)).addImm(Amount);
520139f7f9bSDimitry Andric       } else {
521d88c1a5aSDimitry Andric         assert(Old.getOpcode() == XCore::ADJCALLSTACKUP);
522139f7f9bSDimitry Andric         int Opcode = isU6 ? XCore::LDAWSP_ru6 : XCore::LDAWSP_lru6;
523d88c1a5aSDimitry Andric         New = BuildMI(MF, Old.getDebugLoc(), TII.get(Opcode), XCore::SP)
524139f7f9bSDimitry Andric                   .addImm(Amount);
525139f7f9bSDimitry Andric       }
526139f7f9bSDimitry Andric 
527139f7f9bSDimitry Andric       // Replace the pseudo instruction with a new instruction...
528139f7f9bSDimitry Andric       MBB.insert(I, New);
529139f7f9bSDimitry Andric     }
530139f7f9bSDimitry Andric   }
531139f7f9bSDimitry Andric 
5323ca95b02SDimitry Andric   return MBB.erase(I);
533139f7f9bSDimitry Andric }
534139f7f9bSDimitry Andric 
determineCalleeSaves(MachineFunction & MF,BitVector & SavedRegs,RegScavenger * RS) const535875ed548SDimitry Andric void XCoreFrameLowering::determineCalleeSaves(MachineFunction &MF,
536875ed548SDimitry Andric                                               BitVector &SavedRegs,
5372754fe60SDimitry Andric                                               RegScavenger *RS) const {
538875ed548SDimitry Andric   TargetFrameLowering::determineCalleeSaves(MF, SavedRegs, RS);
539875ed548SDimitry Andric 
54091bc56edSDimitry Andric   XCoreFunctionInfo *XFI = MF.getInfo<XCoreFunctionInfo>();
54191bc56edSDimitry Andric 
542875ed548SDimitry Andric   const MachineRegisterInfo &MRI = MF.getRegInfo();
543875ed548SDimitry Andric   bool LRUsed = MRI.isPhysRegModified(XCore::LR);
54491bc56edSDimitry Andric 
5452cab237bSDimitry Andric   if (!LRUsed && !MF.getFunction().isVarArg() &&
546d88c1a5aSDimitry Andric       MF.getFrameInfo().estimateStackSize(MF))
54791bc56edSDimitry Andric     // If we need to extend the stack it is more efficient to use entsp / retsp.
54891bc56edSDimitry Andric     // We force the LR to be saved so these instructions are used.
54991bc56edSDimitry Andric     LRUsed = true;
55091bc56edSDimitry Andric 
551d88c1a5aSDimitry Andric   if (MF.callsUnwindInit() || MF.callsEHReturn()) {
55291bc56edSDimitry Andric     // The unwinder expects to find spill slots for the exception info regs R0
55391bc56edSDimitry Andric     // & R1. These are used during llvm.eh.return() to 'restore' the exception
55491bc56edSDimitry Andric     // info. N.B. we do not spill or restore R0, R1 during normal operation.
55591bc56edSDimitry Andric     XFI->createEHSpillSlot(MF);
55691bc56edSDimitry Andric     // As we will  have a stack, we force the LR to be saved.
55791bc56edSDimitry Andric     LRUsed = true;
55891bc56edSDimitry Andric   }
55991bc56edSDimitry Andric 
56091bc56edSDimitry Andric   if (LRUsed) {
56191bc56edSDimitry Andric     // We will handle the LR in the prologue/epilogue
56291bc56edSDimitry Andric     // and allocate space on the stack ourselves.
563875ed548SDimitry Andric     SavedRegs.reset(XCore::LR);
56491bc56edSDimitry Andric     XFI->createLRSpillSlot(MF);
56591bc56edSDimitry Andric   }
56691bc56edSDimitry Andric 
56791bc56edSDimitry Andric   if (hasFP(MF))
56891bc56edSDimitry Andric     // A callee save register is used to hold the FP.
56991bc56edSDimitry Andric     // This needs saving / restoring in the epilogue / prologue.
57091bc56edSDimitry Andric     XFI->createFPSpillSlot(MF);
57191bc56edSDimitry Andric }
57291bc56edSDimitry Andric 
57391bc56edSDimitry Andric void XCoreFrameLowering::
processFunctionBeforeFrameFinalized(MachineFunction & MF,RegScavenger * RS) const57491bc56edSDimitry Andric processFunctionBeforeFrameFinalized(MachineFunction &MF,
57591bc56edSDimitry Andric                                     RegScavenger *RS) const {
57691bc56edSDimitry Andric   assert(RS && "requiresRegisterScavenging failed");
577d88c1a5aSDimitry Andric   MachineFrameInfo &MFI = MF.getFrameInfo();
57851690af2SDimitry Andric   const TargetRegisterClass &RC = XCore::GRRegsRegClass;
57951690af2SDimitry Andric   const TargetRegisterInfo &TRI = *MF.getSubtarget().getRegisterInfo();
5802754fe60SDimitry Andric   XCoreFunctionInfo *XFI = MF.getInfo<XCoreFunctionInfo>();
58191bc56edSDimitry Andric   // Reserve slots close to SP or frame pointer for Scavenging spills.
58291bc56edSDimitry Andric   // When using SP for small frames, we don't need any scratch registers.
58391bc56edSDimitry Andric   // When using SP for large frames, we may need 2 scratch registers.
58491bc56edSDimitry Andric   // When using FP, for large or small frames, we may need 1 scratch register.
58551690af2SDimitry Andric   unsigned Size = TRI.getSpillSize(RC);
58651690af2SDimitry Andric   unsigned Align = TRI.getSpillAlignment(RC);
58791bc56edSDimitry Andric   if (XFI->isLargeFrame(MF) || hasFP(MF))
58851690af2SDimitry Andric     RS->addScavengingFrameIndex(MFI.CreateStackObject(Size, Align, false));
58991bc56edSDimitry Andric   if (XFI->isLargeFrame(MF) && !hasFP(MF))
59051690af2SDimitry Andric     RS->addScavengingFrameIndex(MFI.CreateStackObject(Size, Align, false));
5912754fe60SDimitry Andric }
592