void SystemZRegisterInfo::emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const { const MachineFrameInfo *MFI = MF.getFrameInfo(); const TargetFrameInfo &TFI = *MF.getTarget().getFrameInfo(); MachineBasicBlock::iterator MBBI = prior(MBB.end()); SystemZMachineFunctionInfo *SystemZMFI = MF.getInfo<SystemZMachineFunctionInfo>(); unsigned RetOpcode = MBBI->getOpcode(); switch (RetOpcode) { case SystemZ::RET: break; // These are ok default: assert(0 && "Can only insert epilog into returning blocks"); } // Get the number of bytes to allocate from the FrameInfo // Note that area for callee-saved stuff is already allocated, thus we need to // 'undo' the stack movement. uint64_t StackSize = MFI->getStackSize() - SystemZMFI->getCalleeSavedFrameSize(); uint64_t NumBytes = StackSize - TFI.getOffsetOfLocalArea(); // Skip the final terminator instruction. while (MBBI != MBB.begin()) { MachineBasicBlock::iterator PI = prior(MBBI); --MBBI; if (!PI->getDesc().isTerminator()) break; } // During callee-saved restores emission stack frame was not yet finialized // (and thus - the stack size was unknown). Tune the offset having full stack // size in hands. if (StackSize || MFI->hasCalls()) { assert((MBBI->getOpcode() == SystemZ::MOV64rmm || MBBI->getOpcode() == SystemZ::MOV64rm) && "Expected to see callee-save register restore code"); assert(MF.getRegInfo().isPhysRegUsed(SystemZ::R15D) && "Invalid stack frame calculation!"); unsigned i = 0; MachineInstr &MI = *MBBI; while (!MI.getOperand(i).isImm()) { ++i; assert(i < MI.getNumOperands() && "Unexpected restore code!"); } uint64_t Offset = NumBytes + MI.getOperand(i).getImm(); // If Offset does not fit into 20-bit signed displacement field we need to // emit some additional code... if (Offset > 524287) { // Fold the displacement into load instruction as much as possible. NumBytes = Offset - 524287; Offset = 524287; emitSPUpdate(MBB, MBBI, NumBytes, TII); } MI.getOperand(i).ChangeToImmediate(Offset); } }
bool SystemZFrameLowering:: restoreCalleeSavedRegisters(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, const std::vector<CalleeSavedInfo> &CSI, const TargetRegisterInfo *TRI) const { if (CSI.empty()) return false; MachineFunction &MF = *MBB.getParent(); const TargetInstrInfo *TII = MF.getTarget().getInstrInfo(); SystemZMachineFunctionInfo *ZFI = MF.getInfo<SystemZMachineFunctionInfo>(); bool HasFP = hasFP(MF); DebugLoc DL = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc(); // Restore FPRs in the normal TargetInstrInfo way. for (unsigned I = 0, E = CSI.size(); I != E; ++I) { unsigned Reg = CSI[I].getReg(); if (SystemZ::FP64BitRegClass.contains(Reg)) TII->loadRegFromStackSlot(MBB, MBBI, Reg, CSI[I].getFrameIdx(), &SystemZ::FP64BitRegClass, TRI); } // Restore call-saved GPRs (but not call-clobbered varargs, which at // this point might hold return values). unsigned LowGPR = ZFI->getLowSavedGPR(); unsigned HighGPR = ZFI->getHighSavedGPR(); unsigned StartOffset = RegSpillOffsets[LowGPR]; if (LowGPR) { // If we saved any of %r2-%r5 as varargs, we should also be saving // and restoring %r6. If we're saving %r6 or above, we should be // restoring it too. assert(LowGPR != HighGPR && "Should be loading %r15 and something else"); // Build an LMG instruction. MachineInstrBuilder MIB = BuildMI(MBB, MBBI, DL, TII->get(SystemZ::LMG)); // Add the explicit register operands. MIB.addReg(LowGPR, RegState::Define); MIB.addReg(HighGPR, RegState::Define); // Add the address. MIB.addReg(HasFP ? SystemZ::R11D : SystemZ::R15D); MIB.addImm(StartOffset); // Do a second scan adding regs as being defined by instruction for (unsigned I = 0, E = CSI.size(); I != E; ++I) { unsigned Reg = CSI[I].getReg(); if (Reg != LowGPR && Reg != HighGPR) MIB.addReg(Reg, RegState::ImplicitDefine); } } return true; }
bool SystemZInstrInfo::restoreCalleeSavedRegisters(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, const std::vector<CalleeSavedInfo> &CSI) const { if (CSI.empty()) return false; DebugLoc DL = DebugLoc::getUnknownLoc(); if (MI != MBB.end()) DL = MI->getDebugLoc(); MachineFunction &MF = *MBB.getParent(); const TargetRegisterInfo *RegInfo= MF.getTarget().getRegisterInfo(); SystemZMachineFunctionInfo *MFI = MF.getInfo<SystemZMachineFunctionInfo>(); // Restore FP registers for (unsigned i = 0, e = CSI.size(); i != e; ++i) { unsigned Reg = CSI[i].getReg(); const TargetRegisterClass *RegClass = CSI[i].getRegClass(); if (RegClass == &SystemZ::FP64RegClass) loadRegFromStackSlot(MBB, MI, Reg, CSI[i].getFrameIdx(), RegClass); } // Restore GP registers unsigned LowReg = MFI->getLowReg(), HighReg = MFI->getHighReg(); unsigned StartOffset = RegSpillOffsets[LowReg]; if (StartOffset) { // Build a load instruction. Use LOAD MULTIPLE instruction if there are many // registers to load, otherwise - just LOAD. MachineInstrBuilder MIB = BuildMI(MBB, MI, DL, get((LowReg == HighReg ? SystemZ::MOV64rm : SystemZ::MOV64rmm))); // Add store operands. MIB.addReg(LowReg, RegState::Define); if (LowReg != HighReg) MIB.addReg(HighReg, RegState::Define); MIB.addReg((RegInfo->hasFP(MF) ? SystemZ::R11D : SystemZ::R15D)); MIB.addImm(StartOffset); if (LowReg == HighReg) MIB.addReg(0); // Do a second scan adding regs as being defined by instruction for (unsigned i = 0, e = CSI.size(); i != e; ++i) { unsigned Reg = CSI[i].getReg(); if (Reg != LowReg && Reg != HighReg) MIB.addReg(Reg, RegState::ImplicitDefine); } } return true; }
bool SystemZLDCleanup::runOnMachineFunction(MachineFunction &F) { if (skipFunction(*F.getFunction())) return false; TII = static_cast<const SystemZInstrInfo *>(F.getSubtarget().getInstrInfo()); MF = &F; SystemZMachineFunctionInfo* MFI = F.getInfo<SystemZMachineFunctionInfo>(); if (MFI->getNumLocalDynamicTLSAccesses() < 2) { // No point folding accesses if there isn't at least two. return false; } MachineDominatorTree *DT = &getAnalysis<MachineDominatorTree>(); return VisitNode(DT->getRootNode(), 0); }
void SystemZRegisterInfo::emitPrologue(MachineFunction &MF) const { MachineBasicBlock &MBB = MF.front(); // Prolog goes in entry BB const TargetFrameInfo &TFI = *MF.getTarget().getFrameInfo(); MachineFrameInfo *MFI = MF.getFrameInfo(); SystemZMachineFunctionInfo *SystemZMFI = MF.getInfo<SystemZMachineFunctionInfo>(); MachineBasicBlock::iterator MBBI = MBB.begin(); DebugLoc DL = (MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc::getUnknownLoc()); // Get the number of bytes to allocate from the FrameInfo. // Note that area for callee-saved stuff is already allocated, thus we need to // 'undo' the stack movement. uint64_t StackSize = MFI->getStackSize(); StackSize -= SystemZMFI->getCalleeSavedFrameSize(); uint64_t NumBytes = StackSize - TFI.getOffsetOfLocalArea(); // Skip the callee-saved push instructions. while (MBBI != MBB.end() && (MBBI->getOpcode() == SystemZ::MOV64mr || MBBI->getOpcode() == SystemZ::MOV64mrm)) ++MBBI; if (MBBI != MBB.end()) DL = MBBI->getDebugLoc(); // adjust stack pointer: R15 -= numbytes if (StackSize || MFI->hasCalls()) { assert(MF.getRegInfo().isPhysRegUsed(SystemZ::R15D) && "Invalid stack frame calculation!"); emitSPUpdate(MBB, MBBI, -(int64_t)NumBytes, TII); } if (hasFP(MF)) { // Update R11 with the new base value... BuildMI(MBB, MBBI, DL, TII.get(SystemZ::MOV64rr), SystemZ::R11D) .addReg(SystemZ::R15D); // Mark the FramePtr as live-in in every block except the entry. for (MachineFunction::iterator I = llvm::next(MF.begin()), E = MF.end(); I != E; ++I) I->addLiveIn(SystemZ::R11D); } }
int SystemZRegisterInfo::getFrameIndexOffset(MachineFunction &MF, int FI) const { const TargetFrameInfo &TFI = *MF.getTarget().getFrameInfo(); MachineFrameInfo *MFI = MF.getFrameInfo(); SystemZMachineFunctionInfo *SystemZMFI = MF.getInfo<SystemZMachineFunctionInfo>(); int Offset = MFI->getObjectOffset(FI) + MFI->getOffsetAdjustment(); uint64_t StackSize = MFI->getStackSize(); // Fixed objects are really located in the "previous" frame. if (FI < 0) StackSize -= SystemZMFI->getCalleeSavedFrameSize(); Offset += StackSize - TFI.getOffsetOfLocalArea(); // Skip the register save area if we generated the stack frame. if (StackSize || MFI->hasCalls()) Offset -= TFI.getOffsetOfLocalArea(); return Offset; }
void SystemZFrameLowering:: processFunctionBeforeCalleeSavedScan(MachineFunction &MF, RegScavenger *RS) const { MachineFrameInfo *MFFrame = MF.getFrameInfo(); MachineRegisterInfo &MRI = MF.getRegInfo(); const TargetRegisterInfo *TRI = MF.getTarget().getRegisterInfo(); bool HasFP = hasFP(MF); SystemZMachineFunctionInfo *MFI = MF.getInfo<SystemZMachineFunctionInfo>(); bool IsVarArg = MF.getFunction()->isVarArg(); // va_start stores incoming FPR varargs in the normal way, but delegates // the saving of incoming GPR varargs to spillCalleeSavedRegisters(). // Record these pending uses, which typically include the call-saved // argument register R6D. if (IsVarArg) for (unsigned I = MFI->getVarArgsFirstGPR(); I < SystemZ::NumArgGPRs; ++I) MRI.setPhysRegUsed(SystemZ::ArgGPRs[I]); // If the function requires a frame pointer, record that the hard // frame pointer will be clobbered. if (HasFP) MRI.setPhysRegUsed(SystemZ::R11D); // If the function calls other functions, record that the return // address register will be clobbered. if (MFFrame->hasCalls()) MRI.setPhysRegUsed(SystemZ::R14D); // If we are saving GPRs other than the stack pointer, we might as well // save and restore the stack pointer at the same time, via STMG and LMG. // This allows the deallocation to be done by the LMG, rather than needing // a separate %r15 addition. const MCPhysReg *CSRegs = TRI->getCalleeSavedRegs(&MF); for (unsigned I = 0; CSRegs[I]; ++I) { unsigned Reg = CSRegs[I]; if (SystemZ::GR64BitRegClass.contains(Reg) && MRI.isPhysRegUsed(Reg)) { MRI.setPhysRegUsed(SystemZ::R15D); break; } } }
void SystemZFrameLowering::emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const { MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr(); const SystemZInstrInfo *ZII = static_cast<const SystemZInstrInfo*>(MF.getTarget().getInstrInfo()); SystemZMachineFunctionInfo *ZFI = MF.getInfo<SystemZMachineFunctionInfo>(); // Skip the return instruction. assert(MBBI->getOpcode() == SystemZ::RET && "Can only insert epilogue into returning blocks"); uint64_t StackSize = getAllocatedStackSize(MF); if (ZFI->getLowSavedGPR()) { --MBBI; unsigned Opcode = MBBI->getOpcode(); if (Opcode != SystemZ::LMG) llvm_unreachable("Expected to see callee-save register restore code"); unsigned AddrOpNo = 2; DebugLoc DL = MBBI->getDebugLoc(); uint64_t Offset = StackSize + MBBI->getOperand(AddrOpNo + 1).getImm(); unsigned NewOpcode = ZII->getOpcodeForOffset(Opcode, Offset); // If the offset is too large, use the largest stack-aligned offset // and add the rest to the base register (the stack or frame pointer). if (!NewOpcode) { uint64_t NumBytes = Offset - 0x7fff8; emitIncrement(MBB, MBBI, DL, MBBI->getOperand(AddrOpNo).getReg(), NumBytes, ZII); Offset -= NumBytes; NewOpcode = ZII->getOpcodeForOffset(Opcode, Offset); assert(NewOpcode && "No restore instruction available"); } MBBI->setDesc(ZII->get(NewOpcode)); MBBI->getOperand(AddrOpNo + 1).ChangeToImmediate(Offset); } else if (StackSize) { DebugLoc DL = MBBI->getDebugLoc(); emitIncrement(MBB, MBBI, DL, SystemZ::R15D, StackSize, ZII); } }
void SystemZFrameLowering::emitPrologue(MachineFunction &MF) const { MachineBasicBlock &MBB = MF.front(); MachineFrameInfo *MFFrame = MF.getFrameInfo(); auto *ZII = static_cast<const SystemZInstrInfo*>(MF.getTarget().getInstrInfo()); SystemZMachineFunctionInfo *ZFI = MF.getInfo<SystemZMachineFunctionInfo>(); MachineBasicBlock::iterator MBBI = MBB.begin(); MachineModuleInfo &MMI = MF.getMMI(); const MCRegisterInfo *MRI = MMI.getContext().getRegisterInfo(); const std::vector<CalleeSavedInfo> &CSI = MFFrame->getCalleeSavedInfo(); bool HasFP = hasFP(MF); DebugLoc DL = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc(); // The current offset of the stack pointer from the CFA. int64_t SPOffsetFromCFA = -SystemZMC::CFAOffsetFromInitialSP; if (ZFI->getLowSavedGPR()) { // Skip over the GPR saves. if (MBBI != MBB.end() && MBBI->getOpcode() == SystemZ::STMG) ++MBBI; else llvm_unreachable("Couldn't skip over GPR saves"); // Add CFI for the GPR saves. for (auto &Save : CSI) { unsigned Reg = Save.getReg(); if (SystemZ::GR64BitRegClass.contains(Reg)) { int64_t Offset = SPOffsetFromCFA + RegSpillOffsets[Reg]; unsigned CFIIndex = MMI.addFrameInst(MCCFIInstruction::createOffset( nullptr, MRI->getDwarfRegNum(Reg, true), Offset)); BuildMI(MBB, MBBI, DL, ZII->get(TargetOpcode::CFI_INSTRUCTION)) .addCFIIndex(CFIIndex); } } } uint64_t StackSize = getAllocatedStackSize(MF); if (StackSize) { // Allocate StackSize bytes. int64_t Delta = -int64_t(StackSize); emitIncrement(MBB, MBBI, DL, SystemZ::R15D, Delta, ZII); // Add CFI for the allocation. unsigned CFIIndex = MMI.addFrameInst( MCCFIInstruction::createDefCfaOffset(nullptr, SPOffsetFromCFA + Delta)); BuildMI(MBB, MBBI, DL, ZII->get(TargetOpcode::CFI_INSTRUCTION)) .addCFIIndex(CFIIndex); SPOffsetFromCFA += Delta; } if (HasFP) { // Copy the base of the frame to R11. BuildMI(MBB, MBBI, DL, ZII->get(SystemZ::LGR), SystemZ::R11D) .addReg(SystemZ::R15D); // Add CFI for the new frame location. unsigned HardFP = MRI->getDwarfRegNum(SystemZ::R11D, true); unsigned CFIIndex = MMI.addFrameInst( MCCFIInstruction::createDefCfaRegister(nullptr, HardFP)); BuildMI(MBB, MBBI, DL, ZII->get(TargetOpcode::CFI_INSTRUCTION)) .addCFIIndex(CFIIndex); // Mark the FramePtr as live at the beginning of every block except // the entry block. (We'll have marked R11 as live on entry when // saving the GPRs.) for (auto I = std::next(MF.begin()), E = MF.end(); I != E; ++I) I->addLiveIn(SystemZ::R11D); } // Skip over the FPR saves. SmallVector<unsigned, 8> CFIIndexes; for (auto &Save : CSI) { unsigned Reg = Save.getReg(); if (SystemZ::FP64BitRegClass.contains(Reg)) { if (MBBI != MBB.end() && (MBBI->getOpcode() == SystemZ::STD || MBBI->getOpcode() == SystemZ::STDY)) ++MBBI; else llvm_unreachable("Couldn't skip over FPR save"); // Add CFI for the this save. unsigned DwarfReg = MRI->getDwarfRegNum(Reg, true); int64_t Offset = getFrameIndexOffset(MF, Save.getFrameIdx()); unsigned CFIIndex = MMI.addFrameInst(MCCFIInstruction::createOffset( nullptr, DwarfReg, SPOffsetFromCFA + Offset)); CFIIndexes.push_back(CFIIndex); } } // Complete the CFI for the FPR saves, modelling them as taking effect // after the last save. for (auto CFIIndex : CFIIndexes) { BuildMI(MBB, MBBI, DL, ZII->get(TargetOpcode::CFI_INSTRUCTION)) .addCFIIndex(CFIIndex); } }
bool SystemZFrameLowering:: spillCalleeSavedRegisters(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, const std::vector<CalleeSavedInfo> &CSI, const TargetRegisterInfo *TRI) const { if (CSI.empty()) return false; MachineFunction &MF = *MBB.getParent(); const TargetInstrInfo *TII = MF.getTarget().getInstrInfo(); SystemZMachineFunctionInfo *ZFI = MF.getInfo<SystemZMachineFunctionInfo>(); bool IsVarArg = MF.getFunction()->isVarArg(); DebugLoc DL = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc(); // Scan the call-saved GPRs and find the bounds of the register spill area. unsigned LowGPR = 0; unsigned HighGPR = SystemZ::R15D; unsigned StartOffset = -1U; for (unsigned I = 0, E = CSI.size(); I != E; ++I) { unsigned Reg = CSI[I].getReg(); if (SystemZ::GR64BitRegClass.contains(Reg)) { unsigned Offset = RegSpillOffsets[Reg]; assert(Offset && "Unexpected GPR save"); if (StartOffset > Offset) { LowGPR = Reg; StartOffset = Offset; } } } // Save the range of call-saved registers, for use by the epilogue inserter. ZFI->setLowSavedGPR(LowGPR); ZFI->setHighSavedGPR(HighGPR); // Include the GPR varargs, if any. R6D is call-saved, so would // be included by the loop above, but we also need to handle the // call-clobbered argument registers. if (IsVarArg) { unsigned FirstGPR = ZFI->getVarArgsFirstGPR(); if (FirstGPR < SystemZ::NumArgGPRs) { unsigned Reg = SystemZ::ArgGPRs[FirstGPR]; unsigned Offset = RegSpillOffsets[Reg]; if (StartOffset > Offset) { LowGPR = Reg; StartOffset = Offset; } } } // Save GPRs if (LowGPR) { assert(LowGPR != HighGPR && "Should be saving %r15 and something else"); // Build an STMG instruction. MachineInstrBuilder MIB = BuildMI(MBB, MBBI, DL, TII->get(SystemZ::STMG)); // Add the explicit register operands. addSavedGPR(MBB, MIB, LowGPR, false); addSavedGPR(MBB, MIB, HighGPR, false); // Add the address. MIB.addReg(SystemZ::R15D).addImm(StartOffset); // Make sure all call-saved GPRs are included as operands and are // marked as live on entry. for (unsigned I = 0, E = CSI.size(); I != E; ++I) { unsigned Reg = CSI[I].getReg(); if (SystemZ::GR64BitRegClass.contains(Reg)) addSavedGPR(MBB, MIB, Reg, true); } // ...likewise GPR varargs. if (IsVarArg) for (unsigned I = ZFI->getVarArgsFirstGPR(); I < SystemZ::NumArgGPRs; ++I) addSavedGPR(MBB, MIB, SystemZ::ArgGPRs[I], true); } // Save FPRs in the normal TargetInstrInfo way. for (unsigned I = 0, E = CSI.size(); I != E; ++I) { unsigned Reg = CSI[I].getReg(); if (SystemZ::FP64BitRegClass.contains(Reg)) { MBB.addLiveIn(Reg); TII->storeRegToStackSlot(MBB, MBBI, Reg, true, CSI[I].getFrameIdx(), &SystemZ::FP64BitRegClass, TRI); } } return true; }
bool SystemZInstrInfo::spillCalleeSavedRegisters(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, const std::vector<CalleeSavedInfo> &CSI) const { if (CSI.empty()) return false; DebugLoc DL = DebugLoc::getUnknownLoc(); if (MI != MBB.end()) DL = MI->getDebugLoc(); MachineFunction &MF = *MBB.getParent(); SystemZMachineFunctionInfo *MFI = MF.getInfo<SystemZMachineFunctionInfo>(); unsigned CalleeFrameSize = 0; // Scan the callee-saved and find the bounds of register spill area. unsigned LowReg = 0, HighReg = 0, StartOffset = -1U, EndOffset = 0; for (unsigned i = 0, e = CSI.size(); i != e; ++i) { unsigned Reg = CSI[i].getReg(); const TargetRegisterClass *RegClass = CSI[i].getRegClass(); if (RegClass != &SystemZ::FP64RegClass) { unsigned Offset = RegSpillOffsets[Reg]; CalleeFrameSize += 8; if (StartOffset > Offset) { LowReg = Reg; StartOffset = Offset; } if (EndOffset < Offset) { HighReg = Reg; EndOffset = RegSpillOffsets[Reg]; } } } // Save information for epilogue inserter. MFI->setCalleeSavedFrameSize(CalleeFrameSize); MFI->setLowReg(LowReg); MFI->setHighReg(HighReg); // Save GPRs if (StartOffset) { // Build a store instruction. Use STORE MULTIPLE instruction if there are many // registers to store, otherwise - just STORE. MachineInstrBuilder MIB = BuildMI(MBB, MI, DL, get((LowReg == HighReg ? SystemZ::MOV64mr : SystemZ::MOV64mrm))); // Add store operands. MIB.addReg(SystemZ::R15D).addImm(StartOffset); if (LowReg == HighReg) MIB.addReg(0); MIB.addReg(LowReg, RegState::Kill); if (LowReg != HighReg) MIB.addReg(HighReg, RegState::Kill); // Do a second scan adding regs as being killed by instruction for (unsigned i = 0, e = CSI.size(); i != e; ++i) { unsigned Reg = CSI[i].getReg(); // Add the callee-saved register as live-in. It's killed at the spill. MBB.addLiveIn(Reg); if (Reg != LowReg && Reg != HighReg) MIB.addReg(Reg, RegState::ImplicitKill); } } // Save FPRs for (unsigned i = 0, e = CSI.size(); i != e; ++i) { unsigned Reg = CSI[i].getReg(); const TargetRegisterClass *RegClass = CSI[i].getRegClass(); if (RegClass == &SystemZ::FP64RegClass) { MBB.addLiveIn(Reg); storeRegToStackSlot(MBB, MI, Reg, true, CSI[i].getFrameIdx(), RegClass); } } return true; }
void SystemZFrameLowering::emitPrologue(MachineFunction &MF) const { MachineBasicBlock &MBB = MF.front(); MachineFrameInfo *MFFrame = MF.getFrameInfo(); const SystemZInstrInfo *ZII = static_cast<const SystemZInstrInfo*>(MF.getTarget().getInstrInfo()); SystemZMachineFunctionInfo *ZFI = MF.getInfo<SystemZMachineFunctionInfo>(); MachineBasicBlock::iterator MBBI = MBB.begin(); MachineModuleInfo &MMI = MF.getMMI(); const std::vector<CalleeSavedInfo> &CSI = MFFrame->getCalleeSavedInfo(); bool HasFP = hasFP(MF); DebugLoc DL = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc(); // The current offset of the stack pointer from the CFA. int64_t SPOffsetFromCFA = -SystemZMC::CFAOffsetFromInitialSP; if (ZFI->getLowSavedGPR()) { // Skip over the GPR saves. if (MBBI != MBB.end() && MBBI->getOpcode() == SystemZ::STMG) ++MBBI; else llvm_unreachable("Couldn't skip over GPR saves"); // Add CFI for the GPR saves. MCSymbol *GPRSaveLabel = MMI.getContext().CreateTempSymbol(); BuildMI(MBB, MBBI, DL, ZII->get(TargetOpcode::PROLOG_LABEL)).addSym(GPRSaveLabel); for (std::vector<CalleeSavedInfo>::const_iterator I = CSI.begin(), E = CSI.end(); I != E; ++I) { unsigned Reg = I->getReg(); if (SystemZ::GR64BitRegClass.contains(Reg)) { int64_t Offset = SPOffsetFromCFA + RegSpillOffsets[Reg]; MachineLocation StackSlot(MachineLocation::VirtualFP, Offset); MachineLocation RegValue(Reg); MMI.addFrameMove(GPRSaveLabel, StackSlot, RegValue); } } } uint64_t StackSize = getAllocatedStackSize(MF); if (StackSize) { // Allocate StackSize bytes. int64_t Delta = -int64_t(StackSize); emitIncrement(MBB, MBBI, DL, SystemZ::R15D, Delta, ZII); // Add CFI for the allocation. MCSymbol *AdjustSPLabel = MMI.getContext().CreateTempSymbol(); BuildMI(MBB, MBBI, DL, ZII->get(TargetOpcode::PROLOG_LABEL)) .addSym(AdjustSPLabel); MachineLocation FPDest(MachineLocation::VirtualFP); MachineLocation FPSrc(MachineLocation::VirtualFP, SPOffsetFromCFA + Delta); MMI.addFrameMove(AdjustSPLabel, FPDest, FPSrc); SPOffsetFromCFA += Delta; } if (HasFP) { // Copy the base of the frame to R11. BuildMI(MBB, MBBI, DL, ZII->get(SystemZ::LGR), SystemZ::R11D) .addReg(SystemZ::R15D); // Add CFI for the new frame location. MCSymbol *SetFPLabel = MMI.getContext().CreateTempSymbol(); BuildMI(MBB, MBBI, DL, ZII->get(TargetOpcode::PROLOG_LABEL)) .addSym(SetFPLabel); MachineLocation HardFP(SystemZ::R11D); MachineLocation VirtualFP(MachineLocation::VirtualFP); MMI.addFrameMove(SetFPLabel, HardFP, VirtualFP); // Mark the FramePtr as live at the beginning of every block except // the entry block. (We'll have marked R11 as live on entry when // saving the GPRs.) for (MachineFunction::iterator I = llvm::next(MF.begin()), E = MF.end(); I != E; ++I) I->addLiveIn(SystemZ::R11D); } // Skip over the FPR saves. MCSymbol *FPRSaveLabel = 0; for (std::vector<CalleeSavedInfo>::const_iterator I = CSI.begin(), E = CSI.end(); I != E; ++I) { unsigned Reg = I->getReg(); if (SystemZ::FP64BitRegClass.contains(Reg)) { if (MBBI != MBB.end() && (MBBI->getOpcode() == SystemZ::STD || MBBI->getOpcode() == SystemZ::STDY)) ++MBBI; else llvm_unreachable("Couldn't skip over FPR save"); // Add CFI for the this save. if (!FPRSaveLabel) FPRSaveLabel = MMI.getContext().CreateTempSymbol(); unsigned Reg = I->getReg(); int64_t Offset = getFrameIndexOffset(MF, I->getFrameIdx()); MachineLocation Slot(MachineLocation::VirtualFP, SPOffsetFromCFA + Offset); MachineLocation RegValue(Reg); MMI.addFrameMove(FPRSaveLabel, Slot, RegValue); } } // Complete the CFI for the FPR saves, modelling them as taking effect // after the last save. if (FPRSaveLabel) BuildMI(MBB, MBBI, DL, ZII->get(TargetOpcode::PROLOG_LABEL)) .addSym(FPRSaveLabel); }