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/CodeGen/MachineFrameInfo.h" 20 #include "llvm/CodeGen/MachineFunction.h" 21 #include "llvm/CodeGen/MachineInstrBuilder.h" 22 #include "llvm/CodeGen/MachineModuleInfo.h" 23 #include "llvm/CodeGen/MachineRegisterInfo.h" 24 #include "llvm/CodeGen/RegisterScavenging.h" 25 #include "llvm/IR/DataLayout.h" 26 #include "llvm/IR/Function.h" 27 #include "llvm/Support/ErrorHandling.h" 28 #include "llvm/Target/TargetOptions.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 // Do nothing 83 } 84 85 bool XCoreFrameLowering::hasFP(const MachineFunction &MF) const { 86 return MF.getTarget().Options.DisableFramePointerElim(MF) || 87 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 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 const AttributeSet &PAL = MF.getFunction()->getAttributes(); 102 103 if (PAL.hasAttrSomewhere(Attribute::Nest)) 104 loadFromStack(MBB, MBBI, XCore::R11, 0, dl, TII); 105 106 // Work out frame sizes. 107 int FrameSize = MFI->getStackSize(); 108 assert(FrameSize%4 == 0 && "Misaligned frame size"); 109 FrameSize/=4; 110 111 bool isU6 = isImmU6(FrameSize); 112 113 if (!isU6 && !isImmU16(FrameSize)) { 114 // FIXME could emit multiple instructions. 115 report_fatal_error("emitPrologue Frame size too big: " + Twine(FrameSize)); 116 } 117 bool emitFrameMoves = XCoreRegisterInfo::needsFrameMoves(MF); 118 119 // Do we need to allocate space on the stack? 120 if (FrameSize) { 121 bool saveLR = XFI->getUsesLR(); 122 bool LRSavedOnEntry = false; 123 int Opcode; 124 if (saveLR && (MFI->getObjectOffset(XFI->getLRSpillSlot()) == 0)) { 125 Opcode = (isU6) ? XCore::ENTSP_u6 : XCore::ENTSP_lu6; 126 MBB.addLiveIn(XCore::LR); 127 saveLR = false; 128 LRSavedOnEntry = true; 129 } else { 130 Opcode = (isU6) ? XCore::EXTSP_u6 : XCore::EXTSP_lu6; 131 } 132 BuildMI(MBB, MBBI, dl, TII.get(Opcode)).addImm(FrameSize); 133 134 if (emitFrameMoves) { 135 std::vector<MachineMove> &Moves = MMI->getFrameMoves(); 136 137 // Show update of SP. 138 MCSymbol *FrameLabel = MMI->getContext().CreateTempSymbol(); 139 BuildMI(MBB, MBBI, dl, TII.get(XCore::PROLOG_LABEL)).addSym(FrameLabel); 140 141 MachineLocation SPDst(MachineLocation::VirtualFP); 142 MachineLocation SPSrc(MachineLocation::VirtualFP, -FrameSize * 4); 143 Moves.push_back(MachineMove(FrameLabel, SPDst, SPSrc)); 144 145 if (LRSavedOnEntry) { 146 MachineLocation CSDst(MachineLocation::VirtualFP, 0); 147 MachineLocation CSSrc(XCore::LR); 148 Moves.push_back(MachineMove(FrameLabel, CSDst, CSSrc)); 149 } 150 } 151 if (saveLR) { 152 int LRSpillOffset = MFI->getObjectOffset(XFI->getLRSpillSlot()); 153 storeToStack(MBB, MBBI, XCore::LR, LRSpillOffset + FrameSize*4, dl, TII); 154 MBB.addLiveIn(XCore::LR); 155 156 if (emitFrameMoves) { 157 MCSymbol *SaveLRLabel = MMI->getContext().CreateTempSymbol(); 158 BuildMI(MBB, MBBI, dl, TII.get(XCore::PROLOG_LABEL)).addSym(SaveLRLabel); 159 MachineLocation CSDst(MachineLocation::VirtualFP, LRSpillOffset); 160 MachineLocation CSSrc(XCore::LR); 161 MMI->getFrameMoves().push_back(MachineMove(SaveLRLabel, CSDst, CSSrc)); 162 } 163 } 164 } 165 166 if (FP) { 167 // Save R10 to the stack. 168 int FPSpillOffset = MFI->getObjectOffset(XFI->getFPSpillSlot()); 169 storeToStack(MBB, MBBI, XCore::R10, FPSpillOffset + FrameSize*4, dl, TII); 170 // R10 is live-in. It is killed at the spill. 171 MBB.addLiveIn(XCore::R10); 172 if (emitFrameMoves) { 173 MCSymbol *SaveR10Label = MMI->getContext().CreateTempSymbol(); 174 BuildMI(MBB, MBBI, dl, TII.get(XCore::PROLOG_LABEL)).addSym(SaveR10Label); 175 MachineLocation CSDst(MachineLocation::VirtualFP, FPSpillOffset); 176 MachineLocation CSSrc(XCore::R10); 177 MMI->getFrameMoves().push_back(MachineMove(SaveR10Label, CSDst, CSSrc)); 178 } 179 // Set the FP from the SP. 180 unsigned FramePtr = XCore::R10; 181 BuildMI(MBB, MBBI, dl, TII.get(XCore::LDAWSP_ru6), FramePtr) 182 .addImm(0); 183 if (emitFrameMoves) { 184 // Show FP is now valid. 185 MCSymbol *FrameLabel = MMI->getContext().CreateTempSymbol(); 186 BuildMI(MBB, MBBI, dl, TII.get(XCore::PROLOG_LABEL)).addSym(FrameLabel); 187 MachineLocation SPDst(FramePtr); 188 MachineLocation SPSrc(MachineLocation::VirtualFP); 189 MMI->getFrameMoves().push_back(MachineMove(FrameLabel, SPDst, SPSrc)); 190 } 191 } 192 193 if (emitFrameMoves) { 194 // Frame moves for callee saved. 195 std::vector<MachineMove> &Moves = MMI->getFrameMoves(); 196 std::vector<std::pair<MCSymbol*, CalleeSavedInfo> >&SpillLabels = 197 XFI->getSpillLabels(); 198 for (unsigned I = 0, E = SpillLabels.size(); I != E; ++I) { 199 MCSymbol *SpillLabel = SpillLabels[I].first; 200 CalleeSavedInfo &CSI = SpillLabels[I].second; 201 int Offset = MFI->getObjectOffset(CSI.getFrameIdx()); 202 unsigned Reg = CSI.getReg(); 203 MachineLocation CSDst(MachineLocation::VirtualFP, Offset); 204 MachineLocation CSSrc(Reg); 205 Moves.push_back(MachineMove(SpillLabel, CSDst, CSSrc)); 206 } 207 } 208 } 209 210 void XCoreFrameLowering::emitEpilogue(MachineFunction &MF, 211 MachineBasicBlock &MBB) const { 212 MachineFrameInfo *MFI = MF.getFrameInfo(); 213 MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr(); 214 const XCoreInstrInfo &TII = 215 *static_cast<const XCoreInstrInfo*>(MF.getTarget().getInstrInfo()); 216 DebugLoc dl = MBBI->getDebugLoc(); 217 218 bool FP = hasFP(MF); 219 if (FP) { 220 // Restore the stack pointer. 221 unsigned FramePtr = XCore::R10; 222 BuildMI(MBB, MBBI, dl, TII.get(XCore::SETSP_1r)) 223 .addReg(FramePtr); 224 } 225 226 // Work out frame sizes. 227 int FrameSize = MFI->getStackSize(); 228 229 assert(FrameSize%4 == 0 && "Misaligned frame size"); 230 231 FrameSize/=4; 232 233 bool isU6 = isImmU6(FrameSize); 234 235 if (!isU6 && !isImmU16(FrameSize)) { 236 // FIXME could emit multiple instructions. 237 report_fatal_error("emitEpilogue Frame size too big: " + Twine(FrameSize)); 238 } 239 240 if (FrameSize) { 241 XCoreFunctionInfo *XFI = MF.getInfo<XCoreFunctionInfo>(); 242 243 if (FP) { 244 // Restore R10 245 int FPSpillOffset = MFI->getObjectOffset(XFI->getFPSpillSlot()); 246 FPSpillOffset += FrameSize*4; 247 loadFromStack(MBB, MBBI, XCore::R10, FPSpillOffset, dl, TII); 248 } 249 bool restoreLR = XFI->getUsesLR(); 250 if (restoreLR && MFI->getObjectOffset(XFI->getLRSpillSlot()) != 0) { 251 int LRSpillOffset = MFI->getObjectOffset(XFI->getLRSpillSlot()); 252 LRSpillOffset += FrameSize*4; 253 loadFromStack(MBB, MBBI, XCore::LR, LRSpillOffset, dl, TII); 254 restoreLR = false; 255 } 256 if (restoreLR) { 257 // Fold prologue into return instruction 258 assert(MBBI->getOpcode() == XCore::RETSP_u6 259 || MBBI->getOpcode() == XCore::RETSP_lu6); 260 int Opcode = (isU6) ? XCore::RETSP_u6 : XCore::RETSP_lu6; 261 BuildMI(MBB, MBBI, dl, TII.get(Opcode)).addImm(FrameSize); 262 MBB.erase(MBBI); 263 } else { 264 int Opcode = (isU6) ? XCore::LDAWSP_ru6_RRegs : XCore::LDAWSP_lru6_RRegs; 265 BuildMI(MBB, MBBI, dl, TII.get(Opcode), XCore::SP).addImm(FrameSize); 266 } 267 } 268 } 269 270 bool XCoreFrameLowering::spillCalleeSavedRegisters(MachineBasicBlock &MBB, 271 MachineBasicBlock::iterator MI, 272 const std::vector<CalleeSavedInfo> &CSI, 273 const TargetRegisterInfo *TRI) const { 274 if (CSI.empty()) 275 return true; 276 277 MachineFunction *MF = MBB.getParent(); 278 const TargetInstrInfo &TII = *MF->getTarget().getInstrInfo(); 279 280 XCoreFunctionInfo *XFI = MF->getInfo<XCoreFunctionInfo>(); 281 bool emitFrameMoves = XCoreRegisterInfo::needsFrameMoves(*MF); 282 283 DebugLoc DL; 284 if (MI != MBB.end()) DL = MI->getDebugLoc(); 285 286 for (std::vector<CalleeSavedInfo>::const_iterator it = CSI.begin(); 287 it != CSI.end(); ++it) { 288 // Add the callee-saved register as live-in. It's killed at the spill. 289 MBB.addLiveIn(it->getReg()); 290 291 unsigned Reg = it->getReg(); 292 const TargetRegisterClass *RC = TRI->getMinimalPhysRegClass(Reg); 293 TII.storeRegToStackSlot(MBB, MI, Reg, true, 294 it->getFrameIdx(), RC, TRI); 295 if (emitFrameMoves) { 296 MCSymbol *SaveLabel = MF->getContext().CreateTempSymbol(); 297 BuildMI(MBB, MI, DL, TII.get(XCore::PROLOG_LABEL)).addSym(SaveLabel); 298 XFI->getSpillLabels().push_back(std::make_pair(SaveLabel, *it)); 299 } 300 } 301 return true; 302 } 303 304 bool XCoreFrameLowering::restoreCalleeSavedRegisters(MachineBasicBlock &MBB, 305 MachineBasicBlock::iterator MI, 306 const std::vector<CalleeSavedInfo> &CSI, 307 const TargetRegisterInfo *TRI) const{ 308 MachineFunction *MF = MBB.getParent(); 309 const TargetInstrInfo &TII = *MF->getTarget().getInstrInfo(); 310 311 bool AtStart = MI == MBB.begin(); 312 MachineBasicBlock::iterator BeforeI = MI; 313 if (!AtStart) 314 --BeforeI; 315 for (std::vector<CalleeSavedInfo>::const_iterator it = CSI.begin(); 316 it != CSI.end(); ++it) { 317 unsigned Reg = it->getReg(); 318 const TargetRegisterClass *RC = TRI->getMinimalPhysRegClass(Reg); 319 TII.loadRegFromStackSlot(MBB, MI, it->getReg(), it->getFrameIdx(), 320 RC, TRI); 321 assert(MI != MBB.begin() && 322 "loadRegFromStackSlot didn't insert any code!"); 323 // Insert in reverse order. loadRegFromStackSlot can insert multiple 324 // instructions. 325 if (AtStart) 326 MI = MBB.begin(); 327 else { 328 MI = BeforeI; 329 ++MI; 330 } 331 } 332 return true; 333 } 334 335 // This function eliminates ADJCALLSTACKDOWN, 336 // ADJCALLSTACKUP pseudo instructions 337 void XCoreFrameLowering:: 338 eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB, 339 MachineBasicBlock::iterator I) const { 340 const XCoreInstrInfo &TII = 341 *static_cast<const XCoreInstrInfo*>(MF.getTarget().getInstrInfo()); 342 if (!hasReservedCallFrame(MF)) { 343 // Turn the adjcallstackdown instruction into 'extsp <amt>' and the 344 // adjcallstackup instruction into 'ldaw sp, sp[<amt>]' 345 MachineInstr *Old = I; 346 uint64_t Amount = Old->getOperand(0).getImm(); 347 if (Amount != 0) { 348 // We need to keep the stack aligned properly. To do this, we round the 349 // amount of space needed for the outgoing arguments up to the next 350 // alignment boundary. 351 unsigned Align = getStackAlignment(); 352 Amount = (Amount+Align-1)/Align*Align; 353 354 assert(Amount%4 == 0); 355 Amount /= 4; 356 357 bool isU6 = isImmU6(Amount); 358 if (!isU6 && !isImmU16(Amount)) { 359 // FIX could emit multiple instructions in this case. 360 #ifndef NDEBUG 361 errs() << "eliminateCallFramePseudoInstr size too big: " 362 << Amount << "\n"; 363 #endif 364 llvm_unreachable(0); 365 } 366 367 MachineInstr *New; 368 if (Old->getOpcode() == XCore::ADJCALLSTACKDOWN) { 369 int Opcode = isU6 ? XCore::EXTSP_u6 : XCore::EXTSP_lu6; 370 New=BuildMI(MF, Old->getDebugLoc(), TII.get(Opcode)) 371 .addImm(Amount); 372 } else { 373 assert(Old->getOpcode() == XCore::ADJCALLSTACKUP); 374 int Opcode = isU6 ? XCore::LDAWSP_ru6_RRegs : XCore::LDAWSP_lru6_RRegs; 375 New=BuildMI(MF, Old->getDebugLoc(), TII.get(Opcode), XCore::SP) 376 .addImm(Amount); 377 } 378 379 // Replace the pseudo instruction with a new instruction... 380 MBB.insert(I, New); 381 } 382 } 383 384 MBB.erase(I); 385 } 386 387 void 388 XCoreFrameLowering::processFunctionBeforeCalleeSavedScan(MachineFunction &MF, 389 RegScavenger *RS) const { 390 MachineFrameInfo *MFI = MF.getFrameInfo(); 391 const TargetRegisterInfo *RegInfo = MF.getTarget().getRegisterInfo(); 392 bool LRUsed = MF.getRegInfo().isPhysRegUsed(XCore::LR); 393 const TargetRegisterClass *RC = &XCore::GRRegsRegClass; 394 XCoreFunctionInfo *XFI = MF.getInfo<XCoreFunctionInfo>(); 395 if (LRUsed) { 396 MF.getRegInfo().setPhysRegUnused(XCore::LR); 397 398 bool isVarArg = MF.getFunction()->isVarArg(); 399 int FrameIdx; 400 if (! isVarArg) { 401 // A fixed offset of 0 allows us to save / restore LR using entsp / retsp. 402 FrameIdx = MFI->CreateFixedObject(RC->getSize(), 0, true); 403 } else { 404 FrameIdx = MFI->CreateStackObject(RC->getSize(), RC->getAlignment(), 405 false); 406 } 407 XFI->setUsesLR(FrameIdx); 408 XFI->setLRSpillSlot(FrameIdx); 409 } 410 if (RegInfo->requiresRegisterScavenging(MF)) { 411 // Reserve a slot close to SP or frame pointer. 412 RS->setScavengingFrameIndex(MFI->CreateStackObject(RC->getSize(), 413 RC->getAlignment(), 414 false)); 415 } 416 if (hasFP(MF)) { 417 // A callee save register is used to hold the FP. 418 // This needs saving / restoring in the epilogue / prologue. 419 XFI->setFPSpillSlot(MFI->CreateStackObject(RC->getSize(), 420 RC->getAlignment(), 421 false)); 422 } 423 } 424