void XCoreFrameLowering::emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const { MachineFrameInfo *MFI = MF.getFrameInfo(); MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr(); const XCoreInstrInfo &TII = *MF.getSubtarget<XCoreSubtarget>().getInstrInfo(); XCoreFunctionInfo *XFI = MF.getInfo<XCoreFunctionInfo>(); DebugLoc dl = MBBI->getDebugLoc(); unsigned RetOpcode = MBBI->getOpcode(); // Work out frame sizes. // We will adjust the SP in stages towards the final FrameSize. int RemainingAdj = MFI->getStackSize(); assert(RemainingAdj%4 == 0 && "Misaligned frame size"); RemainingAdj /= 4; if (RetOpcode == XCore::EH_RETURN) { // 'Restore' the exception info the unwinder has placed into the stack // slots. SmallVector<StackSlotInfo,2> SpillList; GetEHSpillList(SpillList, MFI, XFI, MF.getSubtarget().getTargetLowering()); RestoreSpillList(MBB, MBBI, dl, TII, RemainingAdj, SpillList); // Return to the landing pad. unsigned EhStackReg = MBBI->getOperand(0).getReg(); unsigned EhHandlerReg = MBBI->getOperand(1).getReg(); BuildMI(MBB, MBBI, dl, TII.get(XCore::SETSP_1r)).addReg(EhStackReg); BuildMI(MBB, MBBI, dl, TII.get(XCore::BAU_1r)).addReg(EhHandlerReg); MBB.erase(MBBI); // Erase the previous return instruction. return; } bool restoreLR = XFI->hasLRSpillSlot(); bool UseRETSP = restoreLR && RemainingAdj && (MFI->getObjectOffset(XFI->getLRSpillSlot()) == 0); if (UseRETSP) restoreLR = false; bool FP = hasFP(MF); if (FP) // Restore the stack pointer. BuildMI(MBB, MBBI, dl, TII.get(XCore::SETSP_1r)).addReg(FramePtr); // If necessary, restore LR and FP from the stack, as we EXTSP. SmallVector<StackSlotInfo,2> SpillList; GetSpillList(SpillList, MFI, XFI, restoreLR, FP); RestoreSpillList(MBB, MBBI, dl, TII, RemainingAdj, SpillList); if (RemainingAdj) { // Complete all but one of the remaining Stack adjustments. IfNeededLDAWSP(MBB, MBBI, dl, TII, 0, RemainingAdj); if (UseRETSP) { // Fold prologue into return instruction assert(RetOpcode == XCore::RETSP_u6 || RetOpcode == XCore::RETSP_lu6); int Opcode = isImmU6(RemainingAdj) ? XCore::RETSP_u6 : XCore::RETSP_lu6; MachineInstrBuilder MIB = BuildMI(MBB, MBBI, dl, TII.get(Opcode)) .addImm(RemainingAdj); for (unsigned i = 3, e = MBBI->getNumOperands(); i < e; ++i) MIB->addOperand(MBBI->getOperand(i)); // copy any variadic operands MBB.erase(MBBI); // Erase the previous return instruction. } else { int Opcode = isImmU6(RemainingAdj) ? XCore::LDAWSP_ru6 : XCore::LDAWSP_lru6; BuildMI(MBB, MBBI, dl, TII.get(Opcode), XCore::SP).addImm(RemainingAdj); // Don't erase the return instruction. } } // else Don't erase the return instruction. }
void XCoreFrameLowering::emitPrologue(MachineFunction &MF, MachineBasicBlock &MBB) const { assert(&MF.front() == &MBB && "Shrink-wrapping not yet supported"); MachineBasicBlock::iterator MBBI = MBB.begin(); MachineFrameInfo *MFI = MF.getFrameInfo(); MachineModuleInfo *MMI = &MF.getMMI(); const MCRegisterInfo *MRI = MMI->getContext().getRegisterInfo(); const XCoreInstrInfo &TII = *MF.getSubtarget<XCoreSubtarget>().getInstrInfo(); XCoreFunctionInfo *XFI = MF.getInfo<XCoreFunctionInfo>(); // Debug location must be unknown since the first debug location is used // to determine the end of the prologue. DebugLoc dl; if (MFI->getMaxAlignment() > getStackAlignment()) report_fatal_error("emitPrologue unsupported alignment: " + Twine(MFI->getMaxAlignment())); const AttributeSet &PAL = MF.getFunction()->getAttributes(); if (PAL.hasAttrSomewhere(Attribute::Nest)) BuildMI(MBB, MBBI, dl, TII.get(XCore::LDWSP_ru6), XCore::R11).addImm(0); // FIX: Needs addMemOperand() but can't use getFixedStack() or getStack(). // Work out frame sizes. // We will adjust the SP in stages towards the final FrameSize. assert(MFI->getStackSize()%4 == 0 && "Misaligned frame size"); const int FrameSize = MFI->getStackSize() / 4; int Adjusted = 0; bool saveLR = XFI->hasLRSpillSlot(); bool UseENTSP = saveLR && FrameSize && (MFI->getObjectOffset(XFI->getLRSpillSlot()) == 0); if (UseENTSP) saveLR = false; bool FP = hasFP(MF); bool emitFrameMoves = XCoreRegisterInfo::needsFrameMoves(MF); if (UseENTSP) { // Allocate space on the stack at the same time as saving LR. Adjusted = (FrameSize > MaxImmU16) ? MaxImmU16 : FrameSize; int Opcode = isImmU6(Adjusted) ? XCore::ENTSP_u6 : XCore::ENTSP_lu6; MBB.addLiveIn(XCore::LR); MachineInstrBuilder MIB = BuildMI(MBB, MBBI, dl, TII.get(Opcode)); MIB.addImm(Adjusted); MIB->addRegisterKilled(XCore::LR, MF.getSubtarget().getRegisterInfo(), true); if (emitFrameMoves) { EmitDefCfaOffset(MBB, MBBI, dl, TII, MMI, Adjusted*4); unsigned DRegNum = MRI->getDwarfRegNum(XCore::LR, true); EmitCfiOffset(MBB, MBBI, dl, TII, MMI, DRegNum, 0); } } // If necessary, save LR and FP to the stack, as we EXTSP. SmallVector<StackSlotInfo,2> SpillList; GetSpillList(SpillList, MFI, XFI, saveLR, FP); // We want the nearest (negative) offsets first, so reverse list. std::reverse(SpillList.begin(), SpillList.end()); for (unsigned i = 0, e = SpillList.size(); i != e; ++i) { assert(SpillList[i].Offset % 4 == 0 && "Misaligned stack offset"); assert(SpillList[i].Offset <= 0 && "Unexpected positive stack offset"); int OffsetFromTop = - SpillList[i].Offset/4; IfNeededExtSP(MBB, MBBI, dl, TII, MMI, OffsetFromTop, Adjusted, FrameSize, emitFrameMoves); int Offset = Adjusted - OffsetFromTop; int Opcode = isImmU6(Offset) ? XCore::STWSP_ru6 : XCore::STWSP_lru6; MBB.addLiveIn(SpillList[i].Reg); BuildMI(MBB, MBBI, dl, TII.get(Opcode)) .addReg(SpillList[i].Reg, RegState::Kill) .addImm(Offset) .addMemOperand(getFrameIndexMMO(MBB, SpillList[i].FI, MachineMemOperand::MOStore)); if (emitFrameMoves) { unsigned DRegNum = MRI->getDwarfRegNum(SpillList[i].Reg, true); EmitCfiOffset(MBB, MBBI, dl, TII, MMI, DRegNum, SpillList[i].Offset); } } // Complete any remaining Stack adjustment. IfNeededExtSP(MBB, MBBI, dl, TII, MMI, FrameSize, Adjusted, FrameSize, emitFrameMoves); assert(Adjusted==FrameSize && "IfNeededExtSP has not completed adjustment"); if (FP) { // Set the FP from the SP. BuildMI(MBB, MBBI, dl, TII.get(XCore::LDAWSP_ru6), FramePtr).addImm(0); if (emitFrameMoves) EmitDefCfaRegister(MBB, MBBI, dl, TII, MMI, MRI->getDwarfRegNum(FramePtr, true)); } if (emitFrameMoves) { // Frame moves for callee saved. for (const auto &SpillLabel : XFI->getSpillLabels()) { MachineBasicBlock::iterator Pos = SpillLabel.first; ++Pos; const CalleeSavedInfo &CSI = SpillLabel.second; int Offset = MFI->getObjectOffset(CSI.getFrameIdx()); unsigned DRegNum = MRI->getDwarfRegNum(CSI.getReg(), true); EmitCfiOffset(MBB, Pos, dl, TII, MMI, DRegNum, Offset); } if (XFI->hasEHSpillSlot()) { // The unwinder requires stack slot & CFI offsets for the exception info. // We do not save/spill these registers. SmallVector<StackSlotInfo,2> SpillList; GetEHSpillList(SpillList, MFI, XFI, MF.getSubtarget().getTargetLowering()); assert(SpillList.size()==2 && "Unexpected SpillList size"); EmitCfiOffset(MBB, MBBI, dl, TII, MMI, MRI->getDwarfRegNum(SpillList[0].Reg, true), SpillList[0].Offset); EmitCfiOffset(MBB, MBBI, dl, TII, MMI, MRI->getDwarfRegNum(SpillList[1].Reg, true), SpillList[1].Offset); } } }