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