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 = MFI->getMachineModuleInfo(); DebugLoc dl = (MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc::getUnknownLoc()); // Prepare for debug frame info. bool hasDebugInfo = MMI && 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"); if (FrameSize > 0 || MFI->hasCalls()) { 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 (isS10Constant(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 (FrameSize <= (1 << 16) - 1 && FrameSize >= -(1 << 16)) { // 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::STQDr32), 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 { std::string msg; raw_string_ostream Msg(msg); Msg << "Unhandled frame size: " << FrameSize; llvm_report_error(Msg.str()); } 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 X86RegisterInfo::emitPrologue(MachineFunction &MF) const { MachineBasicBlock &MBB = MF.front(); // Prolog goes in entry BB MachineFrameInfo *MFI = MF.getFrameInfo(); const Function* Fn = MF.getFunction(); const X86Subtarget* Subtarget = &MF.getTarget().getSubtarget<X86Subtarget>(); MachineModuleInfo *MMI = MFI->getMachineModuleInfo(); X86MachineFunctionInfo *X86FI = MF.getInfo<X86MachineFunctionInfo>(); MachineBasicBlock::iterator MBBI = MBB.begin(); bool needsFrameMoves = (MMI && MMI->hasDebugInfo()) || !Fn->doesNotThrow() || UnwindTablesMandatory; // Prepare for frame info. unsigned FrameLabelId = 0; // Get the number of bytes to allocate from the FrameInfo. uint64_t StackSize = MFI->getStackSize(); // Get desired stack alignment uint64_t MaxAlign = MFI->getMaxAlignment(); // Add RETADDR move area to callee saved frame size. int TailCallReturnAddrDelta = X86FI->getTCReturnAddrDelta(); if (TailCallReturnAddrDelta < 0) X86FI->setCalleeSavedFrameSize( X86FI->getCalleeSavedFrameSize() +(-TailCallReturnAddrDelta)); // If this is x86-64 and the Red Zone is not disabled, if we are a leaf // function, and use up to 128 bytes of stack space, don't have a frame // pointer, calls, or dynamic alloca then we do not need to adjust the // stack pointer (we fit in the Red Zone). if (Is64Bit && !DisableRedZone && !needsStackRealignment(MF) && !MFI->hasVarSizedObjects() && // No dynamic alloca. !MFI->hasCalls()) { // No calls. uint64_t MinSize = X86FI->getCalleeSavedFrameSize(); if (hasFP(MF)) MinSize += SlotSize; StackSize = std::max(MinSize, StackSize > 128 ? StackSize - 128 : 0); MFI->setStackSize(StackSize); } // Insert stack pointer adjustment for later moving of return addr. Only // applies to tail call optimized functions where the callee argument stack // size is bigger than the callers. if (TailCallReturnAddrDelta < 0) { MachineInstr *MI = BuildMI(MBB, MBBI, TII.get(Is64Bit? X86::SUB64ri32 : X86::SUB32ri), StackPtr).addReg(StackPtr).addImm(-TailCallReturnAddrDelta); // The EFLAGS implicit def is dead. MI->getOperand(3).setIsDead(); } uint64_t NumBytes = 0; if (hasFP(MF)) { // Calculate required stack adjustment uint64_t FrameSize = StackSize - SlotSize; if (needsStackRealignment(MF)) FrameSize = (FrameSize + MaxAlign - 1)/MaxAlign*MaxAlign; NumBytes = FrameSize - X86FI->getCalleeSavedFrameSize(); // Get the offset of the stack slot for the EBP register... which is // guaranteed to be the last slot by processFunctionBeforeFrameFinalized. // Update the frame offset adjustment. MFI->setOffsetAdjustment(-NumBytes); // Save EBP into the appropriate stack slot... BuildMI(MBB, MBBI, TII.get(Is64Bit ? X86::PUSH64r : X86::PUSH32r)) .addReg(FramePtr, /*isDef=*/false, /*isImp=*/false, /*isKill=*/true); if (needsFrameMoves) { // Mark effective beginning of when frame pointer becomes valid. FrameLabelId = MMI->NextLabelID(); BuildMI(MBB, MBBI, TII.get(X86::DBG_LABEL)).addImm(FrameLabelId); } // Update EBP with the new base value... BuildMI(MBB, MBBI, TII.get(Is64Bit ? X86::MOV64rr : X86::MOV32rr), FramePtr) .addReg(StackPtr); // Mark the FramePtr as live-in in every block except the entry. for (MachineFunction::iterator I = next(MF.begin()), E = MF.end(); I != E; ++I) I->addLiveIn(FramePtr); // Realign stack if (needsStackRealignment(MF)) { MachineInstr *MI = BuildMI(MBB, MBBI, TII.get(Is64Bit ? X86::AND64ri32 : X86::AND32ri), StackPtr).addReg(StackPtr).addImm(-MaxAlign); // The EFLAGS implicit def is dead. MI->getOperand(3).setIsDead(); } } else NumBytes = StackSize - X86FI->getCalleeSavedFrameSize(); unsigned ReadyLabelId = 0; if (needsFrameMoves) { // Mark effective beginning of when frame pointer is ready. ReadyLabelId = MMI->NextLabelID(); BuildMI(MBB, MBBI, TII.get(X86::DBG_LABEL)).addImm(ReadyLabelId); } // Skip the callee-saved push instructions. while (MBBI != MBB.end() && (MBBI->getOpcode() == X86::PUSH32r || MBBI->getOpcode() == X86::PUSH64r)) ++MBBI; if (NumBytes) { // adjust stack pointer: ESP -= numbytes if (NumBytes >= 4096 && Subtarget->isTargetCygMing()) { // Check, whether EAX is livein for this function bool isEAXAlive = false; for (MachineRegisterInfo::livein_iterator II = MF.getRegInfo().livein_begin(), EE = MF.getRegInfo().livein_end(); (II != EE) && !isEAXAlive; ++II) { unsigned Reg = II->first; isEAXAlive = (Reg == X86::EAX || Reg == X86::AX || Reg == X86::AH || Reg == X86::AL); } // Function prologue calls _alloca to probe the stack when allocating // more than 4k bytes in one go. Touching the stack at 4K increments is // necessary to ensure that the guard pages used by the OS virtual memory // manager are allocated in correct sequence. if (!isEAXAlive) { BuildMI(MBB, MBBI, TII.get(X86::MOV32ri), X86::EAX).addImm(NumBytes); BuildMI(MBB, MBBI, TII.get(X86::CALLpcrel32)) .addExternalSymbol("_alloca"); } else { // Save EAX BuildMI(MBB, MBBI, TII.get(X86::PUSH32r)) .addReg(X86::EAX, /*isDef=*/false, /*isImp=*/false, /*isKill=*/true); // Allocate NumBytes-4 bytes on stack. We'll also use 4 already // allocated bytes for EAX. BuildMI(MBB, MBBI, TII.get(X86::MOV32ri), X86::EAX).addImm(NumBytes-4); BuildMI(MBB, MBBI, TII.get(X86::CALLpcrel32)) .addExternalSymbol("_alloca"); // Restore EAX MachineInstr *MI = addRegOffset(BuildMI(MF, TII.get(X86::MOV32rm),X86::EAX), StackPtr, false, NumBytes-4); MBB.insert(MBBI, MI); } } else { // If there is an SUB32ri of ESP immediately before this instruction, // merge the two. This can be the case when tail call elimination is // enabled and the callee has more arguments then the caller. NumBytes -= mergeSPUpdates(MBB, MBBI, StackPtr, true); // If there is an ADD32ri or SUB32ri of ESP immediately after this // instruction, merge the two instructions. mergeSPUpdatesDown(MBB, MBBI, StackPtr, &NumBytes); if (NumBytes) emitSPUpdate(MBB, MBBI, StackPtr, -(int64_t)NumBytes, Is64Bit, TII); } } if (needsFrameMoves) emitFrameMoves(MF, FrameLabelId, ReadyLabelId); }
void XCoreRegisterInfo::emitPrologue(MachineFunction &MF) const { MachineBasicBlock &MBB = MF.front(); // Prolog goes in entry BB MachineBasicBlock::iterator MBBI = MBB.begin(); MachineFrameInfo *MFI = MF.getFrameInfo(); MachineModuleInfo *MMI = MFI->getMachineModuleInfo(); XCoreFunctionInfo *XFI = MF.getInfo<XCoreFunctionInfo>(); bool FP = hasFP(MF); // Work out frame sizes. int FrameSize = MFI->getStackSize(); assert(FrameSize%4 == 0 && "Misaligned frame size"); FrameSize/=4; bool isU6 = isImmU6(FrameSize); if (!isU6 && !isImmU16(FrameSize)) { // FIXME could emit multiple instructions. cerr << "emitPrologue Frame size too big: " << FrameSize << "\n"; abort(); } bool emitFrameMoves = needsFrameMoves(MF); // Do we need to allocate space on the stack? if (FrameSize) { bool saveLR = XFI->getUsesLR(); bool LRSavedOnEntry = false; int Opcode; if (saveLR && (MFI->getObjectOffset(XFI->getLRSpillSlot()) == 0)) { Opcode = (isU6) ? XCore::ENTSP_u6 : XCore::ENTSP_lu6; MBB.addLiveIn(XCore::LR); saveLR = false; LRSavedOnEntry = true; } else { Opcode = (isU6) ? XCore::EXTSP_u6 : XCore::EXTSP_lu6; } BuildMI(MBB, MBBI, TII.get(Opcode)).addImm(FrameSize); if (emitFrameMoves) { std::vector<MachineMove> &Moves = MMI->getFrameMoves(); // Show update of SP. unsigned FrameLabelId = MMI->NextLabelID(); BuildMI(MBB, MBBI, TII.get(XCore::DBG_LABEL)).addImm(FrameLabelId); MachineLocation SPDst(MachineLocation::VirtualFP); MachineLocation SPSrc(MachineLocation::VirtualFP, -FrameSize * 4); Moves.push_back(MachineMove(FrameLabelId, SPDst, SPSrc)); if (LRSavedOnEntry) { MachineLocation CSDst(MachineLocation::VirtualFP, 0); MachineLocation CSSrc(XCore::LR); Moves.push_back(MachineMove(FrameLabelId, CSDst, CSSrc)); } } if (saveLR) { int LRSpillOffset = MFI->getObjectOffset(XFI->getLRSpillSlot()); storeToStack(MBB, MBBI, XCore::LR, LRSpillOffset + FrameSize*4); MBB.addLiveIn(XCore::LR); if (emitFrameMoves) { unsigned SaveLRLabelId = MMI->NextLabelID(); BuildMI(MBB, MBBI, TII.get(XCore::DBG_LABEL)).addImm(SaveLRLabelId); MachineLocation CSDst(MachineLocation::VirtualFP, LRSpillOffset); MachineLocation CSSrc(XCore::LR); MMI->getFrameMoves().push_back(MachineMove(SaveLRLabelId, CSDst, CSSrc)); } } } if (FP) { // Save R10 to the stack. int FPSpillOffset = MFI->getObjectOffset(XFI->getFPSpillSlot()); storeToStack(MBB, MBBI, XCore::R10, FPSpillOffset + FrameSize*4); // R10 is live-in. It is killed at the spill. MBB.addLiveIn(XCore::R10); if (emitFrameMoves) { unsigned SaveR10LabelId = MMI->NextLabelID(); BuildMI(MBB, MBBI, TII.get(XCore::DBG_LABEL)).addImm(SaveR10LabelId); MachineLocation CSDst(MachineLocation::VirtualFP, FPSpillOffset); MachineLocation CSSrc(XCore::R10); MMI->getFrameMoves().push_back(MachineMove(SaveR10LabelId, CSDst, CSSrc)); } // Set the FP from the SP. unsigned FramePtr = XCore::R10; BuildMI(MBB, MBBI, TII.get(XCore::LDAWSP_ru6), FramePtr) .addImm(0); if (emitFrameMoves) { // Show FP is now valid. unsigned FrameLabelId = MMI->NextLabelID(); BuildMI(MBB, MBBI, TII.get(XCore::DBG_LABEL)).addImm(FrameLabelId); MachineLocation SPDst(FramePtr); MachineLocation SPSrc(MachineLocation::VirtualFP); MMI->getFrameMoves().push_back(MachineMove(FrameLabelId, SPDst, SPSrc)); } } if (emitFrameMoves) { // Frame moves for callee saved. std::vector<MachineMove> &Moves = MMI->getFrameMoves(); std::vector<std::pair<unsigned, CalleeSavedInfo> >&SpillLabels = XFI->getSpillLabels(); for (unsigned I = 0, E = SpillLabels.size(); I != E; ++I) { unsigned SpillLabel = SpillLabels[I].first; CalleeSavedInfo &CSI = SpillLabels[I].second; int Offset = MFI->getObjectOffset(CSI.getFrameIdx()); unsigned Reg = CSI.getReg(); MachineLocation CSDst(MachineLocation::VirtualFP, Offset); MachineLocation CSSrc(Reg); Moves.push_back(MachineMove(SpillLabel, CSDst, CSSrc)); } } }
void X86RegisterInfo::emitFrameMoves(MachineFunction &MF, unsigned FrameLabelId, unsigned ReadyLabelId) const { MachineFrameInfo *MFI = MF.getFrameInfo(); MachineModuleInfo *MMI = MFI->getMachineModuleInfo(); if (!MMI) return; uint64_t StackSize = MFI->getStackSize(); std::vector<MachineMove> &Moves = MMI->getFrameMoves(); const TargetData *TD = MF.getTarget().getTargetData(); // Calculate amount of bytes used for return address storing int stackGrowth = (MF.getTarget().getFrameInfo()->getStackGrowthDirection() == TargetFrameInfo::StackGrowsUp ? TD->getPointerSize() : -TD->getPointerSize()); if (StackSize) { // Show update of SP. if (hasFP(MF)) { // Adjust SP MachineLocation SPDst(MachineLocation::VirtualFP); MachineLocation SPSrc(MachineLocation::VirtualFP, 2*stackGrowth); Moves.push_back(MachineMove(FrameLabelId, SPDst, SPSrc)); } else { MachineLocation SPDst(MachineLocation::VirtualFP); MachineLocation SPSrc(MachineLocation::VirtualFP, -StackSize+stackGrowth); Moves.push_back(MachineMove(FrameLabelId, SPDst, SPSrc)); } } else { //FIXME: Verify & implement for FP MachineLocation SPDst(StackPtr); MachineLocation SPSrc(StackPtr, stackGrowth); Moves.push_back(MachineMove(FrameLabelId, SPDst, SPSrc)); } // Add callee saved registers to move list. const std::vector<CalleeSavedInfo> &CSI = MFI->getCalleeSavedInfo(); // FIXME: This is dirty hack. The code itself is pretty mess right now. // It should be rewritten from scratch and generalized sometimes. // Determine maximum offset (minumum due to stack growth) int64_t MaxOffset = 0; for (unsigned I = 0, E = CSI.size(); I!=E; ++I) MaxOffset = std::min(MaxOffset, MFI->getObjectOffset(CSI[I].getFrameIdx())); // Calculate offsets int64_t saveAreaOffset = (hasFP(MF) ? 3 : 2)*stackGrowth; for (unsigned I = 0, E = CSI.size(); I!=E; ++I) { int64_t Offset = MFI->getObjectOffset(CSI[I].getFrameIdx()); unsigned Reg = CSI[I].getReg(); Offset = (MaxOffset-Offset+saveAreaOffset); MachineLocation CSDst(MachineLocation::VirtualFP, Offset); MachineLocation CSSrc(Reg); Moves.push_back(MachineMove(FrameLabelId, CSDst, CSSrc)); } if (hasFP(MF)) { // Save FP MachineLocation FPDst(MachineLocation::VirtualFP, 2*stackGrowth); MachineLocation FPSrc(FramePtr); Moves.push_back(MachineMove(ReadyLabelId, FPDst, FPSrc)); } MachineLocation FPDst(hasFP(MF) ? FramePtr : StackPtr); MachineLocation FPSrc(MachineLocation::VirtualFP); Moves.push_back(MachineMove(ReadyLabelId, FPDst, FPSrc)); }