XCoreFrameLowering.cpp revision 239462
1//===-- XCoreFrameLowering.cpp - Frame info for XCore Target --------------===// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file is distributed under the University of Illinois Open Source 6// License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9// 10// This file contains XCore frame information that doesn't fit anywhere else 11// cleanly... 12// 13//===----------------------------------------------------------------------===// 14 15#include "XCoreFrameLowering.h" 16#include "XCore.h" 17#include "XCoreInstrInfo.h" 18#include "XCoreMachineFunctionInfo.h" 19#include "llvm/Function.h" 20#include "llvm/CodeGen/MachineFrameInfo.h" 21#include "llvm/CodeGen/MachineFunction.h" 22#include "llvm/CodeGen/MachineInstrBuilder.h" 23#include "llvm/CodeGen/MachineModuleInfo.h" 24#include "llvm/CodeGen/MachineRegisterInfo.h" 25#include "llvm/CodeGen/RegisterScavenging.h" 26#include "llvm/Target/TargetData.h" 27#include "llvm/Target/TargetOptions.h" 28#include "llvm/Support/ErrorHandling.h" 29 30using namespace llvm; 31 32// helper functions. FIXME: Eliminate. 33static inline bool isImmUs(unsigned val) { 34 return val <= 11; 35} 36 37static inline bool isImmU6(unsigned val) { 38 return val < (1 << 6); 39} 40 41static inline bool isImmU16(unsigned val) { 42 return val < (1 << 16); 43} 44 45static void loadFromStack(MachineBasicBlock &MBB, 46 MachineBasicBlock::iterator I, 47 unsigned DstReg, int Offset, DebugLoc dl, 48 const TargetInstrInfo &TII) { 49 assert(Offset%4 == 0 && "Misaligned stack offset"); 50 Offset/=4; 51 bool isU6 = isImmU6(Offset); 52 if (!isU6 && !isImmU16(Offset)) 53 report_fatal_error("loadFromStack offset too big " + Twine(Offset)); 54 int Opcode = isU6 ? XCore::LDWSP_ru6 : XCore::LDWSP_lru6; 55 BuildMI(MBB, I, dl, TII.get(Opcode), DstReg) 56 .addImm(Offset); 57} 58 59 60static void storeToStack(MachineBasicBlock &MBB, 61 MachineBasicBlock::iterator I, 62 unsigned SrcReg, int Offset, DebugLoc dl, 63 const TargetInstrInfo &TII) { 64 assert(Offset%4 == 0 && "Misaligned stack offset"); 65 Offset/=4; 66 bool isU6 = isImmU6(Offset); 67 if (!isU6 && !isImmU16(Offset)) 68 report_fatal_error("storeToStack offset too big " + Twine(Offset)); 69 int Opcode = isU6 ? XCore::STWSP_ru6 : XCore::STWSP_lru6; 70 BuildMI(MBB, I, dl, TII.get(Opcode)) 71 .addReg(SrcReg) 72 .addImm(Offset); 73} 74 75 76//===----------------------------------------------------------------------===// 77// XCoreFrameLowering: 78//===----------------------------------------------------------------------===// 79 80XCoreFrameLowering::XCoreFrameLowering(const XCoreSubtarget &sti) 81 : TargetFrameLowering(TargetFrameLowering::StackGrowsDown, 4, 0) { 82 // Do nothing 83} 84 85bool XCoreFrameLowering::hasFP(const MachineFunction &MF) const { 86 return MF.getTarget().Options.DisableFramePointerElim(MF) || 87 MF.getFrameInfo()->hasVarSizedObjects(); 88} 89 90void XCoreFrameLowering::emitPrologue(MachineFunction &MF) const { 91 MachineBasicBlock &MBB = MF.front(); // Prolog goes in entry BB 92 MachineBasicBlock::iterator MBBI = MBB.begin(); 93 MachineFrameInfo *MFI = MF.getFrameInfo(); 94 MachineModuleInfo *MMI = &MF.getMMI(); 95 const XCoreInstrInfo &TII = 96 *static_cast<const XCoreInstrInfo*>(MF.getTarget().getInstrInfo()); 97 XCoreFunctionInfo *XFI = MF.getInfo<XCoreFunctionInfo>(); 98 DebugLoc dl = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc(); 99 100 bool FP = hasFP(MF); 101 bool Nested = MF.getFunction()-> 102 getAttributes().hasAttrSomewhere(Attribute::Nest); 103 104 if (Nested) { 105 loadFromStack(MBB, MBBI, XCore::R11, 0, dl, TII); 106 } 107 108 // Work out frame sizes. 109 int FrameSize = MFI->getStackSize(); 110 assert(FrameSize%4 == 0 && "Misaligned frame size"); 111 FrameSize/=4; 112 113 bool isU6 = isImmU6(FrameSize); 114 115 if (!isU6 && !isImmU16(FrameSize)) { 116 // FIXME could emit multiple instructions. 117 report_fatal_error("emitPrologue Frame size too big: " + Twine(FrameSize)); 118 } 119 bool emitFrameMoves = XCoreRegisterInfo::needsFrameMoves(MF); 120 121 // Do we need to allocate space on the stack? 122 if (FrameSize) { 123 bool saveLR = XFI->getUsesLR(); 124 bool LRSavedOnEntry = false; 125 int Opcode; 126 if (saveLR && (MFI->getObjectOffset(XFI->getLRSpillSlot()) == 0)) { 127 Opcode = (isU6) ? XCore::ENTSP_u6 : XCore::ENTSP_lu6; 128 MBB.addLiveIn(XCore::LR); 129 saveLR = false; 130 LRSavedOnEntry = true; 131 } else { 132 Opcode = (isU6) ? XCore::EXTSP_u6 : XCore::EXTSP_lu6; 133 } 134 BuildMI(MBB, MBBI, dl, TII.get(Opcode)).addImm(FrameSize); 135 136 if (emitFrameMoves) { 137 std::vector<MachineMove> &Moves = MMI->getFrameMoves(); 138 139 // Show update of SP. 140 MCSymbol *FrameLabel = MMI->getContext().CreateTempSymbol(); 141 BuildMI(MBB, MBBI, dl, TII.get(XCore::PROLOG_LABEL)).addSym(FrameLabel); 142 143 MachineLocation SPDst(MachineLocation::VirtualFP); 144 MachineLocation SPSrc(MachineLocation::VirtualFP, -FrameSize * 4); 145 Moves.push_back(MachineMove(FrameLabel, SPDst, SPSrc)); 146 147 if (LRSavedOnEntry) { 148 MachineLocation CSDst(MachineLocation::VirtualFP, 0); 149 MachineLocation CSSrc(XCore::LR); 150 Moves.push_back(MachineMove(FrameLabel, CSDst, CSSrc)); 151 } 152 } 153 if (saveLR) { 154 int LRSpillOffset = MFI->getObjectOffset(XFI->getLRSpillSlot()); 155 storeToStack(MBB, MBBI, XCore::LR, LRSpillOffset + FrameSize*4, dl, TII); 156 MBB.addLiveIn(XCore::LR); 157 158 if (emitFrameMoves) { 159 MCSymbol *SaveLRLabel = MMI->getContext().CreateTempSymbol(); 160 BuildMI(MBB, MBBI, dl, TII.get(XCore::PROLOG_LABEL)).addSym(SaveLRLabel); 161 MachineLocation CSDst(MachineLocation::VirtualFP, LRSpillOffset); 162 MachineLocation CSSrc(XCore::LR); 163 MMI->getFrameMoves().push_back(MachineMove(SaveLRLabel, CSDst, CSSrc)); 164 } 165 } 166 } 167 168 if (FP) { 169 // Save R10 to the stack. 170 int FPSpillOffset = MFI->getObjectOffset(XFI->getFPSpillSlot()); 171 storeToStack(MBB, MBBI, XCore::R10, FPSpillOffset + FrameSize*4, dl, TII); 172 // R10 is live-in. It is killed at the spill. 173 MBB.addLiveIn(XCore::R10); 174 if (emitFrameMoves) { 175 MCSymbol *SaveR10Label = MMI->getContext().CreateTempSymbol(); 176 BuildMI(MBB, MBBI, dl, TII.get(XCore::PROLOG_LABEL)).addSym(SaveR10Label); 177 MachineLocation CSDst(MachineLocation::VirtualFP, FPSpillOffset); 178 MachineLocation CSSrc(XCore::R10); 179 MMI->getFrameMoves().push_back(MachineMove(SaveR10Label, CSDst, CSSrc)); 180 } 181 // Set the FP from the SP. 182 unsigned FramePtr = XCore::R10; 183 BuildMI(MBB, MBBI, dl, TII.get(XCore::LDAWSP_ru6), FramePtr) 184 .addImm(0); 185 if (emitFrameMoves) { 186 // Show FP is now valid. 187 MCSymbol *FrameLabel = MMI->getContext().CreateTempSymbol(); 188 BuildMI(MBB, MBBI, dl, TII.get(XCore::PROLOG_LABEL)).addSym(FrameLabel); 189 MachineLocation SPDst(FramePtr); 190 MachineLocation SPSrc(MachineLocation::VirtualFP); 191 MMI->getFrameMoves().push_back(MachineMove(FrameLabel, SPDst, SPSrc)); 192 } 193 } 194 195 if (emitFrameMoves) { 196 // Frame moves for callee saved. 197 std::vector<MachineMove> &Moves = MMI->getFrameMoves(); 198 std::vector<std::pair<MCSymbol*, CalleeSavedInfo> >&SpillLabels = 199 XFI->getSpillLabels(); 200 for (unsigned I = 0, E = SpillLabels.size(); I != E; ++I) { 201 MCSymbol *SpillLabel = SpillLabels[I].first; 202 CalleeSavedInfo &CSI = SpillLabels[I].second; 203 int Offset = MFI->getObjectOffset(CSI.getFrameIdx()); 204 unsigned Reg = CSI.getReg(); 205 MachineLocation CSDst(MachineLocation::VirtualFP, Offset); 206 MachineLocation CSSrc(Reg); 207 Moves.push_back(MachineMove(SpillLabel, CSDst, CSSrc)); 208 } 209 } 210} 211 212void XCoreFrameLowering::emitEpilogue(MachineFunction &MF, 213 MachineBasicBlock &MBB) const { 214 MachineFrameInfo *MFI = MF.getFrameInfo(); 215 MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr(); 216 const XCoreInstrInfo &TII = 217 *static_cast<const XCoreInstrInfo*>(MF.getTarget().getInstrInfo()); 218 DebugLoc dl = MBBI->getDebugLoc(); 219 220 bool FP = hasFP(MF); 221 if (FP) { 222 // Restore the stack pointer. 223 unsigned FramePtr = XCore::R10; 224 BuildMI(MBB, MBBI, dl, TII.get(XCore::SETSP_1r)) 225 .addReg(FramePtr); 226 } 227 228 // Work out frame sizes. 229 int FrameSize = MFI->getStackSize(); 230 231 assert(FrameSize%4 == 0 && "Misaligned frame size"); 232 233 FrameSize/=4; 234 235 bool isU6 = isImmU6(FrameSize); 236 237 if (!isU6 && !isImmU16(FrameSize)) { 238 // FIXME could emit multiple instructions. 239 report_fatal_error("emitEpilogue Frame size too big: " + Twine(FrameSize)); 240 } 241 242 if (FrameSize) { 243 XCoreFunctionInfo *XFI = MF.getInfo<XCoreFunctionInfo>(); 244 245 if (FP) { 246 // Restore R10 247 int FPSpillOffset = MFI->getObjectOffset(XFI->getFPSpillSlot()); 248 FPSpillOffset += FrameSize*4; 249 loadFromStack(MBB, MBBI, XCore::R10, FPSpillOffset, dl, TII); 250 } 251 bool restoreLR = XFI->getUsesLR(); 252 if (restoreLR && MFI->getObjectOffset(XFI->getLRSpillSlot()) != 0) { 253 int LRSpillOffset = MFI->getObjectOffset(XFI->getLRSpillSlot()); 254 LRSpillOffset += FrameSize*4; 255 loadFromStack(MBB, MBBI, XCore::LR, LRSpillOffset, dl, TII); 256 restoreLR = false; 257 } 258 if (restoreLR) { 259 // Fold prologue into return instruction 260 assert(MBBI->getOpcode() == XCore::RETSP_u6 261 || MBBI->getOpcode() == XCore::RETSP_lu6); 262 int Opcode = (isU6) ? XCore::RETSP_u6 : XCore::RETSP_lu6; 263 BuildMI(MBB, MBBI, dl, TII.get(Opcode)).addImm(FrameSize); 264 MBB.erase(MBBI); 265 } else { 266 int Opcode = (isU6) ? XCore::LDAWSP_ru6_RRegs : XCore::LDAWSP_lru6_RRegs; 267 BuildMI(MBB, MBBI, dl, TII.get(Opcode), XCore::SP).addImm(FrameSize); 268 } 269 } 270} 271 272bool XCoreFrameLowering::spillCalleeSavedRegisters(MachineBasicBlock &MBB, 273 MachineBasicBlock::iterator MI, 274 const std::vector<CalleeSavedInfo> &CSI, 275 const TargetRegisterInfo *TRI) const { 276 if (CSI.empty()) 277 return true; 278 279 MachineFunction *MF = MBB.getParent(); 280 const TargetInstrInfo &TII = *MF->getTarget().getInstrInfo(); 281 282 XCoreFunctionInfo *XFI = MF->getInfo<XCoreFunctionInfo>(); 283 bool emitFrameMoves = XCoreRegisterInfo::needsFrameMoves(*MF); 284 285 DebugLoc DL; 286 if (MI != MBB.end()) DL = MI->getDebugLoc(); 287 288 for (std::vector<CalleeSavedInfo>::const_iterator it = CSI.begin(); 289 it != CSI.end(); ++it) { 290 // Add the callee-saved register as live-in. It's killed at the spill. 291 MBB.addLiveIn(it->getReg()); 292 293 unsigned Reg = it->getReg(); 294 const TargetRegisterClass *RC = TRI->getMinimalPhysRegClass(Reg); 295 TII.storeRegToStackSlot(MBB, MI, Reg, true, 296 it->getFrameIdx(), RC, TRI); 297 if (emitFrameMoves) { 298 MCSymbol *SaveLabel = MF->getContext().CreateTempSymbol(); 299 BuildMI(MBB, MI, DL, TII.get(XCore::PROLOG_LABEL)).addSym(SaveLabel); 300 XFI->getSpillLabels().push_back(std::make_pair(SaveLabel, *it)); 301 } 302 } 303 return true; 304} 305 306bool XCoreFrameLowering::restoreCalleeSavedRegisters(MachineBasicBlock &MBB, 307 MachineBasicBlock::iterator MI, 308 const std::vector<CalleeSavedInfo> &CSI, 309 const TargetRegisterInfo *TRI) const{ 310 MachineFunction *MF = MBB.getParent(); 311 const TargetInstrInfo &TII = *MF->getTarget().getInstrInfo(); 312 313 bool AtStart = MI == MBB.begin(); 314 MachineBasicBlock::iterator BeforeI = MI; 315 if (!AtStart) 316 --BeforeI; 317 for (std::vector<CalleeSavedInfo>::const_iterator it = CSI.begin(); 318 it != CSI.end(); ++it) { 319 unsigned Reg = it->getReg(); 320 const TargetRegisterClass *RC = TRI->getMinimalPhysRegClass(Reg); 321 TII.loadRegFromStackSlot(MBB, MI, it->getReg(), it->getFrameIdx(), 322 RC, TRI); 323 assert(MI != MBB.begin() && 324 "loadRegFromStackSlot didn't insert any code!"); 325 // Insert in reverse order. loadRegFromStackSlot can insert multiple 326 // instructions. 327 if (AtStart) 328 MI = MBB.begin(); 329 else { 330 MI = BeforeI; 331 ++MI; 332 } 333 } 334 return true; 335} 336 337void 338XCoreFrameLowering::processFunctionBeforeCalleeSavedScan(MachineFunction &MF, 339 RegScavenger *RS) const { 340 MachineFrameInfo *MFI = MF.getFrameInfo(); 341 const TargetRegisterInfo *RegInfo = MF.getTarget().getRegisterInfo(); 342 bool LRUsed = MF.getRegInfo().isPhysRegUsed(XCore::LR); 343 const TargetRegisterClass *RC = &XCore::GRRegsRegClass; 344 XCoreFunctionInfo *XFI = MF.getInfo<XCoreFunctionInfo>(); 345 if (LRUsed) { 346 MF.getRegInfo().setPhysRegUnused(XCore::LR); 347 348 bool isVarArg = MF.getFunction()->isVarArg(); 349 int FrameIdx; 350 if (! isVarArg) { 351 // A fixed offset of 0 allows us to save / restore LR using entsp / retsp. 352 FrameIdx = MFI->CreateFixedObject(RC->getSize(), 0, true); 353 } else { 354 FrameIdx = MFI->CreateStackObject(RC->getSize(), RC->getAlignment(), 355 false); 356 } 357 XFI->setUsesLR(FrameIdx); 358 XFI->setLRSpillSlot(FrameIdx); 359 } 360 if (RegInfo->requiresRegisterScavenging(MF)) { 361 // Reserve a slot close to SP or frame pointer. 362 RS->setScavengingFrameIndex(MFI->CreateStackObject(RC->getSize(), 363 RC->getAlignment(), 364 false)); 365 } 366 if (hasFP(MF)) { 367 // A callee save register is used to hold the FP. 368 // This needs saving / restoring in the epilogue / prologue. 369 XFI->setFPSpillSlot(MFI->CreateStackObject(RC->getSize(), 370 RC->getAlignment(), 371 false)); 372 } 373} 374