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