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