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