LLVM API Documentation

XCoreFrameLowering.cpp
Go to the documentation of this file.
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 }