15f613dfdSUlrich Weigand //===-- SystemZFrameLowering.cpp - Frame lowering for SystemZ -------------===// 25f613dfdSUlrich Weigand // 32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information. 52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 65f613dfdSUlrich Weigand // 75f613dfdSUlrich Weigand //===----------------------------------------------------------------------===// 85f613dfdSUlrich Weigand 95f613dfdSUlrich Weigand #include "SystemZFrameLowering.h" 105f613dfdSUlrich Weigand #include "SystemZCallingConv.h" 115f613dfdSUlrich Weigand #include "SystemZInstrBuilder.h" 12f1bd22dfSEric Christopher #include "SystemZInstrInfo.h" 135f613dfdSUlrich Weigand #include "SystemZMachineFunctionInfo.h" 14f1bd22dfSEric Christopher #include "SystemZRegisterInfo.h" 15d913448bSEric Christopher #include "SystemZSubtarget.h" 165f613dfdSUlrich Weigand #include "llvm/CodeGen/MachineModuleInfo.h" 175f613dfdSUlrich Weigand #include "llvm/CodeGen/MachineRegisterInfo.h" 185dd52f8cSRichard Sandiford #include "llvm/CodeGen/RegisterScavenging.h" 195f613dfdSUlrich Weigand #include "llvm/IR/Function.h" 205f613dfdSUlrich Weigand 215f613dfdSUlrich Weigand using namespace llvm; 225f613dfdSUlrich Weigand 23db39b4a2SRichard Sandiford namespace { 24a7d3f693SJonas Paulsson // The ABI-defined register save slots, relative to the CFA (i.e. 25a7d3f693SJonas Paulsson // incoming stack pointer + SystemZMC::CallFrameSize). 26db39b4a2SRichard Sandiford static const TargetFrameLowering::SpillSlot SpillOffsetTable[] = { 2761f5ba5cSJonas Paulsson { SystemZ::R2D, 0x10 }, 2861f5ba5cSJonas Paulsson { SystemZ::R3D, 0x18 }, 2961f5ba5cSJonas Paulsson { SystemZ::R4D, 0x20 }, 3061f5ba5cSJonas Paulsson { SystemZ::R5D, 0x28 }, 3161f5ba5cSJonas Paulsson { SystemZ::R6D, 0x30 }, 3261f5ba5cSJonas Paulsson { SystemZ::R7D, 0x38 }, 3361f5ba5cSJonas Paulsson { SystemZ::R8D, 0x40 }, 3461f5ba5cSJonas Paulsson { SystemZ::R9D, 0x48 }, 3561f5ba5cSJonas Paulsson { SystemZ::R10D, 0x50 }, 3661f5ba5cSJonas Paulsson { SystemZ::R11D, 0x58 }, 3761f5ba5cSJonas Paulsson { SystemZ::R12D, 0x60 }, 3861f5ba5cSJonas Paulsson { SystemZ::R13D, 0x68 }, 3961f5ba5cSJonas Paulsson { SystemZ::R14D, 0x70 }, 4061f5ba5cSJonas Paulsson { SystemZ::R15D, 0x78 }, 4161f5ba5cSJonas Paulsson { SystemZ::F0D, 0x80 }, 4261f5ba5cSJonas Paulsson { SystemZ::F2D, 0x88 }, 4361f5ba5cSJonas Paulsson { SystemZ::F4D, 0x90 }, 4461f5ba5cSJonas Paulsson { SystemZ::F6D, 0x98 } 455f613dfdSUlrich Weigand }; 46c231269fSRichard Sandiford } // end anonymous namespace 475f613dfdSUlrich Weigand 48f1bd22dfSEric Christopher SystemZFrameLowering::SystemZFrameLowering() 49882c43d7SGuillaume Chatelet : TargetFrameLowering(TargetFrameLowering::StackGrowsDown, Align(8), 5061f5ba5cSJonas Paulsson 0, Align(8), false /* StackRealignable */), 5161f5ba5cSJonas Paulsson RegSpillOffsets(0) { 52a7d3f693SJonas Paulsson // Due to the SystemZ ABI, the DWARF CFA (Canonical Frame Address) is not 53a7d3f693SJonas Paulsson // equal to the incoming stack pointer, but to incoming stack pointer plus 5461f5ba5cSJonas Paulsson // 160. Instead of using a Local Area Offset, the Register save area will 5561f5ba5cSJonas Paulsson // be occupied by fixed frame objects, and all offsets are actually 5661f5ba5cSJonas Paulsson // relative to CFA. 57a7d3f693SJonas Paulsson 585f613dfdSUlrich Weigand // Create a mapping from register number to save slot offset. 59a7d3f693SJonas Paulsson // These offsets are relative to the start of the register save area. 605f613dfdSUlrich Weigand RegSpillOffsets.grow(SystemZ::NUM_TARGET_REGS); 615f613dfdSUlrich Weigand for (unsigned I = 0, E = array_lengthof(SpillOffsetTable); I != E; ++I) 6261f5ba5cSJonas Paulsson RegSpillOffsets[SpillOffsetTable[I].Reg] = SpillOffsetTable[I].Offset; 63db39b4a2SRichard Sandiford } 64db39b4a2SRichard Sandiford 6561f5ba5cSJonas Paulsson bool SystemZFrameLowering:: 6661f5ba5cSJonas Paulsson assignCalleeSavedSpillSlots(MachineFunction &MF, 6761f5ba5cSJonas Paulsson const TargetRegisterInfo *TRI, 6861f5ba5cSJonas Paulsson std::vector<CalleeSavedInfo> &CSI) const { 6961f5ba5cSJonas Paulsson SystemZMachineFunctionInfo *ZFI = MF.getInfo<SystemZMachineFunctionInfo>(); 7061f5ba5cSJonas Paulsson MachineFrameInfo &MFFrame = MF.getFrameInfo(); 7161f5ba5cSJonas Paulsson bool IsVarArg = MF.getFunction().isVarArg(); 7261f5ba5cSJonas Paulsson if (CSI.empty()) 7361f5ba5cSJonas Paulsson return true; // Early exit if no callee saved registers are modified! 7461f5ba5cSJonas Paulsson 7561f5ba5cSJonas Paulsson unsigned LowGPR = 0; 7661f5ba5cSJonas Paulsson unsigned HighGPR = SystemZ::R15D; 7761f5ba5cSJonas Paulsson int StartSPOffset = SystemZMC::CallFrameSize; 7861f5ba5cSJonas Paulsson for (auto &CS : CSI) { 7961f5ba5cSJonas Paulsson unsigned Reg = CS.getReg(); 8082879c29SJonas Paulsson int Offset = getRegSpillOffset(MF, Reg); 8161f5ba5cSJonas Paulsson if (Offset) { 8261f5ba5cSJonas Paulsson if (SystemZ::GR64BitRegClass.contains(Reg) && StartSPOffset > Offset) { 8361f5ba5cSJonas Paulsson LowGPR = Reg; 8461f5ba5cSJonas Paulsson StartSPOffset = Offset; 8561f5ba5cSJonas Paulsson } 8661f5ba5cSJonas Paulsson Offset -= SystemZMC::CallFrameSize; 8761f5ba5cSJonas Paulsson int FrameIdx = MFFrame.CreateFixedSpillStackObject(8, Offset); 8861f5ba5cSJonas Paulsson CS.setFrameIdx(FrameIdx); 8961f5ba5cSJonas Paulsson } else 9061f5ba5cSJonas Paulsson CS.setFrameIdx(INT32_MAX); 9161f5ba5cSJonas Paulsson } 9261f5ba5cSJonas Paulsson 9361f5ba5cSJonas Paulsson // Save the range of call-saved registers, for use by the 9461f5ba5cSJonas Paulsson // prologue/epilogue inserters. 9561f5ba5cSJonas Paulsson ZFI->setRestoreGPRRegs(LowGPR, HighGPR, StartSPOffset); 9661f5ba5cSJonas Paulsson if (IsVarArg) { 9761f5ba5cSJonas Paulsson // Also save the GPR varargs, if any. R6D is call-saved, so would 9861f5ba5cSJonas Paulsson // already be included, but we also need to handle the call-clobbered 9961f5ba5cSJonas Paulsson // argument registers. 10061f5ba5cSJonas Paulsson unsigned FirstGPR = ZFI->getVarArgsFirstGPR(); 10161f5ba5cSJonas Paulsson if (FirstGPR < SystemZ::NumArgGPRs) { 10261f5ba5cSJonas Paulsson unsigned Reg = SystemZ::ArgGPRs[FirstGPR]; 10382879c29SJonas Paulsson int Offset = getRegSpillOffset(MF, Reg); 10461f5ba5cSJonas Paulsson if (StartSPOffset > Offset) { 10561f5ba5cSJonas Paulsson LowGPR = Reg; StartSPOffset = Offset; 10661f5ba5cSJonas Paulsson } 10761f5ba5cSJonas Paulsson } 10861f5ba5cSJonas Paulsson } 10961f5ba5cSJonas Paulsson ZFI->setSpillGPRRegs(LowGPR, HighGPR, StartSPOffset); 11061f5ba5cSJonas Paulsson 11161f5ba5cSJonas Paulsson // Create fixed stack objects for the remaining registers. 11282879c29SJonas Paulsson int CurrOffset = -SystemZMC::CallFrameSize; 11382879c29SJonas Paulsson if (usePackedStack(MF)) 11482879c29SJonas Paulsson CurrOffset += StartSPOffset; 11582879c29SJonas Paulsson 11661f5ba5cSJonas Paulsson for (auto &CS : CSI) { 11761f5ba5cSJonas Paulsson if (CS.getFrameIdx() != INT32_MAX) 11861f5ba5cSJonas Paulsson continue; 11961f5ba5cSJonas Paulsson unsigned Reg = CS.getReg(); 12061f5ba5cSJonas Paulsson const TargetRegisterClass *RC = TRI->getMinimalPhysRegClass(Reg); 12161f5ba5cSJonas Paulsson unsigned Size = TRI->getSpillSize(*RC); 12261f5ba5cSJonas Paulsson CurrOffset -= Size; 12361f5ba5cSJonas Paulsson assert(CurrOffset % 8 == 0 && 12461f5ba5cSJonas Paulsson "8-byte alignment required for for all register save slots"); 12561f5ba5cSJonas Paulsson int FrameIdx = MFFrame.CreateFixedSpillStackObject(Size, CurrOffset); 12661f5ba5cSJonas Paulsson CS.setFrameIdx(FrameIdx); 12761f5ba5cSJonas Paulsson } 12861f5ba5cSJonas Paulsson 12961f5ba5cSJonas Paulsson return true; 1305f613dfdSUlrich Weigand } 1315f613dfdSUlrich Weigand 13202564865SMatthias Braun void SystemZFrameLowering::determineCalleeSaves(MachineFunction &MF, 13302564865SMatthias Braun BitVector &SavedRegs, 1345f613dfdSUlrich Weigand RegScavenger *RS) const { 13502564865SMatthias Braun TargetFrameLowering::determineCalleeSaves(MF, SavedRegs, RS); 13602564865SMatthias Braun 137941a705bSMatthias Braun MachineFrameInfo &MFFrame = MF.getFrameInfo(); 138fc6de428SEric Christopher const TargetRegisterInfo *TRI = MF.getSubtarget().getRegisterInfo(); 1395f613dfdSUlrich Weigand bool HasFP = hasFP(MF); 1405f613dfdSUlrich Weigand SystemZMachineFunctionInfo *MFI = MF.getInfo<SystemZMachineFunctionInfo>(); 141f1caa283SMatthias Braun bool IsVarArg = MF.getFunction().isVarArg(); 1425f613dfdSUlrich Weigand 1435f613dfdSUlrich Weigand // va_start stores incoming FPR varargs in the normal way, but delegates 1445f613dfdSUlrich Weigand // the saving of incoming GPR varargs to spillCalleeSavedRegisters(). 1455f613dfdSUlrich Weigand // Record these pending uses, which typically include the call-saved 1465f613dfdSUlrich Weigand // argument register R6D. 1475f613dfdSUlrich Weigand if (IsVarArg) 1485f613dfdSUlrich Weigand for (unsigned I = MFI->getVarArgsFirstGPR(); I < SystemZ::NumArgGPRs; ++I) 14902564865SMatthias Braun SavedRegs.set(SystemZ::ArgGPRs[I]); 1505f613dfdSUlrich Weigand 151234e5a80SMarcin Koscielnicki // If there are any landing pads, entering them will modify r6/r7. 152d0ee66c2SMatthias Braun if (!MF.getLandingPads().empty()) { 153234e5a80SMarcin Koscielnicki SavedRegs.set(SystemZ::R6D); 154234e5a80SMarcin Koscielnicki SavedRegs.set(SystemZ::R7D); 155234e5a80SMarcin Koscielnicki } 156234e5a80SMarcin Koscielnicki 1575f613dfdSUlrich Weigand // If the function requires a frame pointer, record that the hard 1585f613dfdSUlrich Weigand // frame pointer will be clobbered. 1595f613dfdSUlrich Weigand if (HasFP) 16002564865SMatthias Braun SavedRegs.set(SystemZ::R11D); 1615f613dfdSUlrich Weigand 1625f613dfdSUlrich Weigand // If the function calls other functions, record that the return 1635f613dfdSUlrich Weigand // address register will be clobbered. 164941a705bSMatthias Braun if (MFFrame.hasCalls()) 16502564865SMatthias Braun SavedRegs.set(SystemZ::R14D); 1665f613dfdSUlrich Weigand 1675f613dfdSUlrich Weigand // If we are saving GPRs other than the stack pointer, we might as well 1685f613dfdSUlrich Weigand // save and restore the stack pointer at the same time, via STMG and LMG. 1695f613dfdSUlrich Weigand // This allows the deallocation to be done by the LMG, rather than needing 1705f613dfdSUlrich Weigand // a separate %r15 addition. 171840beec2SCraig Topper const MCPhysReg *CSRegs = TRI->getCalleeSavedRegs(&MF); 1725f613dfdSUlrich Weigand for (unsigned I = 0; CSRegs[I]; ++I) { 1735f613dfdSUlrich Weigand unsigned Reg = CSRegs[I]; 17402564865SMatthias Braun if (SystemZ::GR64BitRegClass.contains(Reg) && SavedRegs.test(Reg)) { 17502564865SMatthias Braun SavedRegs.set(SystemZ::R15D); 1765f613dfdSUlrich Weigand break; 1775f613dfdSUlrich Weigand } 1785f613dfdSUlrich Weigand } 1795f613dfdSUlrich Weigand } 1805f613dfdSUlrich Weigand 1815f613dfdSUlrich Weigand // Add GPR64 to the save instruction being built by MIB, which is in basic 1825f613dfdSUlrich Weigand // block MBB. IsImplicit says whether this is an explicit operand to the 1835f613dfdSUlrich Weigand // instruction, or an implicit one that comes between the explicit start 1845f613dfdSUlrich Weigand // and end registers. 1855f613dfdSUlrich Weigand static void addSavedGPR(MachineBasicBlock &MBB, MachineInstrBuilder &MIB, 1865f613dfdSUlrich Weigand unsigned GPR64, bool IsImplicit) { 187d913448bSEric Christopher const TargetRegisterInfo *RI = 188fc6de428SEric Christopher MBB.getParent()->getSubtarget().getRegisterInfo(); 1890c476111SDaniel Sanders Register GPR32 = RI->getSubReg(GPR64, SystemZ::subreg_l32); 1905f613dfdSUlrich Weigand bool IsLive = MBB.isLiveIn(GPR64) || MBB.isLiveIn(GPR32); 1915f613dfdSUlrich Weigand if (!IsLive || !IsImplicit) { 1925f613dfdSUlrich Weigand MIB.addReg(GPR64, getImplRegState(IsImplicit) | getKillRegState(!IsLive)); 1935f613dfdSUlrich Weigand if (!IsLive) 1945f613dfdSUlrich Weigand MBB.addLiveIn(GPR64); 1955f613dfdSUlrich Weigand } 1965f613dfdSUlrich Weigand } 1975f613dfdSUlrich Weigand 198e4230a9fSBenjamin Kramer bool SystemZFrameLowering::spillCalleeSavedRegisters( 199e4230a9fSBenjamin Kramer MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, 200e4230a9fSBenjamin Kramer ArrayRef<CalleeSavedInfo> CSI, const TargetRegisterInfo *TRI) const { 2015f613dfdSUlrich Weigand if (CSI.empty()) 2025f613dfdSUlrich Weigand return false; 2035f613dfdSUlrich Weigand 2045f613dfdSUlrich Weigand MachineFunction &MF = *MBB.getParent(); 205fc6de428SEric Christopher const TargetInstrInfo *TII = MF.getSubtarget().getInstrInfo(); 2065f613dfdSUlrich Weigand SystemZMachineFunctionInfo *ZFI = MF.getInfo<SystemZMachineFunctionInfo>(); 207f1caa283SMatthias Braun bool IsVarArg = MF.getFunction().isVarArg(); 208057c5a6bSOleg Ranevskyy DebugLoc DL; 2095f613dfdSUlrich Weigand 2105f613dfdSUlrich Weigand // Save GPRs 21161f5ba5cSJonas Paulsson SystemZ::GPRRegs SpillGPRs = ZFI->getSpillGPRRegs(); 21261f5ba5cSJonas Paulsson if (SpillGPRs.LowGPR) { 21361f5ba5cSJonas Paulsson assert(SpillGPRs.LowGPR != SpillGPRs.HighGPR && 21461f5ba5cSJonas Paulsson "Should be saving %r15 and something else"); 2155f613dfdSUlrich Weigand 2165f613dfdSUlrich Weigand // Build an STMG instruction. 2175f613dfdSUlrich Weigand MachineInstrBuilder MIB = BuildMI(MBB, MBBI, DL, TII->get(SystemZ::STMG)); 2185f613dfdSUlrich Weigand 2195f613dfdSUlrich Weigand // Add the explicit register operands. 22061f5ba5cSJonas Paulsson addSavedGPR(MBB, MIB, SpillGPRs.LowGPR, false); 22161f5ba5cSJonas Paulsson addSavedGPR(MBB, MIB, SpillGPRs.HighGPR, false); 2225f613dfdSUlrich Weigand 2235f613dfdSUlrich Weigand // Add the address. 22461f5ba5cSJonas Paulsson MIB.addReg(SystemZ::R15D).addImm(SpillGPRs.GPROffset); 2255f613dfdSUlrich Weigand 2265f613dfdSUlrich Weigand // Make sure all call-saved GPRs are included as operands and are 2275f613dfdSUlrich Weigand // marked as live on entry. 2285f613dfdSUlrich Weigand for (unsigned I = 0, E = CSI.size(); I != E; ++I) { 2295f613dfdSUlrich Weigand unsigned Reg = CSI[I].getReg(); 2305f613dfdSUlrich Weigand if (SystemZ::GR64BitRegClass.contains(Reg)) 231f1bd22dfSEric Christopher addSavedGPR(MBB, MIB, Reg, true); 2325f613dfdSUlrich Weigand } 2335f613dfdSUlrich Weigand 2345f613dfdSUlrich Weigand // ...likewise GPR varargs. 2355f613dfdSUlrich Weigand if (IsVarArg) 2365f613dfdSUlrich Weigand for (unsigned I = ZFI->getVarArgsFirstGPR(); I < SystemZ::NumArgGPRs; ++I) 237f1bd22dfSEric Christopher addSavedGPR(MBB, MIB, SystemZ::ArgGPRs[I], true); 2385f613dfdSUlrich Weigand } 2395f613dfdSUlrich Weigand 2408b19be46SUlrich Weigand // Save FPRs/VRs in the normal TargetInstrInfo way. 2415f613dfdSUlrich Weigand for (unsigned I = 0, E = CSI.size(); I != E; ++I) { 2425f613dfdSUlrich Weigand unsigned Reg = CSI[I].getReg(); 2435f613dfdSUlrich Weigand if (SystemZ::FP64BitRegClass.contains(Reg)) { 2445f613dfdSUlrich Weigand MBB.addLiveIn(Reg); 2455f613dfdSUlrich Weigand TII->storeRegToStackSlot(MBB, MBBI, Reg, true, CSI[I].getFrameIdx(), 2465f613dfdSUlrich Weigand &SystemZ::FP64BitRegClass, TRI); 2475f613dfdSUlrich Weigand } 2488b19be46SUlrich Weigand if (SystemZ::VR128BitRegClass.contains(Reg)) { 2498b19be46SUlrich Weigand MBB.addLiveIn(Reg); 2508b19be46SUlrich Weigand TII->storeRegToStackSlot(MBB, MBBI, Reg, true, CSI[I].getFrameIdx(), 2518b19be46SUlrich Weigand &SystemZ::VR128BitRegClass, TRI); 2528b19be46SUlrich Weigand } 2535f613dfdSUlrich Weigand } 2545f613dfdSUlrich Weigand 2555f613dfdSUlrich Weigand return true; 2565f613dfdSUlrich Weigand } 2575f613dfdSUlrich Weigand 258186dd631SBenjamin Kramer bool SystemZFrameLowering::restoreCalleeSavedRegisters( 259186dd631SBenjamin Kramer MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, 260186dd631SBenjamin Kramer MutableArrayRef<CalleeSavedInfo> CSI, const TargetRegisterInfo *TRI) const { 2615f613dfdSUlrich Weigand if (CSI.empty()) 2625f613dfdSUlrich Weigand return false; 2635f613dfdSUlrich Weigand 2645f613dfdSUlrich Weigand MachineFunction &MF = *MBB.getParent(); 265fc6de428SEric Christopher const TargetInstrInfo *TII = MF.getSubtarget().getInstrInfo(); 2665f613dfdSUlrich Weigand SystemZMachineFunctionInfo *ZFI = MF.getInfo<SystemZMachineFunctionInfo>(); 2675f613dfdSUlrich Weigand bool HasFP = hasFP(MF); 2685f613dfdSUlrich Weigand DebugLoc DL = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc(); 2695f613dfdSUlrich Weigand 2708b19be46SUlrich Weigand // Restore FPRs/VRs in the normal TargetInstrInfo way. 2715f613dfdSUlrich Weigand for (unsigned I = 0, E = CSI.size(); I != E; ++I) { 2725f613dfdSUlrich Weigand unsigned Reg = CSI[I].getReg(); 2735f613dfdSUlrich Weigand if (SystemZ::FP64BitRegClass.contains(Reg)) 2745f613dfdSUlrich Weigand TII->loadRegFromStackSlot(MBB, MBBI, Reg, CSI[I].getFrameIdx(), 2755f613dfdSUlrich Weigand &SystemZ::FP64BitRegClass, TRI); 2768b19be46SUlrich Weigand if (SystemZ::VR128BitRegClass.contains(Reg)) 2778b19be46SUlrich Weigand TII->loadRegFromStackSlot(MBB, MBBI, Reg, CSI[I].getFrameIdx(), 2788b19be46SUlrich Weigand &SystemZ::VR128BitRegClass, TRI); 2795f613dfdSUlrich Weigand } 2805f613dfdSUlrich Weigand 2815f613dfdSUlrich Weigand // Restore call-saved GPRs (but not call-clobbered varargs, which at 2825f613dfdSUlrich Weigand // this point might hold return values). 28361f5ba5cSJonas Paulsson SystemZ::GPRRegs RestoreGPRs = ZFI->getRestoreGPRRegs(); 28461f5ba5cSJonas Paulsson if (RestoreGPRs.LowGPR) { 2855f613dfdSUlrich Weigand // If we saved any of %r2-%r5 as varargs, we should also be saving 2865f613dfdSUlrich Weigand // and restoring %r6. If we're saving %r6 or above, we should be 2875f613dfdSUlrich Weigand // restoring it too. 28861f5ba5cSJonas Paulsson assert(RestoreGPRs.LowGPR != RestoreGPRs.HighGPR && 28961f5ba5cSJonas Paulsson "Should be loading %r15 and something else"); 2905f613dfdSUlrich Weigand 2915f613dfdSUlrich Weigand // Build an LMG instruction. 2925f613dfdSUlrich Weigand MachineInstrBuilder MIB = BuildMI(MBB, MBBI, DL, TII->get(SystemZ::LMG)); 2935f613dfdSUlrich Weigand 2945f613dfdSUlrich Weigand // Add the explicit register operands. 29561f5ba5cSJonas Paulsson MIB.addReg(RestoreGPRs.LowGPR, RegState::Define); 29661f5ba5cSJonas Paulsson MIB.addReg(RestoreGPRs.HighGPR, RegState::Define); 2975f613dfdSUlrich Weigand 2985f613dfdSUlrich Weigand // Add the address. 2995f613dfdSUlrich Weigand MIB.addReg(HasFP ? SystemZ::R11D : SystemZ::R15D); 30061f5ba5cSJonas Paulsson MIB.addImm(RestoreGPRs.GPROffset); 3015f613dfdSUlrich Weigand 3025f613dfdSUlrich Weigand // Do a second scan adding regs as being defined by instruction 3035f613dfdSUlrich Weigand for (unsigned I = 0, E = CSI.size(); I != E; ++I) { 3045f613dfdSUlrich Weigand unsigned Reg = CSI[I].getReg(); 30561f5ba5cSJonas Paulsson if (Reg != RestoreGPRs.LowGPR && Reg != RestoreGPRs.HighGPR && 306f0344826SJonas Paulsson SystemZ::GR64BitRegClass.contains(Reg)) 3075f613dfdSUlrich Weigand MIB.addReg(Reg, RegState::ImplicitDefine); 3085f613dfdSUlrich Weigand } 3095f613dfdSUlrich Weigand } 3105f613dfdSUlrich Weigand 3115f613dfdSUlrich Weigand return true; 3125f613dfdSUlrich Weigand } 3135f613dfdSUlrich Weigand 3145dd52f8cSRichard Sandiford void SystemZFrameLowering:: 3155dd52f8cSRichard Sandiford processFunctionBeforeFrameFinalized(MachineFunction &MF, 3165dd52f8cSRichard Sandiford RegScavenger *RS) const { 317941a705bSMatthias Braun MachineFrameInfo &MFFrame = MF.getFrameInfo(); 318*23762575SJonas Paulsson bool BackChain = MF.getFunction().hasFnAttribute("backchain"); 31961f5ba5cSJonas Paulsson 320*23762575SJonas Paulsson if (!usePackedStack(MF) || BackChain) 321*23762575SJonas Paulsson // Create the incoming register save area. 32261f5ba5cSJonas Paulsson getOrCreateFramePointerSaveIndex(MF); 32361f5ba5cSJonas Paulsson 324af98b748SUlrich Weigand // Get the size of our stack frame to be allocated ... 325af98b748SUlrich Weigand uint64_t StackSize = (MFFrame.estimateStackSize(MF) + 326af98b748SUlrich Weigand SystemZMC::CallFrameSize); 327af98b748SUlrich Weigand // ... and the maximum offset we may need to reach into the 328af98b748SUlrich Weigand // caller's frame to access the save area or stack arguments. 32961f5ba5cSJonas Paulsson int64_t MaxArgOffset = 0; 330af98b748SUlrich Weigand for (int I = MFFrame.getObjectIndexBegin(); I != 0; ++I) 331af98b748SUlrich Weigand if (MFFrame.getObjectOffset(I) >= 0) { 33261f5ba5cSJonas Paulsson int64_t ArgOffset = MFFrame.getObjectOffset(I) + 333af98b748SUlrich Weigand MFFrame.getObjectSize(I); 334af98b748SUlrich Weigand MaxArgOffset = std::max(MaxArgOffset, ArgOffset); 335af98b748SUlrich Weigand } 336af98b748SUlrich Weigand 337af98b748SUlrich Weigand uint64_t MaxReach = StackSize + MaxArgOffset; 33823943229SRichard Sandiford if (!isUInt<12>(MaxReach)) { 33923943229SRichard Sandiford // We may need register scavenging slots if some parts of the frame 3405dd52f8cSRichard Sandiford // are outside the reach of an unsigned 12-bit displacement. 34123943229SRichard Sandiford // Create 2 for the case where both addresses in an MVC are 34223943229SRichard Sandiford // out of range. 343941a705bSMatthias Braun RS->addScavengingFrameIndex(MFFrame.CreateStackObject(8, 8, false)); 344941a705bSMatthias Braun RS->addScavengingFrameIndex(MFFrame.CreateStackObject(8, 8, false)); 34523943229SRichard Sandiford } 3465dd52f8cSRichard Sandiford } 3475dd52f8cSRichard Sandiford 3485f613dfdSUlrich Weigand // Emit instructions before MBBI (in MBB) to add NumBytes to Reg. 3495f613dfdSUlrich Weigand static void emitIncrement(MachineBasicBlock &MBB, 3505f613dfdSUlrich Weigand MachineBasicBlock::iterator &MBBI, 3515f613dfdSUlrich Weigand const DebugLoc &DL, 3525f613dfdSUlrich Weigand unsigned Reg, int64_t NumBytes, 3535f613dfdSUlrich Weigand const TargetInstrInfo *TII) { 3545f613dfdSUlrich Weigand while (NumBytes) { 3555f613dfdSUlrich Weigand unsigned Opcode; 3565f613dfdSUlrich Weigand int64_t ThisVal = NumBytes; 3575f613dfdSUlrich Weigand if (isInt<16>(NumBytes)) 3585f613dfdSUlrich Weigand Opcode = SystemZ::AGHI; 3595f613dfdSUlrich Weigand else { 3605f613dfdSUlrich Weigand Opcode = SystemZ::AGFI; 3615f613dfdSUlrich Weigand // Make sure we maintain 8-byte stack alignment. 362fffd56ecSAlexey Samsonov int64_t MinVal = -uint64_t(1) << 31; 3635f613dfdSUlrich Weigand int64_t MaxVal = (int64_t(1) << 31) - 8; 3645f613dfdSUlrich Weigand if (ThisVal < MinVal) 3655f613dfdSUlrich Weigand ThisVal = MinVal; 3665f613dfdSUlrich Weigand else if (ThisVal > MaxVal) 3675f613dfdSUlrich Weigand ThisVal = MaxVal; 3685f613dfdSUlrich Weigand } 3695f613dfdSUlrich Weigand MachineInstr *MI = BuildMI(MBB, MBBI, DL, TII->get(Opcode), Reg) 3705f613dfdSUlrich Weigand .addReg(Reg).addImm(ThisVal); 37114a44495SRichard Sandiford // The CC implicit def is dead. 3725f613dfdSUlrich Weigand MI->getOperand(3).setIsDead(); 3735f613dfdSUlrich Weigand NumBytes -= ThisVal; 3745f613dfdSUlrich Weigand } 3755f613dfdSUlrich Weigand } 3765f613dfdSUlrich Weigand 37761b305edSQuentin Colombet void SystemZFrameLowering::emitPrologue(MachineFunction &MF, 37861b305edSQuentin Colombet MachineBasicBlock &MBB) const { 37961b305edSQuentin Colombet assert(&MF.front() == &MBB && "Shrink-wrapping not yet supported"); 380941a705bSMatthias Braun MachineFrameInfo &MFFrame = MF.getFrameInfo(); 381fc6de428SEric Christopher auto *ZII = 382fc6de428SEric Christopher static_cast<const SystemZInstrInfo *>(MF.getSubtarget().getInstrInfo()); 3835f613dfdSUlrich Weigand SystemZMachineFunctionInfo *ZFI = MF.getInfo<SystemZMachineFunctionInfo>(); 3845f613dfdSUlrich Weigand MachineBasicBlock::iterator MBBI = MBB.begin(); 3855f613dfdSUlrich Weigand MachineModuleInfo &MMI = MF.getMMI(); 386bc07a890SBill Wendling const MCRegisterInfo *MRI = MMI.getContext().getRegisterInfo(); 387941a705bSMatthias Braun const std::vector<CalleeSavedInfo> &CSI = MFFrame.getCalleeSavedInfo(); 3885f613dfdSUlrich Weigand bool HasFP = hasFP(MF); 389057c5a6bSOleg Ranevskyy 39022f94291SUlrich Weigand // In GHC calling convention C stack space, including the ABI-defined 39122f94291SUlrich Weigand // 160-byte base area, is (de)allocated by GHC itself. This stack space may 39222f94291SUlrich Weigand // be used by LLVM as spill slots for the tail recursive GHC functions. Thus 39322f94291SUlrich Weigand // do not allocate stack space here, too. 39422f94291SUlrich Weigand if (MF.getFunction().getCallingConv() == CallingConv::GHC) { 39522f94291SUlrich Weigand if (MFFrame.getStackSize() > 2048 * sizeof(long)) { 39622f94291SUlrich Weigand report_fatal_error( 39722f94291SUlrich Weigand "Pre allocated stack space for GHC function is too small"); 39822f94291SUlrich Weigand } 39922f94291SUlrich Weigand if (HasFP) { 40022f94291SUlrich Weigand report_fatal_error( 40122f94291SUlrich Weigand "In GHC calling convention a frame pointer is not supported"); 40222f94291SUlrich Weigand } 40322f94291SUlrich Weigand MFFrame.setStackSize(MFFrame.getStackSize() + SystemZMC::CallFrameSize); 40422f94291SUlrich Weigand return; 40522f94291SUlrich Weigand } 40622f94291SUlrich Weigand 407057c5a6bSOleg Ranevskyy // Debug location must be unknown since the first debug location is used 408057c5a6bSOleg Ranevskyy // to determine the end of the prologue. 409057c5a6bSOleg Ranevskyy DebugLoc DL; 4105f613dfdSUlrich Weigand 4115f613dfdSUlrich Weigand // The current offset of the stack pointer from the CFA. 4125f613dfdSUlrich Weigand int64_t SPOffsetFromCFA = -SystemZMC::CFAOffsetFromInitialSP; 4135f613dfdSUlrich Weigand 41461f5ba5cSJonas Paulsson if (ZFI->getSpillGPRRegs().LowGPR) { 4155f613dfdSUlrich Weigand // Skip over the GPR saves. 4165f613dfdSUlrich Weigand if (MBBI != MBB.end() && MBBI->getOpcode() == SystemZ::STMG) 4175f613dfdSUlrich Weigand ++MBBI; 4185f613dfdSUlrich Weigand else 4195f613dfdSUlrich Weigand llvm_unreachable("Couldn't skip over GPR saves"); 4205f613dfdSUlrich Weigand 4215f613dfdSUlrich Weigand // Add CFI for the GPR saves. 42228c111ecSRichard Sandiford for (auto &Save : CSI) { 42328c111ecSRichard Sandiford unsigned Reg = Save.getReg(); 4245f613dfdSUlrich Weigand if (SystemZ::GR64BitRegClass.contains(Reg)) { 42561f5ba5cSJonas Paulsson int FI = Save.getFrameIdx(); 42661f5ba5cSJonas Paulsson int64_t Offset = MFFrame.getObjectOffset(FI); 427f23ef437SMatthias Braun unsigned CFIIndex = MF.addFrameInst(MCCFIInstruction::createOffset( 428b1f25f1bSRafael Espindola nullptr, MRI->getDwarfRegNum(Reg, true), Offset)); 429b1f25f1bSRafael Espindola BuildMI(MBB, MBBI, DL, ZII->get(TargetOpcode::CFI_INSTRUCTION)) 430b1f25f1bSRafael Espindola .addCFIIndex(CFIIndex); 4315f613dfdSUlrich Weigand } 4325f613dfdSUlrich Weigand } 4335f613dfdSUlrich Weigand } 4345f613dfdSUlrich Weigand 43532063888SUlrich Weigand uint64_t StackSize = MFFrame.getStackSize(); 43632063888SUlrich Weigand // We need to allocate the ABI-defined 160-byte base area whenever 43732063888SUlrich Weigand // we allocate stack space for our own use and whenever we call another 43832063888SUlrich Weigand // function. 43961f5ba5cSJonas Paulsson bool HasStackObject = false; 44061f5ba5cSJonas Paulsson for (unsigned i = 0, e = MFFrame.getObjectIndexEnd(); i != e; ++i) 44161f5ba5cSJonas Paulsson if (!MFFrame.isDeadObjectIndex(i)) { 44261f5ba5cSJonas Paulsson HasStackObject = true; 44361f5ba5cSJonas Paulsson break; 44432063888SUlrich Weigand } 44561f5ba5cSJonas Paulsson if (HasStackObject || MFFrame.hasCalls()) 44661f5ba5cSJonas Paulsson StackSize += SystemZMC::CallFrameSize; 44761f5ba5cSJonas Paulsson // Don't allocate the incoming reg save area. 44861f5ba5cSJonas Paulsson StackSize = StackSize > SystemZMC::CallFrameSize 44961f5ba5cSJonas Paulsson ? StackSize - SystemZMC::CallFrameSize 45061f5ba5cSJonas Paulsson : 0; 45161f5ba5cSJonas Paulsson MFFrame.setStackSize(StackSize); 45232063888SUlrich Weigand 4535f613dfdSUlrich Weigand if (StackSize) { 454ad1482c6SMarcin Koscielnicki // Determine if we want to store a backchain. 455f1caa283SMatthias Braun bool StoreBackchain = MF.getFunction().hasFnAttribute("backchain"); 456ad1482c6SMarcin Koscielnicki 457ad1482c6SMarcin Koscielnicki // If we need backchain, save current stack pointer. R1 is free at this 458ad1482c6SMarcin Koscielnicki // point. 459ad1482c6SMarcin Koscielnicki if (StoreBackchain) 460ad1482c6SMarcin Koscielnicki BuildMI(MBB, MBBI, DL, ZII->get(SystemZ::LGR)) 461ad1482c6SMarcin Koscielnicki .addReg(SystemZ::R1D, RegState::Define).addReg(SystemZ::R15D); 462ad1482c6SMarcin Koscielnicki 4635f613dfdSUlrich Weigand // Allocate StackSize bytes. 4645f613dfdSUlrich Weigand int64_t Delta = -int64_t(StackSize); 4655f613dfdSUlrich Weigand emitIncrement(MBB, MBBI, DL, SystemZ::R15D, Delta, ZII); 4665f613dfdSUlrich Weigand 4675f613dfdSUlrich Weigand // Add CFI for the allocation. 468f23ef437SMatthias Braun unsigned CFIIndex = MF.addFrameInst( 469b1f25f1bSRafael Espindola MCCFIInstruction::createDefCfaOffset(nullptr, SPOffsetFromCFA + Delta)); 470b1f25f1bSRafael Espindola BuildMI(MBB, MBBI, DL, ZII->get(TargetOpcode::CFI_INSTRUCTION)) 471b1f25f1bSRafael Espindola .addCFIIndex(CFIIndex); 4725f613dfdSUlrich Weigand SPOffsetFromCFA += Delta; 473ad1482c6SMarcin Koscielnicki 47482879c29SJonas Paulsson if (StoreBackchain) { 47582879c29SJonas Paulsson // The back chain is stored topmost with packed-stack. 47682879c29SJonas Paulsson int Offset = usePackedStack(MF) ? SystemZMC::CallFrameSize - 8 : 0; 477ad1482c6SMarcin Koscielnicki BuildMI(MBB, MBBI, DL, ZII->get(SystemZ::STG)) 47882879c29SJonas Paulsson .addReg(SystemZ::R1D, RegState::Kill).addReg(SystemZ::R15D) 47982879c29SJonas Paulsson .addImm(Offset).addReg(0); 48082879c29SJonas Paulsson } 4815f613dfdSUlrich Weigand } 4825f613dfdSUlrich Weigand 4835f613dfdSUlrich Weigand if (HasFP) { 4845f613dfdSUlrich Weigand // Copy the base of the frame to R11. 4855f613dfdSUlrich Weigand BuildMI(MBB, MBBI, DL, ZII->get(SystemZ::LGR), SystemZ::R11D) 4865f613dfdSUlrich Weigand .addReg(SystemZ::R15D); 4875f613dfdSUlrich Weigand 4885f613dfdSUlrich Weigand // Add CFI for the new frame location. 489bc07a890SBill Wendling unsigned HardFP = MRI->getDwarfRegNum(SystemZ::R11D, true); 490f23ef437SMatthias Braun unsigned CFIIndex = MF.addFrameInst( 491b1f25f1bSRafael Espindola MCCFIInstruction::createDefCfaRegister(nullptr, HardFP)); 492b1f25f1bSRafael Espindola BuildMI(MBB, MBBI, DL, ZII->get(TargetOpcode::CFI_INSTRUCTION)) 493b1f25f1bSRafael Espindola .addCFIIndex(CFIIndex); 4945f613dfdSUlrich Weigand 4955f613dfdSUlrich Weigand // Mark the FramePtr as live at the beginning of every block except 4965f613dfdSUlrich Weigand // the entry block. (We'll have marked R11 as live on entry when 4975f613dfdSUlrich Weigand // saving the GPRs.) 49828c111ecSRichard Sandiford for (auto I = std::next(MF.begin()), E = MF.end(); I != E; ++I) 4995f613dfdSUlrich Weigand I->addLiveIn(SystemZ::R11D); 5005f613dfdSUlrich Weigand } 5015f613dfdSUlrich Weigand 5028b19be46SUlrich Weigand // Skip over the FPR/VR saves. 503b1f25f1bSRafael Espindola SmallVector<unsigned, 8> CFIIndexes; 50428c111ecSRichard Sandiford for (auto &Save : CSI) { 50528c111ecSRichard Sandiford unsigned Reg = Save.getReg(); 5065f613dfdSUlrich Weigand if (SystemZ::FP64BitRegClass.contains(Reg)) { 5075f613dfdSUlrich Weigand if (MBBI != MBB.end() && 5085f613dfdSUlrich Weigand (MBBI->getOpcode() == SystemZ::STD || 5095f613dfdSUlrich Weigand MBBI->getOpcode() == SystemZ::STDY)) 5105f613dfdSUlrich Weigand ++MBBI; 5115f613dfdSUlrich Weigand else 5125f613dfdSUlrich Weigand llvm_unreachable("Couldn't skip over FPR save"); 5138b19be46SUlrich Weigand } else if (SystemZ::VR128BitRegClass.contains(Reg)) { 5148b19be46SUlrich Weigand if (MBBI != MBB.end() && 5158b19be46SUlrich Weigand MBBI->getOpcode() == SystemZ::VST) 5168b19be46SUlrich Weigand ++MBBI; 5178b19be46SUlrich Weigand else 5188b19be46SUlrich Weigand llvm_unreachable("Couldn't skip over VR save"); 5198b19be46SUlrich Weigand } else 5208b19be46SUlrich Weigand continue; 5215f613dfdSUlrich Weigand 5225f613dfdSUlrich Weigand // Add CFI for the this save. 52328c111ecSRichard Sandiford unsigned DwarfReg = MRI->getDwarfRegNum(Reg, true); 5245567bafeSJames Y Knight unsigned IgnoredFrameReg; 5255567bafeSJames Y Knight int64_t Offset = 5265567bafeSJames Y Knight getFrameIndexReference(MF, Save.getFrameIdx(), IgnoredFrameReg); 5275567bafeSJames Y Knight 528f23ef437SMatthias Braun unsigned CFIIndex = MF.addFrameInst(MCCFIInstruction::createOffset( 529b1f25f1bSRafael Espindola nullptr, DwarfReg, SPOffsetFromCFA + Offset)); 530b1f25f1bSRafael Espindola CFIIndexes.push_back(CFIIndex); 5315f613dfdSUlrich Weigand } 5328b19be46SUlrich Weigand // Complete the CFI for the FPR/VR saves, modelling them as taking effect 5335f613dfdSUlrich Weigand // after the last save. 534b1f25f1bSRafael Espindola for (auto CFIIndex : CFIIndexes) { 535b1f25f1bSRafael Espindola BuildMI(MBB, MBBI, DL, ZII->get(TargetOpcode::CFI_INSTRUCTION)) 536b1f25f1bSRafael Espindola .addCFIIndex(CFIIndex); 537b1f25f1bSRafael Espindola } 5385f613dfdSUlrich Weigand } 5395f613dfdSUlrich Weigand 5405f613dfdSUlrich Weigand void SystemZFrameLowering::emitEpilogue(MachineFunction &MF, 5415f613dfdSUlrich Weigand MachineBasicBlock &MBB) const { 5425f613dfdSUlrich Weigand MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr(); 543fc6de428SEric Christopher auto *ZII = 544fc6de428SEric Christopher static_cast<const SystemZInstrInfo *>(MF.getSubtarget().getInstrInfo()); 5455f613dfdSUlrich Weigand SystemZMachineFunctionInfo *ZFI = MF.getInfo<SystemZMachineFunctionInfo>(); 54632063888SUlrich Weigand MachineFrameInfo &MFFrame = MF.getFrameInfo(); 5475f613dfdSUlrich Weigand 54822f94291SUlrich Weigand // See SystemZFrameLowering::emitPrologue 54922f94291SUlrich Weigand if (MF.getFunction().getCallingConv() == CallingConv::GHC) 55022f94291SUlrich Weigand return; 55122f94291SUlrich Weigand 5525f613dfdSUlrich Weigand // Skip the return instruction. 553709bda66SRichard Sandiford assert(MBBI->isReturn() && "Can only insert epilogue into returning blocks"); 5545f613dfdSUlrich Weigand 55532063888SUlrich Weigand uint64_t StackSize = MFFrame.getStackSize(); 55661f5ba5cSJonas Paulsson if (ZFI->getRestoreGPRRegs().LowGPR) { 5575f613dfdSUlrich Weigand --MBBI; 5585f613dfdSUlrich Weigand unsigned Opcode = MBBI->getOpcode(); 5595f613dfdSUlrich Weigand if (Opcode != SystemZ::LMG) 5605f613dfdSUlrich Weigand llvm_unreachable("Expected to see callee-save register restore code"); 5615f613dfdSUlrich Weigand 5625f613dfdSUlrich Weigand unsigned AddrOpNo = 2; 5635f613dfdSUlrich Weigand DebugLoc DL = MBBI->getDebugLoc(); 5645f613dfdSUlrich Weigand uint64_t Offset = StackSize + MBBI->getOperand(AddrOpNo + 1).getImm(); 5655f613dfdSUlrich Weigand unsigned NewOpcode = ZII->getOpcodeForOffset(Opcode, Offset); 5665f613dfdSUlrich Weigand 5675f613dfdSUlrich Weigand // If the offset is too large, use the largest stack-aligned offset 5685f613dfdSUlrich Weigand // and add the rest to the base register (the stack or frame pointer). 5695f613dfdSUlrich Weigand if (!NewOpcode) { 5705f613dfdSUlrich Weigand uint64_t NumBytes = Offset - 0x7fff8; 5715f613dfdSUlrich Weigand emitIncrement(MBB, MBBI, DL, MBBI->getOperand(AddrOpNo).getReg(), 5725f613dfdSUlrich Weigand NumBytes, ZII); 5735f613dfdSUlrich Weigand Offset -= NumBytes; 5745f613dfdSUlrich Weigand NewOpcode = ZII->getOpcodeForOffset(Opcode, Offset); 5755f613dfdSUlrich Weigand assert(NewOpcode && "No restore instruction available"); 5765f613dfdSUlrich Weigand } 5775f613dfdSUlrich Weigand 5785f613dfdSUlrich Weigand MBBI->setDesc(ZII->get(NewOpcode)); 5795f613dfdSUlrich Weigand MBBI->getOperand(AddrOpNo + 1).ChangeToImmediate(Offset); 5805f613dfdSUlrich Weigand } else if (StackSize) { 5815f613dfdSUlrich Weigand DebugLoc DL = MBBI->getDebugLoc(); 5825f613dfdSUlrich Weigand emitIncrement(MBB, MBBI, DL, SystemZ::R15D, StackSize, ZII); 5835f613dfdSUlrich Weigand } 5845f613dfdSUlrich Weigand } 5855f613dfdSUlrich Weigand 5865f613dfdSUlrich Weigand bool SystemZFrameLowering::hasFP(const MachineFunction &MF) const { 5875f613dfdSUlrich Weigand return (MF.getTarget().Options.DisableFramePointerElim(MF) || 588941a705bSMatthias Braun MF.getFrameInfo().hasVarSizedObjects() || 5895f613dfdSUlrich Weigand MF.getInfo<SystemZMachineFunctionInfo>()->getManipulatesSP()); 5905f613dfdSUlrich Weigand } 5915f613dfdSUlrich Weigand 5925f613dfdSUlrich Weigand bool 5935f613dfdSUlrich Weigand SystemZFrameLowering::hasReservedCallFrame(const MachineFunction &MF) const { 5945f613dfdSUlrich Weigand // The ABI requires us to allocate 160 bytes of stack space for the callee, 5955f613dfdSUlrich Weigand // with any outgoing stack arguments being placed above that. It seems 5965f613dfdSUlrich Weigand // better to make that area a permanent feature of the frame even if 5975f613dfdSUlrich Weigand // we're using a frame pointer. 5985f613dfdSUlrich Weigand return true; 5995f613dfdSUlrich Weigand } 6005f613dfdSUlrich Weigand 60161f5ba5cSJonas Paulsson int SystemZFrameLowering::getFrameIndexReference(const MachineFunction &MF, 60261f5ba5cSJonas Paulsson int FI, 60361f5ba5cSJonas Paulsson unsigned &FrameReg) const { 60461f5ba5cSJonas Paulsson // Our incoming SP is actually SystemZMC::CallFrameSize below the CFA, so 60561f5ba5cSJonas Paulsson // add that difference here. 60661f5ba5cSJonas Paulsson int64_t Offset = 60761f5ba5cSJonas Paulsson TargetFrameLowering::getFrameIndexReference(MF, FI, FrameReg); 60861f5ba5cSJonas Paulsson return Offset + SystemZMC::CallFrameSize; 60961f5ba5cSJonas Paulsson } 61061f5ba5cSJonas Paulsson 611e1a2e90fSHans Wennborg MachineBasicBlock::iterator SystemZFrameLowering:: 6125f613dfdSUlrich Weigand eliminateCallFramePseudoInstr(MachineFunction &MF, 6135f613dfdSUlrich Weigand MachineBasicBlock &MBB, 6145f613dfdSUlrich Weigand MachineBasicBlock::iterator MI) const { 6155f613dfdSUlrich Weigand switch (MI->getOpcode()) { 6165f613dfdSUlrich Weigand case SystemZ::ADJCALLSTACKDOWN: 6175f613dfdSUlrich Weigand case SystemZ::ADJCALLSTACKUP: 6185f613dfdSUlrich Weigand assert(hasReservedCallFrame(MF) && 6195f613dfdSUlrich Weigand "ADJSTACKDOWN and ADJSTACKUP should be no-ops"); 620e1a2e90fSHans Wennborg return MBB.erase(MI); 6215f613dfdSUlrich Weigand break; 6225f613dfdSUlrich Weigand 6235f613dfdSUlrich Weigand default: 6245f613dfdSUlrich Weigand llvm_unreachable("Unexpected call frame instruction"); 6255f613dfdSUlrich Weigand } 6265f613dfdSUlrich Weigand } 62761f5ba5cSJonas Paulsson 62882879c29SJonas Paulsson unsigned SystemZFrameLowering::getRegSpillOffset(MachineFunction &MF, 62982879c29SJonas Paulsson unsigned Reg) const { 63082879c29SJonas Paulsson bool IsVarArg = MF.getFunction().isVarArg(); 63182879c29SJonas Paulsson bool BackChain = MF.getFunction().hasFnAttribute("backchain"); 63282879c29SJonas Paulsson bool SoftFloat = MF.getSubtarget<SystemZSubtarget>().hasSoftFloat(); 63382879c29SJonas Paulsson unsigned Offset = RegSpillOffsets[Reg]; 63482879c29SJonas Paulsson if (usePackedStack(MF) && !(IsVarArg && !SoftFloat)) { 63582879c29SJonas Paulsson if (SystemZ::GR64BitRegClass.contains(Reg)) 63682879c29SJonas Paulsson // Put all GPRs at the top of the Register save area with packed 63782879c29SJonas Paulsson // stack. Make room for the backchain if needed. 63882879c29SJonas Paulsson Offset += BackChain ? 24 : 32; 63982879c29SJonas Paulsson else 64082879c29SJonas Paulsson Offset = 0; 64182879c29SJonas Paulsson } 64282879c29SJonas Paulsson return Offset; 64382879c29SJonas Paulsson } 64482879c29SJonas Paulsson 64561f5ba5cSJonas Paulsson int SystemZFrameLowering:: 64661f5ba5cSJonas Paulsson getOrCreateFramePointerSaveIndex(MachineFunction &MF) const { 64761f5ba5cSJonas Paulsson SystemZMachineFunctionInfo *ZFI = MF.getInfo<SystemZMachineFunctionInfo>(); 64861f5ba5cSJonas Paulsson int FI = ZFI->getFramePointerSaveIndex(); 64961f5ba5cSJonas Paulsson if (!FI) { 65061f5ba5cSJonas Paulsson MachineFrameInfo &MFFrame = MF.getFrameInfo(); 65182879c29SJonas Paulsson // The back chain is stored topmost with packed-stack. 65282879c29SJonas Paulsson int Offset = usePackedStack(MF) ? -8 : -SystemZMC::CallFrameSize; 65382879c29SJonas Paulsson FI = MFFrame.CreateFixedObject(8, Offset, false); 65461f5ba5cSJonas Paulsson ZFI->setFramePointerSaveIndex(FI); 65561f5ba5cSJonas Paulsson } 65661f5ba5cSJonas Paulsson return FI; 65761f5ba5cSJonas Paulsson } 65882879c29SJonas Paulsson 65982879c29SJonas Paulsson bool SystemZFrameLowering::usePackedStack(MachineFunction &MF) const { 66082879c29SJonas Paulsson bool HasPackedStackAttr = MF.getFunction().hasFnAttribute("packed-stack"); 66182879c29SJonas Paulsson bool BackChain = MF.getFunction().hasFnAttribute("backchain"); 66282879c29SJonas Paulsson bool SoftFloat = MF.getSubtarget<SystemZSubtarget>().hasSoftFloat(); 66382879c29SJonas Paulsson if (HasPackedStackAttr && BackChain && !SoftFloat) 66482879c29SJonas Paulsson report_fatal_error("packed-stack + backchain + hard-float is unsupported."); 66582879c29SJonas Paulsson bool CallConv = MF.getFunction().getCallingConv() != CallingConv::GHC; 66682879c29SJonas Paulsson return HasPackedStackAttr && CallConv; 66782879c29SJonas Paulsson } 668