10b57cec5SDimitry Andric //===-- SystemZFrameLowering.cpp - Frame lowering for SystemZ -------------===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric 90b57cec5SDimitry Andric #include "SystemZFrameLowering.h" 100b57cec5SDimitry Andric #include "SystemZCallingConv.h" 110b57cec5SDimitry Andric #include "SystemZInstrBuilder.h" 120b57cec5SDimitry Andric #include "SystemZInstrInfo.h" 130b57cec5SDimitry Andric #include "SystemZMachineFunctionInfo.h" 140b57cec5SDimitry Andric #include "SystemZRegisterInfo.h" 150b57cec5SDimitry Andric #include "SystemZSubtarget.h" 160b57cec5SDimitry Andric #include "llvm/CodeGen/MachineModuleInfo.h" 170b57cec5SDimitry Andric #include "llvm/CodeGen/MachineRegisterInfo.h" 180b57cec5SDimitry Andric #include "llvm/CodeGen/RegisterScavenging.h" 190b57cec5SDimitry Andric #include "llvm/IR/Function.h" 200b57cec5SDimitry Andric 210b57cec5SDimitry Andric using namespace llvm; 220b57cec5SDimitry Andric 230b57cec5SDimitry Andric namespace { 24*480093f4SDimitry Andric // The ABI-defined register save slots, relative to the CFA (i.e. 25*480093f4SDimitry Andric // incoming stack pointer + SystemZMC::CallFrameSize). 260b57cec5SDimitry Andric static const TargetFrameLowering::SpillSlot SpillOffsetTable[] = { 270b57cec5SDimitry Andric { SystemZ::R2D, 0x10 }, 280b57cec5SDimitry Andric { SystemZ::R3D, 0x18 }, 290b57cec5SDimitry Andric { SystemZ::R4D, 0x20 }, 300b57cec5SDimitry Andric { SystemZ::R5D, 0x28 }, 310b57cec5SDimitry Andric { SystemZ::R6D, 0x30 }, 320b57cec5SDimitry Andric { SystemZ::R7D, 0x38 }, 330b57cec5SDimitry Andric { SystemZ::R8D, 0x40 }, 340b57cec5SDimitry Andric { SystemZ::R9D, 0x48 }, 350b57cec5SDimitry Andric { SystemZ::R10D, 0x50 }, 360b57cec5SDimitry Andric { SystemZ::R11D, 0x58 }, 370b57cec5SDimitry Andric { SystemZ::R12D, 0x60 }, 380b57cec5SDimitry Andric { SystemZ::R13D, 0x68 }, 390b57cec5SDimitry Andric { SystemZ::R14D, 0x70 }, 400b57cec5SDimitry Andric { SystemZ::R15D, 0x78 }, 410b57cec5SDimitry Andric { SystemZ::F0D, 0x80 }, 420b57cec5SDimitry Andric { SystemZ::F2D, 0x88 }, 430b57cec5SDimitry Andric { SystemZ::F4D, 0x90 }, 440b57cec5SDimitry Andric { SystemZ::F6D, 0x98 } 450b57cec5SDimitry Andric }; 460b57cec5SDimitry Andric } // end anonymous namespace 470b57cec5SDimitry Andric 480b57cec5SDimitry Andric SystemZFrameLowering::SystemZFrameLowering() 498bcb0991SDimitry Andric : TargetFrameLowering(TargetFrameLowering::StackGrowsDown, Align(8), 50*480093f4SDimitry Andric 0, Align(8), false /* StackRealignable */), 51*480093f4SDimitry Andric RegSpillOffsets(0) { 52*480093f4SDimitry Andric // Due to the SystemZ ABI, the DWARF CFA (Canonical Frame Address) is not 53*480093f4SDimitry Andric // equal to the incoming stack pointer, but to incoming stack pointer plus 54*480093f4SDimitry Andric // 160. Instead of using a Local Area Offset, the Register save area will 55*480093f4SDimitry Andric // be occupied by fixed frame objects, and all offsets are actually 56*480093f4SDimitry Andric // relative to CFA. 57*480093f4SDimitry Andric 580b57cec5SDimitry Andric // Create a mapping from register number to save slot offset. 59*480093f4SDimitry Andric // These offsets are relative to the start of the register save area. 600b57cec5SDimitry Andric RegSpillOffsets.grow(SystemZ::NUM_TARGET_REGS); 610b57cec5SDimitry Andric for (unsigned I = 0, E = array_lengthof(SpillOffsetTable); I != E; ++I) 620b57cec5SDimitry Andric RegSpillOffsets[SpillOffsetTable[I].Reg] = SpillOffsetTable[I].Offset; 630b57cec5SDimitry Andric } 640b57cec5SDimitry Andric 65*480093f4SDimitry Andric static bool usePackedStack(MachineFunction &MF) { 66*480093f4SDimitry Andric bool HasPackedStackAttr = MF.getFunction().hasFnAttribute("packed-stack"); 67*480093f4SDimitry Andric bool IsVarArg = MF.getFunction().isVarArg(); 68*480093f4SDimitry Andric bool CallConv = MF.getFunction().getCallingConv() != CallingConv::GHC; 69*480093f4SDimitry Andric bool BackChain = MF.getFunction().hasFnAttribute("backchain"); 70*480093f4SDimitry Andric bool FramAddressTaken = MF.getFrameInfo().isFrameAddressTaken(); 71*480093f4SDimitry Andric if (HasPackedStackAttr && BackChain) 72*480093f4SDimitry Andric report_fatal_error("packed-stack with backchain is currently unsupported."); 73*480093f4SDimitry Andric return HasPackedStackAttr && !IsVarArg && CallConv && !BackChain && 74*480093f4SDimitry Andric !FramAddressTaken; 75*480093f4SDimitry Andric } 76*480093f4SDimitry Andric 77*480093f4SDimitry Andric bool SystemZFrameLowering:: 78*480093f4SDimitry Andric assignCalleeSavedSpillSlots(MachineFunction &MF, 79*480093f4SDimitry Andric const TargetRegisterInfo *TRI, 80*480093f4SDimitry Andric std::vector<CalleeSavedInfo> &CSI) const { 81*480093f4SDimitry Andric SystemZMachineFunctionInfo *ZFI = MF.getInfo<SystemZMachineFunctionInfo>(); 82*480093f4SDimitry Andric MachineFrameInfo &MFFrame = MF.getFrameInfo(); 83*480093f4SDimitry Andric bool IsVarArg = MF.getFunction().isVarArg(); 84*480093f4SDimitry Andric if (CSI.empty()) 85*480093f4SDimitry Andric return true; // Early exit if no callee saved registers are modified! 86*480093f4SDimitry Andric 87*480093f4SDimitry Andric unsigned LowGPR = 0; 88*480093f4SDimitry Andric unsigned HighGPR = SystemZ::R15D; 89*480093f4SDimitry Andric int StartSPOffset = SystemZMC::CallFrameSize; 90*480093f4SDimitry Andric int CurrOffset; 91*480093f4SDimitry Andric if (!usePackedStack(MF)) { 92*480093f4SDimitry Andric for (auto &CS : CSI) { 93*480093f4SDimitry Andric unsigned Reg = CS.getReg(); 94*480093f4SDimitry Andric int Offset = RegSpillOffsets[Reg]; 95*480093f4SDimitry Andric if (Offset) { 96*480093f4SDimitry Andric if (SystemZ::GR64BitRegClass.contains(Reg) && StartSPOffset > Offset) { 97*480093f4SDimitry Andric LowGPR = Reg; 98*480093f4SDimitry Andric StartSPOffset = Offset; 99*480093f4SDimitry Andric } 100*480093f4SDimitry Andric Offset -= SystemZMC::CallFrameSize; 101*480093f4SDimitry Andric int FrameIdx = MFFrame.CreateFixedSpillStackObject(8, Offset); 102*480093f4SDimitry Andric CS.setFrameIdx(FrameIdx); 103*480093f4SDimitry Andric } else 104*480093f4SDimitry Andric CS.setFrameIdx(INT32_MAX); 105*480093f4SDimitry Andric } 106*480093f4SDimitry Andric 107*480093f4SDimitry Andric // Save the range of call-saved registers, for use by the 108*480093f4SDimitry Andric // prologue/epilogue inserters. 109*480093f4SDimitry Andric ZFI->setRestoreGPRRegs(LowGPR, HighGPR, StartSPOffset); 110*480093f4SDimitry Andric if (IsVarArg) { 111*480093f4SDimitry Andric // Also save the GPR varargs, if any. R6D is call-saved, so would 112*480093f4SDimitry Andric // already be included, but we also need to handle the call-clobbered 113*480093f4SDimitry Andric // argument registers. 114*480093f4SDimitry Andric unsigned FirstGPR = ZFI->getVarArgsFirstGPR(); 115*480093f4SDimitry Andric if (FirstGPR < SystemZ::NumArgGPRs) { 116*480093f4SDimitry Andric unsigned Reg = SystemZ::ArgGPRs[FirstGPR]; 117*480093f4SDimitry Andric int Offset = RegSpillOffsets[Reg]; 118*480093f4SDimitry Andric if (StartSPOffset > Offset) { 119*480093f4SDimitry Andric LowGPR = Reg; StartSPOffset = Offset; 120*480093f4SDimitry Andric } 121*480093f4SDimitry Andric } 122*480093f4SDimitry Andric } 123*480093f4SDimitry Andric ZFI->setSpillGPRRegs(LowGPR, HighGPR, StartSPOffset); 124*480093f4SDimitry Andric 125*480093f4SDimitry Andric CurrOffset = -SystemZMC::CallFrameSize; 126*480093f4SDimitry Andric } else { 127*480093f4SDimitry Andric // Packed stack: put all the GPRs at the top of the Register save area. 128*480093f4SDimitry Andric uint32_t LowGR64Num = UINT32_MAX; 129*480093f4SDimitry Andric for (auto &CS : CSI) { 130*480093f4SDimitry Andric unsigned Reg = CS.getReg(); 131*480093f4SDimitry Andric if (SystemZ::GR64BitRegClass.contains(Reg)) { 132*480093f4SDimitry Andric unsigned GR64Num = SystemZMC::getFirstReg(Reg); 133*480093f4SDimitry Andric int Offset = -8 * (15 - GR64Num + 1); 134*480093f4SDimitry Andric if (LowGR64Num > GR64Num) { 135*480093f4SDimitry Andric LowGR64Num = GR64Num; 136*480093f4SDimitry Andric StartSPOffset = SystemZMC::CallFrameSize + Offset; 137*480093f4SDimitry Andric } 138*480093f4SDimitry Andric int FrameIdx = MFFrame.CreateFixedSpillStackObject(8, Offset); 139*480093f4SDimitry Andric CS.setFrameIdx(FrameIdx); 140*480093f4SDimitry Andric } else 141*480093f4SDimitry Andric CS.setFrameIdx(INT32_MAX); 142*480093f4SDimitry Andric } 143*480093f4SDimitry Andric if (LowGR64Num < UINT32_MAX) 144*480093f4SDimitry Andric LowGPR = SystemZMC::GR64Regs[LowGR64Num]; 145*480093f4SDimitry Andric 146*480093f4SDimitry Andric // Save the range of call-saved registers, for use by the 147*480093f4SDimitry Andric // prologue/epilogue inserters. 148*480093f4SDimitry Andric ZFI->setRestoreGPRRegs(LowGPR, HighGPR, StartSPOffset); 149*480093f4SDimitry Andric ZFI->setSpillGPRRegs(LowGPR, HighGPR, StartSPOffset); 150*480093f4SDimitry Andric 151*480093f4SDimitry Andric CurrOffset = LowGPR ? -(SystemZMC::CallFrameSize - StartSPOffset) : 0; 152*480093f4SDimitry Andric } 153*480093f4SDimitry Andric 154*480093f4SDimitry Andric // Create fixed stack objects for the remaining registers. 155*480093f4SDimitry Andric for (auto &CS : CSI) { 156*480093f4SDimitry Andric if (CS.getFrameIdx() != INT32_MAX) 157*480093f4SDimitry Andric continue; 158*480093f4SDimitry Andric unsigned Reg = CS.getReg(); 159*480093f4SDimitry Andric const TargetRegisterClass *RC = TRI->getMinimalPhysRegClass(Reg); 160*480093f4SDimitry Andric unsigned Size = TRI->getSpillSize(*RC); 161*480093f4SDimitry Andric CurrOffset -= Size; 162*480093f4SDimitry Andric assert(CurrOffset % 8 == 0 && 163*480093f4SDimitry Andric "8-byte alignment required for for all register save slots"); 164*480093f4SDimitry Andric int FrameIdx = MFFrame.CreateFixedSpillStackObject(Size, CurrOffset); 165*480093f4SDimitry Andric CS.setFrameIdx(FrameIdx); 166*480093f4SDimitry Andric } 167*480093f4SDimitry Andric 168*480093f4SDimitry Andric return true; 1690b57cec5SDimitry Andric } 1700b57cec5SDimitry Andric 1710b57cec5SDimitry Andric void SystemZFrameLowering::determineCalleeSaves(MachineFunction &MF, 1720b57cec5SDimitry Andric BitVector &SavedRegs, 1730b57cec5SDimitry Andric RegScavenger *RS) const { 1740b57cec5SDimitry Andric TargetFrameLowering::determineCalleeSaves(MF, SavedRegs, RS); 1750b57cec5SDimitry Andric 1760b57cec5SDimitry Andric MachineFrameInfo &MFFrame = MF.getFrameInfo(); 1770b57cec5SDimitry Andric const TargetRegisterInfo *TRI = MF.getSubtarget().getRegisterInfo(); 1780b57cec5SDimitry Andric bool HasFP = hasFP(MF); 1790b57cec5SDimitry Andric SystemZMachineFunctionInfo *MFI = MF.getInfo<SystemZMachineFunctionInfo>(); 1800b57cec5SDimitry Andric bool IsVarArg = MF.getFunction().isVarArg(); 1810b57cec5SDimitry Andric 1820b57cec5SDimitry Andric // va_start stores incoming FPR varargs in the normal way, but delegates 1830b57cec5SDimitry Andric // the saving of incoming GPR varargs to spillCalleeSavedRegisters(). 1840b57cec5SDimitry Andric // Record these pending uses, which typically include the call-saved 1850b57cec5SDimitry Andric // argument register R6D. 1860b57cec5SDimitry Andric if (IsVarArg) 1870b57cec5SDimitry Andric for (unsigned I = MFI->getVarArgsFirstGPR(); I < SystemZ::NumArgGPRs; ++I) 1880b57cec5SDimitry Andric SavedRegs.set(SystemZ::ArgGPRs[I]); 1890b57cec5SDimitry Andric 1900b57cec5SDimitry Andric // If there are any landing pads, entering them will modify r6/r7. 1910b57cec5SDimitry Andric if (!MF.getLandingPads().empty()) { 1920b57cec5SDimitry Andric SavedRegs.set(SystemZ::R6D); 1930b57cec5SDimitry Andric SavedRegs.set(SystemZ::R7D); 1940b57cec5SDimitry Andric } 1950b57cec5SDimitry Andric 1960b57cec5SDimitry Andric // If the function requires a frame pointer, record that the hard 1970b57cec5SDimitry Andric // frame pointer will be clobbered. 1980b57cec5SDimitry Andric if (HasFP) 1990b57cec5SDimitry Andric SavedRegs.set(SystemZ::R11D); 2000b57cec5SDimitry Andric 2010b57cec5SDimitry Andric // If the function calls other functions, record that the return 2020b57cec5SDimitry Andric // address register will be clobbered. 2030b57cec5SDimitry Andric if (MFFrame.hasCalls()) 2040b57cec5SDimitry Andric SavedRegs.set(SystemZ::R14D); 2050b57cec5SDimitry Andric 2060b57cec5SDimitry Andric // If we are saving GPRs other than the stack pointer, we might as well 2070b57cec5SDimitry Andric // save and restore the stack pointer at the same time, via STMG and LMG. 2080b57cec5SDimitry Andric // This allows the deallocation to be done by the LMG, rather than needing 2090b57cec5SDimitry Andric // a separate %r15 addition. 2100b57cec5SDimitry Andric const MCPhysReg *CSRegs = TRI->getCalleeSavedRegs(&MF); 2110b57cec5SDimitry Andric for (unsigned I = 0; CSRegs[I]; ++I) { 2120b57cec5SDimitry Andric unsigned Reg = CSRegs[I]; 2130b57cec5SDimitry Andric if (SystemZ::GR64BitRegClass.contains(Reg) && SavedRegs.test(Reg)) { 2140b57cec5SDimitry Andric SavedRegs.set(SystemZ::R15D); 2150b57cec5SDimitry Andric break; 2160b57cec5SDimitry Andric } 2170b57cec5SDimitry Andric } 2180b57cec5SDimitry Andric } 2190b57cec5SDimitry Andric 2200b57cec5SDimitry Andric // Add GPR64 to the save instruction being built by MIB, which is in basic 2210b57cec5SDimitry Andric // block MBB. IsImplicit says whether this is an explicit operand to the 2220b57cec5SDimitry Andric // instruction, or an implicit one that comes between the explicit start 2230b57cec5SDimitry Andric // and end registers. 2240b57cec5SDimitry Andric static void addSavedGPR(MachineBasicBlock &MBB, MachineInstrBuilder &MIB, 2250b57cec5SDimitry Andric unsigned GPR64, bool IsImplicit) { 2260b57cec5SDimitry Andric const TargetRegisterInfo *RI = 2270b57cec5SDimitry Andric MBB.getParent()->getSubtarget().getRegisterInfo(); 2288bcb0991SDimitry Andric Register GPR32 = RI->getSubReg(GPR64, SystemZ::subreg_l32); 2290b57cec5SDimitry Andric bool IsLive = MBB.isLiveIn(GPR64) || MBB.isLiveIn(GPR32); 2300b57cec5SDimitry Andric if (!IsLive || !IsImplicit) { 2310b57cec5SDimitry Andric MIB.addReg(GPR64, getImplRegState(IsImplicit) | getKillRegState(!IsLive)); 2320b57cec5SDimitry Andric if (!IsLive) 2330b57cec5SDimitry Andric MBB.addLiveIn(GPR64); 2340b57cec5SDimitry Andric } 2350b57cec5SDimitry Andric } 2360b57cec5SDimitry Andric 2370b57cec5SDimitry Andric bool SystemZFrameLowering:: 2380b57cec5SDimitry Andric spillCalleeSavedRegisters(MachineBasicBlock &MBB, 2390b57cec5SDimitry Andric MachineBasicBlock::iterator MBBI, 2400b57cec5SDimitry Andric const std::vector<CalleeSavedInfo> &CSI, 2410b57cec5SDimitry Andric const TargetRegisterInfo *TRI) const { 2420b57cec5SDimitry Andric if (CSI.empty()) 2430b57cec5SDimitry Andric return false; 2440b57cec5SDimitry Andric 2450b57cec5SDimitry Andric MachineFunction &MF = *MBB.getParent(); 2460b57cec5SDimitry Andric const TargetInstrInfo *TII = MF.getSubtarget().getInstrInfo(); 2470b57cec5SDimitry Andric SystemZMachineFunctionInfo *ZFI = MF.getInfo<SystemZMachineFunctionInfo>(); 2480b57cec5SDimitry Andric bool IsVarArg = MF.getFunction().isVarArg(); 2490b57cec5SDimitry Andric DebugLoc DL; 2500b57cec5SDimitry Andric 2510b57cec5SDimitry Andric // Save GPRs 252*480093f4SDimitry Andric SystemZ::GPRRegs SpillGPRs = ZFI->getSpillGPRRegs(); 253*480093f4SDimitry Andric if (SpillGPRs.LowGPR) { 254*480093f4SDimitry Andric assert(SpillGPRs.LowGPR != SpillGPRs.HighGPR && 255*480093f4SDimitry Andric "Should be saving %r15 and something else"); 2560b57cec5SDimitry Andric 2570b57cec5SDimitry Andric // Build an STMG instruction. 2580b57cec5SDimitry Andric MachineInstrBuilder MIB = BuildMI(MBB, MBBI, DL, TII->get(SystemZ::STMG)); 2590b57cec5SDimitry Andric 2600b57cec5SDimitry Andric // Add the explicit register operands. 261*480093f4SDimitry Andric addSavedGPR(MBB, MIB, SpillGPRs.LowGPR, false); 262*480093f4SDimitry Andric addSavedGPR(MBB, MIB, SpillGPRs.HighGPR, false); 2630b57cec5SDimitry Andric 2640b57cec5SDimitry Andric // Add the address. 265*480093f4SDimitry Andric MIB.addReg(SystemZ::R15D).addImm(SpillGPRs.GPROffset); 2660b57cec5SDimitry Andric 2670b57cec5SDimitry Andric // Make sure all call-saved GPRs are included as operands and are 2680b57cec5SDimitry Andric // marked as live on entry. 2690b57cec5SDimitry Andric for (unsigned I = 0, E = CSI.size(); I != E; ++I) { 2700b57cec5SDimitry Andric unsigned Reg = CSI[I].getReg(); 2710b57cec5SDimitry Andric if (SystemZ::GR64BitRegClass.contains(Reg)) 2720b57cec5SDimitry Andric addSavedGPR(MBB, MIB, Reg, true); 2730b57cec5SDimitry Andric } 2740b57cec5SDimitry Andric 2750b57cec5SDimitry Andric // ...likewise GPR varargs. 2760b57cec5SDimitry Andric if (IsVarArg) 2770b57cec5SDimitry Andric for (unsigned I = ZFI->getVarArgsFirstGPR(); I < SystemZ::NumArgGPRs; ++I) 2780b57cec5SDimitry Andric addSavedGPR(MBB, MIB, SystemZ::ArgGPRs[I], true); 2790b57cec5SDimitry Andric } 2800b57cec5SDimitry Andric 2810b57cec5SDimitry Andric // Save FPRs/VRs in the normal TargetInstrInfo way. 2820b57cec5SDimitry Andric for (unsigned I = 0, E = CSI.size(); I != E; ++I) { 2830b57cec5SDimitry Andric unsigned Reg = CSI[I].getReg(); 2840b57cec5SDimitry Andric if (SystemZ::FP64BitRegClass.contains(Reg)) { 2850b57cec5SDimitry Andric MBB.addLiveIn(Reg); 2860b57cec5SDimitry Andric TII->storeRegToStackSlot(MBB, MBBI, Reg, true, CSI[I].getFrameIdx(), 2870b57cec5SDimitry Andric &SystemZ::FP64BitRegClass, TRI); 2880b57cec5SDimitry Andric } 2890b57cec5SDimitry Andric if (SystemZ::VR128BitRegClass.contains(Reg)) { 2900b57cec5SDimitry Andric MBB.addLiveIn(Reg); 2910b57cec5SDimitry Andric TII->storeRegToStackSlot(MBB, MBBI, Reg, true, CSI[I].getFrameIdx(), 2920b57cec5SDimitry Andric &SystemZ::VR128BitRegClass, TRI); 2930b57cec5SDimitry Andric } 2940b57cec5SDimitry Andric } 2950b57cec5SDimitry Andric 2960b57cec5SDimitry Andric return true; 2970b57cec5SDimitry Andric } 2980b57cec5SDimitry Andric 2990b57cec5SDimitry Andric bool SystemZFrameLowering:: 3000b57cec5SDimitry Andric restoreCalleeSavedRegisters(MachineBasicBlock &MBB, 3010b57cec5SDimitry Andric MachineBasicBlock::iterator MBBI, 3020b57cec5SDimitry Andric std::vector<CalleeSavedInfo> &CSI, 3030b57cec5SDimitry Andric const TargetRegisterInfo *TRI) const { 3040b57cec5SDimitry Andric if (CSI.empty()) 3050b57cec5SDimitry Andric return false; 3060b57cec5SDimitry Andric 3070b57cec5SDimitry Andric MachineFunction &MF = *MBB.getParent(); 3080b57cec5SDimitry Andric const TargetInstrInfo *TII = MF.getSubtarget().getInstrInfo(); 3090b57cec5SDimitry Andric SystemZMachineFunctionInfo *ZFI = MF.getInfo<SystemZMachineFunctionInfo>(); 3100b57cec5SDimitry Andric bool HasFP = hasFP(MF); 3110b57cec5SDimitry Andric DebugLoc DL = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc(); 3120b57cec5SDimitry Andric 3130b57cec5SDimitry Andric // Restore FPRs/VRs in the normal TargetInstrInfo way. 3140b57cec5SDimitry Andric for (unsigned I = 0, E = CSI.size(); I != E; ++I) { 3150b57cec5SDimitry Andric unsigned Reg = CSI[I].getReg(); 3160b57cec5SDimitry Andric if (SystemZ::FP64BitRegClass.contains(Reg)) 3170b57cec5SDimitry Andric TII->loadRegFromStackSlot(MBB, MBBI, Reg, CSI[I].getFrameIdx(), 3180b57cec5SDimitry Andric &SystemZ::FP64BitRegClass, TRI); 3190b57cec5SDimitry Andric if (SystemZ::VR128BitRegClass.contains(Reg)) 3200b57cec5SDimitry Andric TII->loadRegFromStackSlot(MBB, MBBI, Reg, CSI[I].getFrameIdx(), 3210b57cec5SDimitry Andric &SystemZ::VR128BitRegClass, TRI); 3220b57cec5SDimitry Andric } 3230b57cec5SDimitry Andric 3240b57cec5SDimitry Andric // Restore call-saved GPRs (but not call-clobbered varargs, which at 3250b57cec5SDimitry Andric // this point might hold return values). 326*480093f4SDimitry Andric SystemZ::GPRRegs RestoreGPRs = ZFI->getRestoreGPRRegs(); 327*480093f4SDimitry Andric if (RestoreGPRs.LowGPR) { 3280b57cec5SDimitry Andric // If we saved any of %r2-%r5 as varargs, we should also be saving 3290b57cec5SDimitry Andric // and restoring %r6. If we're saving %r6 or above, we should be 3300b57cec5SDimitry Andric // restoring it too. 331*480093f4SDimitry Andric assert(RestoreGPRs.LowGPR != RestoreGPRs.HighGPR && 332*480093f4SDimitry Andric "Should be loading %r15 and something else"); 3330b57cec5SDimitry Andric 3340b57cec5SDimitry Andric // Build an LMG instruction. 3350b57cec5SDimitry Andric MachineInstrBuilder MIB = BuildMI(MBB, MBBI, DL, TII->get(SystemZ::LMG)); 3360b57cec5SDimitry Andric 3370b57cec5SDimitry Andric // Add the explicit register operands. 338*480093f4SDimitry Andric MIB.addReg(RestoreGPRs.LowGPR, RegState::Define); 339*480093f4SDimitry Andric MIB.addReg(RestoreGPRs.HighGPR, RegState::Define); 3400b57cec5SDimitry Andric 3410b57cec5SDimitry Andric // Add the address. 3420b57cec5SDimitry Andric MIB.addReg(HasFP ? SystemZ::R11D : SystemZ::R15D); 343*480093f4SDimitry Andric MIB.addImm(RestoreGPRs.GPROffset); 3440b57cec5SDimitry Andric 3450b57cec5SDimitry Andric // Do a second scan adding regs as being defined by instruction 3460b57cec5SDimitry Andric for (unsigned I = 0, E = CSI.size(); I != E; ++I) { 3470b57cec5SDimitry Andric unsigned Reg = CSI[I].getReg(); 348*480093f4SDimitry Andric if (Reg != RestoreGPRs.LowGPR && Reg != RestoreGPRs.HighGPR && 3490b57cec5SDimitry Andric SystemZ::GR64BitRegClass.contains(Reg)) 3500b57cec5SDimitry Andric MIB.addReg(Reg, RegState::ImplicitDefine); 3510b57cec5SDimitry Andric } 3520b57cec5SDimitry Andric } 3530b57cec5SDimitry Andric 3540b57cec5SDimitry Andric return true; 3550b57cec5SDimitry Andric } 3560b57cec5SDimitry Andric 3570b57cec5SDimitry Andric void SystemZFrameLowering:: 3580b57cec5SDimitry Andric processFunctionBeforeFrameFinalized(MachineFunction &MF, 3590b57cec5SDimitry Andric RegScavenger *RS) const { 3600b57cec5SDimitry Andric MachineFrameInfo &MFFrame = MF.getFrameInfo(); 361*480093f4SDimitry Andric 362*480093f4SDimitry Andric if (!usePackedStack(MF)) 363*480093f4SDimitry Andric // Always create the full incoming register save area. 364*480093f4SDimitry Andric getOrCreateFramePointerSaveIndex(MF); 365*480093f4SDimitry Andric 3660b57cec5SDimitry Andric // Get the size of our stack frame to be allocated ... 3670b57cec5SDimitry Andric uint64_t StackSize = (MFFrame.estimateStackSize(MF) + 3680b57cec5SDimitry Andric SystemZMC::CallFrameSize); 3690b57cec5SDimitry Andric // ... and the maximum offset we may need to reach into the 3700b57cec5SDimitry Andric // caller's frame to access the save area or stack arguments. 371*480093f4SDimitry Andric int64_t MaxArgOffset = 0; 3720b57cec5SDimitry Andric for (int I = MFFrame.getObjectIndexBegin(); I != 0; ++I) 3730b57cec5SDimitry Andric if (MFFrame.getObjectOffset(I) >= 0) { 374*480093f4SDimitry Andric int64_t ArgOffset = MFFrame.getObjectOffset(I) + 3750b57cec5SDimitry Andric MFFrame.getObjectSize(I); 3760b57cec5SDimitry Andric MaxArgOffset = std::max(MaxArgOffset, ArgOffset); 3770b57cec5SDimitry Andric } 3780b57cec5SDimitry Andric 3790b57cec5SDimitry Andric uint64_t MaxReach = StackSize + MaxArgOffset; 3800b57cec5SDimitry Andric if (!isUInt<12>(MaxReach)) { 3810b57cec5SDimitry Andric // We may need register scavenging slots if some parts of the frame 3820b57cec5SDimitry Andric // are outside the reach of an unsigned 12-bit displacement. 3830b57cec5SDimitry Andric // Create 2 for the case where both addresses in an MVC are 3840b57cec5SDimitry Andric // out of range. 3850b57cec5SDimitry Andric RS->addScavengingFrameIndex(MFFrame.CreateStackObject(8, 8, false)); 3860b57cec5SDimitry Andric RS->addScavengingFrameIndex(MFFrame.CreateStackObject(8, 8, false)); 3870b57cec5SDimitry Andric } 3880b57cec5SDimitry Andric } 3890b57cec5SDimitry Andric 3900b57cec5SDimitry Andric // Emit instructions before MBBI (in MBB) to add NumBytes to Reg. 3910b57cec5SDimitry Andric static void emitIncrement(MachineBasicBlock &MBB, 3920b57cec5SDimitry Andric MachineBasicBlock::iterator &MBBI, 3930b57cec5SDimitry Andric const DebugLoc &DL, 3940b57cec5SDimitry Andric unsigned Reg, int64_t NumBytes, 3950b57cec5SDimitry Andric const TargetInstrInfo *TII) { 3960b57cec5SDimitry Andric while (NumBytes) { 3970b57cec5SDimitry Andric unsigned Opcode; 3980b57cec5SDimitry Andric int64_t ThisVal = NumBytes; 3990b57cec5SDimitry Andric if (isInt<16>(NumBytes)) 4000b57cec5SDimitry Andric Opcode = SystemZ::AGHI; 4010b57cec5SDimitry Andric else { 4020b57cec5SDimitry Andric Opcode = SystemZ::AGFI; 4030b57cec5SDimitry Andric // Make sure we maintain 8-byte stack alignment. 4040b57cec5SDimitry Andric int64_t MinVal = -uint64_t(1) << 31; 4050b57cec5SDimitry Andric int64_t MaxVal = (int64_t(1) << 31) - 8; 4060b57cec5SDimitry Andric if (ThisVal < MinVal) 4070b57cec5SDimitry Andric ThisVal = MinVal; 4080b57cec5SDimitry Andric else if (ThisVal > MaxVal) 4090b57cec5SDimitry Andric ThisVal = MaxVal; 4100b57cec5SDimitry Andric } 4110b57cec5SDimitry Andric MachineInstr *MI = BuildMI(MBB, MBBI, DL, TII->get(Opcode), Reg) 4120b57cec5SDimitry Andric .addReg(Reg).addImm(ThisVal); 4130b57cec5SDimitry Andric // The CC implicit def is dead. 4140b57cec5SDimitry Andric MI->getOperand(3).setIsDead(); 4150b57cec5SDimitry Andric NumBytes -= ThisVal; 4160b57cec5SDimitry Andric } 4170b57cec5SDimitry Andric } 4180b57cec5SDimitry Andric 4190b57cec5SDimitry Andric void SystemZFrameLowering::emitPrologue(MachineFunction &MF, 4200b57cec5SDimitry Andric MachineBasicBlock &MBB) const { 4210b57cec5SDimitry Andric assert(&MF.front() == &MBB && "Shrink-wrapping not yet supported"); 4220b57cec5SDimitry Andric MachineFrameInfo &MFFrame = MF.getFrameInfo(); 4230b57cec5SDimitry Andric auto *ZII = 4240b57cec5SDimitry Andric static_cast<const SystemZInstrInfo *>(MF.getSubtarget().getInstrInfo()); 4250b57cec5SDimitry Andric SystemZMachineFunctionInfo *ZFI = MF.getInfo<SystemZMachineFunctionInfo>(); 4260b57cec5SDimitry Andric MachineBasicBlock::iterator MBBI = MBB.begin(); 4270b57cec5SDimitry Andric MachineModuleInfo &MMI = MF.getMMI(); 4280b57cec5SDimitry Andric const MCRegisterInfo *MRI = MMI.getContext().getRegisterInfo(); 4290b57cec5SDimitry Andric const std::vector<CalleeSavedInfo> &CSI = MFFrame.getCalleeSavedInfo(); 4300b57cec5SDimitry Andric bool HasFP = hasFP(MF); 4310b57cec5SDimitry Andric 432*480093f4SDimitry Andric // In GHC calling convention C stack space, including the ABI-defined 433*480093f4SDimitry Andric // 160-byte base area, is (de)allocated by GHC itself. This stack space may 434*480093f4SDimitry Andric // be used by LLVM as spill slots for the tail recursive GHC functions. Thus 435*480093f4SDimitry Andric // do not allocate stack space here, too. 436*480093f4SDimitry Andric if (MF.getFunction().getCallingConv() == CallingConv::GHC) { 437*480093f4SDimitry Andric if (MFFrame.getStackSize() > 2048 * sizeof(long)) { 438*480093f4SDimitry Andric report_fatal_error( 439*480093f4SDimitry Andric "Pre allocated stack space for GHC function is too small"); 440*480093f4SDimitry Andric } 441*480093f4SDimitry Andric if (HasFP) { 442*480093f4SDimitry Andric report_fatal_error( 443*480093f4SDimitry Andric "In GHC calling convention a frame pointer is not supported"); 444*480093f4SDimitry Andric } 445*480093f4SDimitry Andric MFFrame.setStackSize(MFFrame.getStackSize() + SystemZMC::CallFrameSize); 446*480093f4SDimitry Andric return; 447*480093f4SDimitry Andric } 448*480093f4SDimitry Andric 4490b57cec5SDimitry Andric // Debug location must be unknown since the first debug location is used 4500b57cec5SDimitry Andric // to determine the end of the prologue. 4510b57cec5SDimitry Andric DebugLoc DL; 4520b57cec5SDimitry Andric 4530b57cec5SDimitry Andric // The current offset of the stack pointer from the CFA. 4540b57cec5SDimitry Andric int64_t SPOffsetFromCFA = -SystemZMC::CFAOffsetFromInitialSP; 4550b57cec5SDimitry Andric 456*480093f4SDimitry Andric if (ZFI->getSpillGPRRegs().LowGPR) { 4570b57cec5SDimitry Andric // Skip over the GPR saves. 4580b57cec5SDimitry Andric if (MBBI != MBB.end() && MBBI->getOpcode() == SystemZ::STMG) 4590b57cec5SDimitry Andric ++MBBI; 4600b57cec5SDimitry Andric else 4610b57cec5SDimitry Andric llvm_unreachable("Couldn't skip over GPR saves"); 4620b57cec5SDimitry Andric 4630b57cec5SDimitry Andric // Add CFI for the GPR saves. 4640b57cec5SDimitry Andric for (auto &Save : CSI) { 4650b57cec5SDimitry Andric unsigned Reg = Save.getReg(); 4660b57cec5SDimitry Andric if (SystemZ::GR64BitRegClass.contains(Reg)) { 467*480093f4SDimitry Andric int FI = Save.getFrameIdx(); 468*480093f4SDimitry Andric int64_t Offset = MFFrame.getObjectOffset(FI); 4690b57cec5SDimitry Andric unsigned CFIIndex = MF.addFrameInst(MCCFIInstruction::createOffset( 4700b57cec5SDimitry Andric nullptr, MRI->getDwarfRegNum(Reg, true), Offset)); 4710b57cec5SDimitry Andric BuildMI(MBB, MBBI, DL, ZII->get(TargetOpcode::CFI_INSTRUCTION)) 4720b57cec5SDimitry Andric .addCFIIndex(CFIIndex); 4730b57cec5SDimitry Andric } 4740b57cec5SDimitry Andric } 4750b57cec5SDimitry Andric } 4760b57cec5SDimitry Andric 4770b57cec5SDimitry Andric uint64_t StackSize = MFFrame.getStackSize(); 4780b57cec5SDimitry Andric // We need to allocate the ABI-defined 160-byte base area whenever 4790b57cec5SDimitry Andric // we allocate stack space for our own use and whenever we call another 4800b57cec5SDimitry Andric // function. 481*480093f4SDimitry Andric bool HasStackObject = false; 482*480093f4SDimitry Andric for (unsigned i = 0, e = MFFrame.getObjectIndexEnd(); i != e; ++i) 483*480093f4SDimitry Andric if (!MFFrame.isDeadObjectIndex(i)) { 484*480093f4SDimitry Andric HasStackObject = true; 485*480093f4SDimitry Andric break; 4860b57cec5SDimitry Andric } 487*480093f4SDimitry Andric if (HasStackObject || MFFrame.hasCalls()) 488*480093f4SDimitry Andric StackSize += SystemZMC::CallFrameSize; 489*480093f4SDimitry Andric // Don't allocate the incoming reg save area. 490*480093f4SDimitry Andric StackSize = StackSize > SystemZMC::CallFrameSize 491*480093f4SDimitry Andric ? StackSize - SystemZMC::CallFrameSize 492*480093f4SDimitry Andric : 0; 493*480093f4SDimitry Andric MFFrame.setStackSize(StackSize); 4940b57cec5SDimitry Andric 4950b57cec5SDimitry Andric if (StackSize) { 4960b57cec5SDimitry Andric // Determine if we want to store a backchain. 4970b57cec5SDimitry Andric bool StoreBackchain = MF.getFunction().hasFnAttribute("backchain"); 4980b57cec5SDimitry Andric 4990b57cec5SDimitry Andric // If we need backchain, save current stack pointer. R1 is free at this 5000b57cec5SDimitry Andric // point. 5010b57cec5SDimitry Andric if (StoreBackchain) 5020b57cec5SDimitry Andric BuildMI(MBB, MBBI, DL, ZII->get(SystemZ::LGR)) 5030b57cec5SDimitry Andric .addReg(SystemZ::R1D, RegState::Define).addReg(SystemZ::R15D); 5040b57cec5SDimitry Andric 5050b57cec5SDimitry Andric // Allocate StackSize bytes. 5060b57cec5SDimitry Andric int64_t Delta = -int64_t(StackSize); 5070b57cec5SDimitry Andric emitIncrement(MBB, MBBI, DL, SystemZ::R15D, Delta, ZII); 5080b57cec5SDimitry Andric 5090b57cec5SDimitry Andric // Add CFI for the allocation. 5100b57cec5SDimitry Andric unsigned CFIIndex = MF.addFrameInst( 5110b57cec5SDimitry Andric MCCFIInstruction::createDefCfaOffset(nullptr, SPOffsetFromCFA + Delta)); 5120b57cec5SDimitry Andric BuildMI(MBB, MBBI, DL, ZII->get(TargetOpcode::CFI_INSTRUCTION)) 5130b57cec5SDimitry Andric .addCFIIndex(CFIIndex); 5140b57cec5SDimitry Andric SPOffsetFromCFA += Delta; 5150b57cec5SDimitry Andric 5160b57cec5SDimitry Andric if (StoreBackchain) 5170b57cec5SDimitry Andric BuildMI(MBB, MBBI, DL, ZII->get(SystemZ::STG)) 518*480093f4SDimitry Andric .addReg(SystemZ::R1D, RegState::Kill).addReg(SystemZ::R15D).addImm(0) 519*480093f4SDimitry Andric .addReg(0); 5200b57cec5SDimitry Andric } 5210b57cec5SDimitry Andric 5220b57cec5SDimitry Andric if (HasFP) { 5230b57cec5SDimitry Andric // Copy the base of the frame to R11. 5240b57cec5SDimitry Andric BuildMI(MBB, MBBI, DL, ZII->get(SystemZ::LGR), SystemZ::R11D) 5250b57cec5SDimitry Andric .addReg(SystemZ::R15D); 5260b57cec5SDimitry Andric 5270b57cec5SDimitry Andric // Add CFI for the new frame location. 5280b57cec5SDimitry Andric unsigned HardFP = MRI->getDwarfRegNum(SystemZ::R11D, true); 5290b57cec5SDimitry Andric unsigned CFIIndex = MF.addFrameInst( 5300b57cec5SDimitry Andric MCCFIInstruction::createDefCfaRegister(nullptr, HardFP)); 5310b57cec5SDimitry Andric BuildMI(MBB, MBBI, DL, ZII->get(TargetOpcode::CFI_INSTRUCTION)) 5320b57cec5SDimitry Andric .addCFIIndex(CFIIndex); 5330b57cec5SDimitry Andric 5340b57cec5SDimitry Andric // Mark the FramePtr as live at the beginning of every block except 5350b57cec5SDimitry Andric // the entry block. (We'll have marked R11 as live on entry when 5360b57cec5SDimitry Andric // saving the GPRs.) 5370b57cec5SDimitry Andric for (auto I = std::next(MF.begin()), E = MF.end(); I != E; ++I) 5380b57cec5SDimitry Andric I->addLiveIn(SystemZ::R11D); 5390b57cec5SDimitry Andric } 5400b57cec5SDimitry Andric 5410b57cec5SDimitry Andric // Skip over the FPR/VR saves. 5420b57cec5SDimitry Andric SmallVector<unsigned, 8> CFIIndexes; 5430b57cec5SDimitry Andric for (auto &Save : CSI) { 5440b57cec5SDimitry Andric unsigned Reg = Save.getReg(); 5450b57cec5SDimitry Andric if (SystemZ::FP64BitRegClass.contains(Reg)) { 5460b57cec5SDimitry Andric if (MBBI != MBB.end() && 5470b57cec5SDimitry Andric (MBBI->getOpcode() == SystemZ::STD || 5480b57cec5SDimitry Andric MBBI->getOpcode() == SystemZ::STDY)) 5490b57cec5SDimitry Andric ++MBBI; 5500b57cec5SDimitry Andric else 5510b57cec5SDimitry Andric llvm_unreachable("Couldn't skip over FPR save"); 5520b57cec5SDimitry Andric } else if (SystemZ::VR128BitRegClass.contains(Reg)) { 5530b57cec5SDimitry Andric if (MBBI != MBB.end() && 5540b57cec5SDimitry Andric MBBI->getOpcode() == SystemZ::VST) 5550b57cec5SDimitry Andric ++MBBI; 5560b57cec5SDimitry Andric else 5570b57cec5SDimitry Andric llvm_unreachable("Couldn't skip over VR save"); 5580b57cec5SDimitry Andric } else 5590b57cec5SDimitry Andric continue; 5600b57cec5SDimitry Andric 5610b57cec5SDimitry Andric // Add CFI for the this save. 5620b57cec5SDimitry Andric unsigned DwarfReg = MRI->getDwarfRegNum(Reg, true); 5630b57cec5SDimitry Andric unsigned IgnoredFrameReg; 5640b57cec5SDimitry Andric int64_t Offset = 5650b57cec5SDimitry Andric getFrameIndexReference(MF, Save.getFrameIdx(), IgnoredFrameReg); 5660b57cec5SDimitry Andric 5670b57cec5SDimitry Andric unsigned CFIIndex = MF.addFrameInst(MCCFIInstruction::createOffset( 5680b57cec5SDimitry Andric nullptr, DwarfReg, SPOffsetFromCFA + Offset)); 5690b57cec5SDimitry Andric CFIIndexes.push_back(CFIIndex); 5700b57cec5SDimitry Andric } 5710b57cec5SDimitry Andric // Complete the CFI for the FPR/VR saves, modelling them as taking effect 5720b57cec5SDimitry Andric // after the last save. 5730b57cec5SDimitry Andric for (auto CFIIndex : CFIIndexes) { 5740b57cec5SDimitry Andric BuildMI(MBB, MBBI, DL, ZII->get(TargetOpcode::CFI_INSTRUCTION)) 5750b57cec5SDimitry Andric .addCFIIndex(CFIIndex); 5760b57cec5SDimitry Andric } 5770b57cec5SDimitry Andric } 5780b57cec5SDimitry Andric 5790b57cec5SDimitry Andric void SystemZFrameLowering::emitEpilogue(MachineFunction &MF, 5800b57cec5SDimitry Andric MachineBasicBlock &MBB) const { 5810b57cec5SDimitry Andric MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr(); 5820b57cec5SDimitry Andric auto *ZII = 5830b57cec5SDimitry Andric static_cast<const SystemZInstrInfo *>(MF.getSubtarget().getInstrInfo()); 5840b57cec5SDimitry Andric SystemZMachineFunctionInfo *ZFI = MF.getInfo<SystemZMachineFunctionInfo>(); 5850b57cec5SDimitry Andric MachineFrameInfo &MFFrame = MF.getFrameInfo(); 5860b57cec5SDimitry Andric 587*480093f4SDimitry Andric // See SystemZFrameLowering::emitPrologue 588*480093f4SDimitry Andric if (MF.getFunction().getCallingConv() == CallingConv::GHC) 589*480093f4SDimitry Andric return; 590*480093f4SDimitry Andric 5910b57cec5SDimitry Andric // Skip the return instruction. 5920b57cec5SDimitry Andric assert(MBBI->isReturn() && "Can only insert epilogue into returning blocks"); 5930b57cec5SDimitry Andric 5940b57cec5SDimitry Andric uint64_t StackSize = MFFrame.getStackSize(); 595*480093f4SDimitry Andric if (ZFI->getRestoreGPRRegs().LowGPR) { 5960b57cec5SDimitry Andric --MBBI; 5970b57cec5SDimitry Andric unsigned Opcode = MBBI->getOpcode(); 5980b57cec5SDimitry Andric if (Opcode != SystemZ::LMG) 5990b57cec5SDimitry Andric llvm_unreachable("Expected to see callee-save register restore code"); 6000b57cec5SDimitry Andric 6010b57cec5SDimitry Andric unsigned AddrOpNo = 2; 6020b57cec5SDimitry Andric DebugLoc DL = MBBI->getDebugLoc(); 6030b57cec5SDimitry Andric uint64_t Offset = StackSize + MBBI->getOperand(AddrOpNo + 1).getImm(); 6040b57cec5SDimitry Andric unsigned NewOpcode = ZII->getOpcodeForOffset(Opcode, Offset); 6050b57cec5SDimitry Andric 6060b57cec5SDimitry Andric // If the offset is too large, use the largest stack-aligned offset 6070b57cec5SDimitry Andric // and add the rest to the base register (the stack or frame pointer). 6080b57cec5SDimitry Andric if (!NewOpcode) { 6090b57cec5SDimitry Andric uint64_t NumBytes = Offset - 0x7fff8; 6100b57cec5SDimitry Andric emitIncrement(MBB, MBBI, DL, MBBI->getOperand(AddrOpNo).getReg(), 6110b57cec5SDimitry Andric NumBytes, ZII); 6120b57cec5SDimitry Andric Offset -= NumBytes; 6130b57cec5SDimitry Andric NewOpcode = ZII->getOpcodeForOffset(Opcode, Offset); 6140b57cec5SDimitry Andric assert(NewOpcode && "No restore instruction available"); 6150b57cec5SDimitry Andric } 6160b57cec5SDimitry Andric 6170b57cec5SDimitry Andric MBBI->setDesc(ZII->get(NewOpcode)); 6180b57cec5SDimitry Andric MBBI->getOperand(AddrOpNo + 1).ChangeToImmediate(Offset); 6190b57cec5SDimitry Andric } else if (StackSize) { 6200b57cec5SDimitry Andric DebugLoc DL = MBBI->getDebugLoc(); 6210b57cec5SDimitry Andric emitIncrement(MBB, MBBI, DL, SystemZ::R15D, StackSize, ZII); 6220b57cec5SDimitry Andric } 6230b57cec5SDimitry Andric } 6240b57cec5SDimitry Andric 6250b57cec5SDimitry Andric bool SystemZFrameLowering::hasFP(const MachineFunction &MF) const { 6260b57cec5SDimitry Andric return (MF.getTarget().Options.DisableFramePointerElim(MF) || 6270b57cec5SDimitry Andric MF.getFrameInfo().hasVarSizedObjects() || 6280b57cec5SDimitry Andric MF.getInfo<SystemZMachineFunctionInfo>()->getManipulatesSP()); 6290b57cec5SDimitry Andric } 6300b57cec5SDimitry Andric 6310b57cec5SDimitry Andric bool 6320b57cec5SDimitry Andric SystemZFrameLowering::hasReservedCallFrame(const MachineFunction &MF) const { 6330b57cec5SDimitry Andric // The ABI requires us to allocate 160 bytes of stack space for the callee, 6340b57cec5SDimitry Andric // with any outgoing stack arguments being placed above that. It seems 6350b57cec5SDimitry Andric // better to make that area a permanent feature of the frame even if 6360b57cec5SDimitry Andric // we're using a frame pointer. 6370b57cec5SDimitry Andric return true; 6380b57cec5SDimitry Andric } 6390b57cec5SDimitry Andric 640*480093f4SDimitry Andric int SystemZFrameLowering::getFrameIndexReference(const MachineFunction &MF, 641*480093f4SDimitry Andric int FI, 642*480093f4SDimitry Andric unsigned &FrameReg) const { 643*480093f4SDimitry Andric // Our incoming SP is actually SystemZMC::CallFrameSize below the CFA, so 644*480093f4SDimitry Andric // add that difference here. 645*480093f4SDimitry Andric int64_t Offset = 646*480093f4SDimitry Andric TargetFrameLowering::getFrameIndexReference(MF, FI, FrameReg); 647*480093f4SDimitry Andric return Offset + SystemZMC::CallFrameSize; 648*480093f4SDimitry Andric } 649*480093f4SDimitry Andric 6500b57cec5SDimitry Andric MachineBasicBlock::iterator SystemZFrameLowering:: 6510b57cec5SDimitry Andric eliminateCallFramePseudoInstr(MachineFunction &MF, 6520b57cec5SDimitry Andric MachineBasicBlock &MBB, 6530b57cec5SDimitry Andric MachineBasicBlock::iterator MI) const { 6540b57cec5SDimitry Andric switch (MI->getOpcode()) { 6550b57cec5SDimitry Andric case SystemZ::ADJCALLSTACKDOWN: 6560b57cec5SDimitry Andric case SystemZ::ADJCALLSTACKUP: 6570b57cec5SDimitry Andric assert(hasReservedCallFrame(MF) && 6580b57cec5SDimitry Andric "ADJSTACKDOWN and ADJSTACKUP should be no-ops"); 6590b57cec5SDimitry Andric return MBB.erase(MI); 6600b57cec5SDimitry Andric break; 6610b57cec5SDimitry Andric 6620b57cec5SDimitry Andric default: 6630b57cec5SDimitry Andric llvm_unreachable("Unexpected call frame instruction"); 6640b57cec5SDimitry Andric } 6650b57cec5SDimitry Andric } 666*480093f4SDimitry Andric 667*480093f4SDimitry Andric int SystemZFrameLowering:: 668*480093f4SDimitry Andric getOrCreateFramePointerSaveIndex(MachineFunction &MF) const { 669*480093f4SDimitry Andric SystemZMachineFunctionInfo *ZFI = MF.getInfo<SystemZMachineFunctionInfo>(); 670*480093f4SDimitry Andric int FI = ZFI->getFramePointerSaveIndex(); 671*480093f4SDimitry Andric if (!FI) { 672*480093f4SDimitry Andric MachineFrameInfo &MFFrame = MF.getFrameInfo(); 673*480093f4SDimitry Andric FI = MFFrame.CreateFixedObject(8, -SystemZMC::CallFrameSize, false); 674*480093f4SDimitry Andric ZFI->setFramePointerSaveIndex(FI); 675*480093f4SDimitry Andric } 676*480093f4SDimitry Andric return FI; 677*480093f4SDimitry Andric } 678