XCoreFrameLowering.cpp revision 9d30e7208e6b2bc3fa48305e3ae371188f643425
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"
253574eca1b02600bac4e625297f4ecf745f4c4f32Micah Villmow#include "llvm/DataLayout.h"
26d04a8d4b33ff316ca4cf961e06c9e312eff8e64fChandler Carruth#include "llvm/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
11933464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov  // Do we need to allocate space on the stack?
12033464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov  if (FrameSize) {
12133464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov    bool saveLR = XFI->getUsesLR();
12233464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov    bool LRSavedOnEntry = false;
12333464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov    int Opcode;
12433464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov    if (saveLR && (MFI->getObjectOffset(XFI->getLRSpillSlot()) == 0)) {
12533464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov      Opcode = (isU6) ? XCore::ENTSP_u6 : XCore::ENTSP_lu6;
12633464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov      MBB.addLiveIn(XCore::LR);
12733464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov      saveLR = false;
12833464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov      LRSavedOnEntry = true;
12933464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov    } else {
13033464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov      Opcode = (isU6) ? XCore::EXTSP_u6 : XCore::EXTSP_lu6;
13133464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov    }
13233464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov    BuildMI(MBB, MBBI, dl, TII.get(Opcode)).addImm(FrameSize);
13333464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov
13433464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov    if (emitFrameMoves) {
13533464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov      std::vector<MachineMove> &Moves = MMI->getFrameMoves();
13633464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov
13733464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov      // Show update of SP.
13833464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov      MCSymbol *FrameLabel = MMI->getContext().CreateTempSymbol();
13933464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov      BuildMI(MBB, MBBI, dl, TII.get(XCore::PROLOG_LABEL)).addSym(FrameLabel);
14033464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov
14133464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov      MachineLocation SPDst(MachineLocation::VirtualFP);
14233464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov      MachineLocation SPSrc(MachineLocation::VirtualFP, -FrameSize * 4);
14333464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov      Moves.push_back(MachineMove(FrameLabel, SPDst, SPSrc));
14433464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov
14533464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov      if (LRSavedOnEntry) {
14633464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov        MachineLocation CSDst(MachineLocation::VirtualFP, 0);
14733464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov        MachineLocation CSSrc(XCore::LR);
14833464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov        Moves.push_back(MachineMove(FrameLabel, CSDst, CSSrc));
14933464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov      }
15033464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov    }
15133464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov    if (saveLR) {
15233464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov      int LRSpillOffset = MFI->getObjectOffset(XFI->getLRSpillSlot());
15333464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov      storeToStack(MBB, MBBI, XCore::LR, LRSpillOffset + FrameSize*4, dl, TII);
15433464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov      MBB.addLiveIn(XCore::LR);
15533464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov
15633464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov      if (emitFrameMoves) {
15733464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov        MCSymbol *SaveLRLabel = MMI->getContext().CreateTempSymbol();
15833464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov        BuildMI(MBB, MBBI, dl, TII.get(XCore::PROLOG_LABEL)).addSym(SaveLRLabel);
15933464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov        MachineLocation CSDst(MachineLocation::VirtualFP, LRSpillOffset);
16033464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov        MachineLocation CSSrc(XCore::LR);
16133464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov        MMI->getFrameMoves().push_back(MachineMove(SaveLRLabel, CSDst, CSSrc));
16233464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov      }
16333464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov    }
16433464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov  }
16533464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov
16633464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov  if (FP) {
16733464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov    // Save R10 to the stack.
16833464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov    int FPSpillOffset = MFI->getObjectOffset(XFI->getFPSpillSlot());
16933464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov    storeToStack(MBB, MBBI, XCore::R10, FPSpillOffset + FrameSize*4, dl, TII);
17033464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov    // R10 is live-in. It is killed at the spill.
17133464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov    MBB.addLiveIn(XCore::R10);
17233464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov    if (emitFrameMoves) {
17333464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov      MCSymbol *SaveR10Label = MMI->getContext().CreateTempSymbol();
17433464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov      BuildMI(MBB, MBBI, dl, TII.get(XCore::PROLOG_LABEL)).addSym(SaveR10Label);
17533464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov      MachineLocation CSDst(MachineLocation::VirtualFP, FPSpillOffset);
17633464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov      MachineLocation CSSrc(XCore::R10);
17733464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov      MMI->getFrameMoves().push_back(MachineMove(SaveR10Label, CSDst, CSSrc));
17833464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov    }
17933464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov    // Set the FP from the SP.
18033464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov    unsigned FramePtr = XCore::R10;
18133464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov    BuildMI(MBB, MBBI, dl, TII.get(XCore::LDAWSP_ru6), FramePtr)
18233464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov      .addImm(0);
18333464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov    if (emitFrameMoves) {
18433464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov      // Show FP is now valid.
18533464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov      MCSymbol *FrameLabel = MMI->getContext().CreateTempSymbol();
18633464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov      BuildMI(MBB, MBBI, dl, TII.get(XCore::PROLOG_LABEL)).addSym(FrameLabel);
18733464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov      MachineLocation SPDst(FramePtr);
18833464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov      MachineLocation SPSrc(MachineLocation::VirtualFP);
18933464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov      MMI->getFrameMoves().push_back(MachineMove(FrameLabel, SPDst, SPSrc));
19033464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov    }
19133464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov  }
19233464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov
19333464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov  if (emitFrameMoves) {
19433464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov    // Frame moves for callee saved.
19533464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov    std::vector<MachineMove> &Moves = MMI->getFrameMoves();
19633464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov    std::vector<std::pair<MCSymbol*, CalleeSavedInfo> >&SpillLabels =
19733464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov        XFI->getSpillLabels();
19833464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov    for (unsigned I = 0, E = SpillLabels.size(); I != E; ++I) {
19933464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov      MCSymbol *SpillLabel = SpillLabels[I].first;
20033464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov      CalleeSavedInfo &CSI = SpillLabels[I].second;
20133464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov      int Offset = MFI->getObjectOffset(CSI.getFrameIdx());
20233464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov      unsigned Reg = CSI.getReg();
20333464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov      MachineLocation CSDst(MachineLocation::VirtualFP, Offset);
20433464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov      MachineLocation CSSrc(Reg);
20533464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov      Moves.push_back(MachineMove(SpillLabel, CSDst, CSSrc));
20633464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov    }
20733464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov  }
20833464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov}
20933464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov
21016c29b5f285f375be53dabaa73e3e91107485fe4Anton Korobeynikovvoid XCoreFrameLowering::emitEpilogue(MachineFunction &MF,
21133464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov                                     MachineBasicBlock &MBB) const {
21233464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov  MachineFrameInfo *MFI            = MF.getFrameInfo();
213f7ca976e74eafeeab0e9097f0fb07d6bb447415bJakob Stoklund Olesen  MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr();
21433464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov  const XCoreInstrInfo &TII =
21533464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov    *static_cast<const XCoreInstrInfo*>(MF.getTarget().getInstrInfo());
21633464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov  DebugLoc dl = MBBI->getDebugLoc();
21733464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov
218d0c38176690e9602a93a20a43f1bd084564a8116Anton Korobeynikov  bool FP = hasFP(MF);
21933464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov  if (FP) {
22033464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov    // Restore the stack pointer.
22133464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov    unsigned FramePtr = XCore::R10;
22233464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov    BuildMI(MBB, MBBI, dl, TII.get(XCore::SETSP_1r))
22333464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov      .addReg(FramePtr);
22433464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov  }
22533464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov
22633464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov  // Work out frame sizes.
22733464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov  int FrameSize = MFI->getStackSize();
22833464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov
22933464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov  assert(FrameSize%4 == 0 && "Misaligned frame size");
23033464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov
23133464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov  FrameSize/=4;
23233464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov
23333464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov  bool isU6 = isImmU6(FrameSize);
23433464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov
23533464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov  if (!isU6 && !isImmU16(FrameSize)) {
23633464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov    // FIXME could emit multiple instructions.
23733464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov    report_fatal_error("emitEpilogue Frame size too big: " + Twine(FrameSize));
23833464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov  }
23933464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov
24033464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov  if (FrameSize) {
24133464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov    XCoreFunctionInfo *XFI = MF.getInfo<XCoreFunctionInfo>();
24233464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov
24333464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov    if (FP) {
24433464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov      // Restore R10
24533464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov      int FPSpillOffset = MFI->getObjectOffset(XFI->getFPSpillSlot());
24633464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov      FPSpillOffset += FrameSize*4;
24733464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov      loadFromStack(MBB, MBBI, XCore::R10, FPSpillOffset, dl, TII);
24833464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov    }
24933464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov    bool restoreLR = XFI->getUsesLR();
25033464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov    if (restoreLR && MFI->getObjectOffset(XFI->getLRSpillSlot()) != 0) {
25133464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov      int LRSpillOffset = MFI->getObjectOffset(XFI->getLRSpillSlot());
25233464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov      LRSpillOffset += FrameSize*4;
25333464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov      loadFromStack(MBB, MBBI, XCore::LR, LRSpillOffset, dl, TII);
25433464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov      restoreLR = false;
25533464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov    }
25633464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov    if (restoreLR) {
25733464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov      // Fold prologue into return instruction
25833464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov      assert(MBBI->getOpcode() == XCore::RETSP_u6
25933464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov        || MBBI->getOpcode() == XCore::RETSP_lu6);
26033464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov      int Opcode = (isU6) ? XCore::RETSP_u6 : XCore::RETSP_lu6;
26133464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov      BuildMI(MBB, MBBI, dl, TII.get(Opcode)).addImm(FrameSize);
26233464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov      MBB.erase(MBBI);
26333464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov    } else {
26433464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov      int Opcode = (isU6) ? XCore::LDAWSP_ru6_RRegs : XCore::LDAWSP_lru6_RRegs;
26533464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov      BuildMI(MBB, MBBI, dl, TII.get(Opcode), XCore::SP).addImm(FrameSize);
26633464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov    }
26733464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov  }
26833464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov}
269d9e3385ced2dc887e2fe8e1c071bd2611e4d3edeAnton Korobeynikov
27016c29b5f285f375be53dabaa73e3e91107485fe4Anton Korobeynikovbool XCoreFrameLowering::spillCalleeSavedRegisters(MachineBasicBlock &MBB,
271cd775ceff0b25a0b026f643a7990c2924bd310a3Anton Korobeynikov                                               MachineBasicBlock::iterator MI,
272cd775ceff0b25a0b026f643a7990c2924bd310a3Anton Korobeynikov                                        const std::vector<CalleeSavedInfo> &CSI,
273cd775ceff0b25a0b026f643a7990c2924bd310a3Anton Korobeynikov                                          const TargetRegisterInfo *TRI) const {
274cd775ceff0b25a0b026f643a7990c2924bd310a3Anton Korobeynikov  if (CSI.empty())
275cd775ceff0b25a0b026f643a7990c2924bd310a3Anton Korobeynikov    return true;
276cd775ceff0b25a0b026f643a7990c2924bd310a3Anton Korobeynikov
277cd775ceff0b25a0b026f643a7990c2924bd310a3Anton Korobeynikov  MachineFunction *MF = MBB.getParent();
278cd775ceff0b25a0b026f643a7990c2924bd310a3Anton Korobeynikov  const TargetInstrInfo &TII = *MF->getTarget().getInstrInfo();
279cd775ceff0b25a0b026f643a7990c2924bd310a3Anton Korobeynikov
280cd775ceff0b25a0b026f643a7990c2924bd310a3Anton Korobeynikov  XCoreFunctionInfo *XFI = MF->getInfo<XCoreFunctionInfo>();
281cd775ceff0b25a0b026f643a7990c2924bd310a3Anton Korobeynikov  bool emitFrameMoves = XCoreRegisterInfo::needsFrameMoves(*MF);
282cd775ceff0b25a0b026f643a7990c2924bd310a3Anton Korobeynikov
283cd775ceff0b25a0b026f643a7990c2924bd310a3Anton Korobeynikov  DebugLoc DL;
284cd775ceff0b25a0b026f643a7990c2924bd310a3Anton Korobeynikov  if (MI != MBB.end()) DL = MI->getDebugLoc();
285cd775ceff0b25a0b026f643a7990c2924bd310a3Anton Korobeynikov
286cd775ceff0b25a0b026f643a7990c2924bd310a3Anton Korobeynikov  for (std::vector<CalleeSavedInfo>::const_iterator it = CSI.begin();
287cd775ceff0b25a0b026f643a7990c2924bd310a3Anton Korobeynikov                                                    it != CSI.end(); ++it) {
288cd775ceff0b25a0b026f643a7990c2924bd310a3Anton Korobeynikov    // Add the callee-saved register as live-in. It's killed at the spill.
289cd775ceff0b25a0b026f643a7990c2924bd310a3Anton Korobeynikov    MBB.addLiveIn(it->getReg());
290cd775ceff0b25a0b026f643a7990c2924bd310a3Anton Korobeynikov
291cd775ceff0b25a0b026f643a7990c2924bd310a3Anton Korobeynikov    unsigned Reg = it->getReg();
292cd775ceff0b25a0b026f643a7990c2924bd310a3Anton Korobeynikov    const TargetRegisterClass *RC = TRI->getMinimalPhysRegClass(Reg);
293cd775ceff0b25a0b026f643a7990c2924bd310a3Anton Korobeynikov    TII.storeRegToStackSlot(MBB, MI, Reg, true,
294cd775ceff0b25a0b026f643a7990c2924bd310a3Anton Korobeynikov                            it->getFrameIdx(), RC, TRI);
295cd775ceff0b25a0b026f643a7990c2924bd310a3Anton Korobeynikov    if (emitFrameMoves) {
296cd775ceff0b25a0b026f643a7990c2924bd310a3Anton Korobeynikov      MCSymbol *SaveLabel = MF->getContext().CreateTempSymbol();
297cd775ceff0b25a0b026f643a7990c2924bd310a3Anton Korobeynikov      BuildMI(MBB, MI, DL, TII.get(XCore::PROLOG_LABEL)).addSym(SaveLabel);
298cd775ceff0b25a0b026f643a7990c2924bd310a3Anton Korobeynikov      XFI->getSpillLabels().push_back(std::make_pair(SaveLabel, *it));
299cd775ceff0b25a0b026f643a7990c2924bd310a3Anton Korobeynikov    }
300cd775ceff0b25a0b026f643a7990c2924bd310a3Anton Korobeynikov  }
301cd775ceff0b25a0b026f643a7990c2924bd310a3Anton Korobeynikov  return true;
302cd775ceff0b25a0b026f643a7990c2924bd310a3Anton Korobeynikov}
303cd775ceff0b25a0b026f643a7990c2924bd310a3Anton Korobeynikov
30416c29b5f285f375be53dabaa73e3e91107485fe4Anton Korobeynikovbool XCoreFrameLowering::restoreCalleeSavedRegisters(MachineBasicBlock &MBB,
305cd775ceff0b25a0b026f643a7990c2924bd310a3Anton Korobeynikov                                                 MachineBasicBlock::iterator MI,
306cd775ceff0b25a0b026f643a7990c2924bd310a3Anton Korobeynikov                                        const std::vector<CalleeSavedInfo> &CSI,
307cd775ceff0b25a0b026f643a7990c2924bd310a3Anton Korobeynikov                                            const TargetRegisterInfo *TRI) const{
308cd775ceff0b25a0b026f643a7990c2924bd310a3Anton Korobeynikov  MachineFunction *MF = MBB.getParent();
309cd775ceff0b25a0b026f643a7990c2924bd310a3Anton Korobeynikov  const TargetInstrInfo &TII = *MF->getTarget().getInstrInfo();
310cd775ceff0b25a0b026f643a7990c2924bd310a3Anton Korobeynikov
311cd775ceff0b25a0b026f643a7990c2924bd310a3Anton Korobeynikov  bool AtStart = MI == MBB.begin();
312cd775ceff0b25a0b026f643a7990c2924bd310a3Anton Korobeynikov  MachineBasicBlock::iterator BeforeI = MI;
313cd775ceff0b25a0b026f643a7990c2924bd310a3Anton Korobeynikov  if (!AtStart)
314cd775ceff0b25a0b026f643a7990c2924bd310a3Anton Korobeynikov    --BeforeI;
315cd775ceff0b25a0b026f643a7990c2924bd310a3Anton Korobeynikov  for (std::vector<CalleeSavedInfo>::const_iterator it = CSI.begin();
316cd775ceff0b25a0b026f643a7990c2924bd310a3Anton Korobeynikov                                                    it != CSI.end(); ++it) {
317cd775ceff0b25a0b026f643a7990c2924bd310a3Anton Korobeynikov    unsigned Reg = it->getReg();
318cd775ceff0b25a0b026f643a7990c2924bd310a3Anton Korobeynikov    const TargetRegisterClass *RC = TRI->getMinimalPhysRegClass(Reg);
319cd775ceff0b25a0b026f643a7990c2924bd310a3Anton Korobeynikov    TII.loadRegFromStackSlot(MBB, MI, it->getReg(), it->getFrameIdx(),
320cd775ceff0b25a0b026f643a7990c2924bd310a3Anton Korobeynikov                             RC, TRI);
321cd775ceff0b25a0b026f643a7990c2924bd310a3Anton Korobeynikov    assert(MI != MBB.begin() &&
322cd775ceff0b25a0b026f643a7990c2924bd310a3Anton Korobeynikov           "loadRegFromStackSlot didn't insert any code!");
323cd775ceff0b25a0b026f643a7990c2924bd310a3Anton Korobeynikov    // Insert in reverse order.  loadRegFromStackSlot can insert multiple
324cd775ceff0b25a0b026f643a7990c2924bd310a3Anton Korobeynikov    // instructions.
325cd775ceff0b25a0b026f643a7990c2924bd310a3Anton Korobeynikov    if (AtStart)
326cd775ceff0b25a0b026f643a7990c2924bd310a3Anton Korobeynikov      MI = MBB.begin();
327cd775ceff0b25a0b026f643a7990c2924bd310a3Anton Korobeynikov    else {
328cd775ceff0b25a0b026f643a7990c2924bd310a3Anton Korobeynikov      MI = BeforeI;
329cd775ceff0b25a0b026f643a7990c2924bd310a3Anton Korobeynikov      ++MI;
330cd775ceff0b25a0b026f643a7990c2924bd310a3Anton Korobeynikov    }
331cd775ceff0b25a0b026f643a7990c2924bd310a3Anton Korobeynikov  }
332cd775ceff0b25a0b026f643a7990c2924bd310a3Anton Korobeynikov  return true;
333cd775ceff0b25a0b026f643a7990c2924bd310a3Anton Korobeynikov}
33494c5ae08750f314bc3cf1bf882b686244a3927d9Anton Korobeynikov
33594c5ae08750f314bc3cf1bf882b686244a3927d9Anton Korobeynikovvoid
33616c29b5f285f375be53dabaa73e3e91107485fe4Anton KorobeynikovXCoreFrameLowering::processFunctionBeforeCalleeSavedScan(MachineFunction &MF,
33794c5ae08750f314bc3cf1bf882b686244a3927d9Anton Korobeynikov                                                     RegScavenger *RS) const {
33894c5ae08750f314bc3cf1bf882b686244a3927d9Anton Korobeynikov  MachineFrameInfo *MFI = MF.getFrameInfo();
33994c5ae08750f314bc3cf1bf882b686244a3927d9Anton Korobeynikov  const TargetRegisterInfo *RegInfo = MF.getTarget().getRegisterInfo();
34094c5ae08750f314bc3cf1bf882b686244a3927d9Anton Korobeynikov  bool LRUsed = MF.getRegInfo().isPhysRegUsed(XCore::LR);
341420761a0f193e87d08ee1c51b26bba23ab4bac7fCraig Topper  const TargetRegisterClass *RC = &XCore::GRRegsRegClass;
34294c5ae08750f314bc3cf1bf882b686244a3927d9Anton Korobeynikov  XCoreFunctionInfo *XFI = MF.getInfo<XCoreFunctionInfo>();
34394c5ae08750f314bc3cf1bf882b686244a3927d9Anton Korobeynikov  if (LRUsed) {
34494c5ae08750f314bc3cf1bf882b686244a3927d9Anton Korobeynikov    MF.getRegInfo().setPhysRegUnused(XCore::LR);
34594c5ae08750f314bc3cf1bf882b686244a3927d9Anton Korobeynikov
34694c5ae08750f314bc3cf1bf882b686244a3927d9Anton Korobeynikov    bool isVarArg = MF.getFunction()->isVarArg();
34794c5ae08750f314bc3cf1bf882b686244a3927d9Anton Korobeynikov    int FrameIdx;
34894c5ae08750f314bc3cf1bf882b686244a3927d9Anton Korobeynikov    if (! isVarArg) {
34994c5ae08750f314bc3cf1bf882b686244a3927d9Anton Korobeynikov      // A fixed offset of 0 allows us to save / restore LR using entsp / retsp.
35094c5ae08750f314bc3cf1bf882b686244a3927d9Anton Korobeynikov      FrameIdx = MFI->CreateFixedObject(RC->getSize(), 0, true);
35194c5ae08750f314bc3cf1bf882b686244a3927d9Anton Korobeynikov    } else {
35294c5ae08750f314bc3cf1bf882b686244a3927d9Anton Korobeynikov      FrameIdx = MFI->CreateStackObject(RC->getSize(), RC->getAlignment(),
35394c5ae08750f314bc3cf1bf882b686244a3927d9Anton Korobeynikov                                        false);
35494c5ae08750f314bc3cf1bf882b686244a3927d9Anton Korobeynikov    }
35594c5ae08750f314bc3cf1bf882b686244a3927d9Anton Korobeynikov    XFI->setUsesLR(FrameIdx);
35694c5ae08750f314bc3cf1bf882b686244a3927d9Anton Korobeynikov    XFI->setLRSpillSlot(FrameIdx);
35794c5ae08750f314bc3cf1bf882b686244a3927d9Anton Korobeynikov  }
35894c5ae08750f314bc3cf1bf882b686244a3927d9Anton Korobeynikov  if (RegInfo->requiresRegisterScavenging(MF)) {
35994c5ae08750f314bc3cf1bf882b686244a3927d9Anton Korobeynikov    // Reserve a slot close to SP or frame pointer.
36094c5ae08750f314bc3cf1bf882b686244a3927d9Anton Korobeynikov    RS->setScavengingFrameIndex(MFI->CreateStackObject(RC->getSize(),
36194c5ae08750f314bc3cf1bf882b686244a3927d9Anton Korobeynikov                                                       RC->getAlignment(),
36294c5ae08750f314bc3cf1bf882b686244a3927d9Anton Korobeynikov                                                       false));
36394c5ae08750f314bc3cf1bf882b686244a3927d9Anton Korobeynikov  }
36494c5ae08750f314bc3cf1bf882b686244a3927d9Anton Korobeynikov  if (hasFP(MF)) {
36594c5ae08750f314bc3cf1bf882b686244a3927d9Anton Korobeynikov    // A callee save register is used to hold the FP.
36694c5ae08750f314bc3cf1bf882b686244a3927d9Anton Korobeynikov    // This needs saving / restoring in the epilogue / prologue.
36794c5ae08750f314bc3cf1bf882b686244a3927d9Anton Korobeynikov    XFI->setFPSpillSlot(MFI->CreateStackObject(RC->getSize(),
36894c5ae08750f314bc3cf1bf882b686244a3927d9Anton Korobeynikov                                               RC->getAlignment(),
36994c5ae08750f314bc3cf1bf882b686244a3927d9Anton Korobeynikov                                               false));
37094c5ae08750f314bc3cf1bf882b686244a3927d9Anton Korobeynikov  }
37194c5ae08750f314bc3cf1bf882b686244a3927d9Anton Korobeynikov}
372