LLVM API Documentation
00001 //===-- XCoreFrameLowering.cpp - Frame info for XCore Target --------------===// 00002 // 00003 // The LLVM Compiler Infrastructure 00004 // 00005 // This file is distributed under the University of Illinois Open Source 00006 // License. See LICENSE.TXT for details. 00007 // 00008 //===----------------------------------------------------------------------===// 00009 // 00010 // This file contains XCore frame information that doesn't fit anywhere else 00011 // cleanly... 00012 // 00013 //===----------------------------------------------------------------------===// 00014 00015 #include "XCoreFrameLowering.h" 00016 #include "XCore.h" 00017 #include "XCoreInstrInfo.h" 00018 #include "XCoreMachineFunctionInfo.h" 00019 #include "llvm/CodeGen/MachineFrameInfo.h" 00020 #include "llvm/CodeGen/MachineFunction.h" 00021 #include "llvm/CodeGen/MachineInstrBuilder.h" 00022 #include "llvm/CodeGen/MachineModuleInfo.h" 00023 #include "llvm/CodeGen/MachineRegisterInfo.h" 00024 #include "llvm/CodeGen/RegisterScavenging.h" 00025 #include "llvm/IR/DataLayout.h" 00026 #include "llvm/IR/Function.h" 00027 #include "llvm/Support/ErrorHandling.h" 00028 #include "llvm/Target/TargetOptions.h" 00029 00030 using namespace llvm; 00031 00032 // helper functions. FIXME: Eliminate. 00033 static inline bool isImmUs(unsigned val) { 00034 return val <= 11; 00035 } 00036 00037 static inline bool isImmU6(unsigned val) { 00038 return val < (1 << 6); 00039 } 00040 00041 static inline bool isImmU16(unsigned val) { 00042 return val < (1 << 16); 00043 } 00044 00045 static void loadFromStack(MachineBasicBlock &MBB, 00046 MachineBasicBlock::iterator I, 00047 unsigned DstReg, int Offset, DebugLoc dl, 00048 const TargetInstrInfo &TII) { 00049 assert(Offset%4 == 0 && "Misaligned stack offset"); 00050 Offset/=4; 00051 bool isU6 = isImmU6(Offset); 00052 if (!isU6 && !isImmU16(Offset)) 00053 report_fatal_error("loadFromStack offset too big " + Twine(Offset)); 00054 int Opcode = isU6 ? XCore::LDWSP_ru6 : XCore::LDWSP_lru6; 00055 BuildMI(MBB, I, dl, TII.get(Opcode), DstReg) 00056 .addImm(Offset); 00057 } 00058 00059 00060 static void storeToStack(MachineBasicBlock &MBB, 00061 MachineBasicBlock::iterator I, 00062 unsigned SrcReg, int Offset, DebugLoc dl, 00063 const TargetInstrInfo &TII) { 00064 assert(Offset%4 == 0 && "Misaligned stack offset"); 00065 Offset/=4; 00066 bool isU6 = isImmU6(Offset); 00067 if (!isU6 && !isImmU16(Offset)) 00068 report_fatal_error("storeToStack offset too big " + Twine(Offset)); 00069 int Opcode = isU6 ? XCore::STWSP_ru6 : XCore::STWSP_lru6; 00070 BuildMI(MBB, I, dl, TII.get(Opcode)) 00071 .addReg(SrcReg) 00072 .addImm(Offset); 00073 } 00074 00075 00076 //===----------------------------------------------------------------------===// 00077 // XCoreFrameLowering: 00078 //===----------------------------------------------------------------------===// 00079 00080 XCoreFrameLowering::XCoreFrameLowering(const XCoreSubtarget &sti) 00081 : TargetFrameLowering(TargetFrameLowering::StackGrowsDown, 4, 0) { 00082 // Do nothing 00083 } 00084 00085 bool XCoreFrameLowering::hasFP(const MachineFunction &MF) const { 00086 return MF.getTarget().Options.DisableFramePointerElim(MF) || 00087 MF.getFrameInfo()->hasVarSizedObjects(); 00088 } 00089 00090 void XCoreFrameLowering::emitPrologue(MachineFunction &MF) const { 00091 MachineBasicBlock &MBB = MF.front(); // Prolog goes in entry BB 00092 MachineBasicBlock::iterator MBBI = MBB.begin(); 00093 MachineFrameInfo *MFI = MF.getFrameInfo(); 00094 MachineModuleInfo *MMI = &MF.getMMI(); 00095 const XCoreInstrInfo &TII = 00096 *static_cast<const XCoreInstrInfo*>(MF.getTarget().getInstrInfo()); 00097 XCoreFunctionInfo *XFI = MF.getInfo<XCoreFunctionInfo>(); 00098 DebugLoc dl = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc(); 00099 00100 bool FP = hasFP(MF); 00101 const AttributeSet &PAL = MF.getFunction()->getAttributes(); 00102 00103 if (PAL.hasAttrSomewhere(Attribute::Nest)) 00104 loadFromStack(MBB, MBBI, XCore::R11, 0, dl, TII); 00105 00106 // Work out frame sizes. 00107 int FrameSize = MFI->getStackSize(); 00108 assert(FrameSize%4 == 0 && "Misaligned frame size"); 00109 FrameSize/=4; 00110 00111 bool isU6 = isImmU6(FrameSize); 00112 00113 if (!isU6 && !isImmU16(FrameSize)) { 00114 // FIXME could emit multiple instructions. 00115 report_fatal_error("emitPrologue Frame size too big: " + Twine(FrameSize)); 00116 } 00117 bool emitFrameMoves = XCoreRegisterInfo::needsFrameMoves(MF); 00118 00119 bool saveLR = XFI->getUsesLR(); 00120 // Do we need to allocate space on the stack? 00121 if (FrameSize) { 00122 int Opcode; 00123 if (saveLR && (MFI->getObjectOffset(XFI->getLRSpillSlot()) == 0)) { 00124 Opcode = (isU6) ? XCore::ENTSP_u6 : XCore::ENTSP_lu6; 00125 MBB.addLiveIn(XCore::LR); 00126 saveLR = false; 00127 } else { 00128 Opcode = (isU6) ? XCore::EXTSP_u6 : XCore::EXTSP_lu6; 00129 } 00130 BuildMI(MBB, MBBI, dl, TII.get(Opcode)).addImm(FrameSize); 00131 00132 if (emitFrameMoves) { 00133 00134 // Show update of SP. 00135 MCSymbol *FrameLabel = MMI->getContext().CreateTempSymbol(); 00136 BuildMI(MBB, MBBI, dl, TII.get(XCore::PROLOG_LABEL)).addSym(FrameLabel); 00137 } 00138 } 00139 if (saveLR) { 00140 int LRSpillOffset = MFI->getObjectOffset(XFI->getLRSpillSlot()); 00141 storeToStack(MBB, MBBI, XCore::LR, LRSpillOffset + FrameSize*4, dl, TII); 00142 MBB.addLiveIn(XCore::LR); 00143 00144 if (emitFrameMoves) { 00145 MCSymbol *SaveLRLabel = MMI->getContext().CreateTempSymbol(); 00146 BuildMI(MBB, MBBI, dl, TII.get(XCore::PROLOG_LABEL)).addSym(SaveLRLabel); 00147 } 00148 } 00149 00150 if (FP) { 00151 // Save R10 to the stack. 00152 int FPSpillOffset = MFI->getObjectOffset(XFI->getFPSpillSlot()); 00153 storeToStack(MBB, MBBI, XCore::R10, FPSpillOffset + FrameSize*4, dl, TII); 00154 // R10 is live-in. It is killed at the spill. 00155 MBB.addLiveIn(XCore::R10); 00156 if (emitFrameMoves) { 00157 MCSymbol *SaveR10Label = MMI->getContext().CreateTempSymbol(); 00158 BuildMI(MBB, MBBI, dl, TII.get(XCore::PROLOG_LABEL)).addSym(SaveR10Label); 00159 } 00160 // Set the FP from the SP. 00161 unsigned FramePtr = XCore::R10; 00162 BuildMI(MBB, MBBI, dl, TII.get(XCore::LDAWSP_ru6), FramePtr) 00163 .addImm(0); 00164 if (emitFrameMoves) { 00165 // Show FP is now valid. 00166 MCSymbol *FrameLabel = MMI->getContext().CreateTempSymbol(); 00167 BuildMI(MBB, MBBI, dl, TII.get(XCore::PROLOG_LABEL)).addSym(FrameLabel); 00168 } 00169 } 00170 } 00171 00172 void XCoreFrameLowering::emitEpilogue(MachineFunction &MF, 00173 MachineBasicBlock &MBB) const { 00174 MachineFrameInfo *MFI = MF.getFrameInfo(); 00175 MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr(); 00176 const XCoreInstrInfo &TII = 00177 *static_cast<const XCoreInstrInfo*>(MF.getTarget().getInstrInfo()); 00178 XCoreFunctionInfo *XFI = MF.getInfo<XCoreFunctionInfo>(); 00179 DebugLoc dl = MBBI->getDebugLoc(); 00180 00181 bool FP = hasFP(MF); 00182 if (FP) { 00183 // Restore the stack pointer. 00184 unsigned FramePtr = XCore::R10; 00185 BuildMI(MBB, MBBI, dl, TII.get(XCore::SETSP_1r)) 00186 .addReg(FramePtr); 00187 } 00188 00189 // Work out frame sizes. 00190 int FrameSize = MFI->getStackSize(); 00191 00192 assert(FrameSize%4 == 0 && "Misaligned frame size"); 00193 00194 FrameSize/=4; 00195 00196 bool isU6 = isImmU6(FrameSize); 00197 00198 if (!isU6 && !isImmU16(FrameSize)) { 00199 // FIXME could emit multiple instructions. 00200 report_fatal_error("emitEpilogue Frame size too big: " + Twine(FrameSize)); 00201 } 00202 00203 if (FP) { 00204 // Restore R10 00205 int FPSpillOffset = MFI->getObjectOffset(XFI->getFPSpillSlot()); 00206 FPSpillOffset += FrameSize*4; 00207 loadFromStack(MBB, MBBI, XCore::R10, FPSpillOffset, dl, TII); 00208 } 00209 00210 bool restoreLR = XFI->getUsesLR(); 00211 if (restoreLR && 00212 (FrameSize == 0 || MFI->getObjectOffset(XFI->getLRSpillSlot()) != 0)) { 00213 int LRSpillOffset = MFI->getObjectOffset(XFI->getLRSpillSlot()); 00214 LRSpillOffset += FrameSize*4; 00215 loadFromStack(MBB, MBBI, XCore::LR, LRSpillOffset, dl, TII); 00216 restoreLR = false; 00217 } 00218 00219 if (FrameSize) { 00220 if (restoreLR) { 00221 // Fold prologue into return instruction 00222 assert(MFI->getObjectOffset(XFI->getLRSpillSlot()) == 0); 00223 assert(MBBI->getOpcode() == XCore::RETSP_u6 00224 || MBBI->getOpcode() == XCore::RETSP_lu6); 00225 int Opcode = (isU6) ? XCore::RETSP_u6 : XCore::RETSP_lu6; 00226 BuildMI(MBB, MBBI, dl, TII.get(Opcode)).addImm(FrameSize); 00227 MBB.erase(MBBI); 00228 } else { 00229 int Opcode = (isU6) ? XCore::LDAWSP_ru6 : XCore::LDAWSP_lru6; 00230 BuildMI(MBB, MBBI, dl, TII.get(Opcode), XCore::SP).addImm(FrameSize); 00231 } 00232 } 00233 } 00234 00235 bool XCoreFrameLowering::spillCalleeSavedRegisters(MachineBasicBlock &MBB, 00236 MachineBasicBlock::iterator MI, 00237 const std::vector<CalleeSavedInfo> &CSI, 00238 const TargetRegisterInfo *TRI) const { 00239 if (CSI.empty()) 00240 return true; 00241 00242 MachineFunction *MF = MBB.getParent(); 00243 const TargetInstrInfo &TII = *MF->getTarget().getInstrInfo(); 00244 00245 XCoreFunctionInfo *XFI = MF->getInfo<XCoreFunctionInfo>(); 00246 bool emitFrameMoves = XCoreRegisterInfo::needsFrameMoves(*MF); 00247 00248 DebugLoc DL; 00249 if (MI != MBB.end()) DL = MI->getDebugLoc(); 00250 00251 for (std::vector<CalleeSavedInfo>::const_iterator it = CSI.begin(); 00252 it != CSI.end(); ++it) { 00253 // Add the callee-saved register as live-in. It's killed at the spill. 00254 MBB.addLiveIn(it->getReg()); 00255 00256 unsigned Reg = it->getReg(); 00257 const TargetRegisterClass *RC = TRI->getMinimalPhysRegClass(Reg); 00258 TII.storeRegToStackSlot(MBB, MI, Reg, true, 00259 it->getFrameIdx(), RC, TRI); 00260 if (emitFrameMoves) { 00261 MCSymbol *SaveLabel = MF->getContext().CreateTempSymbol(); 00262 BuildMI(MBB, MI, DL, TII.get(XCore::PROLOG_LABEL)).addSym(SaveLabel); 00263 XFI->getSpillLabels().push_back(std::make_pair(SaveLabel, *it)); 00264 } 00265 } 00266 return true; 00267 } 00268 00269 bool XCoreFrameLowering::restoreCalleeSavedRegisters(MachineBasicBlock &MBB, 00270 MachineBasicBlock::iterator MI, 00271 const std::vector<CalleeSavedInfo> &CSI, 00272 const TargetRegisterInfo *TRI) const{ 00273 MachineFunction *MF = MBB.getParent(); 00274 const TargetInstrInfo &TII = *MF->getTarget().getInstrInfo(); 00275 00276 bool AtStart = MI == MBB.begin(); 00277 MachineBasicBlock::iterator BeforeI = MI; 00278 if (!AtStart) 00279 --BeforeI; 00280 for (std::vector<CalleeSavedInfo>::const_iterator it = CSI.begin(); 00281 it != CSI.end(); ++it) { 00282 unsigned Reg = it->getReg(); 00283 const TargetRegisterClass *RC = TRI->getMinimalPhysRegClass(Reg); 00284 TII.loadRegFromStackSlot(MBB, MI, it->getReg(), it->getFrameIdx(), 00285 RC, TRI); 00286 assert(MI != MBB.begin() && 00287 "loadRegFromStackSlot didn't insert any code!"); 00288 // Insert in reverse order. loadRegFromStackSlot can insert multiple 00289 // instructions. 00290 if (AtStart) 00291 MI = MBB.begin(); 00292 else { 00293 MI = BeforeI; 00294 ++MI; 00295 } 00296 } 00297 return true; 00298 } 00299 00300 // This function eliminates ADJCALLSTACKDOWN, 00301 // ADJCALLSTACKUP pseudo instructions 00302 void XCoreFrameLowering:: 00303 eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB, 00304 MachineBasicBlock::iterator I) const { 00305 const XCoreInstrInfo &TII = 00306 *static_cast<const XCoreInstrInfo*>(MF.getTarget().getInstrInfo()); 00307 if (!hasReservedCallFrame(MF)) { 00308 // Turn the adjcallstackdown instruction into 'extsp <amt>' and the 00309 // adjcallstackup instruction into 'ldaw sp, sp[<amt>]' 00310 MachineInstr *Old = I; 00311 uint64_t Amount = Old->getOperand(0).getImm(); 00312 if (Amount != 0) { 00313 // We need to keep the stack aligned properly. To do this, we round the 00314 // amount of space needed for the outgoing arguments up to the next 00315 // alignment boundary. 00316 unsigned Align = getStackAlignment(); 00317 Amount = (Amount+Align-1)/Align*Align; 00318 00319 assert(Amount%4 == 0); 00320 Amount /= 4; 00321 00322 bool isU6 = isImmU6(Amount); 00323 if (!isU6 && !isImmU16(Amount)) { 00324 // FIX could emit multiple instructions in this case. 00325 #ifndef NDEBUG 00326 errs() << "eliminateCallFramePseudoInstr size too big: " 00327 << Amount << "\n"; 00328 #endif 00329 llvm_unreachable(0); 00330 } 00331 00332 MachineInstr *New; 00333 if (Old->getOpcode() == XCore::ADJCALLSTACKDOWN) { 00334 int Opcode = isU6 ? XCore::EXTSP_u6 : XCore::EXTSP_lu6; 00335 New=BuildMI(MF, Old->getDebugLoc(), TII.get(Opcode)) 00336 .addImm(Amount); 00337 } else { 00338 assert(Old->getOpcode() == XCore::ADJCALLSTACKUP); 00339 int Opcode = isU6 ? XCore::LDAWSP_ru6 : XCore::LDAWSP_lru6; 00340 New=BuildMI(MF, Old->getDebugLoc(), TII.get(Opcode), XCore::SP) 00341 .addImm(Amount); 00342 } 00343 00344 // Replace the pseudo instruction with a new instruction... 00345 MBB.insert(I, New); 00346 } 00347 } 00348 00349 MBB.erase(I); 00350 } 00351 00352 void 00353 XCoreFrameLowering::processFunctionBeforeCalleeSavedScan(MachineFunction &MF, 00354 RegScavenger *RS) const { 00355 MachineFrameInfo *MFI = MF.getFrameInfo(); 00356 const TargetRegisterInfo *RegInfo = MF.getTarget().getRegisterInfo(); 00357 bool LRUsed = MF.getRegInfo().isPhysRegUsed(XCore::LR); 00358 const TargetRegisterClass *RC = &XCore::GRRegsRegClass; 00359 XCoreFunctionInfo *XFI = MF.getInfo<XCoreFunctionInfo>(); 00360 if (LRUsed) { 00361 MF.getRegInfo().setPhysRegUnused(XCore::LR); 00362 00363 bool isVarArg = MF.getFunction()->isVarArg(); 00364 int FrameIdx; 00365 if (! isVarArg) { 00366 // A fixed offset of 0 allows us to save / restore LR using entsp / retsp. 00367 FrameIdx = MFI->CreateFixedObject(RC->getSize(), 0, true); 00368 } else { 00369 FrameIdx = MFI->CreateStackObject(RC->getSize(), RC->getAlignment(), 00370 false); 00371 } 00372 XFI->setUsesLR(FrameIdx); 00373 XFI->setLRSpillSlot(FrameIdx); 00374 } 00375 if (RegInfo->requiresRegisterScavenging(MF)) { 00376 // Reserve a slot close to SP or frame pointer. 00377 RS->addScavengingFrameIndex(MFI->CreateStackObject(RC->getSize(), 00378 RC->getAlignment(), 00379 false)); 00380 } 00381 if (hasFP(MF)) { 00382 // A callee save register is used to hold the FP. 00383 // This needs saving / restoring in the epilogue / prologue. 00384 XFI->setFPSpillSlot(MFI->CreateStackObject(RC->getSize(), 00385 RC->getAlignment(), 00386 false)); 00387 } 00388 }