XCoreFrameLowering.cpp revision 8a8d479214745c82ef00f08d4e4f1c173b5f9ce2
116c29b5f285f375be53dabaa73e3e91107485fe4Anton Korobeynikov//===-- XCoreFrameLowering.cpp - Frame info for XCore Target -----*- C++ -*-==//
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
15b25baef26f03b9909b65dd5f762b38f93000445dRichard Osborne#include "XCore.h"
1616c29b5f285f375be53dabaa73e3e91107485fe4Anton Korobeynikov#include "XCoreFrameLowering.h"
1733464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov#include "XCoreInstrInfo.h"
1833464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov#include "XCoreMachineFunctionInfo.h"
1933464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov#include "llvm/Function.h"
2033464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov#include "llvm/CodeGen/MachineFrameInfo.h"
2133464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov#include "llvm/CodeGen/MachineFunction.h"
2233464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov#include "llvm/CodeGen/MachineInstrBuilder.h"
2333464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov#include "llvm/CodeGen/MachineModuleInfo.h"
2433464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov#include "llvm/CodeGen/MachineRegisterInfo.h"
2594c5ae08750f314bc3cf1bf882b686244a3927d9Anton Korobeynikov#include "llvm/CodeGen/RegisterScavenging.h"
2633464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov#include "llvm/Target/TargetData.h"
2733464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov#include "llvm/Target/TargetOptions.h"
2833464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov#include "llvm/Support/ErrorHandling.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)
8116c29b5f285f375be53dabaa73e3e91107485fe4Anton Korobeynikov  : TargetFrameLowering(TargetFrameLowering::StackGrowsDown, 4, 0),
8233464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov    STI(sti) {
83b25baef26f03b9909b65dd5f762b38f93000445dRichard Osborne  // Do nothing
84b25baef26f03b9909b65dd5f762b38f93000445dRichard Osborne}
8533464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov
8616c29b5f285f375be53dabaa73e3e91107485fe4Anton Korobeynikovbool XCoreFrameLowering::hasFP(const MachineFunction &MF) const {
878a8d479214745c82ef00f08d4e4f1c173b5f9ce2Nick Lewycky  return MF.getTarget().Options.DisableFramePointerElim(MF) ||
888a8d479214745c82ef00f08d4e4f1c173b5f9ce2Nick Lewycky    MF.getFrameInfo()->hasVarSizedObjects();
89d0c38176690e9602a93a20a43f1bd084564a8116Anton Korobeynikov}
90d0c38176690e9602a93a20a43f1bd084564a8116Anton Korobeynikov
9116c29b5f285f375be53dabaa73e3e91107485fe4Anton Korobeynikovvoid XCoreFrameLowering::emitPrologue(MachineFunction &MF) const {
9233464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov  MachineBasicBlock &MBB = MF.front();   // Prolog goes in entry BB
9333464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov  MachineBasicBlock::iterator MBBI = MBB.begin();
9433464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov  MachineFrameInfo *MFI = MF.getFrameInfo();
9533464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov  MachineModuleInfo *MMI = &MF.getMMI();
9633464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov  const XCoreRegisterInfo *RegInfo =
9733464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov    static_cast<const XCoreRegisterInfo*>(MF.getTarget().getRegisterInfo());
9833464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov  const XCoreInstrInfo &TII =
9933464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov    *static_cast<const XCoreInstrInfo*>(MF.getTarget().getInstrInfo());
10033464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov  XCoreFunctionInfo *XFI = MF.getInfo<XCoreFunctionInfo>();
10133464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov  DebugLoc dl = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc();
10233464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov
103d0c38176690e9602a93a20a43f1bd084564a8116Anton Korobeynikov  bool FP = hasFP(MF);
1040353dab90ec502b02cbf2cee845e07d51627248bRichard Osborne  bool Nested = MF.getFunction()->
1050353dab90ec502b02cbf2cee845e07d51627248bRichard Osborne                getAttributes().hasAttrSomewhere(Attribute::Nest);
106ff0c5014b2127b16815121d9e723dc85bd164a79Richard Osborne
107ff0c5014b2127b16815121d9e723dc85bd164a79Richard Osborne  if (Nested) {
108ff0c5014b2127b16815121d9e723dc85bd164a79Richard Osborne    loadFromStack(MBB, MBBI, XCore::R11, 0, dl, TII);
109ff0c5014b2127b16815121d9e723dc85bd164a79Richard Osborne  }
11033464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov
11133464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov  // Work out frame sizes.
11233464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov  int FrameSize = MFI->getStackSize();
11333464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov  assert(FrameSize%4 == 0 && "Misaligned frame size");
11433464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov  FrameSize/=4;
11533464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov
11633464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov  bool isU6 = isImmU6(FrameSize);
11733464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov
11833464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov  if (!isU6 && !isImmU16(FrameSize)) {
11933464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov    // FIXME could emit multiple instructions.
12033464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov    report_fatal_error("emitPrologue Frame size too big: " + Twine(FrameSize));
12133464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov  }
12233464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov  bool emitFrameMoves = RegInfo->needsFrameMoves(MF);
12333464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov
12433464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov  // Do we need to allocate space on the stack?
12533464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov  if (FrameSize) {
12633464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov    bool saveLR = XFI->getUsesLR();
12733464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov    bool LRSavedOnEntry = false;
12833464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov    int Opcode;
12933464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov    if (saveLR && (MFI->getObjectOffset(XFI->getLRSpillSlot()) == 0)) {
13033464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov      Opcode = (isU6) ? XCore::ENTSP_u6 : XCore::ENTSP_lu6;
13133464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov      MBB.addLiveIn(XCore::LR);
13233464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov      saveLR = false;
13333464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov      LRSavedOnEntry = true;
13433464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov    } else {
13533464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov      Opcode = (isU6) ? XCore::EXTSP_u6 : XCore::EXTSP_lu6;
13633464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov    }
13733464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov    BuildMI(MBB, MBBI, dl, TII.get(Opcode)).addImm(FrameSize);
13833464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov
13933464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov    if (emitFrameMoves) {
14033464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov      std::vector<MachineMove> &Moves = MMI->getFrameMoves();
14133464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov
14233464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov      // Show update of SP.
14333464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov      MCSymbol *FrameLabel = MMI->getContext().CreateTempSymbol();
14433464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov      BuildMI(MBB, MBBI, dl, TII.get(XCore::PROLOG_LABEL)).addSym(FrameLabel);
14533464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov
14633464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov      MachineLocation SPDst(MachineLocation::VirtualFP);
14733464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov      MachineLocation SPSrc(MachineLocation::VirtualFP, -FrameSize * 4);
14833464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov      Moves.push_back(MachineMove(FrameLabel, SPDst, SPSrc));
14933464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov
15033464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov      if (LRSavedOnEntry) {
15133464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov        MachineLocation CSDst(MachineLocation::VirtualFP, 0);
15233464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov        MachineLocation CSSrc(XCore::LR);
15333464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov        Moves.push_back(MachineMove(FrameLabel, CSDst, CSSrc));
15433464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov      }
15533464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov    }
15633464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov    if (saveLR) {
15733464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov      int LRSpillOffset = MFI->getObjectOffset(XFI->getLRSpillSlot());
15833464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov      storeToStack(MBB, MBBI, XCore::LR, LRSpillOffset + FrameSize*4, dl, TII);
15933464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov      MBB.addLiveIn(XCore::LR);
16033464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov
16133464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov      if (emitFrameMoves) {
16233464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov        MCSymbol *SaveLRLabel = MMI->getContext().CreateTempSymbol();
16333464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov        BuildMI(MBB, MBBI, dl, TII.get(XCore::PROLOG_LABEL)).addSym(SaveLRLabel);
16433464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov        MachineLocation CSDst(MachineLocation::VirtualFP, LRSpillOffset);
16533464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov        MachineLocation CSSrc(XCore::LR);
16633464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov        MMI->getFrameMoves().push_back(MachineMove(SaveLRLabel, CSDst, CSSrc));
16733464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov      }
16833464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov    }
16933464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov  }
17033464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov
17133464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov  if (FP) {
17233464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov    // Save R10 to the stack.
17333464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov    int FPSpillOffset = MFI->getObjectOffset(XFI->getFPSpillSlot());
17433464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov    storeToStack(MBB, MBBI, XCore::R10, FPSpillOffset + FrameSize*4, dl, TII);
17533464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov    // R10 is live-in. It is killed at the spill.
17633464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov    MBB.addLiveIn(XCore::R10);
17733464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov    if (emitFrameMoves) {
17833464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov      MCSymbol *SaveR10Label = MMI->getContext().CreateTempSymbol();
17933464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov      BuildMI(MBB, MBBI, dl, TII.get(XCore::PROLOG_LABEL)).addSym(SaveR10Label);
18033464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov      MachineLocation CSDst(MachineLocation::VirtualFP, FPSpillOffset);
18133464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov      MachineLocation CSSrc(XCore::R10);
18233464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov      MMI->getFrameMoves().push_back(MachineMove(SaveR10Label, CSDst, CSSrc));
18333464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov    }
18433464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov    // Set the FP from the SP.
18533464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov    unsigned FramePtr = XCore::R10;
18633464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov    BuildMI(MBB, MBBI, dl, TII.get(XCore::LDAWSP_ru6), FramePtr)
18733464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov      .addImm(0);
18833464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov    if (emitFrameMoves) {
18933464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov      // Show FP is now valid.
19033464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov      MCSymbol *FrameLabel = MMI->getContext().CreateTempSymbol();
19133464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov      BuildMI(MBB, MBBI, dl, TII.get(XCore::PROLOG_LABEL)).addSym(FrameLabel);
19233464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov      MachineLocation SPDst(FramePtr);
19333464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov      MachineLocation SPSrc(MachineLocation::VirtualFP);
19433464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov      MMI->getFrameMoves().push_back(MachineMove(FrameLabel, SPDst, SPSrc));
19533464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov    }
19633464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov  }
19733464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov
19833464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov  if (emitFrameMoves) {
19933464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov    // Frame moves for callee saved.
20033464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov    std::vector<MachineMove> &Moves = MMI->getFrameMoves();
20133464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov    std::vector<std::pair<MCSymbol*, CalleeSavedInfo> >&SpillLabels =
20233464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov        XFI->getSpillLabels();
20333464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov    for (unsigned I = 0, E = SpillLabels.size(); I != E; ++I) {
20433464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov      MCSymbol *SpillLabel = SpillLabels[I].first;
20533464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov      CalleeSavedInfo &CSI = SpillLabels[I].second;
20633464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov      int Offset = MFI->getObjectOffset(CSI.getFrameIdx());
20733464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov      unsigned Reg = CSI.getReg();
20833464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov      MachineLocation CSDst(MachineLocation::VirtualFP, Offset);
20933464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov      MachineLocation CSSrc(Reg);
21033464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov      Moves.push_back(MachineMove(SpillLabel, CSDst, CSSrc));
21133464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov    }
21233464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov  }
21333464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov}
21433464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov
21516c29b5f285f375be53dabaa73e3e91107485fe4Anton Korobeynikovvoid XCoreFrameLowering::emitEpilogue(MachineFunction &MF,
21633464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov                                     MachineBasicBlock &MBB) const {
21733464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov  MachineFrameInfo *MFI            = MF.getFrameInfo();
218f7ca976e74eafeeab0e9097f0fb07d6bb447415bJakob Stoklund Olesen  MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr();
21933464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov  const XCoreInstrInfo &TII =
22033464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov    *static_cast<const XCoreInstrInfo*>(MF.getTarget().getInstrInfo());
22133464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov  DebugLoc dl = MBBI->getDebugLoc();
22233464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov
223d0c38176690e9602a93a20a43f1bd084564a8116Anton Korobeynikov  bool FP = hasFP(MF);
22433464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov  if (FP) {
22533464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov    // Restore the stack pointer.
22633464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov    unsigned FramePtr = XCore::R10;
22733464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov    BuildMI(MBB, MBBI, dl, TII.get(XCore::SETSP_1r))
22833464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov      .addReg(FramePtr);
22933464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov  }
23033464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov
23133464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov  // Work out frame sizes.
23233464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov  int FrameSize = MFI->getStackSize();
23333464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov
23433464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov  assert(FrameSize%4 == 0 && "Misaligned frame size");
23533464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov
23633464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov  FrameSize/=4;
23733464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov
23833464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov  bool isU6 = isImmU6(FrameSize);
23933464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov
24033464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov  if (!isU6 && !isImmU16(FrameSize)) {
24133464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov    // FIXME could emit multiple instructions.
24233464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov    report_fatal_error("emitEpilogue Frame size too big: " + Twine(FrameSize));
24333464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov  }
24433464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov
24533464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov  if (FrameSize) {
24633464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov    XCoreFunctionInfo *XFI = MF.getInfo<XCoreFunctionInfo>();
24733464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov
24833464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov    if (FP) {
24933464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov      // Restore R10
25033464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov      int FPSpillOffset = MFI->getObjectOffset(XFI->getFPSpillSlot());
25133464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov      FPSpillOffset += FrameSize*4;
25233464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov      loadFromStack(MBB, MBBI, XCore::R10, FPSpillOffset, dl, TII);
25333464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov    }
25433464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov    bool restoreLR = XFI->getUsesLR();
25533464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov    if (restoreLR && MFI->getObjectOffset(XFI->getLRSpillSlot()) != 0) {
25633464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov      int LRSpillOffset = MFI->getObjectOffset(XFI->getLRSpillSlot());
25733464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov      LRSpillOffset += FrameSize*4;
25833464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov      loadFromStack(MBB, MBBI, XCore::LR, LRSpillOffset, dl, TII);
25933464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov      restoreLR = false;
26033464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov    }
26133464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov    if (restoreLR) {
26233464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov      // Fold prologue into return instruction
26333464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov      assert(MBBI->getOpcode() == XCore::RETSP_u6
26433464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov        || MBBI->getOpcode() == XCore::RETSP_lu6);
26533464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov      int Opcode = (isU6) ? XCore::RETSP_u6 : XCore::RETSP_lu6;
26633464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov      BuildMI(MBB, MBBI, dl, TII.get(Opcode)).addImm(FrameSize);
26733464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov      MBB.erase(MBBI);
26833464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov    } else {
26933464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov      int Opcode = (isU6) ? XCore::LDAWSP_ru6_RRegs : XCore::LDAWSP_lru6_RRegs;
27033464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov      BuildMI(MBB, MBBI, dl, TII.get(Opcode), XCore::SP).addImm(FrameSize);
27133464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov    }
27233464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov  }
27333464912237efaa0ed7060829e66b59055bdd48bAnton Korobeynikov}
274d9e3385ced2dc887e2fe8e1c071bd2611e4d3edeAnton Korobeynikov
27516c29b5f285f375be53dabaa73e3e91107485fe4Anton Korobeynikovbool XCoreFrameLowering::spillCalleeSavedRegisters(MachineBasicBlock &MBB,
276cd775ceff0b25a0b026f643a7990c2924bd310a3Anton Korobeynikov                                               MachineBasicBlock::iterator MI,
277cd775ceff0b25a0b026f643a7990c2924bd310a3Anton Korobeynikov                                        const std::vector<CalleeSavedInfo> &CSI,
278cd775ceff0b25a0b026f643a7990c2924bd310a3Anton Korobeynikov                                          const TargetRegisterInfo *TRI) const {
279cd775ceff0b25a0b026f643a7990c2924bd310a3Anton Korobeynikov  if (CSI.empty())
280cd775ceff0b25a0b026f643a7990c2924bd310a3Anton Korobeynikov    return true;
281cd775ceff0b25a0b026f643a7990c2924bd310a3Anton Korobeynikov
282cd775ceff0b25a0b026f643a7990c2924bd310a3Anton Korobeynikov  MachineFunction *MF = MBB.getParent();
283cd775ceff0b25a0b026f643a7990c2924bd310a3Anton Korobeynikov  const TargetInstrInfo &TII = *MF->getTarget().getInstrInfo();
284cd775ceff0b25a0b026f643a7990c2924bd310a3Anton Korobeynikov
285cd775ceff0b25a0b026f643a7990c2924bd310a3Anton Korobeynikov  XCoreFunctionInfo *XFI = MF->getInfo<XCoreFunctionInfo>();
286cd775ceff0b25a0b026f643a7990c2924bd310a3Anton Korobeynikov  bool emitFrameMoves = XCoreRegisterInfo::needsFrameMoves(*MF);
287cd775ceff0b25a0b026f643a7990c2924bd310a3Anton Korobeynikov
288cd775ceff0b25a0b026f643a7990c2924bd310a3Anton Korobeynikov  DebugLoc DL;
289cd775ceff0b25a0b026f643a7990c2924bd310a3Anton Korobeynikov  if (MI != MBB.end()) DL = MI->getDebugLoc();
290cd775ceff0b25a0b026f643a7990c2924bd310a3Anton Korobeynikov
291cd775ceff0b25a0b026f643a7990c2924bd310a3Anton Korobeynikov  for (std::vector<CalleeSavedInfo>::const_iterator it = CSI.begin();
292cd775ceff0b25a0b026f643a7990c2924bd310a3Anton Korobeynikov                                                    it != CSI.end(); ++it) {
293cd775ceff0b25a0b026f643a7990c2924bd310a3Anton Korobeynikov    // Add the callee-saved register as live-in. It's killed at the spill.
294cd775ceff0b25a0b026f643a7990c2924bd310a3Anton Korobeynikov    MBB.addLiveIn(it->getReg());
295cd775ceff0b25a0b026f643a7990c2924bd310a3Anton Korobeynikov
296cd775ceff0b25a0b026f643a7990c2924bd310a3Anton Korobeynikov    unsigned Reg = it->getReg();
297cd775ceff0b25a0b026f643a7990c2924bd310a3Anton Korobeynikov    const TargetRegisterClass *RC = TRI->getMinimalPhysRegClass(Reg);
298cd775ceff0b25a0b026f643a7990c2924bd310a3Anton Korobeynikov    TII.storeRegToStackSlot(MBB, MI, Reg, true,
299cd775ceff0b25a0b026f643a7990c2924bd310a3Anton Korobeynikov                            it->getFrameIdx(), RC, TRI);
300cd775ceff0b25a0b026f643a7990c2924bd310a3Anton Korobeynikov    if (emitFrameMoves) {
301cd775ceff0b25a0b026f643a7990c2924bd310a3Anton Korobeynikov      MCSymbol *SaveLabel = MF->getContext().CreateTempSymbol();
302cd775ceff0b25a0b026f643a7990c2924bd310a3Anton Korobeynikov      BuildMI(MBB, MI, DL, TII.get(XCore::PROLOG_LABEL)).addSym(SaveLabel);
303cd775ceff0b25a0b026f643a7990c2924bd310a3Anton Korobeynikov      XFI->getSpillLabels().push_back(std::make_pair(SaveLabel, *it));
304cd775ceff0b25a0b026f643a7990c2924bd310a3Anton Korobeynikov    }
305cd775ceff0b25a0b026f643a7990c2924bd310a3Anton Korobeynikov  }
306cd775ceff0b25a0b026f643a7990c2924bd310a3Anton Korobeynikov  return true;
307cd775ceff0b25a0b026f643a7990c2924bd310a3Anton Korobeynikov}
308cd775ceff0b25a0b026f643a7990c2924bd310a3Anton Korobeynikov
30916c29b5f285f375be53dabaa73e3e91107485fe4Anton Korobeynikovbool XCoreFrameLowering::restoreCalleeSavedRegisters(MachineBasicBlock &MBB,
310cd775ceff0b25a0b026f643a7990c2924bd310a3Anton Korobeynikov                                                 MachineBasicBlock::iterator MI,
311cd775ceff0b25a0b026f643a7990c2924bd310a3Anton Korobeynikov                                        const std::vector<CalleeSavedInfo> &CSI,
312cd775ceff0b25a0b026f643a7990c2924bd310a3Anton Korobeynikov                                            const TargetRegisterInfo *TRI) const{
313cd775ceff0b25a0b026f643a7990c2924bd310a3Anton Korobeynikov  MachineFunction *MF = MBB.getParent();
314cd775ceff0b25a0b026f643a7990c2924bd310a3Anton Korobeynikov  const TargetInstrInfo &TII = *MF->getTarget().getInstrInfo();
315cd775ceff0b25a0b026f643a7990c2924bd310a3Anton Korobeynikov
316cd775ceff0b25a0b026f643a7990c2924bd310a3Anton Korobeynikov  bool AtStart = MI == MBB.begin();
317cd775ceff0b25a0b026f643a7990c2924bd310a3Anton Korobeynikov  MachineBasicBlock::iterator BeforeI = MI;
318cd775ceff0b25a0b026f643a7990c2924bd310a3Anton Korobeynikov  if (!AtStart)
319cd775ceff0b25a0b026f643a7990c2924bd310a3Anton Korobeynikov    --BeforeI;
320cd775ceff0b25a0b026f643a7990c2924bd310a3Anton Korobeynikov  for (std::vector<CalleeSavedInfo>::const_iterator it = CSI.begin();
321cd775ceff0b25a0b026f643a7990c2924bd310a3Anton Korobeynikov                                                    it != CSI.end(); ++it) {
322cd775ceff0b25a0b026f643a7990c2924bd310a3Anton Korobeynikov    unsigned Reg = it->getReg();
323cd775ceff0b25a0b026f643a7990c2924bd310a3Anton Korobeynikov    const TargetRegisterClass *RC = TRI->getMinimalPhysRegClass(Reg);
324cd775ceff0b25a0b026f643a7990c2924bd310a3Anton Korobeynikov    TII.loadRegFromStackSlot(MBB, MI, it->getReg(), it->getFrameIdx(),
325cd775ceff0b25a0b026f643a7990c2924bd310a3Anton Korobeynikov                             RC, TRI);
326cd775ceff0b25a0b026f643a7990c2924bd310a3Anton Korobeynikov    assert(MI != MBB.begin() &&
327cd775ceff0b25a0b026f643a7990c2924bd310a3Anton Korobeynikov           "loadRegFromStackSlot didn't insert any code!");
328cd775ceff0b25a0b026f643a7990c2924bd310a3Anton Korobeynikov    // Insert in reverse order.  loadRegFromStackSlot can insert multiple
329cd775ceff0b25a0b026f643a7990c2924bd310a3Anton Korobeynikov    // instructions.
330cd775ceff0b25a0b026f643a7990c2924bd310a3Anton Korobeynikov    if (AtStart)
331cd775ceff0b25a0b026f643a7990c2924bd310a3Anton Korobeynikov      MI = MBB.begin();
332cd775ceff0b25a0b026f643a7990c2924bd310a3Anton Korobeynikov    else {
333cd775ceff0b25a0b026f643a7990c2924bd310a3Anton Korobeynikov      MI = BeforeI;
334cd775ceff0b25a0b026f643a7990c2924bd310a3Anton Korobeynikov      ++MI;
335cd775ceff0b25a0b026f643a7990c2924bd310a3Anton Korobeynikov    }
336cd775ceff0b25a0b026f643a7990c2924bd310a3Anton Korobeynikov  }
337cd775ceff0b25a0b026f643a7990c2924bd310a3Anton Korobeynikov  return true;
338cd775ceff0b25a0b026f643a7990c2924bd310a3Anton Korobeynikov}
33994c5ae08750f314bc3cf1bf882b686244a3927d9Anton Korobeynikov
34094c5ae08750f314bc3cf1bf882b686244a3927d9Anton Korobeynikovvoid
34116c29b5f285f375be53dabaa73e3e91107485fe4Anton KorobeynikovXCoreFrameLowering::processFunctionBeforeCalleeSavedScan(MachineFunction &MF,
34294c5ae08750f314bc3cf1bf882b686244a3927d9Anton Korobeynikov                                                     RegScavenger *RS) const {
34394c5ae08750f314bc3cf1bf882b686244a3927d9Anton Korobeynikov  MachineFrameInfo *MFI = MF.getFrameInfo();
34494c5ae08750f314bc3cf1bf882b686244a3927d9Anton Korobeynikov  const TargetRegisterInfo *RegInfo = MF.getTarget().getRegisterInfo();
34594c5ae08750f314bc3cf1bf882b686244a3927d9Anton Korobeynikov  bool LRUsed = MF.getRegInfo().isPhysRegUsed(XCore::LR);
34694c5ae08750f314bc3cf1bf882b686244a3927d9Anton Korobeynikov  const TargetRegisterClass *RC = XCore::GRRegsRegisterClass;
34794c5ae08750f314bc3cf1bf882b686244a3927d9Anton Korobeynikov  XCoreFunctionInfo *XFI = MF.getInfo<XCoreFunctionInfo>();
34894c5ae08750f314bc3cf1bf882b686244a3927d9Anton Korobeynikov  if (LRUsed) {
34994c5ae08750f314bc3cf1bf882b686244a3927d9Anton Korobeynikov    MF.getRegInfo().setPhysRegUnused(XCore::LR);
35094c5ae08750f314bc3cf1bf882b686244a3927d9Anton Korobeynikov
35194c5ae08750f314bc3cf1bf882b686244a3927d9Anton Korobeynikov    bool isVarArg = MF.getFunction()->isVarArg();
35294c5ae08750f314bc3cf1bf882b686244a3927d9Anton Korobeynikov    int FrameIdx;
35394c5ae08750f314bc3cf1bf882b686244a3927d9Anton Korobeynikov    if (! isVarArg) {
35494c5ae08750f314bc3cf1bf882b686244a3927d9Anton Korobeynikov      // A fixed offset of 0 allows us to save / restore LR using entsp / retsp.
35594c5ae08750f314bc3cf1bf882b686244a3927d9Anton Korobeynikov      FrameIdx = MFI->CreateFixedObject(RC->getSize(), 0, true);
35694c5ae08750f314bc3cf1bf882b686244a3927d9Anton Korobeynikov    } else {
35794c5ae08750f314bc3cf1bf882b686244a3927d9Anton Korobeynikov      FrameIdx = MFI->CreateStackObject(RC->getSize(), RC->getAlignment(),
35894c5ae08750f314bc3cf1bf882b686244a3927d9Anton Korobeynikov                                        false);
35994c5ae08750f314bc3cf1bf882b686244a3927d9Anton Korobeynikov    }
36094c5ae08750f314bc3cf1bf882b686244a3927d9Anton Korobeynikov    XFI->setUsesLR(FrameIdx);
36194c5ae08750f314bc3cf1bf882b686244a3927d9Anton Korobeynikov    XFI->setLRSpillSlot(FrameIdx);
36294c5ae08750f314bc3cf1bf882b686244a3927d9Anton Korobeynikov  }
36394c5ae08750f314bc3cf1bf882b686244a3927d9Anton Korobeynikov  if (RegInfo->requiresRegisterScavenging(MF)) {
36494c5ae08750f314bc3cf1bf882b686244a3927d9Anton Korobeynikov    // Reserve a slot close to SP or frame pointer.
36594c5ae08750f314bc3cf1bf882b686244a3927d9Anton Korobeynikov    RS->setScavengingFrameIndex(MFI->CreateStackObject(RC->getSize(),
36694c5ae08750f314bc3cf1bf882b686244a3927d9Anton Korobeynikov                                                       RC->getAlignment(),
36794c5ae08750f314bc3cf1bf882b686244a3927d9Anton Korobeynikov                                                       false));
36894c5ae08750f314bc3cf1bf882b686244a3927d9Anton Korobeynikov  }
36994c5ae08750f314bc3cf1bf882b686244a3927d9Anton Korobeynikov  if (hasFP(MF)) {
37094c5ae08750f314bc3cf1bf882b686244a3927d9Anton Korobeynikov    // A callee save register is used to hold the FP.
37194c5ae08750f314bc3cf1bf882b686244a3927d9Anton Korobeynikov    // This needs saving / restoring in the epilogue / prologue.
37294c5ae08750f314bc3cf1bf882b686244a3927d9Anton Korobeynikov    XFI->setFPSpillSlot(MFI->CreateStackObject(RC->getSize(),
37394c5ae08750f314bc3cf1bf882b686244a3927d9Anton Korobeynikov                                               RC->getAlignment(),
37494c5ae08750f314bc3cf1bf882b686244a3927d9Anton Korobeynikov                                               false));
37594c5ae08750f314bc3cf1bf882b686244a3927d9Anton Korobeynikov  }
37694c5ae08750f314bc3cf1bf882b686244a3927d9Anton Korobeynikov}
37794c5ae08750f314bc3cf1bf882b686244a3927d9Anton Korobeynikov
37816c29b5f285f375be53dabaa73e3e91107485fe4Anton Korobeynikovvoid XCoreFrameLowering::
37994c5ae08750f314bc3cf1bf882b686244a3927d9Anton KorobeynikovprocessFunctionBeforeFrameFinalized(MachineFunction &MF) const {
38094c5ae08750f314bc3cf1bf882b686244a3927d9Anton Korobeynikov
38194c5ae08750f314bc3cf1bf882b686244a3927d9Anton Korobeynikov}
382