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