131d157ae1ac2cd9c787dc3c1d28e64c682803844Jia Liu//===-- XCoreFrameLowering.cpp - Frame info for XCore Target --------------===//
2b25baef26f03b9909b65dd5f762b38f93000445dRichard Osborne//
3b25baef26f03b9909b65dd5f762b38f93000445dRichard Osborne//                     The LLVM Compiler Infrastructure
4b25baef26f03b9909b65dd5f762b38f93000445dRichard Osborne//
5b25baef26f03b9909b65dd5f762b38f93000445dRichard Osborne// This file is distributed under the University of Illinois Open Source
6b25baef26f03b9909b65dd5f762b38f93000445dRichard Osborne// License. See LICENSE.TXT for details.
7b25baef26f03b9909b65dd5f762b38f93000445dRichard Osborne//
8b25baef26f03b9909b65dd5f762b38f93000445dRichard Osborne//===----------------------------------------------------------------------===//
9b25baef26f03b9909b65dd5f762b38f93000445dRichard Osborne//
10b25baef26f03b9909b65dd5f762b38f93000445dRichard Osborne// This file contains XCore frame information that doesn't fit anywhere else
11b25baef26f03b9909b65dd5f762b38f93000445dRichard Osborne// cleanly...
12b25baef26f03b9909b65dd5f762b38f93000445dRichard Osborne//
13b25baef26f03b9909b65dd5f762b38f93000445dRichard Osborne//===----------------------------------------------------------------------===//
14b25baef26f03b9909b65dd5f762b38f93000445dRichard Osborne
1516c29b5f285f375be53dabaa73e3e91107485fe4Anton Korobeynikov#include "XCoreFrameLowering.h"
1679aa3417eb6f58d668aadfedf075240a41d35a26Craig Topper#include "XCore.h"
1733464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov#include "XCoreInstrInfo.h"
1833464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov#include "XCoreMachineFunctionInfo.h"
1933464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov#include "llvm/CodeGen/MachineFrameInfo.h"
2033464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov#include "llvm/CodeGen/MachineFunction.h"
2133464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov#include "llvm/CodeGen/MachineInstrBuilder.h"
2233464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov#include "llvm/CodeGen/MachineModuleInfo.h"
2333464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov#include "llvm/CodeGen/MachineRegisterInfo.h"
2494c5ae08750f314bc3cf1bf882b686244a3927d9Anton Korobeynikov#include "llvm/CodeGen/RegisterScavenging.h"
250b8c9a80f20772c3793201ab5b251d3520b9cea3Chandler Carruth#include "llvm/IR/DataLayout.h"
260b8c9a80f20772c3793201ab5b251d3520b9cea3Chandler Carruth#include "llvm/IR/Function.h"
2733464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov#include "llvm/Support/ErrorHandling.h"
28d04a8d4b33ff316ca4cf961e06c9e312eff8e64fChandler Carruth#include "llvm/Target/TargetOptions.h"
2933464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov
30b25baef26f03b9909b65dd5f762b38f93000445dRichard Osborneusing namespace llvm;
31b25baef26f03b9909b65dd5f762b38f93000445dRichard Osborne
3233464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov// helper functions. FIXME: Eliminate.
3333464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikovstatic inline bool isImmUs(unsigned val) {
3433464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov  return val <= 11;
3533464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov}
3633464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov
3733464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikovstatic inline bool isImmU6(unsigned val) {
3833464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov  return val < (1 << 6);
3933464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov}
4033464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov
4133464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikovstatic inline bool isImmU16(unsigned val) {
4233464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov  return val < (1 << 16);
4333464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov}
4433464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov
4533464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikovstatic void loadFromStack(MachineBasicBlock &MBB,
4633464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov                          MachineBasicBlock::iterator I,
4733464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov                          unsigned DstReg, int Offset, DebugLoc dl,
4833464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov                          const TargetInstrInfo &TII) {
4933464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov  assert(Offset%4 == 0 && "Misaligned stack offset");
5033464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov  Offset/=4;
5133464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov  bool isU6 = isImmU6(Offset);
5233464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov  if (!isU6 && !isImmU16(Offset))
5333464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov    report_fatal_error("loadFromStack offset too big " + Twine(Offset));
5433464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov  int Opcode = isU6 ? XCore::LDWSP_ru6 : XCore::LDWSP_lru6;
5533464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov  BuildMI(MBB, I, dl, TII.get(Opcode), DstReg)
5633464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov    .addImm(Offset);
5733464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov}
5833464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov
5933464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov
6033464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikovstatic void storeToStack(MachineBasicBlock &MBB,
6133464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov                         MachineBasicBlock::iterator I,
6233464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov                         unsigned SrcReg, int Offset, DebugLoc dl,
6333464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov                         const TargetInstrInfo &TII) {
6433464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov  assert(Offset%4 == 0 && "Misaligned stack offset");
6533464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov  Offset/=4;
6633464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov  bool isU6 = isImmU6(Offset);
6733464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov  if (!isU6 && !isImmU16(Offset))
6833464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov    report_fatal_error("storeToStack offset too big " + Twine(Offset));
6933464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov  int Opcode = isU6 ? XCore::STWSP_ru6 : XCore::STWSP_lru6;
7033464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov  BuildMI(MBB, I, dl, TII.get(Opcode))
7133464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov    .addReg(SrcReg)
7233464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov    .addImm(Offset);
7333464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov}
7433464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov
7533464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov
76b25baef26f03b9909b65dd5f762b38f93000445dRichard Osborne//===----------------------------------------------------------------------===//
7716c29b5f285f375be53dabaa73e3e91107485fe4Anton Korobeynikov// XCoreFrameLowering:
78b25baef26f03b9909b65dd5f762b38f93000445dRichard Osborne//===----------------------------------------------------------------------===//
79b25baef26f03b9909b65dd5f762b38f93000445dRichard Osborne
8016c29b5f285f375be53dabaa73e3e91107485fe4Anton KorobeynikovXCoreFrameLowering::XCoreFrameLowering(const XCoreSubtarget &sti)
8195a9d937728ca9cf2bf44f86ff1184df318b3bd7Benjamin Kramer  : TargetFrameLowering(TargetFrameLowering::StackGrowsDown, 4, 0) {
82b25baef26f03b9909b65dd5f762b38f93000445dRichard Osborne  // Do nothing
83b25baef26f03b9909b65dd5f762b38f93000445dRichard Osborne}
8433464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov
8516c29b5f285f375be53dabaa73e3e91107485fe4Anton Korobeynikovbool XCoreFrameLowering::hasFP(const MachineFunction &MF) const {
868a8d479214745c82ef00f08d4e4f1c173b5f9ce2Nick Lewycky  return MF.getTarget().Options.DisableFramePointerElim(MF) ||
878a8d479214745c82ef00f08d4e4f1c173b5f9ce2Nick Lewycky    MF.getFrameInfo()->hasVarSizedObjects();
88d0c38176690e9602a93a20a43f1bd084564a8116Anton Korobeynikov}
89d0c38176690e9602a93a20a43f1bd084564a8116Anton Korobeynikov
9016c29b5f285f375be53dabaa73e3e91107485fe4Anton Korobeynikovvoid XCoreFrameLowering::emitPrologue(MachineFunction &MF) const {
9133464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov  MachineBasicBlock &MBB = MF.front();   // Prolog goes in entry BB
9233464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov  MachineBasicBlock::iterator MBBI = MBB.begin();
9333464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov  MachineFrameInfo *MFI = MF.getFrameInfo();
9433464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov  MachineModuleInfo *MMI = &MF.getMMI();
9533464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov  const XCoreInstrInfo &TII =
9633464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov    *static_cast<const XCoreInstrInfo*>(MF.getTarget().getInstrInfo());
9733464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov  XCoreFunctionInfo *XFI = MF.getInfo<XCoreFunctionInfo>();
9833464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov  DebugLoc dl = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc();
9933464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov
100d0c38176690e9602a93a20a43f1bd084564a8116Anton Korobeynikov  bool FP = hasFP(MF);
10199faa3b4ec6d03ac7808fe4ff3fbf3d04e375502Bill Wendling  const AttributeSet &PAL = MF.getFunction()->getAttributes();
102ff0c5014b2127b16815121d9e723dc85bd164a79Richard Osborne
1039d30e7208e6b2bc3fa48305e3ae371188f643425Bill Wendling  if (PAL.hasAttrSomewhere(Attribute::Nest))
1049d30e7208e6b2bc3fa48305e3ae371188f643425Bill Wendling    loadFromStack(MBB, MBBI, XCore::R11, 0, dl, TII);
10533464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov
10633464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov  // Work out frame sizes.
10733464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov  int FrameSize = MFI->getStackSize();
10833464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov  assert(FrameSize%4 == 0 && "Misaligned frame size");
10933464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov  FrameSize/=4;
11033464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov
11133464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov  bool isU6 = isImmU6(FrameSize);
11233464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov
11333464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov  if (!isU6 && !isImmU16(FrameSize)) {
11433464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov    // FIXME could emit multiple instructions.
11533464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov    report_fatal_error("emitPrologue Frame size too big: " + Twine(FrameSize));
11633464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov  }
11719411101a1c6e252af9a425793221ecec722c35cRichard Osborne  bool emitFrameMoves = XCoreRegisterInfo::needsFrameMoves(MF);
11833464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov
1199bd913c4c1f350562b5a31e79a82dcaf143b06e0Richard Osborne  bool saveLR = XFI->getUsesLR();
12033464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov  // Do we need to allocate space on the stack?
12133464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov  if (FrameSize) {
12233464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov    int Opcode;
12333464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov    if (saveLR && (MFI->getObjectOffset(XFI->getLRSpillSlot()) == 0)) {
12433464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov      Opcode = (isU6) ? XCore::ENTSP_u6 : XCore::ENTSP_lu6;
12533464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov      MBB.addLiveIn(XCore::LR);
12633464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov      saveLR = false;
12733464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov    } else {
12833464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov      Opcode = (isU6) ? XCore::EXTSP_u6 : XCore::EXTSP_lu6;
12933464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov    }
13033464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov    BuildMI(MBB, MBBI, dl, TII.get(Opcode)).addImm(FrameSize);
13133464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov
13233464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov    if (emitFrameMoves) {
13333464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov
13433464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov      // Show update of SP.
13533464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov      MCSymbol *FrameLabel = MMI->getContext().CreateTempSymbol();
13633464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov      BuildMI(MBB, MBBI, dl, TII.get(XCore::PROLOG_LABEL)).addSym(FrameLabel);
13733464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov    }
1389bd913c4c1f350562b5a31e79a82dcaf143b06e0Richard Osborne  }
1399bd913c4c1f350562b5a31e79a82dcaf143b06e0Richard Osborne  if (saveLR) {
1409bd913c4c1f350562b5a31e79a82dcaf143b06e0Richard Osborne    int LRSpillOffset = MFI->getObjectOffset(XFI->getLRSpillSlot());
1419bd913c4c1f350562b5a31e79a82dcaf143b06e0Richard Osborne    storeToStack(MBB, MBBI, XCore::LR, LRSpillOffset + FrameSize*4, dl, TII);
1429bd913c4c1f350562b5a31e79a82dcaf143b06e0Richard Osborne    MBB.addLiveIn(XCore::LR);
14333464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov
1449bd913c4c1f350562b5a31e79a82dcaf143b06e0Richard Osborne    if (emitFrameMoves) {
1459bd913c4c1f350562b5a31e79a82dcaf143b06e0Richard Osborne      MCSymbol *SaveLRLabel = MMI->getContext().CreateTempSymbol();
1469bd913c4c1f350562b5a31e79a82dcaf143b06e0Richard Osborne      BuildMI(MBB, MBBI, dl, TII.get(XCore::PROLOG_LABEL)).addSym(SaveLRLabel);
14733464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov    }
14833464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov  }
14933464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov
15033464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov  if (FP) {
15133464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov    // Save R10 to the stack.
15233464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov    int FPSpillOffset = MFI->getObjectOffset(XFI->getFPSpillSlot());
15333464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov    storeToStack(MBB, MBBI, XCore::R10, FPSpillOffset + FrameSize*4, dl, TII);
15433464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov    // R10 is live-in. It is killed at the spill.
15533464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov    MBB.addLiveIn(XCore::R10);
15633464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov    if (emitFrameMoves) {
15733464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov      MCSymbol *SaveR10Label = MMI->getContext().CreateTempSymbol();
15833464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov      BuildMI(MBB, MBBI, dl, TII.get(XCore::PROLOG_LABEL)).addSym(SaveR10Label);
15933464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov    }
16033464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov    // Set the FP from the SP.
16133464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov    unsigned FramePtr = XCore::R10;
16233464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov    BuildMI(MBB, MBBI, dl, TII.get(XCore::LDAWSP_ru6), FramePtr)
16333464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov      .addImm(0);
16433464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov    if (emitFrameMoves) {
16533464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov      // Show FP is now valid.
16633464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov      MCSymbol *FrameLabel = MMI->getContext().CreateTempSymbol();
16733464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov      BuildMI(MBB, MBBI, dl, TII.get(XCore::PROLOG_LABEL)).addSym(FrameLabel);
16833464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov    }
16933464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov  }
17033464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov}
17133464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov
17216c29b5f285f375be53dabaa73e3e91107485fe4Anton Korobeynikovvoid XCoreFrameLowering::emitEpilogue(MachineFunction &MF,
17333464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov                                     MachineBasicBlock &MBB) const {
17433464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov  MachineFrameInfo *MFI            = MF.getFrameInfo();
175f7ca976e74eafeeab0e9097f0fb07d6bb447415bJakob Stoklund Olesen  MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr();
17633464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov  const XCoreInstrInfo &TII =
17733464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov    *static_cast<const XCoreInstrInfo*>(MF.getTarget().getInstrInfo());
1789bd913c4c1f350562b5a31e79a82dcaf143b06e0Richard Osborne  XCoreFunctionInfo *XFI = MF.getInfo<XCoreFunctionInfo>();
17933464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov  DebugLoc dl = MBBI->getDebugLoc();
18033464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov
181d0c38176690e9602a93a20a43f1bd084564a8116Anton Korobeynikov  bool FP = hasFP(MF);
18233464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov  if (FP) {
18333464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov    // Restore the stack pointer.
18433464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov    unsigned FramePtr = XCore::R10;
18533464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov    BuildMI(MBB, MBBI, dl, TII.get(XCore::SETSP_1r))
18633464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov      .addReg(FramePtr);
18733464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov  }
18833464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov
18933464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov  // Work out frame sizes.
19033464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov  int FrameSize = MFI->getStackSize();
19133464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov
19233464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov  assert(FrameSize%4 == 0 && "Misaligned frame size");
19333464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov
19433464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov  FrameSize/=4;
19533464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov
19633464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov  bool isU6 = isImmU6(FrameSize);
19733464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov
19833464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov  if (!isU6 && !isImmU16(FrameSize)) {
19933464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov    // FIXME could emit multiple instructions.
20033464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov    report_fatal_error("emitEpilogue Frame size too big: " + Twine(FrameSize));
20133464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov  }
20233464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov
2039bd913c4c1f350562b5a31e79a82dcaf143b06e0Richard Osborne  if (FP) {
2049bd913c4c1f350562b5a31e79a82dcaf143b06e0Richard Osborne    // Restore R10
2059bd913c4c1f350562b5a31e79a82dcaf143b06e0Richard Osborne    int FPSpillOffset = MFI->getObjectOffset(XFI->getFPSpillSlot());
2069bd913c4c1f350562b5a31e79a82dcaf143b06e0Richard Osborne    FPSpillOffset += FrameSize*4;
2079bd913c4c1f350562b5a31e79a82dcaf143b06e0Richard Osborne    loadFromStack(MBB, MBBI, XCore::R10, FPSpillOffset, dl, TII);
2089bd913c4c1f350562b5a31e79a82dcaf143b06e0Richard Osborne  }
20933464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov
2109bd913c4c1f350562b5a31e79a82dcaf143b06e0Richard Osborne  bool restoreLR = XFI->getUsesLR();
2119bd913c4c1f350562b5a31e79a82dcaf143b06e0Richard Osborne  if (restoreLR &&
2129bd913c4c1f350562b5a31e79a82dcaf143b06e0Richard Osborne      (FrameSize == 0 || MFI->getObjectOffset(XFI->getLRSpillSlot()) != 0)) {
2139bd913c4c1f350562b5a31e79a82dcaf143b06e0Richard Osborne    int LRSpillOffset = MFI->getObjectOffset(XFI->getLRSpillSlot());
2149bd913c4c1f350562b5a31e79a82dcaf143b06e0Richard Osborne    LRSpillOffset += FrameSize*4;
2159bd913c4c1f350562b5a31e79a82dcaf143b06e0Richard Osborne    loadFromStack(MBB, MBBI, XCore::LR, LRSpillOffset, dl, TII);
2169bd913c4c1f350562b5a31e79a82dcaf143b06e0Richard Osborne    restoreLR = false;
2179bd913c4c1f350562b5a31e79a82dcaf143b06e0Richard Osborne  }
2189bd913c4c1f350562b5a31e79a82dcaf143b06e0Richard Osborne
2199bd913c4c1f350562b5a31e79a82dcaf143b06e0Richard Osborne  if (FrameSize) {
22033464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov    if (restoreLR) {
22133464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov      // Fold prologue into return instruction
2229bd913c4c1f350562b5a31e79a82dcaf143b06e0Richard Osborne      assert(MFI->getObjectOffset(XFI->getLRSpillSlot()) == 0);
22333464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov      assert(MBBI->getOpcode() == XCore::RETSP_u6
22433464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov        || MBBI->getOpcode() == XCore::RETSP_lu6);
22533464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov      int Opcode = (isU6) ? XCore::RETSP_u6 : XCore::RETSP_lu6;
226dcc4207a00b31687018f87de75846579bbdb9c77Richard Osborne      MachineInstrBuilder MIB  = BuildMI(MBB, MBBI, dl, TII.get(Opcode)).addImm(FrameSize);
227dcc4207a00b31687018f87de75846579bbdb9c77Richard Osborne      for (unsigned i = 3, e = MBBI->getNumOperands(); i < e; ++i)
228dcc4207a00b31687018f87de75846579bbdb9c77Richard Osborne        MIB->addOperand(MBBI->getOperand(i)); // copy any variadic operands
22933464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov      MBB.erase(MBBI);
23033464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov    } else {
231c6ff29713d69b4a41c225cbde9c82e4a350dbfacRichard Osborne      int Opcode = (isU6) ? XCore::LDAWSP_ru6 : XCore::LDAWSP_lru6;
23233464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov      BuildMI(MBB, MBBI, dl, TII.get(Opcode), XCore::SP).addImm(FrameSize);
23333464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov    }
23433464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov  }
23533464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov}
236d9e3385ced2dc887e2fe8e1c071bd2611e4d3edeAnton Korobeynikov
23716c29b5f285f375be53dabaa73e3e91107485fe4Anton Korobeynikovbool XCoreFrameLowering::spillCalleeSavedRegisters(MachineBasicBlock &MBB,
238cd775ceff0b25a0b026f643a7990c2924bd310a3Anton Korobeynikov                                               MachineBasicBlock::iterator MI,
239cd775ceff0b25a0b026f643a7990c2924bd310a3Anton Korobeynikov                                        const std::vector<CalleeSavedInfo> &CSI,
240cd775ceff0b25a0b026f643a7990c2924bd310a3Anton Korobeynikov                                          const TargetRegisterInfo *TRI) const {
241cd775ceff0b25a0b026f643a7990c2924bd310a3Anton Korobeynikov  if (CSI.empty())
242cd775ceff0b25a0b026f643a7990c2924bd310a3Anton Korobeynikov    return true;
243cd775ceff0b25a0b026f643a7990c2924bd310a3Anton Korobeynikov
244cd775ceff0b25a0b026f643a7990c2924bd310a3Anton Korobeynikov  MachineFunction *MF = MBB.getParent();
245cd775ceff0b25a0b026f643a7990c2924bd310a3Anton Korobeynikov  const TargetInstrInfo &TII = *MF->getTarget().getInstrInfo();
246cd775ceff0b25a0b026f643a7990c2924bd310a3Anton Korobeynikov
247cd775ceff0b25a0b026f643a7990c2924bd310a3Anton Korobeynikov  XCoreFunctionInfo *XFI = MF->getInfo<XCoreFunctionInfo>();
248cd775ceff0b25a0b026f643a7990c2924bd310a3Anton Korobeynikov  bool emitFrameMoves = XCoreRegisterInfo::needsFrameMoves(*MF);
249cd775ceff0b25a0b026f643a7990c2924bd310a3Anton Korobeynikov
250cd775ceff0b25a0b026f643a7990c2924bd310a3Anton Korobeynikov  DebugLoc DL;
251cd775ceff0b25a0b026f643a7990c2924bd310a3Anton Korobeynikov  if (MI != MBB.end()) DL = MI->getDebugLoc();
252cd775ceff0b25a0b026f643a7990c2924bd310a3Anton Korobeynikov
253cd775ceff0b25a0b026f643a7990c2924bd310a3Anton Korobeynikov  for (std::vector<CalleeSavedInfo>::const_iterator it = CSI.begin();
254cd775ceff0b25a0b026f643a7990c2924bd310a3Anton Korobeynikov                                                    it != CSI.end(); ++it) {
255cd775ceff0b25a0b026f643a7990c2924bd310a3Anton Korobeynikov    // Add the callee-saved register as live-in. It's killed at the spill.
256cd775ceff0b25a0b026f643a7990c2924bd310a3Anton Korobeynikov    MBB.addLiveIn(it->getReg());
257cd775ceff0b25a0b026f643a7990c2924bd310a3Anton Korobeynikov
258cd775ceff0b25a0b026f643a7990c2924bd310a3Anton Korobeynikov    unsigned Reg = it->getReg();
259cd775ceff0b25a0b026f643a7990c2924bd310a3Anton Korobeynikov    const TargetRegisterClass *RC = TRI->getMinimalPhysRegClass(Reg);
260cd775ceff0b25a0b026f643a7990c2924bd310a3Anton Korobeynikov    TII.storeRegToStackSlot(MBB, MI, Reg, true,
261cd775ceff0b25a0b026f643a7990c2924bd310a3Anton Korobeynikov                            it->getFrameIdx(), RC, TRI);
262cd775ceff0b25a0b026f643a7990c2924bd310a3Anton Korobeynikov    if (emitFrameMoves) {
263cd775ceff0b25a0b026f643a7990c2924bd310a3Anton Korobeynikov      MCSymbol *SaveLabel = MF->getContext().CreateTempSymbol();
264cd775ceff0b25a0b026f643a7990c2924bd310a3Anton Korobeynikov      BuildMI(MBB, MI, DL, TII.get(XCore::PROLOG_LABEL)).addSym(SaveLabel);
265cd775ceff0b25a0b026f643a7990c2924bd310a3Anton Korobeynikov      XFI->getSpillLabels().push_back(std::make_pair(SaveLabel, *it));
266cd775ceff0b25a0b026f643a7990c2924bd310a3Anton Korobeynikov    }
267cd775ceff0b25a0b026f643a7990c2924bd310a3Anton Korobeynikov  }
268cd775ceff0b25a0b026f643a7990c2924bd310a3Anton Korobeynikov  return true;
269cd775ceff0b25a0b026f643a7990c2924bd310a3Anton Korobeynikov}
270cd775ceff0b25a0b026f643a7990c2924bd310a3Anton Korobeynikov
27116c29b5f285f375be53dabaa73e3e91107485fe4Anton Korobeynikovbool XCoreFrameLowering::restoreCalleeSavedRegisters(MachineBasicBlock &MBB,
272cd775ceff0b25a0b026f643a7990c2924bd310a3Anton Korobeynikov                                                 MachineBasicBlock::iterator MI,
273cd775ceff0b25a0b026f643a7990c2924bd310a3Anton Korobeynikov                                        const std::vector<CalleeSavedInfo> &CSI,
274cd775ceff0b25a0b026f643a7990c2924bd310a3Anton Korobeynikov                                            const TargetRegisterInfo *TRI) const{
275cd775ceff0b25a0b026f643a7990c2924bd310a3Anton Korobeynikov  MachineFunction *MF = MBB.getParent();
276cd775ceff0b25a0b026f643a7990c2924bd310a3Anton Korobeynikov  const TargetInstrInfo &TII = *MF->getTarget().getInstrInfo();
277cd775ceff0b25a0b026f643a7990c2924bd310a3Anton Korobeynikov
278cd775ceff0b25a0b026f643a7990c2924bd310a3Anton Korobeynikov  bool AtStart = MI == MBB.begin();
279cd775ceff0b25a0b026f643a7990c2924bd310a3Anton Korobeynikov  MachineBasicBlock::iterator BeforeI = MI;
280cd775ceff0b25a0b026f643a7990c2924bd310a3Anton Korobeynikov  if (!AtStart)
281cd775ceff0b25a0b026f643a7990c2924bd310a3Anton Korobeynikov    --BeforeI;
282cd775ceff0b25a0b026f643a7990c2924bd310a3Anton Korobeynikov  for (std::vector<CalleeSavedInfo>::const_iterator it = CSI.begin();
283cd775ceff0b25a0b026f643a7990c2924bd310a3Anton Korobeynikov                                                    it != CSI.end(); ++it) {
284cd775ceff0b25a0b026f643a7990c2924bd310a3Anton Korobeynikov    unsigned Reg = it->getReg();
285cd775ceff0b25a0b026f643a7990c2924bd310a3Anton Korobeynikov    const TargetRegisterClass *RC = TRI->getMinimalPhysRegClass(Reg);
286cd775ceff0b25a0b026f643a7990c2924bd310a3Anton Korobeynikov    TII.loadRegFromStackSlot(MBB, MI, it->getReg(), it->getFrameIdx(),
287cd775ceff0b25a0b026f643a7990c2924bd310a3Anton Korobeynikov                             RC, TRI);
288cd775ceff0b25a0b026f643a7990c2924bd310a3Anton Korobeynikov    assert(MI != MBB.begin() &&
289cd775ceff0b25a0b026f643a7990c2924bd310a3Anton Korobeynikov           "loadRegFromStackSlot didn't insert any code!");
290cd775ceff0b25a0b026f643a7990c2924bd310a3Anton Korobeynikov    // Insert in reverse order.  loadRegFromStackSlot can insert multiple
291cd775ceff0b25a0b026f643a7990c2924bd310a3Anton Korobeynikov    // instructions.
292cd775ceff0b25a0b026f643a7990c2924bd310a3Anton Korobeynikov    if (AtStart)
293cd775ceff0b25a0b026f643a7990c2924bd310a3Anton Korobeynikov      MI = MBB.begin();
294cd775ceff0b25a0b026f643a7990c2924bd310a3Anton Korobeynikov    else {
295cd775ceff0b25a0b026f643a7990c2924bd310a3Anton Korobeynikov      MI = BeforeI;
296cd775ceff0b25a0b026f643a7990c2924bd310a3Anton Korobeynikov      ++MI;
297cd775ceff0b25a0b026f643a7990c2924bd310a3Anton Korobeynikov    }
298cd775ceff0b25a0b026f643a7990c2924bd310a3Anton Korobeynikov  }
299cd775ceff0b25a0b026f643a7990c2924bd310a3Anton Korobeynikov  return true;
300cd775ceff0b25a0b026f643a7990c2924bd310a3Anton Korobeynikov}
30194c5ae08750f314bc3cf1bf882b686244a3927d9Anton Korobeynikov
302700ed80d3da5e98e05ceb90e9bfb66058581a6dbEli Bendersky// This function eliminates ADJCALLSTACKDOWN,
303700ed80d3da5e98e05ceb90e9bfb66058581a6dbEli Bendersky// ADJCALLSTACKUP pseudo instructions
304700ed80d3da5e98e05ceb90e9bfb66058581a6dbEli Benderskyvoid XCoreFrameLowering::
305700ed80d3da5e98e05ceb90e9bfb66058581a6dbEli BenderskyeliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB,
306700ed80d3da5e98e05ceb90e9bfb66058581a6dbEli Bendersky                              MachineBasicBlock::iterator I) const {
307700ed80d3da5e98e05ceb90e9bfb66058581a6dbEli Bendersky  const XCoreInstrInfo &TII =
308700ed80d3da5e98e05ceb90e9bfb66058581a6dbEli Bendersky    *static_cast<const XCoreInstrInfo*>(MF.getTarget().getInstrInfo());
309700ed80d3da5e98e05ceb90e9bfb66058581a6dbEli Bendersky  if (!hasReservedCallFrame(MF)) {
310700ed80d3da5e98e05ceb90e9bfb66058581a6dbEli Bendersky    // Turn the adjcallstackdown instruction into 'extsp <amt>' and the
311700ed80d3da5e98e05ceb90e9bfb66058581a6dbEli Bendersky    // adjcallstackup instruction into 'ldaw sp, sp[<amt>]'
312700ed80d3da5e98e05ceb90e9bfb66058581a6dbEli Bendersky    MachineInstr *Old = I;
313700ed80d3da5e98e05ceb90e9bfb66058581a6dbEli Bendersky    uint64_t Amount = Old->getOperand(0).getImm();
314700ed80d3da5e98e05ceb90e9bfb66058581a6dbEli Bendersky    if (Amount != 0) {
315700ed80d3da5e98e05ceb90e9bfb66058581a6dbEli Bendersky      // We need to keep the stack aligned properly.  To do this, we round the
316700ed80d3da5e98e05ceb90e9bfb66058581a6dbEli Bendersky      // amount of space needed for the outgoing arguments up to the next
317700ed80d3da5e98e05ceb90e9bfb66058581a6dbEli Bendersky      // alignment boundary.
318700ed80d3da5e98e05ceb90e9bfb66058581a6dbEli Bendersky      unsigned Align = getStackAlignment();
319700ed80d3da5e98e05ceb90e9bfb66058581a6dbEli Bendersky      Amount = (Amount+Align-1)/Align*Align;
320700ed80d3da5e98e05ceb90e9bfb66058581a6dbEli Bendersky
321700ed80d3da5e98e05ceb90e9bfb66058581a6dbEli Bendersky      assert(Amount%4 == 0);
322700ed80d3da5e98e05ceb90e9bfb66058581a6dbEli Bendersky      Amount /= 4;
323700ed80d3da5e98e05ceb90e9bfb66058581a6dbEli Bendersky
324700ed80d3da5e98e05ceb90e9bfb66058581a6dbEli Bendersky      bool isU6 = isImmU6(Amount);
325700ed80d3da5e98e05ceb90e9bfb66058581a6dbEli Bendersky      if (!isU6 && !isImmU16(Amount)) {
326700ed80d3da5e98e05ceb90e9bfb66058581a6dbEli Bendersky        // FIX could emit multiple instructions in this case.
327700ed80d3da5e98e05ceb90e9bfb66058581a6dbEli Bendersky#ifndef NDEBUG
328700ed80d3da5e98e05ceb90e9bfb66058581a6dbEli Bendersky        errs() << "eliminateCallFramePseudoInstr size too big: "
329700ed80d3da5e98e05ceb90e9bfb66058581a6dbEli Bendersky               << Amount << "\n";
330700ed80d3da5e98e05ceb90e9bfb66058581a6dbEli Bendersky#endif
331700ed80d3da5e98e05ceb90e9bfb66058581a6dbEli Bendersky        llvm_unreachable(0);
332700ed80d3da5e98e05ceb90e9bfb66058581a6dbEli Bendersky      }
333700ed80d3da5e98e05ceb90e9bfb66058581a6dbEli Bendersky
334700ed80d3da5e98e05ceb90e9bfb66058581a6dbEli Bendersky      MachineInstr *New;
335700ed80d3da5e98e05ceb90e9bfb66058581a6dbEli Bendersky      if (Old->getOpcode() == XCore::ADJCALLSTACKDOWN) {
336700ed80d3da5e98e05ceb90e9bfb66058581a6dbEli Bendersky        int Opcode = isU6 ? XCore::EXTSP_u6 : XCore::EXTSP_lu6;
337700ed80d3da5e98e05ceb90e9bfb66058581a6dbEli Bendersky        New=BuildMI(MF, Old->getDebugLoc(), TII.get(Opcode))
338700ed80d3da5e98e05ceb90e9bfb66058581a6dbEli Bendersky          .addImm(Amount);
339700ed80d3da5e98e05ceb90e9bfb66058581a6dbEli Bendersky      } else {
340700ed80d3da5e98e05ceb90e9bfb66058581a6dbEli Bendersky        assert(Old->getOpcode() == XCore::ADJCALLSTACKUP);
341c6ff29713d69b4a41c225cbde9c82e4a350dbfacRichard Osborne        int Opcode = isU6 ? XCore::LDAWSP_ru6 : XCore::LDAWSP_lru6;
342700ed80d3da5e98e05ceb90e9bfb66058581a6dbEli Bendersky        New=BuildMI(MF, Old->getDebugLoc(), TII.get(Opcode), XCore::SP)
343700ed80d3da5e98e05ceb90e9bfb66058581a6dbEli Bendersky          .addImm(Amount);
344700ed80d3da5e98e05ceb90e9bfb66058581a6dbEli Bendersky      }
345700ed80d3da5e98e05ceb90e9bfb66058581a6dbEli Bendersky
346700ed80d3da5e98e05ceb90e9bfb66058581a6dbEli Bendersky      // Replace the pseudo instruction with a new instruction...
347700ed80d3da5e98e05ceb90e9bfb66058581a6dbEli Bendersky      MBB.insert(I, New);
348700ed80d3da5e98e05ceb90e9bfb66058581a6dbEli Bendersky    }
349700ed80d3da5e98e05ceb90e9bfb66058581a6dbEli Bendersky  }
350700ed80d3da5e98e05ceb90e9bfb66058581a6dbEli Bendersky
351700ed80d3da5e98e05ceb90e9bfb66058581a6dbEli Bendersky  MBB.erase(I);
352700ed80d3da5e98e05ceb90e9bfb66058581a6dbEli Bendersky}
353700ed80d3da5e98e05ceb90e9bfb66058581a6dbEli Bendersky
35494c5ae08750f314bc3cf1bf882b686244a3927d9Anton Korobeynikovvoid
35516c29b5f285f375be53dabaa73e3e91107485fe4Anton KorobeynikovXCoreFrameLowering::processFunctionBeforeCalleeSavedScan(MachineFunction &MF,
35694c5ae08750f314bc3cf1bf882b686244a3927d9Anton Korobeynikov                                                     RegScavenger *RS) const {
35794c5ae08750f314bc3cf1bf882b686244a3927d9Anton Korobeynikov  MachineFrameInfo *MFI = MF.getFrameInfo();
35894c5ae08750f314bc3cf1bf882b686244a3927d9Anton Korobeynikov  const TargetRegisterInfo *RegInfo = MF.getTarget().getRegisterInfo();
35994c5ae08750f314bc3cf1bf882b686244a3927d9Anton Korobeynikov  bool LRUsed = MF.getRegInfo().isPhysRegUsed(XCore::LR);
360420761a0f193e87d08ee1c51b26bba23ab4bac7fCraig Topper  const TargetRegisterClass *RC = &XCore::GRRegsRegClass;
36194c5ae08750f314bc3cf1bf882b686244a3927d9Anton Korobeynikov  XCoreFunctionInfo *XFI = MF.getInfo<XCoreFunctionInfo>();
36294c5ae08750f314bc3cf1bf882b686244a3927d9Anton Korobeynikov  if (LRUsed) {
36394c5ae08750f314bc3cf1bf882b686244a3927d9Anton Korobeynikov    MF.getRegInfo().setPhysRegUnused(XCore::LR);
36494c5ae08750f314bc3cf1bf882b686244a3927d9Anton Korobeynikov
36594c5ae08750f314bc3cf1bf882b686244a3927d9Anton Korobeynikov    bool isVarArg = MF.getFunction()->isVarArg();
36694c5ae08750f314bc3cf1bf882b686244a3927d9Anton Korobeynikov    int FrameIdx;
36794c5ae08750f314bc3cf1bf882b686244a3927d9Anton Korobeynikov    if (! isVarArg) {
36894c5ae08750f314bc3cf1bf882b686244a3927d9Anton Korobeynikov      // A fixed offset of 0 allows us to save / restore LR using entsp / retsp.
36994c5ae08750f314bc3cf1bf882b686244a3927d9Anton Korobeynikov      FrameIdx = MFI->CreateFixedObject(RC->getSize(), 0, true);
37094c5ae08750f314bc3cf1bf882b686244a3927d9Anton Korobeynikov    } else {
37194c5ae08750f314bc3cf1bf882b686244a3927d9Anton Korobeynikov      FrameIdx = MFI->CreateStackObject(RC->getSize(), RC->getAlignment(),
37294c5ae08750f314bc3cf1bf882b686244a3927d9Anton Korobeynikov                                        false);
37394c5ae08750f314bc3cf1bf882b686244a3927d9Anton Korobeynikov    }
37494c5ae08750f314bc3cf1bf882b686244a3927d9Anton Korobeynikov    XFI->setUsesLR(FrameIdx);
37594c5ae08750f314bc3cf1bf882b686244a3927d9Anton Korobeynikov    XFI->setLRSpillSlot(FrameIdx);
37694c5ae08750f314bc3cf1bf882b686244a3927d9Anton Korobeynikov  }
37794c5ae08750f314bc3cf1bf882b686244a3927d9Anton Korobeynikov  if (RegInfo->requiresRegisterScavenging(MF)) {
37894c5ae08750f314bc3cf1bf882b686244a3927d9Anton Korobeynikov    // Reserve a slot close to SP or frame pointer.
379dc3beb90178fc316f63790812b22201884eaa017Hal Finkel    RS->addScavengingFrameIndex(MFI->CreateStackObject(RC->getSize(),
38094c5ae08750f314bc3cf1bf882b686244a3927d9Anton Korobeynikov                                                       RC->getAlignment(),
38194c5ae08750f314bc3cf1bf882b686244a3927d9Anton Korobeynikov                                                       false));
38294c5ae08750f314bc3cf1bf882b686244a3927d9Anton Korobeynikov  }
38394c5ae08750f314bc3cf1bf882b686244a3927d9Anton Korobeynikov  if (hasFP(MF)) {
38494c5ae08750f314bc3cf1bf882b686244a3927d9Anton Korobeynikov    // A callee save register is used to hold the FP.
38594c5ae08750f314bc3cf1bf882b686244a3927d9Anton Korobeynikov    // This needs saving / restoring in the epilogue / prologue.
38694c5ae08750f314bc3cf1bf882b686244a3927d9Anton Korobeynikov    XFI->setFPSpillSlot(MFI->CreateStackObject(RC->getSize(),
38794c5ae08750f314bc3cf1bf882b686244a3927d9Anton Korobeynikov                                               RC->getAlignment(),
38894c5ae08750f314bc3cf1bf882b686244a3927d9Anton Korobeynikov                                               false));
38994c5ae08750f314bc3cf1bf882b686244a3927d9Anton Korobeynikov  }
39094c5ae08750f314bc3cf1bf882b686244a3927d9Anton Korobeynikov}
391