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