void XCoreFrameLowering:: processFunctionBeforeCalleeSavedScan(MachineFunction &MF, RegScavenger *RS) const { XCoreFunctionInfo *XFI = MF.getInfo<XCoreFunctionInfo>(); bool LRUsed = MF.getRegInfo().isPhysRegUsed(XCore::LR); if (!LRUsed && !MF.getFunction()->isVarArg() && MF.getFrameInfo()->estimateStackSize(MF)) // If we need to extend the stack it is more efficient to use entsp / retsp. // We force the LR to be saved so these instructions are used. LRUsed = true; if (MF.getMMI().callsUnwindInit() || MF.getMMI().callsEHReturn()) { // The unwinder expects to find spill slots for the exception info regs R0 // & R1. These are used during llvm.eh.return() to 'restore' the exception // info. N.B. we do not spill or restore R0, R1 during normal operation. XFI->createEHSpillSlot(MF); // As we will have a stack, we force the LR to be saved. LRUsed = true; } if (LRUsed) { // We will handle the LR in the prologue/epilogue // and allocate space on the stack ourselves. MF.getRegInfo().setPhysRegUnused(XCore::LR); XFI->createLRSpillSlot(MF); } if (hasFP(MF)) // A callee save register is used to hold the FP. // This needs saving / restoring in the epilogue / prologue. XFI->createFPSpillSlot(MF); }
void NyuziFrameLowering::emitPrologue(MachineFunction &MF, MachineBasicBlock &MBB) const { assert(&MF.front() == &MBB); MachineFrameInfo *MFI = MF.getFrameInfo(); const NyuziInstrInfo &TII = *static_cast<const NyuziInstrInfo *>(MF.getSubtarget().getInstrInfo()); MachineModuleInfo &MMI = MF.getMMI(); const MCRegisterInfo *MRI = MMI.getContext().getRegisterInfo(); MachineBasicBlock::iterator MBBI = MBB.begin(); DebugLoc DL = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc(); // Compute stack size to allocate, keeping SP 64 byte aligned so we // can do block vector load/stores int StackSize = RoundUpToAlignment(MFI->getStackSize(), getStackAlignment()); // Bail if there is no stack allocation if (StackSize == 0 && !MFI->adjustsStack()) return; TII.adjustStackPointer(MBB, MBBI, -StackSize); // Emit DW_CFA_def_cfa unsigned CFIIndex = MMI.addFrameInst( MCCFIInstruction::createDefCfaOffset(nullptr, -StackSize)); BuildMI(MBB, MBBI, DL, TII.get(TargetOpcode::CFI_INSTRUCTION)) .addCFIIndex(CFIIndex); // Find the instruction past the last instruction that saves a callee-saved // register to the stack. We need to set up FP after its old value has been // saved. const std::vector<CalleeSavedInfo> &CSI = MFI->getCalleeSavedInfo(); if (CSI.size()) { for (unsigned i = 0; i < CSI.size(); ++i) ++MBBI; // Iterate over list of callee-saved registers and emit .cfi_offset // directives (debug information) for (const auto &I : CSI) { int64_t Offset = MFI->getObjectOffset(I.getFrameIdx()); unsigned Reg = I.getReg(); unsigned CFIIndex = MMI.addFrameInst(MCCFIInstruction::createOffset( nullptr, MRI->getDwarfRegNum(Reg, 1), Offset)); BuildMI(MBB, MBBI, DL, TII.get(TargetOpcode::CFI_INSTRUCTION)) .addCFIIndex(CFIIndex); } } // fp = sp if (hasFP(MF)) { BuildMI(MBB, MBBI, DL, TII.get(Nyuzi::MOVESS)) .addReg(Nyuzi::FP_REG) .addReg(Nyuzi::SP_REG); // emit ".cfi_def_cfa_register $fp" (debug information) unsigned CFIIndex = MMI.addFrameInst(MCCFIInstruction::createDefCfaRegister( nullptr, MRI->getDwarfRegNum(Nyuzi::FP_REG, true))); BuildMI(MBB, MBBI, DL, TII.get(TargetOpcode::CFI_INSTRUCTION)) .addCFIIndex(CFIIndex); } }
void MIRPrinter::print(const MachineFunction &MF) { initRegisterMaskIds(MF); yaml::MachineFunction YamlMF; YamlMF.Name = MF.getName(); YamlMF.Alignment = MF.getAlignment(); YamlMF.ExposesReturnsTwice = MF.exposesReturnsTwice(); YamlMF.HasInlineAsm = MF.hasInlineAsm(); convert(YamlMF, MF.getRegInfo(), MF.getSubtarget().getRegisterInfo()); ModuleSlotTracker MST(MF.getFunction()->getParent()); MST.incorporateFunction(*MF.getFunction()); convert(MST, YamlMF.FrameInfo, *MF.getFrameInfo()); convertStackObjects(YamlMF, *MF.getFrameInfo(), MF.getMMI(), MST, MF.getSubtarget().getRegisterInfo()); if (const auto *ConstantPool = MF.getConstantPool()) convert(YamlMF, *ConstantPool); if (const auto *JumpTableInfo = MF.getJumpTableInfo()) convert(MST, YamlMF.JumpTableInfo, *JumpTableInfo); raw_string_ostream StrOS(YamlMF.Body.Value.Value); bool IsNewlineNeeded = false; for (const auto &MBB : MF) { if (IsNewlineNeeded) StrOS << "\n"; MIPrinter(StrOS, MST, RegisterMaskIds, StackObjectOperandMapping) .print(MBB); IsNewlineNeeded = true; } StrOS.flush(); yaml::Output Out(OS); Out << YamlMF; }
/// replaceFrameIndices - Replace all MO_FrameIndex operands with physical /// register references and actual offsets. /// void PEI::replaceFrameIndices(MachineFunction &Fn) { const TargetFrameLowering &TFI = *Fn.getSubtarget().getFrameLowering(); if (!TFI.needsFrameIndexResolution(Fn)) return; MachineModuleInfo &MMI = Fn.getMMI(); const Function *F = Fn.getFunction(); const Function *ParentF = MMI.getWinEHParent(F); unsigned FrameReg; if (F == ParentF) { WinEHFuncInfo &FuncInfo = MMI.getWinEHFuncInfo(Fn.getFunction()); // FIXME: This should be unconditional but we have bugs in the preparation // pass. if (FuncInfo.UnwindHelpFrameIdx != INT_MAX) FuncInfo.UnwindHelpFrameOffset = TFI.getFrameIndexReferenceFromSP( Fn, FuncInfo.UnwindHelpFrameIdx, FrameReg); for (WinEHTryBlockMapEntry &TBME : FuncInfo.TryBlockMap) { for (WinEHHandlerType &H : TBME.HandlerArray) { unsigned UnusedReg; if (H.CatchObj.FrameIndex == INT_MAX) H.CatchObj.FrameOffset = INT_MAX; else H.CatchObj.FrameOffset = TFI.getFrameIndexReference(Fn, H.CatchObj.FrameIndex, UnusedReg); } } } // Store SPAdj at exit of a basic block. SmallVector<int, 8> SPState; SPState.resize(Fn.getNumBlockIDs()); SmallPtrSet<MachineBasicBlock*, 8> Reachable; // Iterate over the reachable blocks in DFS order. for (auto DFI = df_ext_begin(&Fn, Reachable), DFE = df_ext_end(&Fn, Reachable); DFI != DFE; ++DFI) { int SPAdj = 0; // Check the exit state of the DFS stack predecessor. if (DFI.getPathLength() >= 2) { MachineBasicBlock *StackPred = DFI.getPath(DFI.getPathLength() - 2); assert(Reachable.count(StackPred) && "DFS stack predecessor is already visited.\n"); SPAdj = SPState[StackPred->getNumber()]; } MachineBasicBlock *BB = *DFI; replaceFrameIndices(BB, Fn, SPAdj); SPState[BB->getNumber()] = SPAdj; } // Handle the unreachable blocks. for (MachineFunction::iterator BB = Fn.begin(), E = Fn.end(); BB != E; ++BB) { if (Reachable.count(BB)) // Already handled in DFS traversal. continue; int SPAdj = 0; replaceFrameIndices(BB, Fn, SPAdj); } }
bool AArch64FrameLowering::assignCalleeSavedSpillSlots( MachineFunction &MF, const TargetRegisterInfo *TRI, std::vector<CalleeSavedInfo> &CSI, unsigned &MinCSFrameIndex, unsigned &MaxCSFrameIndex) const { const AArch64RegisterInfo *RegInfo = static_cast<const AArch64RegisterInfo *>( MF.getSubtarget().getRegisterInfo()); if (!MF.getFunction()->getAttributes().hasAttrSomewhere( Attribute::SwiftError)) return false; if (CSI.empty()) return true; // Early exit if no callee saved registers are modified! MachineFrameInfo *MFI = MF.getFrameInfo(); // Simplify the logic here since AArch64 does not have fixed or reserved // spill slots. // Now that we know which registers need to be saved and restored, allocate // stack slots according to getCalleeSavedRegsForLayout. const MCPhysReg *CSRegs = RegInfo->getCalleeSavedRegsForLayout(&MF); for (unsigned i = 0; CSRegs[i]; ++i) { unsigned Reg = CSRegs[i]; // Assign a slot for functions which call __builtin_unwind_init. if (!MF.getRegInfo().isPhysRegUsed(Reg) && !MF.getMMI().callsUnwindInit()) continue; DEBUG(dbgs() << "try to allocate stack slot for reg " << Reg << '\n'); const TargetRegisterClass *RC = RegInfo->getMinimalPhysRegClass(Reg); // Just spill it anywhere convenient. unsigned Align = RC->getAlignment(); unsigned StackAlign = getStackAlignment(); // We may not be able to satisfy the desired alignment specification of // the TargetRegisterClass if the stack alignment is smaller. Use the // min. Align = std::min(Align, StackAlign); int FrameIdx = MFI->CreateStackObject(RC->getSize(), Align, true); if ((unsigned)FrameIdx < MinCSFrameIndex) MinCSFrameIndex = FrameIdx; if ((unsigned)FrameIdx > MaxCSFrameIndex) MaxCSFrameIndex = FrameIdx; // Find the corresponding entry in CSI for Reg. for (std::vector<CalleeSavedInfo>::iterator I = CSI.begin(), E = CSI.end(); I != E; ++I) if (I->getReg() == Reg) { I->setFrameIdx(FrameIdx); break; } } return true; }
/// hasFP - Return true if the specified function should have a dedicated frame /// pointer register. This is true if the function has variable sized allocas /// or if frame pointer elimination is disabled. bool X86FrameInfo::hasFP(const MachineFunction &MF) const { const MachineFrameInfo *MFI = MF.getFrameInfo(); const MachineModuleInfo &MMI = MF.getMMI(); const TargetRegisterInfo *RI = TM.getRegisterInfo(); return (DisableFramePointerElim(MF) || RI->needsStackRealignment(MF) || MFI->hasVarSizedObjects() || MFI->isFrameAddressTaken() || MF.getInfo<X86MachineFunctionInfo>()->getForceFramePointer() || MMI.callsUnwindInit()); }
void Mips16FrameLowering::emitPrologue(MachineFunction &MF, MachineBasicBlock &MBB) const { assert(&MF.front() == &MBB && "Shrink-wrapping not yet supported"); MachineFrameInfo *MFI = MF.getFrameInfo(); const Mips16InstrInfo &TII = *static_cast<const Mips16InstrInfo *>(STI.getInstrInfo()); MachineBasicBlock::iterator MBBI = MBB.begin(); // Debug location must be unknown since the first debug location is used // to determine the end of the prologue. DebugLoc dl; uint64_t StackSize = MFI->getStackSize(); // No need to allocate space on the stack. if (StackSize == 0 && !MFI->adjustsStack()) return; MachineModuleInfo &MMI = MF.getMMI(); const MCRegisterInfo *MRI = MMI.getContext().getRegisterInfo(); MachineLocation DstML, SrcML; // Adjust stack. TII.makeFrame(Mips::SP, StackSize, MBB, MBBI); // emit ".cfi_def_cfa_offset StackSize" unsigned CFIIndex = MMI.addFrameInst( MCCFIInstruction::createDefCfaOffset(nullptr, -StackSize)); BuildMI(MBB, MBBI, dl, TII.get(TargetOpcode::CFI_INSTRUCTION)) .addCFIIndex(CFIIndex); const std::vector<CalleeSavedInfo> &CSI = MFI->getCalleeSavedInfo(); if (CSI.size()) { const std::vector<CalleeSavedInfo> &CSI = MFI->getCalleeSavedInfo(); for (std::vector<CalleeSavedInfo>::const_iterator I = CSI.begin(), E = CSI.end(); I != E; ++I) { int64_t Offset = MFI->getObjectOffset(I->getFrameIdx()); unsigned Reg = I->getReg(); unsigned DReg = MRI->getDwarfRegNum(Reg, true); unsigned CFIIndex = MMI.addFrameInst( MCCFIInstruction::createOffset(nullptr, DReg, Offset)); BuildMI(MBB, MBBI, dl, TII.get(TargetOpcode::CFI_INSTRUCTION)) .addCFIIndex(CFIIndex); } } if (hasFP(MF)) BuildMI(MBB, MBBI, dl, TII.get(Mips::MoveR3216), Mips::S0) .addReg(Mips::SP).setMIFlag(MachineInstr::FrameSetup); }
void Mips16FrameLowering::emitPrologue(MachineFunction &MF) const { MachineBasicBlock &MBB = MF.front(); MachineFrameInfo *MFI = MF.getFrameInfo(); const Mips16InstrInfo &TII = *static_cast<const Mips16InstrInfo*>(MF.getTarget().getInstrInfo()); MachineBasicBlock::iterator MBBI = MBB.begin(); DebugLoc dl = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc(); uint64_t StackSize = MFI->getStackSize(); // No need to allocate space on the stack. if (StackSize == 0 && !MFI->adjustsStack()) return; MachineModuleInfo &MMI = MF.getMMI(); const MCRegisterInfo *MRI = MMI.getContext().getRegisterInfo(); MachineLocation DstML, SrcML; // Adjust stack. TII.makeFrame(Mips::SP, StackSize, MBB, MBBI); // emit ".cfi_def_cfa_offset StackSize" MCSymbol *AdjustSPLabel = MMI.getContext().CreateTempSymbol(); BuildMI(MBB, MBBI, dl, TII.get(TargetOpcode::PROLOG_LABEL)).addSym(AdjustSPLabel); MMI.addFrameInst( MCCFIInstruction::createDefCfaOffset(AdjustSPLabel, -StackSize)); const std::vector<CalleeSavedInfo> &CSI = MFI->getCalleeSavedInfo(); if (CSI.size()) { MCSymbol *CSLabel = MMI.getContext().CreateTempSymbol(); BuildMI(MBB, MBBI, dl, TII.get(TargetOpcode::PROLOG_LABEL)).addSym(CSLabel); const std::vector<CalleeSavedInfo> &CSI = MFI->getCalleeSavedInfo(); for (std::vector<CalleeSavedInfo>::const_iterator I = CSI.begin(), E = CSI.end(); I != E; ++I) { int64_t Offset = MFI->getObjectOffset(I->getFrameIdx()); unsigned Reg = I->getReg(); unsigned DReg = MRI->getDwarfRegNum(Reg, true); MMI.addFrameInst(MCCFIInstruction::createOffset(CSLabel, DReg, Offset)); } } if (hasFP(MF)) BuildMI(MBB, MBBI, dl, TII.get(Mips::MoveR3216), Mips::S0) .addReg(Mips::SP); }
// This checks whether the transformation is legal. // Also returns false in cases where it's potentially legal, but // we don't even want to try. bool X86CallFrameOptimization::isLegal(MachineFunction &MF) { if (NoX86CFOpt.getValue()) return false; // We currently only support call sequences where *all* parameters. // are passed on the stack. // No point in running this in 64-bit mode, since some arguments are // passed in-register in all common calling conventions, so the pattern // we're looking for will never match. if (STI->is64Bit()) return false; // We can't encode multiple DW_CFA_GNU_args_size or DW_CFA_def_cfa_offset // in the compact unwind encoding that Darwin uses. So, bail if there // is a danger of that being generated. if (STI->isTargetDarwin() && (!MF.getMMI().getLandingPads().empty() || (MF.getFunction()->needsUnwindTableEntry() && !TFL->hasFP(MF)))) return false; // You would expect straight-line code between call-frame setup and // call-frame destroy. You would be wrong. There are circumstances (e.g. // CMOV_GR8 expansion of a select that feeds a function call!) where we can // end up with the setup and the destroy in different basic blocks. // This is bad, and breaks SP adjustment. // So, check that all of the frames in the function are closed inside // the same block, and, for good measure, that there are no nested frames. unsigned FrameSetupOpcode = TII->getCallFrameSetupOpcode(); unsigned FrameDestroyOpcode = TII->getCallFrameDestroyOpcode(); for (MachineBasicBlock &BB : MF) { bool InsideFrameSequence = false; for (MachineInstr &MI : BB) { if (MI.getOpcode() == FrameSetupOpcode) { if (InsideFrameSequence) return false; InsideFrameSequence = true; } else if (MI.getOpcode() == FrameDestroyOpcode) { if (!InsideFrameSequence) return false; InsideFrameSequence = false; } } if (InsideFrameSequence) return false; } return true; }
/// insertPrologEpilogCode - Scan the function for modified callee saved /// registers, insert spill code for these callee saved registers, then add /// prolog and epilog code to the function. void PEI::insertPrologEpilogCode(MachineFunction &MF) { const TargetFrameLowering &TFI = *MF.getSubtarget().getFrameLowering(); // Add prologue to the function... for (MachineBasicBlock *SaveBlock : SaveBlocks) TFI.emitPrologue(MF, *SaveBlock); // Add epilogue to restore the callee-save registers in each exiting block. for (MachineBasicBlock *RestoreBlock : RestoreBlocks) TFI.emitEpilogue(MF, *RestoreBlock); for (MachineBasicBlock *SaveBlock : SaveBlocks) TFI.inlineStackProbe(MF, *SaveBlock); // Emit additional code that is required to support segmented stacks, if // we've been asked for it. This, when linked with a runtime with support // for segmented stacks (libgcc is one), will result in allocating stack // space in small chunks instead of one large contiguous block. if (MF.shouldSplitStack()) { for (MachineBasicBlock *SaveBlock : SaveBlocks) TFI.adjustForSegmentedStacks(MF, *SaveBlock); // Record that there are split-stack functions, so we will emit a // special section to tell the linker. MF.getMMI().setHasSplitStack(true); } else MF.getMMI().setHasNosplitStack(true); // Emit additional code that is required to explicitly handle the stack in // HiPE native code (if needed) when loaded in the Erlang/OTP runtime. The // approach is rather similar to that of Segmented Stacks, but it uses a // different conditional check and another BIF for allocating more stack // space. if (MF.getFunction().getCallingConv() == CallingConv::HiPE) for (MachineBasicBlock *SaveBlock : SaveBlocks) TFI.adjustForHiPEPrologue(MF, *SaveBlock); }
bool ImplicitNullChecks::runOnMachineFunction(MachineFunction &MF) { TII = MF.getSubtarget().getInstrInfo(); TRI = MF.getRegInfo().getTargetRegisterInfo(); MMI = &MF.getMMI(); SmallVector<NullCheck, 16> NullCheckList; for (auto &MBB : MF) analyzeBlockForNullChecks(MBB, NullCheckList); if (!NullCheckList.empty()) rewriteNullChecks(NullCheckList); return !NullCheckList.empty(); }
void SparcFrameLowering::emitPrologue(MachineFunction &MF, MachineBasicBlock &MBB) const { SparcMachineFunctionInfo *FuncInfo = MF.getInfo<SparcMachineFunctionInfo>(); assert(&MF.front() == &MBB && "Shrink-wrapping not yet supported"); MachineFrameInfo *MFI = MF.getFrameInfo(); const SparcInstrInfo &TII = *static_cast<const SparcInstrInfo *>(MF.getSubtarget().getInstrInfo()); MachineBasicBlock::iterator MBBI = MBB.begin(); DebugLoc dl = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc(); // Get the number of bytes to allocate from the FrameInfo int NumBytes = (int) MFI->getStackSize(); unsigned SAVEri = SP::SAVEri; unsigned SAVErr = SP::SAVErr; if (FuncInfo->isLeafProc()) { if (NumBytes == 0) return; SAVEri = SP::ADDri; SAVErr = SP::ADDrr; } NumBytes = -MF.getSubtarget<SparcSubtarget>().getAdjustedFrameSize(NumBytes); emitSPAdjustment(MF, MBB, MBBI, NumBytes, SAVErr, SAVEri); MachineModuleInfo &MMI = MF.getMMI(); const MCRegisterInfo *MRI = MMI.getContext().getRegisterInfo(); unsigned regFP = MRI->getDwarfRegNum(SP::I6, true); // Emit ".cfi_def_cfa_register 30". unsigned CFIIndex = MMI.addFrameInst(MCCFIInstruction::createDefCfaRegister(nullptr, regFP)); BuildMI(MBB, MBBI, dl, TII.get(TargetOpcode::CFI_INSTRUCTION)) .addCFIIndex(CFIIndex); // Emit ".cfi_window_save". CFIIndex = MMI.addFrameInst(MCCFIInstruction::createWindowSave(nullptr)); BuildMI(MBB, MBBI, dl, TII.get(TargetOpcode::CFI_INSTRUCTION)) .addCFIIndex(CFIIndex); unsigned regInRA = MRI->getDwarfRegNum(SP::I7, true); unsigned regOutRA = MRI->getDwarfRegNum(SP::O7, true); // Emit ".cfi_register 15, 31". CFIIndex = MMI.addFrameInst( MCCFIInstruction::createRegister(nullptr, regOutRA, regInRA)); BuildMI(MBB, MBBI, dl, TII.get(TargetOpcode::CFI_INSTRUCTION)) .addCFIIndex(CFIIndex); }
void Mips16FrameLowering::emitPrologue(MachineFunction &MF) const { MachineBasicBlock &MBB = MF.front(); MachineFrameInfo *MFI = MF.getFrameInfo(); const Mips16InstrInfo &TII = *static_cast<const Mips16InstrInfo*>(MF.getTarget().getInstrInfo()); MachineBasicBlock::iterator MBBI = MBB.begin(); DebugLoc dl = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc(); uint64_t StackSize = MFI->getStackSize(); // No need to allocate space on the stack. if (StackSize == 0 && !MFI->adjustsStack()) return; MachineModuleInfo &MMI = MF.getMMI(); MachineLocation DstML, SrcML; // Adjust stack. TII.makeFrame(Mips::SP, StackSize, MBB, MBBI); // emit ".cfi_def_cfa_offset StackSize" MCSymbol *AdjustSPLabel = MMI.getContext().CreateTempSymbol(); BuildMI(MBB, MBBI, dl, TII.get(TargetOpcode::PROLOG_LABEL)).addSym(AdjustSPLabel); DstML = MachineLocation(MachineLocation::VirtualFP); SrcML = MachineLocation(MachineLocation::VirtualFP, -StackSize); MMI.addFrameMove(AdjustSPLabel, DstML, SrcML); MCSymbol *CSLabel = MMI.getContext().CreateTempSymbol(); BuildMI(MBB, MBBI, dl, TII.get(TargetOpcode::PROLOG_LABEL)).addSym(CSLabel); DstML = MachineLocation(MachineLocation::VirtualFP, -8); SrcML = MachineLocation(Mips::S1); MMI.addFrameMove(CSLabel, DstML, SrcML); DstML = MachineLocation(MachineLocation::VirtualFP, -12); SrcML = MachineLocation(Mips::S0); MMI.addFrameMove(CSLabel, DstML, SrcML); DstML = MachineLocation(MachineLocation::VirtualFP, -4); SrcML = MachineLocation(Mips::RA); MMI.addFrameMove(CSLabel, DstML, SrcML); if (hasFP(MF)) BuildMI(MBB, MBBI, dl, TII.get(Mips::MoveR3216), Mips::S0) .addReg(Mips::SP); }
// This checks whether the transformation is legal. // Also returns false in cases where it's potentially legal, but // we don't even want to try. bool X86CallFrameOptimization::isLegal(MachineFunction &MF) { if (NoX86CFOpt.getValue()) return false; // We can't encode multiple DW_CFA_GNU_args_size or DW_CFA_def_cfa_offset // in the compact unwind encoding that Darwin uses. So, bail if there // is a danger of that being generated. if (STI->isTargetDarwin() && (!MF.getMMI().getLandingPads().empty() || (MF.getFunction()->needsUnwindTableEntry() && !TFL->hasFP(MF)))) return false; // It is not valid to change the stack pointer outside the prolog/epilog // on 64-bit Windows. if (STI->isTargetWin64()) return false; // You would expect straight-line code between call-frame setup and // call-frame destroy. You would be wrong. There are circumstances (e.g. // CMOV_GR8 expansion of a select that feeds a function call!) where we can // end up with the setup and the destroy in different basic blocks. // This is bad, and breaks SP adjustment. // So, check that all of the frames in the function are closed inside // the same block, and, for good measure, that there are no nested frames. unsigned FrameSetupOpcode = TII->getCallFrameSetupOpcode(); unsigned FrameDestroyOpcode = TII->getCallFrameDestroyOpcode(); for (MachineBasicBlock &BB : MF) { bool InsideFrameSequence = false; for (MachineInstr &MI : BB) { if (MI.getOpcode() == FrameSetupOpcode) { if (InsideFrameSequence) return false; InsideFrameSequence = true; } else if (MI.getOpcode() == FrameDestroyOpcode) { if (!InsideFrameSequence) return false; InsideFrameSequence = false; } } if (InsideFrameSequence) return false; } return true; }
void SparcFrameLowering::emitPrologue(MachineFunction &MF) const { SparcMachineFunctionInfo *FuncInfo = MF.getInfo<SparcMachineFunctionInfo>(); MachineBasicBlock &MBB = MF.front(); MachineFrameInfo *MFI = MF.getFrameInfo(); const SparcInstrInfo &TII = *static_cast<const SparcInstrInfo*>(MF.getTarget().getInstrInfo()); MachineBasicBlock::iterator MBBI = MBB.begin(); DebugLoc dl = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc(); // Get the number of bytes to allocate from the FrameInfo int NumBytes = (int) MFI->getStackSize(); unsigned SAVEri = SP::SAVEri; unsigned SAVErr = SP::SAVErr; if (FuncInfo->isLeafProc()) { if (NumBytes == 0) return; SAVEri = SP::ADDri; SAVErr = SP::ADDrr; } NumBytes = - SubTarget.getAdjustedFrameSize(NumBytes); emitSPAdjustment(MF, MBB, MBBI, NumBytes, SAVErr, SAVEri); MachineModuleInfo &MMI = MF.getMMI(); const MCRegisterInfo *MRI = MMI.getContext().getRegisterInfo(); MCSymbol *FrameLabel = MMI.getContext().CreateTempSymbol(); BuildMI(MBB, MBBI, dl, TII.get(SP::PROLOG_LABEL)).addSym(FrameLabel); unsigned regFP = MRI->getDwarfRegNum(SP::I6, true); // Emit ".cfi_def_cfa_register 30". MMI.addFrameInst(MCCFIInstruction::createDefCfaRegister(FrameLabel, regFP)); // Emit ".cfi_window_save". MMI.addFrameInst(MCCFIInstruction::createWindowSave(FrameLabel)); unsigned regInRA = MRI->getDwarfRegNum(SP::I7, true); unsigned regOutRA = MRI->getDwarfRegNum(SP::O7, true); // Emit ".cfi_register 15, 31". MMI.addFrameInst(MCCFIInstruction::createRegister(FrameLabel, regOutRA, regInRA)); }
bool MIRParserImpl::parseStackObjectsDebugInfo( MachineFunction &MF, PerFunctionMIParsingState &PFS, const yaml::MachineStackObject &Object, int FrameIdx) { // Debug information can only be attached to stack objects; Fixed stack // objects aren't supported. assert(FrameIdx >= 0 && "Expected a stack object frame index"); MDNode *Var = nullptr, *Expr = nullptr, *Loc = nullptr; if (parseMDNode(Var, Object.DebugVar, MF, PFS) || parseMDNode(Expr, Object.DebugExpr, MF, PFS) || parseMDNode(Loc, Object.DebugLoc, MF, PFS)) return true; if (!Var && !Expr && !Loc) return false; DILocalVariable *DIVar = nullptr; DIExpression *DIExpr = nullptr; DILocation *DILoc = nullptr; if (typecheckMDNode(DIVar, Var, Object.DebugVar, "DILocalVariable", *this) || typecheckMDNode(DIExpr, Expr, Object.DebugExpr, "DIExpression", *this) || typecheckMDNode(DILoc, Loc, Object.DebugLoc, "DILocation", *this)) return true; MF.getMMI().setVariableDbgInfo(DIVar, DIExpr, unsigned(FrameIdx), DILoc); return false; }
bool SIDebuggerInsertNops::runOnMachineFunction(MachineFunction &MF) { // Skip this pass if "amdgpu-debugger-insert-nops" attribute was not // specified. const AMDGPUSubtarget &ST = MF.getSubtarget<AMDGPUSubtarget>(); if (!ST.debuggerInsertNops()) return false; // Skip machine functions without debug info. if (!MF.getMMI().hasDebugInfo()) return false; // Target instruction info. const SIInstrInfo *TII = static_cast<const SIInstrInfo*>(MF.getSubtarget().getInstrInfo()); // Set containing line numbers that have nop inserted. DenseSet<unsigned> NopInserted; for (auto &MBB : MF) { for (auto MI = MBB.begin(); MI != MBB.end(); ++MI) { // Skip DBG_VALUE instructions and instructions without location. if (MI->isDebugValue() || !MI->getDebugLoc()) continue; // Insert nop instruction if line number does not have nop inserted. auto DL = MI->getDebugLoc(); if (NopInserted.find(DL.getLine()) == NopInserted.end()) { BuildMI(MBB, *MI, DL, TII->get(AMDGPU::S_NOP)) .addImm(0); NopInserted.insert(DL.getLine()); } } } return true; }
bool XCoreRegisterInfo::needsFrameMoves(const MachineFunction &MF) { return MF.getMMI().hasDebugInfo() || MF.getFunction()->needsUnwindTableEntry(); }
void SPURegisterInfo::emitPrologue(MachineFunction &MF) const { MachineBasicBlock &MBB = MF.front(); // Prolog goes in entry BB MachineBasicBlock::iterator MBBI = MBB.begin(); MachineFrameInfo *MFI = MF.getFrameInfo(); MachineModuleInfo &MMI = MF.getMMI(); DebugLoc dl = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc(); // Prepare for debug frame info. bool hasDebugInfo = MMI.hasDebugInfo(); MCSymbol *FrameLabel = 0; // Move MBBI back to the beginning of the function. MBBI = MBB.begin(); // Work out frame sizes. determineFrameLayout(MF); int FrameSize = MFI->getStackSize(); assert((FrameSize & 0xf) == 0 && "SPURegisterInfo::emitPrologue: FrameSize not aligned"); // the "empty" frame size is 16 - just the register scavenger spill slot if (FrameSize > 16 || MFI->adjustsStack()) { FrameSize = -(FrameSize + SPUFrameInfo::minStackSize()); if (hasDebugInfo) { // Mark effective beginning of when frame pointer becomes valid. FrameLabel = MMI.getContext().CreateTempSymbol(); BuildMI(MBB, MBBI, dl, TII.get(SPU::DBG_LABEL)).addSym(FrameLabel); } // Adjust stack pointer, spilling $lr -> 16($sp) and $sp -> -FrameSize($sp) // for the ABI BuildMI(MBB, MBBI, dl, TII.get(SPU::STQDr32), SPU::R0).addImm(16) .addReg(SPU::R1); if (isInt<10>(FrameSize)) { // Spill $sp to adjusted $sp BuildMI(MBB, MBBI, dl, TII.get(SPU::STQDr32), SPU::R1).addImm(FrameSize) .addReg(SPU::R1); // Adjust $sp by required amout BuildMI(MBB, MBBI, dl, TII.get(SPU::AIr32), SPU::R1).addReg(SPU::R1) .addImm(FrameSize); } else if (isInt<16>(FrameSize)) { // Frame size can be loaded into ILr32n, so temporarily spill $r2 and use // $r2 to adjust $sp: BuildMI(MBB, MBBI, dl, TII.get(SPU::STQDr128), SPU::R2) .addImm(-16) .addReg(SPU::R1); BuildMI(MBB, MBBI, dl, TII.get(SPU::ILr32), SPU::R2) .addImm(FrameSize); BuildMI(MBB, MBBI, dl, TII.get(SPU::STQXr32), SPU::R1) .addReg(SPU::R2) .addReg(SPU::R1); BuildMI(MBB, MBBI, dl, TII.get(SPU::Ar32), SPU::R1) .addReg(SPU::R1) .addReg(SPU::R2); BuildMI(MBB, MBBI, dl, TII.get(SPU::SFIr32), SPU::R2) .addReg(SPU::R2) .addImm(16); BuildMI(MBB, MBBI, dl, TII.get(SPU::LQXr128), SPU::R2) .addReg(SPU::R2) .addReg(SPU::R1); } else { report_fatal_error("Unhandled frame size: " + Twine(FrameSize)); } if (hasDebugInfo) { std::vector<MachineMove> &Moves = MMI.getFrameMoves(); // Show update of SP. MachineLocation SPDst(MachineLocation::VirtualFP); MachineLocation SPSrc(MachineLocation::VirtualFP, -FrameSize); Moves.push_back(MachineMove(FrameLabel, SPDst, SPSrc)); // Add callee saved registers to move list. const std::vector<CalleeSavedInfo> &CSI = MFI->getCalleeSavedInfo(); for (unsigned I = 0, E = CSI.size(); I != E; ++I) { int Offset = MFI->getObjectOffset(CSI[I].getFrameIdx()); unsigned Reg = CSI[I].getReg(); if (Reg == SPU::R0) continue; MachineLocation CSDst(MachineLocation::VirtualFP, Offset); MachineLocation CSSrc(Reg); Moves.push_back(MachineMove(FrameLabel, CSDst, CSSrc)); } // Mark effective beginning of when frame pointer is ready. MCSymbol *ReadyLabel = MMI.getContext().CreateTempSymbol(); BuildMI(MBB, MBBI, dl, TII.get(SPU::DBG_LABEL)).addSym(ReadyLabel); MachineLocation FPDst(SPU::R1); MachineLocation FPSrc(MachineLocation::VirtualFP); Moves.push_back(MachineMove(ReadyLabel, FPDst, FPSrc)); } } else { // This is a leaf function -- insert a branch hint iff there are // sufficient number instructions in the basic block. Note that // this is just a best guess based on the basic block's size. if (MBB.size() >= (unsigned) SPUFrameInfo::branchHintPenalty()) { MachineBasicBlock::iterator MBBI = prior(MBB.end()); dl = MBBI->getDebugLoc(); // Insert terminator label BuildMI(MBB, MBBI, dl, TII.get(SPU::DBG_LABEL)) .addSym(MMI.getContext().CreateTempSymbol()); } } }
void Cpu0FrameLowering::emitPrologue(MachineFunction &MF) const { MachineBasicBlock &MBB = MF.front(); MachineFrameInfo *MFI = MF.getFrameInfo(); Cpu0FunctionInfo *Cpu0FI = MF.getInfo<Cpu0FunctionInfo>(); const Cpu0InstrInfo &TII = *static_cast<const Cpu0InstrInfo*>(MF.getTarget().getInstrInfo()); MachineBasicBlock::iterator MBBI = MBB.begin(); DebugLoc dl = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc(); unsigned SP = Cpu0::SP; // lbd document - mark - Cpu0::SP unsigned FP = Cpu0::FP; unsigned ZERO = Cpu0::ZERO; unsigned ADDu = Cpu0::ADDu; // lbd document - mark - Cpu0::ADDu unsigned ADDiu = Cpu0::ADDiu; // First, compute final stack size. unsigned StackAlign = getStackAlignment(); unsigned RegSize = 4; unsigned LocalVarAreaOffset = Cpu0FI->needGPSaveRestore() ? (MFI->getObjectOffset(Cpu0FI->getGPFI()) + RegSize) : Cpu0FI->getMaxCallFrameSize(); uint64_t StackSize = RoundUpToAlignment(LocalVarAreaOffset, StackAlign) + RoundUpToAlignment(MFI->getStackSize(), StackAlign); // Update stack size MFI->setStackSize(StackSize); // No need to allocate space on the stack. if (StackSize == 0 && !MFI->adjustsStack()) return; MachineModuleInfo &MMI = MF.getMMI(); const MCRegisterInfo *MRI = MMI.getContext().getRegisterInfo(); MachineLocation DstML, SrcML; // Adjust stack. if (isInt<16>(-StackSize)) // addiu sp, sp, (-stacksize) BuildMI(MBB, MBBI, dl, TII.get(ADDiu), SP).addReg(SP).addImm(-StackSize); else { // Expand immediate that doesn't fit in 16-bit. Cpu0FI->setEmitNOAT(); expandLargeImm(SP, -StackSize, TII, MBB, MBBI, dl); } // emit ".cfi_def_cfa_offset StackSize" MCSymbol *AdjustSPLabel = MMI.getContext().CreateTempSymbol(); BuildMI(MBB, MBBI, dl, TII.get(TargetOpcode::PROLOG_LABEL)).addSym(AdjustSPLabel); MMI.addFrameInst( MCCFIInstruction::createDefCfaOffset(AdjustSPLabel, -StackSize)); const std::vector<CalleeSavedInfo> &CSI = MFI->getCalleeSavedInfo(); if (CSI.size()) { // Find the instruction past the last instruction that saves a callee-saved // register to the stack. for (unsigned i = 0; i < CSI.size(); ++i) ++MBBI; // Iterate over list of callee-saved registers and emit .cfi_offset // directives. MCSymbol *CSLabel = MMI.getContext().CreateTempSymbol(); BuildMI(MBB, MBBI, dl, TII.get(TargetOpcode::PROLOG_LABEL)).addSym(CSLabel); for (std::vector<CalleeSavedInfo>::const_iterator I = CSI.begin(), E = CSI.end(); I != E; ++I) { int64_t Offset = MFI->getObjectOffset(I->getFrameIdx()); unsigned Reg = I->getReg(); { // Reg is in CPURegs. MMI.addFrameInst(MCCFIInstruction::createOffset( CSLabel, MRI->getDwarfRegNum(Reg, 1), Offset)); } } } // if framepointer enabled, set it to point to the stack pointer. if (hasFP(MF)) { // Insert instruction "move $fp, $sp" at this location. BuildMI(MBB, MBBI, dl, TII.get(ADDu), FP).addReg(SP).addReg(ZERO); // emit ".cfi_def_cfa_register $fp" MCSymbol *SetFPLabel = MMI.getContext().CreateTempSymbol(); BuildMI(MBB, MBBI, dl, TII.get(TargetOpcode::PROLOG_LABEL)).addSym(SetFPLabel); MMI.addFrameInst(MCCFIInstruction::createDefCfaRegister( SetFPLabel, MRI->getDwarfRegNum(FP, true))); } // Restore GP from the saved stack location if (Cpu0FI->needGPSaveRestore()) { unsigned Offset = MFI->getObjectOffset(Cpu0FI->getGPFI()); BuildMI(MBB, MBBI, dl, TII.get(Cpu0::CPRESTORE)).addImm(Offset) .addReg(Cpu0::GP); } // lbd document - mark - if (Cpu0FI->needGPSaveRestore()) }
void AArch64FrameLowering::emitPrologue(MachineFunction &MF) const { AArch64MachineFunctionInfo *FuncInfo = MF.getInfo<AArch64MachineFunctionInfo>(); MachineBasicBlock &MBB = MF.front(); MachineBasicBlock::iterator MBBI = MBB.begin(); MachineFrameInfo *MFI = MF.getFrameInfo(); const TargetInstrInfo &TII = *MF.getTarget().getInstrInfo(); DebugLoc DL = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc(); MachineModuleInfo &MMI = MF.getMMI(); const MCRegisterInfo *MRI = MMI.getContext().getRegisterInfo(); bool NeedsFrameMoves = MMI.hasDebugInfo() || MF.getFunction()->needsUnwindTableEntry(); uint64_t NumInitialBytes, NumResidualBytes; // Currently we expect the stack to be laid out by // sub sp, sp, #initial // stp x29, x30, [sp, #offset] // ... // str xxx, [sp, #offset] // sub sp, sp, #rest (possibly via extra instructions). if (MFI->getCalleeSavedInfo().size()) { // If there are callee-saved registers, we want to store them efficiently as // a block, and virtual base assignment happens too early to do it for us so // we adjust the stack in two phases: first just for callee-saved fiddling, // then to allocate the rest of the frame. splitSPAdjustments(MFI->getStackSize(), NumInitialBytes, NumResidualBytes); } else { // If there aren't any callee-saved registers, two-phase adjustment is // inefficient. It's more efficient to adjust with NumInitialBytes too // because when we're in a "callee pops argument space" situation, that pop // must be tacked onto Initial for correctness. NumInitialBytes = MFI->getStackSize(); NumResidualBytes = 0; } // Tell everyone else how much adjustment we're expecting them to use. In // particular if an adjustment is required for a tail call the epilogue could // have a different view of things. FuncInfo->setInitialStackAdjust(NumInitialBytes); emitSPUpdate(MBB, MBBI, DL, TII, AArch64::X16, -NumInitialBytes, MachineInstr::FrameSetup); if (NeedsFrameMoves && NumInitialBytes) { // We emit this update even if the CFA is set from a frame pointer later so // that the CFA is valid in the interim. MachineLocation Dst(MachineLocation::VirtualFP); unsigned Reg = MRI->getDwarfRegNum(AArch64::XSP, true); unsigned CFIIndex = MMI.addFrameInst( MCCFIInstruction::createDefCfa(nullptr, Reg, -NumInitialBytes)); BuildMI(MBB, MBBI, DL, TII.get(TargetOpcode::CFI_INSTRUCTION)) .addCFIIndex(CFIIndex); } // Otherwise we need to set the frame pointer and/or add a second stack // adjustment. bool FPNeedsSetting = hasFP(MF); for (; MBBI != MBB.end(); ++MBBI) { // Note that this search makes strong assumptions about the operation used // to store the frame-pointer: it must be "STP x29, x30, ...". This could // change in future, but until then there's no point in implementing // untestable more generic cases. if (FPNeedsSetting && MBBI->getOpcode() == AArch64::LSPair64_STR && MBBI->getOperand(0).getReg() == AArch64::X29) { int64_t X29FrameIdx = MBBI->getOperand(2).getIndex(); FuncInfo->setFramePointerOffset(MFI->getObjectOffset(X29FrameIdx)); ++MBBI; emitRegUpdate(MBB, MBBI, DL, TII, AArch64::X29, AArch64::XSP, AArch64::X29, NumInitialBytes + MFI->getObjectOffset(X29FrameIdx), MachineInstr::FrameSetup); // The offset adjustment used when emitting debugging locations relative // to whatever frame base is set. AArch64 uses the default frame base (FP // or SP) and this adjusts the calculations to be correct. MFI->setOffsetAdjustment(- MFI->getObjectOffset(X29FrameIdx) - MFI->getStackSize()); if (NeedsFrameMoves) { unsigned Reg = MRI->getDwarfRegNum(AArch64::X29, true); unsigned Offset = MFI->getObjectOffset(X29FrameIdx); unsigned CFIIndex = MMI.addFrameInst( MCCFIInstruction::createDefCfa(nullptr, Reg, Offset)); BuildMI(MBB, MBBI, DL, TII.get(TargetOpcode::CFI_INSTRUCTION)) .addCFIIndex(CFIIndex); } FPNeedsSetting = false; } if (!MBBI->getFlag(MachineInstr::FrameSetup)) break; } assert(!FPNeedsSetting && "Frame pointer couldn't be set"); emitSPUpdate(MBB, MBBI, DL, TII, AArch64::X16, -NumResidualBytes, MachineInstr::FrameSetup); // Now we emit the rest of the frame setup information, if necessary: we've // already noted the FP and initial SP moves so we're left with the prologue's // final SP update and callee-saved register locations. if (!NeedsFrameMoves) return; // The rest of the stack adjustment if (!hasFP(MF) && NumResidualBytes) { MachineLocation Dst(MachineLocation::VirtualFP); unsigned Reg = MRI->getDwarfRegNum(AArch64::XSP, true); unsigned Offset = NumResidualBytes + NumInitialBytes; unsigned CFIIndex = MMI.addFrameInst(MCCFIInstruction::createDefCfa(nullptr, Reg, -Offset)); BuildMI(MBB, MBBI, DL, TII.get(TargetOpcode::CFI_INSTRUCTION)) .addCFIIndex(CFIIndex); } // And any callee-saved registers (it's fine to leave them to the end here, // because the old values are still valid at this point. const std::vector<CalleeSavedInfo> &CSI = MFI->getCalleeSavedInfo(); if (CSI.size()) { for (std::vector<CalleeSavedInfo>::const_iterator I = CSI.begin(), E = CSI.end(); I != E; ++I) { unsigned Offset = MFI->getObjectOffset(I->getFrameIdx()); unsigned Reg = MRI->getDwarfRegNum(I->getReg(), true); unsigned CFIIndex = MMI.addFrameInst( MCCFIInstruction::createOffset(nullptr, Reg, Offset)); BuildMI(MBB, MBBI, DL, TII.get(TargetOpcode::CFI_INSTRUCTION)) .addCFIIndex(CFIIndex); } } }
void HexagonFrameLowering::emitPrologue(MachineFunction &MF) const { MachineBasicBlock &MBB = MF.front(); MachineFrameInfo *MFI = MF.getFrameInfo(); MachineModuleInfo &MMI = MF.getMMI(); MachineBasicBlock::iterator MBBI = MBB.begin(); const HexagonRegisterInfo *QRI = static_cast<const HexagonRegisterInfo *>(MF.getTarget().getRegisterInfo()); DebugLoc dl = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc(); determineFrameLayout(MF); // Check if frame moves are needed for EH. bool needsFrameMoves = MMI.hasDebugInfo() || !MF.getFunction()->needsUnwindTableEntry(); // Get the number of bytes to allocate from the FrameInfo. int NumBytes = (int) MFI->getStackSize(); // LLVM expects allocframe not to be the first instruction in the // basic block. MachineBasicBlock::iterator InsertPt = MBB.begin(); // // ALLOCA adjust regs. Iterate over ADJDYNALLOC nodes and change the offset. // HexagonMachineFunctionInfo *FuncInfo = MF.getInfo<HexagonMachineFunctionInfo>(); const std::vector<MachineInstr*>& AdjustRegs = FuncInfo->getAllocaAdjustInsts(); for (std::vector<MachineInstr*>::const_iterator i = AdjustRegs.begin(), e = AdjustRegs.end(); i != e; ++i) { MachineInstr* MI = *i; assert((MI->getOpcode() == Hexagon::ADJDYNALLOC) && "Expected adjust alloca node"); MachineOperand& MO = MI->getOperand(2); assert(MO.isImm() && "Expected immediate"); MO.setImm(MFI->getMaxCallFrameSize()); } std::vector<MachineMove> &Moves = MMI.getFrameMoves(); if (needsFrameMoves) { // Advance CFA. DW_CFA_def_cfa unsigned FPReg = QRI->getFrameRegister(); unsigned RAReg = QRI->getRARegister(); MachineLocation Dst(MachineLocation::VirtualFP); MachineLocation Src(FPReg, -8); Moves.push_back(MachineMove(0, Dst, Src)); // R31 = (R31 - #4) MachineLocation LRDst(RAReg, -4); MachineLocation LRSrc(RAReg); Moves.push_back(MachineMove(0, LRDst, LRSrc)); // R30 = (R30 - #8) MachineLocation SPDst(FPReg, -8); MachineLocation SPSrc(FPReg); Moves.push_back(MachineMove(0, SPDst, SPSrc)); } // // Only insert ALLOCFRAME if we need to. // if (hasFP(MF)) { // Check for overflow. // Hexagon_TODO: Ugh! hardcoding. Is there an API that can be used? const int ALLOCFRAME_MAX = 16384; const TargetInstrInfo &TII = *MF.getTarget().getInstrInfo(); if (NumBytes >= ALLOCFRAME_MAX) { // Emit allocframe(#0). BuildMI(MBB, InsertPt, dl, TII.get(Hexagon::ALLOCFRAME)).addImm(0); // Subtract offset from frame pointer. BuildMI(MBB, InsertPt, dl, TII.get(Hexagon::CONST32_Int_Real), HEXAGON_RESERVED_REG_1).addImm(NumBytes); BuildMI(MBB, InsertPt, dl, TII.get(Hexagon::SUB_rr), QRI->getStackRegister()). addReg(QRI->getStackRegister()). addReg(HEXAGON_RESERVED_REG_1); } else { BuildMI(MBB, InsertPt, dl, TII.get(Hexagon::ALLOCFRAME)).addImm(NumBytes); } } }
void MipsFrameLowering::emitPrologue(MachineFunction &MF) const { MachineBasicBlock &MBB = MF.front(); MachineFrameInfo *MFI = MF.getFrameInfo(); MipsFunctionInfo *MipsFI = MF.getInfo<MipsFunctionInfo>(); const MipsRegisterInfo *RegInfo = static_cast<const MipsRegisterInfo*>(MF.getTarget().getRegisterInfo()); const MipsInstrInfo &TII = *static_cast<const MipsInstrInfo*>(MF.getTarget().getInstrInfo()); MachineBasicBlock::iterator MBBI = MBB.begin(); DebugLoc dl = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc(); bool isPIC = (MF.getTarget().getRelocationModel() == Reloc::PIC_); unsigned SP = STI.isABI_N64() ? Mips::SP_64 : Mips::SP; unsigned FP = STI.isABI_N64() ? Mips::FP_64 : Mips::FP; unsigned ZERO = STI.isABI_N64() ? Mips::ZERO_64 : Mips::ZERO; unsigned ADDu = STI.isABI_N64() ? Mips::DADDu : Mips::ADDu; unsigned ADDiu = STI.isABI_N64() ? Mips::DADDiu : Mips::ADDiu; // First, compute final stack size. unsigned RegSize = STI.isGP32bit() ? 4 : 8; unsigned StackAlign = getStackAlignment(); unsigned LocalVarAreaOffset = MipsFI->needGPSaveRestore() ? (MFI->getObjectOffset(MipsFI->getGPFI()) + RegSize) : MipsFI->getMaxCallFrameSize(); uint64_t StackSize = RoundUpToAlignment(LocalVarAreaOffset, StackAlign) + RoundUpToAlignment(MFI->getStackSize(), StackAlign); // Update stack size MFI->setStackSize(StackSize); // Emit instructions that set the global base register if the target ABI is // O32. if (isPIC && MipsFI->globalBaseRegSet() && STI.isABI_O32() && !MipsFI->globalBaseRegFixed()) { // See MipsInstrInfo.td for explanation. MachineBasicBlock *NewEntry = MF.CreateMachineBasicBlock(); MF.insert(&MBB, NewEntry); NewEntry->addSuccessor(&MBB); // Copy live in registers. for (MachineBasicBlock::livein_iterator R = MBB.livein_begin(); R != MBB.livein_end(); ++R) NewEntry->addLiveIn(*R); BuildMI(*NewEntry, NewEntry->begin(), dl, TII.get(Mips:: SETGP01), Mips::V0); } // No need to allocate space on the stack. if (StackSize == 0 && !MFI->adjustsStack()) return; MachineModuleInfo &MMI = MF.getMMI(); std::vector<MachineMove> &Moves = MMI.getFrameMoves(); MachineLocation DstML, SrcML; // Adjust stack. if (isInt<16>(-StackSize)) // addi sp, sp, (-stacksize) BuildMI(MBB, MBBI, dl, TII.get(ADDiu), SP).addReg(SP).addImm(-StackSize); else { // Expand immediate that doesn't fit in 16-bit. MipsFI->setEmitNOAT(); expandLargeImm(SP, -StackSize, STI.isABI_N64(), TII, MBB, MBBI, dl); } // emit ".cfi_def_cfa_offset StackSize" MCSymbol *AdjustSPLabel = MMI.getContext().CreateTempSymbol(); BuildMI(MBB, MBBI, dl, TII.get(TargetOpcode::PROLOG_LABEL)).addSym(AdjustSPLabel); DstML = MachineLocation(MachineLocation::VirtualFP); SrcML = MachineLocation(MachineLocation::VirtualFP, -StackSize); Moves.push_back(MachineMove(AdjustSPLabel, DstML, SrcML)); const std::vector<CalleeSavedInfo> &CSI = MFI->getCalleeSavedInfo(); if (CSI.size()) { // Find the instruction past the last instruction that saves a callee-saved // register to the stack. for (unsigned i = 0; i < CSI.size(); ++i) ++MBBI; // Iterate over list of callee-saved registers and emit .cfi_offset // directives. MCSymbol *CSLabel = MMI.getContext().CreateTempSymbol(); BuildMI(MBB, MBBI, dl, TII.get(TargetOpcode::PROLOG_LABEL)).addSym(CSLabel); for (std::vector<CalleeSavedInfo>::const_iterator I = CSI.begin(), E = CSI.end(); I != E; ++I) { int64_t Offset = MFI->getObjectOffset(I->getFrameIdx()); unsigned Reg = I->getReg(); // If Reg is a double precision register, emit two cfa_offsets, // one for each of the paired single precision registers. if (Mips::AFGR64RegisterClass->contains(Reg)) { const uint16_t *SubRegs = RegInfo->getSubRegisters(Reg); MachineLocation DstML0(MachineLocation::VirtualFP, Offset); MachineLocation DstML1(MachineLocation::VirtualFP, Offset + 4); MachineLocation SrcML0(*SubRegs); MachineLocation SrcML1(*(SubRegs + 1)); if (!STI.isLittle()) std::swap(SrcML0, SrcML1); Moves.push_back(MachineMove(CSLabel, DstML0, SrcML0)); Moves.push_back(MachineMove(CSLabel, DstML1, SrcML1)); } else { // Reg is either in CPURegs or FGR32. DstML = MachineLocation(MachineLocation::VirtualFP, Offset); SrcML = MachineLocation(Reg); Moves.push_back(MachineMove(CSLabel, DstML, SrcML)); } } } // if framepointer enabled, set it to point to the stack pointer. if (hasFP(MF)) { // Insert instruction "move $fp, $sp" at this location. BuildMI(MBB, MBBI, dl, TII.get(ADDu), FP).addReg(SP).addReg(ZERO); // emit ".cfi_def_cfa_register $fp" MCSymbol *SetFPLabel = MMI.getContext().CreateTempSymbol(); BuildMI(MBB, MBBI, dl, TII.get(TargetOpcode::PROLOG_LABEL)).addSym(SetFPLabel); DstML = MachineLocation(FP); SrcML = MachineLocation(MachineLocation::VirtualFP); Moves.push_back(MachineMove(SetFPLabel, DstML, SrcML)); } // Restore GP from the saved stack location if (MipsFI->needGPSaveRestore()) { unsigned Offset = MFI->getObjectOffset(MipsFI->getGPFI()); BuildMI(MBB, MBBI, dl, TII.get(Mips::CPRESTORE)).addImm(Offset) .addReg(Mips::GP); } }
/// Insert prolog code into the function. /// For ARC, this inserts a call to a function that puts required callee saved /// registers onto the stack, when enough callee saved registers are required. void ARCFrameLowering::emitPrologue(MachineFunction &MF, MachineBasicBlock &MBB) const { LLVM_DEBUG(dbgs() << "Emit Prologue: " << MF.getName() << "\n"); auto *AFI = MF.getInfo<ARCFunctionInfo>(); MachineModuleInfo &MMI = MF.getMMI(); MCContext &Context = MMI.getContext(); const MCRegisterInfo *MRI = Context.getRegisterInfo(); const ARCInstrInfo *TII = MF.getSubtarget<ARCSubtarget>().getInstrInfo(); MachineBasicBlock::iterator MBBI = MBB.begin(); // Debug location must be unknown since the first debug location is used // to determine the end of the prologue. DebugLoc dl; MachineFrameInfo &MFI = MF.getFrameInfo(); const std::vector<CalleeSavedInfo> &CSI = MFI.getCalleeSavedInfo(); unsigned Last = determineLastCalleeSave(CSI); unsigned StackSlotsUsedByFunclet = 0; bool SavedBlink = false; unsigned AlreadyAdjusted = 0; if (MF.getFunction().isVarArg()) { // Add in the varargs area here first. LLVM_DEBUG(dbgs() << "Varargs\n"); unsigned VarArgsBytes = MFI.getObjectSize(AFI->getVarArgsFrameIndex()); BuildMI(MBB, MBBI, dl, TII->get(ARC::SUB_rru6)) .addReg(ARC::SP) .addReg(ARC::SP) .addImm(VarArgsBytes); } if (hasFP(MF)) { LLVM_DEBUG(dbgs() << "Saving FP\n"); BuildMI(MBB, MBBI, dl, TII->get(ARC::ST_AW_rs9)) .addReg(ARC::SP, RegState::Define) .addReg(ARC::FP) .addReg(ARC::SP) .addImm(-4); AlreadyAdjusted += 4; } if (UseSaveRestoreFunclet && Last > ARC::R14) { LLVM_DEBUG(dbgs() << "Creating store funclet.\n"); // BL to __save_r13_to_<TRI->getRegAsmName()> StackSlotsUsedByFunclet = Last - ARC::R12; BuildMI(MBB, MBBI, dl, TII->get(ARC::PUSH_S_BLINK)); BuildMI(MBB, MBBI, dl, TII->get(ARC::SUB_rru6)) .addReg(ARC::SP) .addReg(ARC::SP) .addImm(4 * StackSlotsUsedByFunclet); BuildMI(MBB, MBBI, dl, TII->get(ARC::BL)) .addExternalSymbol(store_funclet_name[Last - ARC::R15]) .addReg(ARC::BLINK, RegState::Implicit | RegState::Kill); AlreadyAdjusted += 4 * (StackSlotsUsedByFunclet + 1); SavedBlink = true; } // If we haven't saved BLINK, but we need to...do that now. if (MFI.hasCalls() && !SavedBlink) { LLVM_DEBUG(dbgs() << "Creating save blink.\n"); BuildMI(MBB, MBBI, dl, TII->get(ARC::PUSH_S_BLINK)); AlreadyAdjusted += 4; } if (AFI->MaxCallStackReq > 0) MFI.setStackSize(MFI.getStackSize() + AFI->MaxCallStackReq); // We have already saved some of the stack... LLVM_DEBUG(dbgs() << "Adjusting stack by: " << (MFI.getStackSize() - AlreadyAdjusted) << "\n"); generateStackAdjustment(MBB, MBBI, *ST.getInstrInfo(), dl, -(MFI.getStackSize() - AlreadyAdjusted), ARC::SP); if (hasFP(MF)) { LLVM_DEBUG(dbgs() << "Setting FP from SP.\n"); BuildMI(MBB, MBBI, dl, TII->get(isUInt<6>(MFI.getStackSize()) ? ARC::ADD_rru6 : ARC::ADD_rrlimm), ARC::FP) .addReg(ARC::SP) .addImm(MFI.getStackSize()); } // Emit CFI records: // .cfi_def_cfa_offset StackSize // .cfi_offset fp, -StackSize // .cfi_offset blink, -StackSize+4 unsigned CFIIndex = MF.addFrameInst( MCCFIInstruction::createDefCfaOffset(nullptr, -MFI.getStackSize())); BuildMI(MBB, MBBI, dl, TII->get(TargetOpcode::CFI_INSTRUCTION)) .addCFIIndex(CFIIndex) .setMIFlags(MachineInstr::FrameSetup); int CurOffset = -4; if (hasFP(MF)) { CFIIndex = MF.addFrameInst(MCCFIInstruction::createOffset( nullptr, MRI->getDwarfRegNum(ARC::FP, true), CurOffset)); BuildMI(MBB, MBBI, dl, TII->get(TargetOpcode::CFI_INSTRUCTION)) .addCFIIndex(CFIIndex) .setMIFlags(MachineInstr::FrameSetup); CurOffset -= 4; } if (MFI.hasCalls()) { CFIIndex = MF.addFrameInst(MCCFIInstruction::createOffset( nullptr, MRI->getDwarfRegNum(ARC::BLINK, true), CurOffset)); BuildMI(MBB, MBBI, dl, TII->get(TargetOpcode::CFI_INSTRUCTION)) .addCFIIndex(CFIIndex) .setMIFlags(MachineInstr::FrameSetup); } // CFI for the rest of the registers. for (const auto &Entry : CSI) { unsigned Reg = Entry.getReg(); int FI = Entry.getFrameIdx(); // Skip BLINK and FP. if ((hasFP(MF) && Reg == ARC::FP) || (MFI.hasCalls() && Reg == ARC::BLINK)) continue; CFIIndex = MF.addFrameInst(MCCFIInstruction::createOffset( nullptr, MRI->getDwarfRegNum(Reg, true), MFI.getObjectOffset(FI))); BuildMI(MBB, MBBI, dl, TII->get(TargetOpcode::CFI_INSTRUCTION)) .addCFIIndex(CFIIndex) .setMIFlags(MachineInstr::FrameSetup); } }
void MipsFrameLowering::emitPrologue(MachineFunction &MF) const { MachineBasicBlock &MBB = MF.front(); MachineFrameInfo *MFI = MF.getFrameInfo(); MipsFunctionInfo *MipsFI = MF.getInfo<MipsFunctionInfo>(); const MipsRegisterInfo *RegInfo = static_cast<const MipsRegisterInfo*>(MF.getTarget().getRegisterInfo()); const MipsInstrInfo &TII = *static_cast<const MipsInstrInfo*>(MF.getTarget().getInstrInfo()); MachineBasicBlock::iterator MBBI = MBB.begin(); DebugLoc dl = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc(); bool isPIC = (MF.getTarget().getRelocationModel() == Reloc::PIC_); unsigned NewReg = 0; int NewImm = 0; bool ATUsed; // First, compute final stack size. unsigned RegSize = STI.isGP32bit() ? 4 : 8; unsigned StackAlign = getStackAlignment(); unsigned LocalVarAreaOffset = MipsFI->needGPSaveRestore() ? (MFI->getObjectOffset(MipsFI->getGPFI()) + RegSize) : MipsFI->getMaxCallFrameSize(); unsigned StackSize = AlignOffset(LocalVarAreaOffset, StackAlign) + AlignOffset(MFI->getStackSize(), StackAlign); // Update stack size MFI->setStackSize(StackSize); BuildMI(MBB, MBBI, dl, TII.get(Mips::NOREORDER)); // TODO: check need from GP here. if (isPIC && STI.isABI_O32()) BuildMI(MBB, MBBI, dl, TII.get(Mips::CPLOAD)) .addReg(RegInfo->getPICCallReg()); BuildMI(MBB, MBBI, dl, TII.get(Mips::NOMACRO)); // No need to allocate space on the stack. if (StackSize == 0 && !MFI->adjustsStack()) return; // Adjust stack : addi sp, sp, (-imm) ATUsed = expandRegLargeImmPair(Mips::SP, -StackSize, NewReg, NewImm, MBB, MBBI); BuildMI(MBB, MBBI, dl, TII.get(Mips::ADDiu), Mips::SP) .addReg(NewReg).addImm(NewImm); // FIXME: change this when mips goes MC". if (ATUsed) BuildMI(MBB, MBBI, dl, TII.get(Mips::ATMACRO)); // Find the instruction past the last instruction that saves a callee-saved // register to the stack. const std::vector<CalleeSavedInfo> &CSI = MFI->getCalleeSavedInfo(); for (unsigned i = 0; i < CSI.size(); ++i) ++MBBI; // if framepointer enabled, set it to point to the stack pointer. if (hasFP(MF)) // Insert instruction "move $fp, $sp" at this location. BuildMI(MBB, MBBI, dl, TII.get(Mips::ADDu), Mips::FP) .addReg(Mips::SP).addReg(Mips::ZERO); // Restore GP from the saved stack location if (MipsFI->needGPSaveRestore()) BuildMI(MBB, MBBI, dl, TII.get(Mips::CPRESTORE)) .addImm(MFI->getObjectOffset(MipsFI->getGPFI())); // EH Frame infomation. MachineModuleInfo &MMI = MF.getMMI(); std::vector<MachineMove> &Moves = MMI.getFrameMoves(); MCSymbol *FrameLabel = MMI.getContext().CreateTempSymbol(); BuildMI(MBB, MBBI, dl, TII.get(TargetOpcode::PROLOG_LABEL)).addSym(FrameLabel); if (hasFP(MF)) { MachineLocation SPDst(Mips::FP); MachineLocation SPSrc(Mips::SP); Moves.push_back(MachineMove(FrameLabel, SPDst, SPSrc)); } if (StackSize) { MachineLocation SPDst(MachineLocation::VirtualFP); MachineLocation SPSrc(MachineLocation::VirtualFP, -StackSize); Moves.push_back(MachineMove(FrameLabel, SPDst, SPSrc)); } for (std::vector<CalleeSavedInfo>::const_iterator I = CSI.begin(), E = CSI.end(); I != E; ++I) { int64_t Offset = MFI->getObjectOffset(I->getFrameIdx()); MachineLocation CSDst(MachineLocation::VirtualFP, Offset); MachineLocation CSSrc(I->getReg()); Moves.push_back(MachineMove(FrameLabel, CSDst, CSSrc)); } }
DenseMap<const MachineBasicBlock *, int> llvm::getFuncletMembership(const MachineFunction &MF) { DenseMap<const MachineBasicBlock *, int> FuncletMembership; // We don't have anything to do if there aren't any EH pads. if (!MF.getMMI().hasEHFunclets()) return FuncletMembership; int EntryBBNumber = MF.front().getNumber(); bool IsSEH = isAsynchronousEHPersonality( classifyEHPersonality(MF.getFunction()->getPersonalityFn())); const TargetInstrInfo *TII = MF.getSubtarget().getInstrInfo(); SmallVector<const MachineBasicBlock *, 16> FuncletBlocks; SmallVector<const MachineBasicBlock *, 16> UnreachableBlocks; SmallVector<const MachineBasicBlock *, 16> SEHCatchPads; SmallVector<std::pair<const MachineBasicBlock *, int>, 16> CatchRetSuccessors; for (const MachineBasicBlock &MBB : MF) { if (MBB.isEHFuncletEntry()) { FuncletBlocks.push_back(&MBB); } else if (IsSEH && MBB.isEHPad()) { SEHCatchPads.push_back(&MBB); } else if (MBB.pred_empty()) { UnreachableBlocks.push_back(&MBB); } MachineBasicBlock::const_iterator MBBI = MBB.getFirstTerminator(); // CatchPads are not funclets for SEH so do not consider CatchRet to // transfer control to another funclet. if (MBBI->getOpcode() != TII->getCatchReturnOpcode()) continue; // FIXME: SEH CatchPads are not necessarily in the parent function: // they could be inside a finally block. const MachineBasicBlock *Successor = MBBI->getOperand(0).getMBB(); const MachineBasicBlock *SuccessorColor = MBBI->getOperand(1).getMBB(); CatchRetSuccessors.push_back( {Successor, IsSEH ? EntryBBNumber : SuccessorColor->getNumber()}); } // We don't have anything to do if there aren't any EH pads. if (FuncletBlocks.empty()) return FuncletMembership; // Identify all the basic blocks reachable from the function entry. collectFuncletMembers(FuncletMembership, EntryBBNumber, &MF.front()); // All blocks not part of a funclet are in the parent function. for (const MachineBasicBlock *MBB : UnreachableBlocks) collectFuncletMembers(FuncletMembership, EntryBBNumber, MBB); // Next, identify all the blocks inside the funclets. for (const MachineBasicBlock *MBB : FuncletBlocks) collectFuncletMembers(FuncletMembership, MBB->getNumber(), MBB); // SEH CatchPads aren't really funclets, handle them separately. for (const MachineBasicBlock *MBB : SEHCatchPads) collectFuncletMembers(FuncletMembership, EntryBBNumber, MBB); // Finally, identify all the targets of a catchret. for (std::pair<const MachineBasicBlock *, int> CatchRetPair : CatchRetSuccessors) collectFuncletMembers(FuncletMembership, CatchRetPair.second, CatchRetPair.first); return FuncletMembership; }
void AArch64FrameLowering::emitPrologue(MachineFunction &MF, MachineBasicBlock &MBB) const { MachineBasicBlock::iterator MBBI = MBB.begin(); const MachineFrameInfo *MFI = MF.getFrameInfo(); const Function *Fn = MF.getFunction(); const AArch64Subtarget &Subtarget = MF.getSubtarget<AArch64Subtarget>(); const AArch64RegisterInfo *RegInfo = Subtarget.getRegisterInfo(); const TargetInstrInfo *TII = Subtarget.getInstrInfo(); MachineModuleInfo &MMI = MF.getMMI(); AArch64FunctionInfo *AFI = MF.getInfo<AArch64FunctionInfo>(); bool needsFrameMoves = MMI.hasDebugInfo() || Fn->needsUnwindTableEntry(); bool HasFP = hasFP(MF); // Debug location must be unknown since the first debug location is used // to determine the end of the prologue. DebugLoc DL; // All calls are tail calls in GHC calling conv, and functions have no // prologue/epilogue. if (MF.getFunction()->getCallingConv() == CallingConv::GHC) return; int NumBytes = (int)MFI->getStackSize(); if (!AFI->hasStackFrame()) { assert(!HasFP && "unexpected function without stack frame but with FP"); // All of the stack allocation is for locals. AFI->setLocalStackSize(NumBytes); // Label used to tie together the PROLOG_LABEL and the MachineMoves. MCSymbol *FrameLabel = MMI.getContext().createTempSymbol(); // REDZONE: If the stack size is less than 128 bytes, we don't need // to actually allocate. if (NumBytes && !canUseRedZone(MF)) { emitFrameOffset(MBB, MBBI, DL, AArch64::SP, AArch64::SP, -NumBytes, TII, MachineInstr::FrameSetup); // Encode the stack size of the leaf function. unsigned CFIIndex = MMI.addFrameInst( MCCFIInstruction::createDefCfaOffset(FrameLabel, -NumBytes)); BuildMI(MBB, MBBI, DL, TII->get(TargetOpcode::CFI_INSTRUCTION)) .addCFIIndex(CFIIndex) .setMIFlags(MachineInstr::FrameSetup); } else if (NumBytes) { ++NumRedZoneFunctions; } return; } // Only set up FP if we actually need to. int FPOffset = 0; if (HasFP) FPOffset = getFPOffsetInPrologue(MBBI); // Move past the saves of the callee-saved registers. while (isCSSave(MBBI)) { ++MBBI; NumBytes -= 16; } assert(NumBytes >= 0 && "Negative stack allocation size!?"); if (HasFP) { // Issue sub fp, sp, FPOffset or // mov fp,sp when FPOffset is zero. // Note: All stores of callee-saved registers are marked as "FrameSetup". // This code marks the instruction(s) that set the FP also. emitFrameOffset(MBB, MBBI, DL, AArch64::FP, AArch64::SP, FPOffset, TII, MachineInstr::FrameSetup); } // All of the remaining stack allocations are for locals. AFI->setLocalStackSize(NumBytes); // Allocate space for the rest of the frame. const unsigned Alignment = MFI->getMaxAlignment(); const bool NeedsRealignment = RegInfo->needsStackRealignment(MF); unsigned scratchSPReg = AArch64::SP; if (NumBytes && NeedsRealignment) { // Use the first callee-saved register as a scratch register. scratchSPReg = AArch64::X9; } // If we're a leaf function, try using the red zone. if (NumBytes && !canUseRedZone(MF)) // FIXME: in the case of dynamic re-alignment, NumBytes doesn't have // the correct value here, as NumBytes also includes padding bytes, // which shouldn't be counted here. emitFrameOffset(MBB, MBBI, DL, scratchSPReg, AArch64::SP, -NumBytes, TII, MachineInstr::FrameSetup); if (NumBytes && NeedsRealignment) { const unsigned NrBitsToZero = countTrailingZeros(Alignment); assert(NrBitsToZero > 1); assert(scratchSPReg != AArch64::SP); // SUB X9, SP, NumBytes // -- X9 is temporary register, so shouldn't contain any live data here, // -- free to use. This is already produced by emitFrameOffset above. // AND SP, X9, 0b11111...0000 // The logical immediates have a non-trivial encoding. The following // formula computes the encoded immediate with all ones but // NrBitsToZero zero bits as least significant bits. uint32_t andMaskEncoded = (1 <<12) // = N | ((64-NrBitsToZero) << 6) // immr | ((64-NrBitsToZero-1) << 0) // imms ; BuildMI(MBB, MBBI, DL, TII->get(AArch64::ANDXri), AArch64::SP) .addReg(scratchSPReg, RegState::Kill) .addImm(andMaskEncoded); } // If we need a base pointer, set it up here. It's whatever the value of the // stack pointer is at this point. Any variable size objects will be allocated // after this, so we can still use the base pointer to reference locals. // // FIXME: Clarify FrameSetup flags here. // Note: Use emitFrameOffset() like above for FP if the FrameSetup flag is // needed. if (RegInfo->hasBasePointer(MF)) { TII->copyPhysReg(MBB, MBBI, DL, RegInfo->getBaseRegister(), AArch64::SP, false); } if (needsFrameMoves) { const DataLayout &TD = MF.getDataLayout(); const int StackGrowth = -TD.getPointerSize(0); unsigned FramePtr = RegInfo->getFrameRegister(MF); // An example of the prologue: // // .globl __foo // .align 2 // __foo: // Ltmp0: // .cfi_startproc // .cfi_personality 155, ___gxx_personality_v0 // Leh_func_begin: // .cfi_lsda 16, Lexception33 // // stp xa,bx, [sp, -#offset]! // ... // stp x28, x27, [sp, #offset-32] // stp fp, lr, [sp, #offset-16] // add fp, sp, #offset - 16 // sub sp, sp, #1360 // // The Stack: // +-------------------------------------------+ // 10000 | ........ | ........ | ........ | ........ | // 10004 | ........ | ........ | ........ | ........ | // +-------------------------------------------+ // 10008 | ........ | ........ | ........ | ........ | // 1000c | ........ | ........ | ........ | ........ | // +===========================================+ // 10010 | X28 Register | // 10014 | X28 Register | // +-------------------------------------------+ // 10018 | X27 Register | // 1001c | X27 Register | // +===========================================+ // 10020 | Frame Pointer | // 10024 | Frame Pointer | // +-------------------------------------------+ // 10028 | Link Register | // 1002c | Link Register | // +===========================================+ // 10030 | ........ | ........ | ........ | ........ | // 10034 | ........ | ........ | ........ | ........ | // +-------------------------------------------+ // 10038 | ........ | ........ | ........ | ........ | // 1003c | ........ | ........ | ........ | ........ | // +-------------------------------------------+ // // [sp] = 10030 :: >>initial value<< // sp = 10020 :: stp fp, lr, [sp, #-16]! // fp = sp == 10020 :: mov fp, sp // [sp] == 10020 :: stp x28, x27, [sp, #-16]! // sp == 10010 :: >>final value<< // // The frame pointer (w29) points to address 10020. If we use an offset of // '16' from 'w29', we get the CFI offsets of -8 for w30, -16 for w29, -24 // for w27, and -32 for w28: // // Ltmp1: // .cfi_def_cfa w29, 16 // Ltmp2: // .cfi_offset w30, -8 // Ltmp3: // .cfi_offset w29, -16 // Ltmp4: // .cfi_offset w27, -24 // Ltmp5: // .cfi_offset w28, -32 if (HasFP) { // Define the current CFA rule to use the provided FP. unsigned Reg = RegInfo->getDwarfRegNum(FramePtr, true); unsigned CFIIndex = MMI.addFrameInst( MCCFIInstruction::createDefCfa(nullptr, Reg, 2 * StackGrowth)); BuildMI(MBB, MBBI, DL, TII->get(TargetOpcode::CFI_INSTRUCTION)) .addCFIIndex(CFIIndex) .setMIFlags(MachineInstr::FrameSetup); // Record the location of the stored LR unsigned LR = RegInfo->getDwarfRegNum(AArch64::LR, true); CFIIndex = MMI.addFrameInst( MCCFIInstruction::createOffset(nullptr, LR, StackGrowth)); BuildMI(MBB, MBBI, DL, TII->get(TargetOpcode::CFI_INSTRUCTION)) .addCFIIndex(CFIIndex) .setMIFlags(MachineInstr::FrameSetup); // Record the location of the stored FP CFIIndex = MMI.addFrameInst( MCCFIInstruction::createOffset(nullptr, Reg, 2 * StackGrowth)); BuildMI(MBB, MBBI, DL, TII->get(TargetOpcode::CFI_INSTRUCTION)) .addCFIIndex(CFIIndex) .setMIFlags(MachineInstr::FrameSetup); } else { // Encode the stack size of the leaf function. unsigned CFIIndex = MMI.addFrameInst( MCCFIInstruction::createDefCfaOffset(nullptr, -MFI->getStackSize())); BuildMI(MBB, MBBI, DL, TII->get(TargetOpcode::CFI_INSTRUCTION)) .addCFIIndex(CFIIndex) .setMIFlags(MachineInstr::FrameSetup); } // Now emit the moves for whatever callee saved regs we have. emitCalleeSavedFrameMoves(MBB, MBBI, FramePtr); } }
void AArch64FrameLowering::emitPrologue(MachineFunction &MF) const { MachineBasicBlock &MBB = MF.front(); // Prologue goes in entry BB. MachineBasicBlock::iterator MBBI = MBB.begin(); const MachineFrameInfo *MFI = MF.getFrameInfo(); const Function *Fn = MF.getFunction(); const AArch64RegisterInfo *RegInfo = static_cast<const AArch64RegisterInfo *>( MF.getSubtarget().getRegisterInfo()); const TargetInstrInfo *TII = MF.getSubtarget().getInstrInfo(); MachineModuleInfo &MMI = MF.getMMI(); AArch64FunctionInfo *AFI = MF.getInfo<AArch64FunctionInfo>(); bool needsFrameMoves = MMI.hasDebugInfo() || Fn->needsUnwindTableEntry(); bool HasFP = hasFP(MF); DebugLoc DL = MBB.findDebugLoc(MBBI); int NumBytes = (int)MFI->getStackSize(); if (!AFI->hasStackFrame()) { assert(!HasFP && "unexpected function without stack frame but with FP"); // All of the stack allocation is for locals. AFI->setLocalStackSize(NumBytes); // Label used to tie together the PROLOG_LABEL and the MachineMoves. MCSymbol *FrameLabel = MMI.getContext().CreateTempSymbol(); // REDZONE: If the stack size is less than 128 bytes, we don't need // to actually allocate. if (NumBytes && !canUseRedZone(MF)) { emitFrameOffset(MBB, MBBI, DL, AArch64::SP, AArch64::SP, -NumBytes, TII, MachineInstr::FrameSetup); // Encode the stack size of the leaf function. unsigned CFIIndex = MMI.addFrameInst( MCCFIInstruction::createDefCfaOffset(FrameLabel, -NumBytes)); BuildMI(MBB, MBBI, DL, TII->get(TargetOpcode::CFI_INSTRUCTION)) .addCFIIndex(CFIIndex); } else if (NumBytes) { ++NumRedZoneFunctions; } return; } // Only set up FP if we actually need to. int FPOffset = 0; if (HasFP) { // First instruction must a) allocate the stack and b) have an immediate // that is a multiple of -2. assert((MBBI->getOpcode() == AArch64::STPXpre || MBBI->getOpcode() == AArch64::STPDpre) && MBBI->getOperand(3).getReg() == AArch64::SP && MBBI->getOperand(4).getImm() < 0 && (MBBI->getOperand(4).getImm() & 1) == 0); // Frame pointer is fp = sp - 16. Since the STPXpre subtracts the space // required for the callee saved register area we get the frame pointer // by addding that offset - 16 = -getImm()*8 - 2*8 = -(getImm() + 2) * 8. FPOffset = -(MBBI->getOperand(4).getImm() + 2) * 8; assert(FPOffset >= 0 && "Bad Framepointer Offset"); } // Move past the saves of the callee-saved registers. while (MBBI->getOpcode() == AArch64::STPXi || MBBI->getOpcode() == AArch64::STPDi || MBBI->getOpcode() == AArch64::STPXpre || MBBI->getOpcode() == AArch64::STPDpre) { ++MBBI; NumBytes -= 16; } assert(NumBytes >= 0 && "Negative stack allocation size!?"); if (HasFP) { // Issue sub fp, sp, FPOffset or // mov fp,sp when FPOffset is zero. // Note: All stores of callee-saved registers are marked as "FrameSetup". // This code marks the instruction(s) that set the FP also. emitFrameOffset(MBB, MBBI, DL, AArch64::FP, AArch64::SP, FPOffset, TII, MachineInstr::FrameSetup); } // All of the remaining stack allocations are for locals. AFI->setLocalStackSize(NumBytes); // Allocate space for the rest of the frame. if (NumBytes) { // If we're a leaf function, try using the red zone. if (!canUseRedZone(MF)) emitFrameOffset(MBB, MBBI, DL, AArch64::SP, AArch64::SP, -NumBytes, TII, MachineInstr::FrameSetup); } // If we need a base pointer, set it up here. It's whatever the value of the // stack pointer is at this point. Any variable size objects will be allocated // after this, so we can still use the base pointer to reference locals. // // FIXME: Clarify FrameSetup flags here. // Note: Use emitFrameOffset() like above for FP if the FrameSetup flag is // needed. // if (RegInfo->hasBasePointer(MF)) TII->copyPhysReg(MBB, MBBI, DL, AArch64::X19, AArch64::SP, false); if (needsFrameMoves) { const DataLayout *TD = MF.getSubtarget().getDataLayout(); const int StackGrowth = -TD->getPointerSize(0); unsigned FramePtr = RegInfo->getFrameRegister(MF); // An example of the prologue: // // .globl __foo // .align 2 // __foo: // Ltmp0: // .cfi_startproc // .cfi_personality 155, ___gxx_personality_v0 // Leh_func_begin: // .cfi_lsda 16, Lexception33 // // stp xa,bx, [sp, -#offset]! // ... // stp x28, x27, [sp, #offset-32] // stp fp, lr, [sp, #offset-16] // add fp, sp, #offset - 16 // sub sp, sp, #1360 // // The Stack: // +-------------------------------------------+ // 10000 | ........ | ........ | ........ | ........ | // 10004 | ........ | ........ | ........ | ........ | // +-------------------------------------------+ // 10008 | ........ | ........ | ........ | ........ | // 1000c | ........ | ........ | ........ | ........ | // +===========================================+ // 10010 | X28 Register | // 10014 | X28 Register | // +-------------------------------------------+ // 10018 | X27 Register | // 1001c | X27 Register | // +===========================================+ // 10020 | Frame Pointer | // 10024 | Frame Pointer | // +-------------------------------------------+ // 10028 | Link Register | // 1002c | Link Register | // +===========================================+ // 10030 | ........ | ........ | ........ | ........ | // 10034 | ........ | ........ | ........ | ........ | // +-------------------------------------------+ // 10038 | ........ | ........ | ........ | ........ | // 1003c | ........ | ........ | ........ | ........ | // +-------------------------------------------+ // // [sp] = 10030 :: >>initial value<< // sp = 10020 :: stp fp, lr, [sp, #-16]! // fp = sp == 10020 :: mov fp, sp // [sp] == 10020 :: stp x28, x27, [sp, #-16]! // sp == 10010 :: >>final value<< // // The frame pointer (w29) points to address 10020. If we use an offset of // '16' from 'w29', we get the CFI offsets of -8 for w30, -16 for w29, -24 // for w27, and -32 for w28: // // Ltmp1: // .cfi_def_cfa w29, 16 // Ltmp2: // .cfi_offset w30, -8 // Ltmp3: // .cfi_offset w29, -16 // Ltmp4: // .cfi_offset w27, -24 // Ltmp5: // .cfi_offset w28, -32 if (HasFP) { // Define the current CFA rule to use the provided FP. unsigned Reg = RegInfo->getDwarfRegNum(FramePtr, true); unsigned CFIIndex = MMI.addFrameInst( MCCFIInstruction::createDefCfa(nullptr, Reg, 2 * StackGrowth)); BuildMI(MBB, MBBI, DL, TII->get(TargetOpcode::CFI_INSTRUCTION)) .addCFIIndex(CFIIndex); // Record the location of the stored LR unsigned LR = RegInfo->getDwarfRegNum(AArch64::LR, true); CFIIndex = MMI.addFrameInst( MCCFIInstruction::createOffset(nullptr, LR, StackGrowth)); BuildMI(MBB, MBBI, DL, TII->get(TargetOpcode::CFI_INSTRUCTION)) .addCFIIndex(CFIIndex); // Record the location of the stored FP CFIIndex = MMI.addFrameInst( MCCFIInstruction::createOffset(nullptr, Reg, 2 * StackGrowth)); BuildMI(MBB, MBBI, DL, TII->get(TargetOpcode::CFI_INSTRUCTION)) .addCFIIndex(CFIIndex); } else { // Encode the stack size of the leaf function. unsigned CFIIndex = MMI.addFrameInst( MCCFIInstruction::createDefCfaOffset(nullptr, -MFI->getStackSize())); BuildMI(MBB, MBBI, DL, TII->get(TargetOpcode::CFI_INSTRUCTION)) .addCFIIndex(CFIIndex); } // Now emit the moves for whatever callee saved regs we have. emitCalleeSavedFrameMoves(MBB, MBBI, FramePtr); } }
/// calculateCalleeSavedRegisters - Scan the function for modified callee saved /// registers. void PEI::calculateCalleeSavedRegisters(MachineFunction &F) { const TargetRegisterInfo *RegInfo = F.getSubtarget().getRegisterInfo(); const TargetFrameLowering *TFI = F.getSubtarget().getFrameLowering(); MachineFrameInfo *MFI = F.getFrameInfo(); // Get the callee saved register list... const MCPhysReg *CSRegs = RegInfo->getCalleeSavedRegs(&F); // These are used to keep track the callee-save area. Initialize them. MinCSFrameIndex = INT_MAX; MaxCSFrameIndex = 0; // Early exit for targets which have no callee saved registers. if (!CSRegs || CSRegs[0] == 0) return; // In Naked functions we aren't going to save any registers. if (F.getFunction()->hasFnAttribute(Attribute::Naked)) return; std::vector<CalleeSavedInfo> CSI; for (unsigned i = 0; CSRegs[i]; ++i) { unsigned Reg = CSRegs[i]; // Functions which call __builtin_unwind_init get all their registers saved. if (F.getRegInfo().isPhysRegUsed(Reg) || F.getMMI().callsUnwindInit()) { // If the reg is modified, save it! CSI.push_back(CalleeSavedInfo(Reg)); } } if (!TFI->assignCalleeSavedSpillSlots(F, RegInfo, CSI)) { // If target doesn't implement this, use generic code. if (CSI.empty()) return; // Early exit if no callee saved registers are modified! unsigned NumFixedSpillSlots; const TargetFrameLowering::SpillSlot *FixedSpillSlots = TFI->getCalleeSavedSpillSlots(NumFixedSpillSlots); // Now that we know which registers need to be saved and restored, allocate // stack slots for them. for (std::vector<CalleeSavedInfo>::iterator I = CSI.begin(), E = CSI.end(); I != E; ++I) { unsigned Reg = I->getReg(); const TargetRegisterClass *RC = RegInfo->getMinimalPhysRegClass(Reg); int FrameIdx; if (RegInfo->hasReservedSpillSlot(F, Reg, FrameIdx)) { I->setFrameIdx(FrameIdx); continue; } // Check to see if this physreg must be spilled to a particular stack slot // on this target. const TargetFrameLowering::SpillSlot *FixedSlot = FixedSpillSlots; while (FixedSlot != FixedSpillSlots + NumFixedSpillSlots && FixedSlot->Reg != Reg) ++FixedSlot; if (FixedSlot == FixedSpillSlots + NumFixedSpillSlots) { // Nope, just spill it anywhere convenient. unsigned Align = RC->getAlignment(); unsigned StackAlign = TFI->getStackAlignment(); // We may not be able to satisfy the desired alignment specification of // the TargetRegisterClass if the stack alignment is smaller. Use the // min. Align = std::min(Align, StackAlign); FrameIdx = MFI->CreateStackObject(RC->getSize(), Align, true); if ((unsigned)FrameIdx < MinCSFrameIndex) MinCSFrameIndex = FrameIdx; if ((unsigned)FrameIdx > MaxCSFrameIndex) MaxCSFrameIndex = FrameIdx; } else { // Spill it to the stack where we must. FrameIdx = MFI->CreateFixedSpillStackObject(RC->getSize(), FixedSlot->Offset); } I->setFrameIdx(FrameIdx); } } MFI->setCalleeSavedInfo(CSI); }
void Thumb1FrameLowering::emitPrologue(MachineFunction &MF, MachineBasicBlock &MBB) const { MachineBasicBlock::iterator MBBI = MBB.begin(); MachineFrameInfo *MFI = MF.getFrameInfo(); ARMFunctionInfo *AFI = MF.getInfo<ARMFunctionInfo>(); MachineModuleInfo &MMI = MF.getMMI(); const MCRegisterInfo *MRI = MMI.getContext().getRegisterInfo(); const ThumbRegisterInfo *RegInfo = static_cast<const ThumbRegisterInfo *>(STI.getRegisterInfo()); const Thumb1InstrInfo &TII = *static_cast<const Thumb1InstrInfo *>(STI.getInstrInfo()); unsigned ArgRegsSaveSize = AFI->getArgRegsSaveSize(); unsigned NumBytes = MFI->getStackSize(); assert(NumBytes >= ArgRegsSaveSize && "ArgRegsSaveSize is included in NumBytes"); const std::vector<CalleeSavedInfo> &CSI = MFI->getCalleeSavedInfo(); // Debug location must be unknown since the first debug location is used // to determine the end of the prologue. DebugLoc dl; unsigned FramePtr = RegInfo->getFrameRegister(MF); unsigned BasePtr = RegInfo->getBaseRegister(); int CFAOffset = 0; // Thumb add/sub sp, imm8 instructions implicitly multiply the offset by 4. NumBytes = (NumBytes + 3) & ~3; MFI->setStackSize(NumBytes); // Determine the sizes of each callee-save spill areas and record which frame // belongs to which callee-save spill areas. unsigned GPRCS1Size = 0, GPRCS2Size = 0, DPRCSSize = 0; int FramePtrSpillFI = 0; if (ArgRegsSaveSize) { emitSPUpdate(MBB, MBBI, TII, dl, *RegInfo, -ArgRegsSaveSize, MachineInstr::FrameSetup); CFAOffset -= ArgRegsSaveSize; unsigned CFIIndex = MMI.addFrameInst( MCCFIInstruction::createDefCfaOffset(nullptr, CFAOffset)); BuildMI(MBB, MBBI, dl, TII.get(TargetOpcode::CFI_INSTRUCTION)) .addCFIIndex(CFIIndex) .setMIFlags(MachineInstr::FrameSetup); } if (!AFI->hasStackFrame()) { if (NumBytes - ArgRegsSaveSize != 0) { emitSPUpdate(MBB, MBBI, TII, dl, *RegInfo, -(NumBytes - ArgRegsSaveSize), MachineInstr::FrameSetup); CFAOffset -= NumBytes - ArgRegsSaveSize; unsigned CFIIndex = MMI.addFrameInst( MCCFIInstruction::createDefCfaOffset(nullptr, CFAOffset)); BuildMI(MBB, MBBI, dl, TII.get(TargetOpcode::CFI_INSTRUCTION)) .addCFIIndex(CFIIndex) .setMIFlags(MachineInstr::FrameSetup); } return; } for (unsigned i = 0, e = CSI.size(); i != e; ++i) { unsigned Reg = CSI[i].getReg(); int FI = CSI[i].getFrameIdx(); switch (Reg) { case ARM::R8: case ARM::R9: case ARM::R10: case ARM::R11: if (STI.isTargetMachO()) { GPRCS2Size += 4; break; } // fallthrough case ARM::R4: case ARM::R5: case ARM::R6: case ARM::R7: case ARM::LR: if (Reg == FramePtr) FramePtrSpillFI = FI; GPRCS1Size += 4; break; default: DPRCSSize += 8; } } if (MBBI != MBB.end() && MBBI->getOpcode() == ARM::tPUSH) { ++MBBI; } // Determine starting offsets of spill areas. unsigned DPRCSOffset = NumBytes - ArgRegsSaveSize - (GPRCS1Size + GPRCS2Size + DPRCSSize); unsigned GPRCS2Offset = DPRCSOffset + DPRCSSize; unsigned GPRCS1Offset = GPRCS2Offset + GPRCS2Size; bool HasFP = hasFP(MF); if (HasFP) AFI->setFramePtrSpillOffset(MFI->getObjectOffset(FramePtrSpillFI) + NumBytes); AFI->setGPRCalleeSavedArea1Offset(GPRCS1Offset); AFI->setGPRCalleeSavedArea2Offset(GPRCS2Offset); AFI->setDPRCalleeSavedAreaOffset(DPRCSOffset); NumBytes = DPRCSOffset; int FramePtrOffsetInBlock = 0; unsigned adjustedGPRCS1Size = GPRCS1Size; if (tryFoldSPUpdateIntoPushPop(STI, MF, std::prev(MBBI), NumBytes)) { FramePtrOffsetInBlock = NumBytes; adjustedGPRCS1Size += NumBytes; NumBytes = 0; } if (adjustedGPRCS1Size) { CFAOffset -= adjustedGPRCS1Size; unsigned CFIIndex = MMI.addFrameInst( MCCFIInstruction::createDefCfaOffset(nullptr, CFAOffset)); BuildMI(MBB, MBBI, dl, TII.get(TargetOpcode::CFI_INSTRUCTION)) .addCFIIndex(CFIIndex) .setMIFlags(MachineInstr::FrameSetup); } for (std::vector<CalleeSavedInfo>::const_iterator I = CSI.begin(), E = CSI.end(); I != E; ++I) { unsigned Reg = I->getReg(); int FI = I->getFrameIdx(); switch (Reg) { case ARM::R8: case ARM::R9: case ARM::R10: case ARM::R11: case ARM::R12: if (STI.isTargetMachO()) break; // fallthough case ARM::R0: case ARM::R1: case ARM::R2: case ARM::R3: case ARM::R4: case ARM::R5: case ARM::R6: case ARM::R7: case ARM::LR: unsigned CFIIndex = MMI.addFrameInst(MCCFIInstruction::createOffset( nullptr, MRI->getDwarfRegNum(Reg, true), MFI->getObjectOffset(FI))); BuildMI(MBB, MBBI, dl, TII.get(TargetOpcode::CFI_INSTRUCTION)) .addCFIIndex(CFIIndex) .setMIFlags(MachineInstr::FrameSetup); break; } } // Adjust FP so it point to the stack slot that contains the previous FP. if (HasFP) { FramePtrOffsetInBlock += MFI->getObjectOffset(FramePtrSpillFI) + GPRCS1Size + ArgRegsSaveSize; AddDefaultPred(BuildMI(MBB, MBBI, dl, TII.get(ARM::tADDrSPi), FramePtr) .addReg(ARM::SP).addImm(FramePtrOffsetInBlock / 4) .setMIFlags(MachineInstr::FrameSetup)); if(FramePtrOffsetInBlock) { CFAOffset += FramePtrOffsetInBlock; unsigned CFIIndex = MMI.addFrameInst(MCCFIInstruction::createDefCfa( nullptr, MRI->getDwarfRegNum(FramePtr, true), CFAOffset)); BuildMI(MBB, MBBI, dl, TII.get(TargetOpcode::CFI_INSTRUCTION)) .addCFIIndex(CFIIndex) .setMIFlags(MachineInstr::FrameSetup); } else { unsigned CFIIndex = MMI.addFrameInst(MCCFIInstruction::createDefCfaRegister( nullptr, MRI->getDwarfRegNum(FramePtr, true))); BuildMI(MBB, MBBI, dl, TII.get(TargetOpcode::CFI_INSTRUCTION)) .addCFIIndex(CFIIndex) .setMIFlags(MachineInstr::FrameSetup); } if (NumBytes > 508) // If offset is > 508 then sp cannot be adjusted in a single instruction, // try restoring from fp instead. AFI->setShouldRestoreSPFromFP(true); } if (NumBytes) { // Insert it after all the callee-save spills. emitSPUpdate(MBB, MBBI, TII, dl, *RegInfo, -NumBytes, MachineInstr::FrameSetup); if (!HasFP) { CFAOffset -= NumBytes; unsigned CFIIndex = MMI.addFrameInst( MCCFIInstruction::createDefCfaOffset(nullptr, CFAOffset)); BuildMI(MBB, MBBI, dl, TII.get(TargetOpcode::CFI_INSTRUCTION)) .addCFIIndex(CFIIndex) .setMIFlags(MachineInstr::FrameSetup); } } if (STI.isTargetELF() && HasFP) MFI->setOffsetAdjustment(MFI->getOffsetAdjustment() - AFI->getFramePtrSpillOffset()); AFI->setGPRCalleeSavedArea1Size(GPRCS1Size); AFI->setGPRCalleeSavedArea2Size(GPRCS2Size); AFI->setDPRCalleeSavedAreaSize(DPRCSSize); // Thumb1 does not currently support dynamic stack realignment. Report a // fatal error rather then silently generate bad code. if (RegInfo->needsStackRealignment(MF)) report_fatal_error("Dynamic stack realignment not supported for thumb1."); // If we need a base pointer, set it up here. It's whatever the value // of the stack pointer is at this point. Any variable size objects // will be allocated after this, so we can still use the base pointer // to reference locals. if (RegInfo->hasBasePointer(MF)) AddDefaultPred(BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVr), BasePtr) .addReg(ARM::SP)); // If the frame has variable sized objects then the epilogue must restore // the sp from fp. We can assume there's an FP here since hasFP already // checks for hasVarSizedObjects. if (MFI->hasVarSizedObjects()) AFI->setShouldRestoreSPFromFP(true); }