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"
20fe0006c8SSimon Pilgrim #include "llvm/Target/TargetMachine.h"
215f613dfdSUlrich Weigand 
225f613dfdSUlrich Weigand using namespace llvm;
235f613dfdSUlrich Weigand 
24db39b4a2SRichard Sandiford namespace {
25a7d3f693SJonas Paulsson // The ABI-defined register save slots, relative to the CFA (i.e.
26023b5c1eSYusra Syeda // incoming stack pointer + SystemZMC::ELFCallFrameSize).
270a950a2eSKai Nacke static const TargetFrameLowering::SpillSlot ELFSpillOffsetTable[] = {
2861f5ba5cSJonas Paulsson   { SystemZ::R2D,  0x10 },
2961f5ba5cSJonas Paulsson   { SystemZ::R3D,  0x18 },
3061f5ba5cSJonas Paulsson   { SystemZ::R4D,  0x20 },
3161f5ba5cSJonas Paulsson   { SystemZ::R5D,  0x28 },
3261f5ba5cSJonas Paulsson   { SystemZ::R6D,  0x30 },
3361f5ba5cSJonas Paulsson   { SystemZ::R7D,  0x38 },
3461f5ba5cSJonas Paulsson   { SystemZ::R8D,  0x40 },
3561f5ba5cSJonas Paulsson   { SystemZ::R9D,  0x48 },
3661f5ba5cSJonas Paulsson   { SystemZ::R10D, 0x50 },
3761f5ba5cSJonas Paulsson   { SystemZ::R11D, 0x58 },
3861f5ba5cSJonas Paulsson   { SystemZ::R12D, 0x60 },
3961f5ba5cSJonas Paulsson   { SystemZ::R13D, 0x68 },
4061f5ba5cSJonas Paulsson   { SystemZ::R14D, 0x70 },
4161f5ba5cSJonas Paulsson   { SystemZ::R15D, 0x78 },
4261f5ba5cSJonas Paulsson   { SystemZ::F0D,  0x80 },
4361f5ba5cSJonas Paulsson   { SystemZ::F2D,  0x88 },
4461f5ba5cSJonas Paulsson   { SystemZ::F4D,  0x90 },
4561f5ba5cSJonas Paulsson   { SystemZ::F6D,  0x98 }
465f613dfdSUlrich Weigand };
470a950a2eSKai Nacke 
480a950a2eSKai Nacke static const TargetFrameLowering::SpillSlot XPLINKSpillOffsetTable[] = {
490a950a2eSKai Nacke     {SystemZ::R4D, 0x00},  {SystemZ::R5D, 0x08},  {SystemZ::R6D, 0x10},
500a950a2eSKai Nacke     {SystemZ::R7D, 0x18},  {SystemZ::R8D, 0x20},  {SystemZ::R9D, 0x28},
510a950a2eSKai Nacke     {SystemZ::R10D, 0x30}, {SystemZ::R11D, 0x38}, {SystemZ::R12D, 0x40},
520a950a2eSKai Nacke     {SystemZ::R13D, 0x48}, {SystemZ::R14D, 0x50}, {SystemZ::R15D, 0x58}};
53c231269fSRichard Sandiford } // end anonymous namespace
545f613dfdSUlrich Weigand 
550782e55cSNeumann Hon SystemZFrameLowering::SystemZFrameLowering(StackDirection D, Align StackAl,
560782e55cSNeumann Hon                                            int LAO, Align TransAl,
570782e55cSNeumann Hon                                            bool StackReal)
580782e55cSNeumann Hon     : TargetFrameLowering(D, StackAl, LAO, TransAl, StackReal) {}
59a7d3f693SJonas Paulsson 
600782e55cSNeumann Hon std::unique_ptr<SystemZFrameLowering>
610782e55cSNeumann Hon SystemZFrameLowering::create(const SystemZSubtarget &STI) {
620782e55cSNeumann Hon   if (STI.isTargetXPLINK64())
630782e55cSNeumann Hon     return std::make_unique<SystemZXPLINKFrameLowering>();
640782e55cSNeumann Hon   return std::make_unique<SystemZELFFrameLowering>();
65db39b4a2SRichard Sandiford }
66db39b4a2SRichard Sandiford 
670782e55cSNeumann Hon MachineBasicBlock::iterator SystemZFrameLowering::eliminateCallFramePseudoInstr(
680782e55cSNeumann Hon     MachineFunction &MF, MachineBasicBlock &MBB,
690782e55cSNeumann Hon     MachineBasicBlock::iterator MI) const {
700782e55cSNeumann Hon   switch (MI->getOpcode()) {
710782e55cSNeumann Hon   case SystemZ::ADJCALLSTACKDOWN:
720782e55cSNeumann Hon   case SystemZ::ADJCALLSTACKUP:
730782e55cSNeumann Hon     assert(hasReservedCallFrame(MF) &&
740782e55cSNeumann Hon            "ADJSTACKDOWN and ADJSTACKUP should be no-ops");
750782e55cSNeumann Hon     return MBB.erase(MI);
760782e55cSNeumann Hon     break;
770782e55cSNeumann Hon 
780782e55cSNeumann Hon   default:
790782e55cSNeumann Hon     llvm_unreachable("Unexpected call frame instruction");
800782e55cSNeumann Hon   }
810782e55cSNeumann Hon }
820782e55cSNeumann Hon 
830782e55cSNeumann Hon bool SystemZFrameLowering::hasReservedCallFrame(
840782e55cSNeumann Hon     const MachineFunction &MF) const {
850782e55cSNeumann Hon   // The ELF ABI requires us to allocate 160 bytes of stack space for the
860782e55cSNeumann Hon   // callee, with any outgoing stack arguments being placed above that. It
870782e55cSNeumann Hon   // seems better to make that area a permanent feature of the frame even if
880782e55cSNeumann Hon   // we're using a frame pointer. Similarly, 64-bit XPLINK requires 96 bytes
890782e55cSNeumann Hon   // of stack space for the register save area.
900782e55cSNeumann Hon   return true;
910782e55cSNeumann Hon }
920782e55cSNeumann Hon 
930782e55cSNeumann Hon bool SystemZELFFrameLowering::assignCalleeSavedSpillSlots(
940782e55cSNeumann Hon     MachineFunction &MF, const TargetRegisterInfo *TRI,
9561f5ba5cSJonas Paulsson     std::vector<CalleeSavedInfo> &CSI) const {
9661f5ba5cSJonas Paulsson   SystemZMachineFunctionInfo *ZFI = MF.getInfo<SystemZMachineFunctionInfo>();
9761f5ba5cSJonas Paulsson   MachineFrameInfo &MFFrame = MF.getFrameInfo();
9861f5ba5cSJonas Paulsson   bool IsVarArg = MF.getFunction().isVarArg();
9961f5ba5cSJonas Paulsson   if (CSI.empty())
10061f5ba5cSJonas Paulsson     return true; // Early exit if no callee saved registers are modified!
10161f5ba5cSJonas Paulsson 
10261f5ba5cSJonas Paulsson   unsigned LowGPR = 0;
10361f5ba5cSJonas Paulsson   unsigned HighGPR = SystemZ::R15D;
104023b5c1eSYusra Syeda   int StartSPOffset = SystemZMC::ELFCallFrameSize;
10561f5ba5cSJonas Paulsson   for (auto &CS : CSI) {
10661f5ba5cSJonas Paulsson     unsigned Reg = CS.getReg();
10782879c29SJonas Paulsson     int Offset = getRegSpillOffset(MF, Reg);
10861f5ba5cSJonas Paulsson     if (Offset) {
10961f5ba5cSJonas Paulsson       if (SystemZ::GR64BitRegClass.contains(Reg) && StartSPOffset > Offset) {
11061f5ba5cSJonas Paulsson         LowGPR = Reg;
11161f5ba5cSJonas Paulsson         StartSPOffset = Offset;
11261f5ba5cSJonas Paulsson       }
113023b5c1eSYusra Syeda       Offset -= SystemZMC::ELFCallFrameSize;
11461f5ba5cSJonas Paulsson       int FrameIdx = MFFrame.CreateFixedSpillStackObject(8, Offset);
11561f5ba5cSJonas Paulsson       CS.setFrameIdx(FrameIdx);
11661f5ba5cSJonas Paulsson     } else
11761f5ba5cSJonas Paulsson       CS.setFrameIdx(INT32_MAX);
11861f5ba5cSJonas Paulsson   }
11961f5ba5cSJonas Paulsson 
12061f5ba5cSJonas Paulsson   // Save the range of call-saved registers, for use by the
12161f5ba5cSJonas Paulsson   // prologue/epilogue inserters.
12261f5ba5cSJonas Paulsson   ZFI->setRestoreGPRRegs(LowGPR, HighGPR, StartSPOffset);
12361f5ba5cSJonas Paulsson   if (IsVarArg) {
12461f5ba5cSJonas Paulsson     // Also save the GPR varargs, if any.  R6D is call-saved, so would
12561f5ba5cSJonas Paulsson     // already be included, but we also need to handle the call-clobbered
12661f5ba5cSJonas Paulsson     // argument registers.
12761f5ba5cSJonas Paulsson     unsigned FirstGPR = ZFI->getVarArgsFirstGPR();
128023b5c1eSYusra Syeda     if (FirstGPR < SystemZ::ELFNumArgGPRs) {
129023b5c1eSYusra Syeda       unsigned Reg = SystemZ::ELFArgGPRs[FirstGPR];
13082879c29SJonas Paulsson       int Offset = getRegSpillOffset(MF, Reg);
13161f5ba5cSJonas Paulsson       if (StartSPOffset > Offset) {
13261f5ba5cSJonas Paulsson         LowGPR = Reg; StartSPOffset = Offset;
13361f5ba5cSJonas Paulsson       }
13461f5ba5cSJonas Paulsson     }
13561f5ba5cSJonas Paulsson   }
13661f5ba5cSJonas Paulsson   ZFI->setSpillGPRRegs(LowGPR, HighGPR, StartSPOffset);
13761f5ba5cSJonas Paulsson 
13861f5ba5cSJonas Paulsson   // Create fixed stack objects for the remaining registers.
139023b5c1eSYusra Syeda   int CurrOffset = -SystemZMC::ELFCallFrameSize;
14082879c29SJonas Paulsson   if (usePackedStack(MF))
14182879c29SJonas Paulsson     CurrOffset += StartSPOffset;
14282879c29SJonas Paulsson 
14361f5ba5cSJonas Paulsson   for (auto &CS : CSI) {
14461f5ba5cSJonas Paulsson     if (CS.getFrameIdx() != INT32_MAX)
14561f5ba5cSJonas Paulsson       continue;
14661f5ba5cSJonas Paulsson     unsigned Reg = CS.getReg();
14761f5ba5cSJonas Paulsson     const TargetRegisterClass *RC = TRI->getMinimalPhysRegClass(Reg);
14861f5ba5cSJonas Paulsson     unsigned Size = TRI->getSpillSize(*RC);
14961f5ba5cSJonas Paulsson     CurrOffset -= Size;
15061f5ba5cSJonas Paulsson     assert(CurrOffset % 8 == 0 &&
15161f5ba5cSJonas Paulsson            "8-byte alignment required for for all register save slots");
15261f5ba5cSJonas Paulsson     int FrameIdx = MFFrame.CreateFixedSpillStackObject(Size, CurrOffset);
15361f5ba5cSJonas Paulsson     CS.setFrameIdx(FrameIdx);
15461f5ba5cSJonas Paulsson   }
15561f5ba5cSJonas Paulsson 
15661f5ba5cSJonas Paulsson   return true;
1575f613dfdSUlrich Weigand }
1585f613dfdSUlrich Weigand 
1590782e55cSNeumann Hon void SystemZELFFrameLowering::determineCalleeSaves(MachineFunction &MF,
16002564865SMatthias Braun                                                    BitVector &SavedRegs,
1615f613dfdSUlrich Weigand                                                    RegScavenger *RS) const {
16202564865SMatthias Braun   TargetFrameLowering::determineCalleeSaves(MF, SavedRegs, RS);
16302564865SMatthias Braun 
164941a705bSMatthias Braun   MachineFrameInfo &MFFrame = MF.getFrameInfo();
165fc6de428SEric Christopher   const TargetRegisterInfo *TRI = MF.getSubtarget().getRegisterInfo();
1665f613dfdSUlrich Weigand   bool HasFP = hasFP(MF);
1675f613dfdSUlrich Weigand   SystemZMachineFunctionInfo *MFI = MF.getInfo<SystemZMachineFunctionInfo>();
168f1caa283SMatthias Braun   bool IsVarArg = MF.getFunction().isVarArg();
1695f613dfdSUlrich Weigand 
1705f613dfdSUlrich Weigand   // va_start stores incoming FPR varargs in the normal way, but delegates
1715f613dfdSUlrich Weigand   // the saving of incoming GPR varargs to spillCalleeSavedRegisters().
1725f613dfdSUlrich Weigand   // Record these pending uses, which typically include the call-saved
1735f613dfdSUlrich Weigand   // argument register R6D.
1745f613dfdSUlrich Weigand   if (IsVarArg)
175023b5c1eSYusra Syeda     for (unsigned I = MFI->getVarArgsFirstGPR(); I < SystemZ::ELFNumArgGPRs; ++I)
176023b5c1eSYusra Syeda       SavedRegs.set(SystemZ::ELFArgGPRs[I]);
1775f613dfdSUlrich Weigand 
178234e5a80SMarcin Koscielnicki   // If there are any landing pads, entering them will modify r6/r7.
179d0ee66c2SMatthias Braun   if (!MF.getLandingPads().empty()) {
180234e5a80SMarcin Koscielnicki     SavedRegs.set(SystemZ::R6D);
181234e5a80SMarcin Koscielnicki     SavedRegs.set(SystemZ::R7D);
182234e5a80SMarcin Koscielnicki   }
183234e5a80SMarcin Koscielnicki 
1845f613dfdSUlrich Weigand   // If the function requires a frame pointer, record that the hard
1855f613dfdSUlrich Weigand   // frame pointer will be clobbered.
1865f613dfdSUlrich Weigand   if (HasFP)
18702564865SMatthias Braun     SavedRegs.set(SystemZ::R11D);
1885f613dfdSUlrich Weigand 
1895f613dfdSUlrich Weigand   // If the function calls other functions, record that the return
1905f613dfdSUlrich Weigand   // address register will be clobbered.
191941a705bSMatthias Braun   if (MFFrame.hasCalls())
19202564865SMatthias Braun     SavedRegs.set(SystemZ::R14D);
1935f613dfdSUlrich Weigand 
1945f613dfdSUlrich Weigand   // If we are saving GPRs other than the stack pointer, we might as well
1955f613dfdSUlrich Weigand   // save and restore the stack pointer at the same time, via STMG and LMG.
1965f613dfdSUlrich Weigand   // This allows the deallocation to be done by the LMG, rather than needing
1975f613dfdSUlrich Weigand   // a separate %r15 addition.
198840beec2SCraig Topper   const MCPhysReg *CSRegs = TRI->getCalleeSavedRegs(&MF);
1995f613dfdSUlrich Weigand   for (unsigned I = 0; CSRegs[I]; ++I) {
2005f613dfdSUlrich Weigand     unsigned Reg = CSRegs[I];
20102564865SMatthias Braun     if (SystemZ::GR64BitRegClass.contains(Reg) && SavedRegs.test(Reg)) {
20202564865SMatthias Braun       SavedRegs.set(SystemZ::R15D);
2035f613dfdSUlrich Weigand       break;
2045f613dfdSUlrich Weigand     }
2055f613dfdSUlrich Weigand   }
2065f613dfdSUlrich Weigand }
2075f613dfdSUlrich Weigand 
2080782e55cSNeumann Hon SystemZELFFrameLowering::SystemZELFFrameLowering()
2090782e55cSNeumann Hon     : SystemZFrameLowering(TargetFrameLowering::StackGrowsDown, Align(8), 0,
2100a950a2eSKai Nacke                            Align(8), /* StackRealignable */ false),
2110782e55cSNeumann Hon       RegSpillOffsets(0) {
2120a950a2eSKai Nacke 
2130782e55cSNeumann Hon   // Due to the SystemZ ABI, the DWARF CFA (Canonical Frame Address) is not
2140782e55cSNeumann Hon   // equal to the incoming stack pointer, but to incoming stack pointer plus
2150782e55cSNeumann Hon   // 160.  Instead of using a Local Area Offset, the Register save area will
2160782e55cSNeumann Hon   // be occupied by fixed frame objects, and all offsets are actually
2170782e55cSNeumann Hon   // relative to CFA.
2180782e55cSNeumann Hon 
2190782e55cSNeumann Hon   // Create a mapping from register number to save slot offset.
2200782e55cSNeumann Hon   // These offsets are relative to the start of the register save area.
2210782e55cSNeumann Hon   RegSpillOffsets.grow(SystemZ::NUM_TARGET_REGS);
2220a950a2eSKai Nacke   for (unsigned I = 0, E = array_lengthof(ELFSpillOffsetTable); I != E; ++I)
2230a950a2eSKai Nacke     RegSpillOffsets[ELFSpillOffsetTable[I].Reg] = ELFSpillOffsetTable[I].Offset;
2240782e55cSNeumann Hon }
2250782e55cSNeumann Hon 
2265f613dfdSUlrich Weigand // Add GPR64 to the save instruction being built by MIB, which is in basic
2275f613dfdSUlrich Weigand // block MBB.  IsImplicit says whether this is an explicit operand to the
2285f613dfdSUlrich Weigand // instruction, or an implicit one that comes between the explicit start
2295f613dfdSUlrich Weigand // and end registers.
2305f613dfdSUlrich Weigand static void addSavedGPR(MachineBasicBlock &MBB, MachineInstrBuilder &MIB,
2315f613dfdSUlrich Weigand                         unsigned GPR64, bool IsImplicit) {
232d913448bSEric Christopher   const TargetRegisterInfo *RI =
233fc6de428SEric Christopher       MBB.getParent()->getSubtarget().getRegisterInfo();
2340c476111SDaniel Sanders   Register GPR32 = RI->getSubReg(GPR64, SystemZ::subreg_l32);
2355f613dfdSUlrich Weigand   bool IsLive = MBB.isLiveIn(GPR64) || MBB.isLiveIn(GPR32);
2365f613dfdSUlrich Weigand   if (!IsLive || !IsImplicit) {
2375f613dfdSUlrich Weigand     MIB.addReg(GPR64, getImplRegState(IsImplicit) | getKillRegState(!IsLive));
2385f613dfdSUlrich Weigand     if (!IsLive)
2395f613dfdSUlrich Weigand       MBB.addLiveIn(GPR64);
2405f613dfdSUlrich Weigand   }
2415f613dfdSUlrich Weigand }
2425f613dfdSUlrich Weigand 
2430782e55cSNeumann Hon bool SystemZELFFrameLowering::spillCalleeSavedRegisters(
244e4230a9fSBenjamin Kramer     MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
245e4230a9fSBenjamin Kramer     ArrayRef<CalleeSavedInfo> CSI, const TargetRegisterInfo *TRI) const {
2465f613dfdSUlrich Weigand   if (CSI.empty())
2475f613dfdSUlrich Weigand     return false;
2485f613dfdSUlrich Weigand 
2495f613dfdSUlrich Weigand   MachineFunction &MF = *MBB.getParent();
250fc6de428SEric Christopher   const TargetInstrInfo *TII = MF.getSubtarget().getInstrInfo();
2515f613dfdSUlrich Weigand   SystemZMachineFunctionInfo *ZFI = MF.getInfo<SystemZMachineFunctionInfo>();
252f1caa283SMatthias Braun   bool IsVarArg = MF.getFunction().isVarArg();
253057c5a6bSOleg Ranevskyy   DebugLoc DL;
2545f613dfdSUlrich Weigand 
2555f613dfdSUlrich Weigand   // Save GPRs
25661f5ba5cSJonas Paulsson   SystemZ::GPRRegs SpillGPRs = ZFI->getSpillGPRRegs();
25761f5ba5cSJonas Paulsson   if (SpillGPRs.LowGPR) {
25861f5ba5cSJonas Paulsson     assert(SpillGPRs.LowGPR != SpillGPRs.HighGPR &&
25961f5ba5cSJonas Paulsson            "Should be saving %r15 and something else");
2605f613dfdSUlrich Weigand 
2615f613dfdSUlrich Weigand     // Build an STMG instruction.
2625f613dfdSUlrich Weigand     MachineInstrBuilder MIB = BuildMI(MBB, MBBI, DL, TII->get(SystemZ::STMG));
2635f613dfdSUlrich Weigand 
2645f613dfdSUlrich Weigand     // Add the explicit register operands.
26561f5ba5cSJonas Paulsson     addSavedGPR(MBB, MIB, SpillGPRs.LowGPR, false);
26661f5ba5cSJonas Paulsson     addSavedGPR(MBB, MIB, SpillGPRs.HighGPR, false);
2675f613dfdSUlrich Weigand 
2685f613dfdSUlrich Weigand     // Add the address.
26961f5ba5cSJonas Paulsson     MIB.addReg(SystemZ::R15D).addImm(SpillGPRs.GPROffset);
2705f613dfdSUlrich Weigand 
2715f613dfdSUlrich Weigand     // Make sure all call-saved GPRs are included as operands and are
2725f613dfdSUlrich Weigand     // marked as live on entry.
273*ea5421bdSKazu Hirata     for (const CalleeSavedInfo &I : CSI) {
274*ea5421bdSKazu Hirata       unsigned Reg = I.getReg();
2755f613dfdSUlrich Weigand       if (SystemZ::GR64BitRegClass.contains(Reg))
276f1bd22dfSEric Christopher         addSavedGPR(MBB, MIB, Reg, true);
2775f613dfdSUlrich Weigand     }
2785f613dfdSUlrich Weigand 
2795f613dfdSUlrich Weigand     // ...likewise GPR varargs.
2805f613dfdSUlrich Weigand     if (IsVarArg)
281023b5c1eSYusra Syeda       for (unsigned I = ZFI->getVarArgsFirstGPR(); I < SystemZ::ELFNumArgGPRs; ++I)
282023b5c1eSYusra Syeda         addSavedGPR(MBB, MIB, SystemZ::ELFArgGPRs[I], true);
2835f613dfdSUlrich Weigand   }
2845f613dfdSUlrich Weigand 
2858b19be46SUlrich Weigand   // Save FPRs/VRs in the normal TargetInstrInfo way.
286*ea5421bdSKazu Hirata   for (const CalleeSavedInfo &I : CSI) {
287*ea5421bdSKazu Hirata     unsigned Reg = I.getReg();
2885f613dfdSUlrich Weigand     if (SystemZ::FP64BitRegClass.contains(Reg)) {
2895f613dfdSUlrich Weigand       MBB.addLiveIn(Reg);
290*ea5421bdSKazu Hirata       TII->storeRegToStackSlot(MBB, MBBI, Reg, true, I.getFrameIdx(),
2915f613dfdSUlrich Weigand                                &SystemZ::FP64BitRegClass, TRI);
2925f613dfdSUlrich Weigand     }
2938b19be46SUlrich Weigand     if (SystemZ::VR128BitRegClass.contains(Reg)) {
2948b19be46SUlrich Weigand       MBB.addLiveIn(Reg);
295*ea5421bdSKazu Hirata       TII->storeRegToStackSlot(MBB, MBBI, Reg, true, I.getFrameIdx(),
2968b19be46SUlrich Weigand                                &SystemZ::VR128BitRegClass, TRI);
2978b19be46SUlrich Weigand     }
2985f613dfdSUlrich Weigand   }
2995f613dfdSUlrich Weigand 
3005f613dfdSUlrich Weigand   return true;
3015f613dfdSUlrich Weigand }
3025f613dfdSUlrich Weigand 
3030782e55cSNeumann Hon bool SystemZELFFrameLowering::restoreCalleeSavedRegisters(
304186dd631SBenjamin Kramer     MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
305186dd631SBenjamin Kramer     MutableArrayRef<CalleeSavedInfo> CSI, const TargetRegisterInfo *TRI) const {
3065f613dfdSUlrich Weigand   if (CSI.empty())
3075f613dfdSUlrich Weigand     return false;
3085f613dfdSUlrich Weigand 
3095f613dfdSUlrich Weigand   MachineFunction &MF = *MBB.getParent();
310fc6de428SEric Christopher   const TargetInstrInfo *TII = MF.getSubtarget().getInstrInfo();
3115f613dfdSUlrich Weigand   SystemZMachineFunctionInfo *ZFI = MF.getInfo<SystemZMachineFunctionInfo>();
3125f613dfdSUlrich Weigand   bool HasFP = hasFP(MF);
3135f613dfdSUlrich Weigand   DebugLoc DL = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc();
3145f613dfdSUlrich Weigand 
3158b19be46SUlrich Weigand   // Restore FPRs/VRs in the normal TargetInstrInfo way.
316*ea5421bdSKazu Hirata   for (const CalleeSavedInfo &I : CSI) {
317*ea5421bdSKazu Hirata     unsigned Reg = I.getReg();
3185f613dfdSUlrich Weigand     if (SystemZ::FP64BitRegClass.contains(Reg))
319*ea5421bdSKazu Hirata       TII->loadRegFromStackSlot(MBB, MBBI, Reg, I.getFrameIdx(),
3205f613dfdSUlrich Weigand                                 &SystemZ::FP64BitRegClass, TRI);
3218b19be46SUlrich Weigand     if (SystemZ::VR128BitRegClass.contains(Reg))
322*ea5421bdSKazu Hirata       TII->loadRegFromStackSlot(MBB, MBBI, Reg, I.getFrameIdx(),
3238b19be46SUlrich Weigand                                 &SystemZ::VR128BitRegClass, TRI);
3245f613dfdSUlrich Weigand   }
3255f613dfdSUlrich Weigand 
3265f613dfdSUlrich Weigand   // Restore call-saved GPRs (but not call-clobbered varargs, which at
3275f613dfdSUlrich Weigand   // this point might hold return values).
32861f5ba5cSJonas Paulsson   SystemZ::GPRRegs RestoreGPRs = ZFI->getRestoreGPRRegs();
32961f5ba5cSJonas Paulsson   if (RestoreGPRs.LowGPR) {
3305f613dfdSUlrich Weigand     // If we saved any of %r2-%r5 as varargs, we should also be saving
3315f613dfdSUlrich Weigand     // and restoring %r6.  If we're saving %r6 or above, we should be
3325f613dfdSUlrich Weigand     // restoring it too.
33361f5ba5cSJonas Paulsson     assert(RestoreGPRs.LowGPR != RestoreGPRs.HighGPR &&
33461f5ba5cSJonas Paulsson            "Should be loading %r15 and something else");
3355f613dfdSUlrich Weigand 
3365f613dfdSUlrich Weigand     // Build an LMG instruction.
3375f613dfdSUlrich Weigand     MachineInstrBuilder MIB = BuildMI(MBB, MBBI, DL, TII->get(SystemZ::LMG));
3385f613dfdSUlrich Weigand 
3395f613dfdSUlrich Weigand     // Add the explicit register operands.
34061f5ba5cSJonas Paulsson     MIB.addReg(RestoreGPRs.LowGPR, RegState::Define);
34161f5ba5cSJonas Paulsson     MIB.addReg(RestoreGPRs.HighGPR, RegState::Define);
3425f613dfdSUlrich Weigand 
3435f613dfdSUlrich Weigand     // Add the address.
3445f613dfdSUlrich Weigand     MIB.addReg(HasFP ? SystemZ::R11D : SystemZ::R15D);
34561f5ba5cSJonas Paulsson     MIB.addImm(RestoreGPRs.GPROffset);
3465f613dfdSUlrich Weigand 
3475f613dfdSUlrich Weigand     // Do a second scan adding regs as being defined by instruction
348*ea5421bdSKazu Hirata     for (const CalleeSavedInfo &I : CSI) {
349*ea5421bdSKazu Hirata       unsigned Reg = I.getReg();
35061f5ba5cSJonas Paulsson       if (Reg != RestoreGPRs.LowGPR && Reg != RestoreGPRs.HighGPR &&
351f0344826SJonas Paulsson           SystemZ::GR64BitRegClass.contains(Reg))
3525f613dfdSUlrich Weigand         MIB.addReg(Reg, RegState::ImplicitDefine);
3535f613dfdSUlrich Weigand     }
3545f613dfdSUlrich Weigand   }
3555f613dfdSUlrich Weigand 
3565f613dfdSUlrich Weigand   return true;
3575f613dfdSUlrich Weigand }
3585f613dfdSUlrich Weigand 
3590782e55cSNeumann Hon void SystemZELFFrameLowering::processFunctionBeforeFrameFinalized(
3600782e55cSNeumann Hon     MachineFunction &MF, RegScavenger *RS) const {
361941a705bSMatthias Braun   MachineFrameInfo &MFFrame = MF.getFrameInfo();
3621606755dSJonas Paulsson   SystemZMachineFunctionInfo *ZFI = MF.getInfo<SystemZMachineFunctionInfo>();
3631606755dSJonas Paulsson   MachineRegisterInfo *MRI = &MF.getRegInfo();
36423762575SJonas Paulsson   bool BackChain = MF.getFunction().hasFnAttribute("backchain");
36561f5ba5cSJonas Paulsson 
36623762575SJonas Paulsson   if (!usePackedStack(MF) || BackChain)
36723762575SJonas Paulsson     // Create the incoming register save area.
36861f5ba5cSJonas Paulsson     getOrCreateFramePointerSaveIndex(MF);
36961f5ba5cSJonas Paulsson 
370af98b748SUlrich Weigand   // Get the size of our stack frame to be allocated ...
371af98b748SUlrich Weigand   uint64_t StackSize = (MFFrame.estimateStackSize(MF) +
372023b5c1eSYusra Syeda                         SystemZMC::ELFCallFrameSize);
373af98b748SUlrich Weigand   // ... and the maximum offset we may need to reach into the
374af98b748SUlrich Weigand   // caller's frame to access the save area or stack arguments.
37561f5ba5cSJonas Paulsson   int64_t MaxArgOffset = 0;
376af98b748SUlrich Weigand   for (int I = MFFrame.getObjectIndexBegin(); I != 0; ++I)
377af98b748SUlrich Weigand     if (MFFrame.getObjectOffset(I) >= 0) {
37861f5ba5cSJonas Paulsson       int64_t ArgOffset = MFFrame.getObjectOffset(I) +
379af98b748SUlrich Weigand                           MFFrame.getObjectSize(I);
380af98b748SUlrich Weigand       MaxArgOffset = std::max(MaxArgOffset, ArgOffset);
381af98b748SUlrich Weigand     }
382af98b748SUlrich Weigand 
383af98b748SUlrich Weigand   uint64_t MaxReach = StackSize + MaxArgOffset;
38423943229SRichard Sandiford   if (!isUInt<12>(MaxReach)) {
38523943229SRichard Sandiford     // We may need register scavenging slots if some parts of the frame
3865dd52f8cSRichard Sandiford     // are outside the reach of an unsigned 12-bit displacement.
38723943229SRichard Sandiford     // Create 2 for the case where both addresses in an MVC are
38823943229SRichard Sandiford     // out of range.
38928de229bSGuillaume Chatelet     RS->addScavengingFrameIndex(MFFrame.CreateStackObject(8, Align(8), false));
39028de229bSGuillaume Chatelet     RS->addScavengingFrameIndex(MFFrame.CreateStackObject(8, Align(8), false));
39123943229SRichard Sandiford   }
3921606755dSJonas Paulsson 
3931606755dSJonas Paulsson   // If R6 is used as an argument register it is still callee saved. If it in
3941606755dSJonas Paulsson   // this case is not clobbered (and restored) it should never be marked as
3951606755dSJonas Paulsson   // killed.
3961606755dSJonas Paulsson   if (MF.front().isLiveIn(SystemZ::R6D) &&
3971606755dSJonas Paulsson       ZFI->getRestoreGPRRegs().LowGPR != SystemZ::R6D)
3981606755dSJonas Paulsson     for (auto &MO : MRI->use_nodbg_operands(SystemZ::R6D))
3991606755dSJonas Paulsson       MO.setIsKill(false);
4005dd52f8cSRichard Sandiford }
4015dd52f8cSRichard Sandiford 
4025f613dfdSUlrich Weigand // Emit instructions before MBBI (in MBB) to add NumBytes to Reg.
4035f613dfdSUlrich Weigand static void emitIncrement(MachineBasicBlock &MBB,
4042481f26aSMatt Arsenault                           MachineBasicBlock::iterator &MBBI, const DebugLoc &DL,
4052481f26aSMatt Arsenault                           Register Reg, int64_t NumBytes,
4065f613dfdSUlrich Weigand                           const TargetInstrInfo *TII) {
4075f613dfdSUlrich Weigand   while (NumBytes) {
4085f613dfdSUlrich Weigand     unsigned Opcode;
4095f613dfdSUlrich Weigand     int64_t ThisVal = NumBytes;
4105f613dfdSUlrich Weigand     if (isInt<16>(NumBytes))
4115f613dfdSUlrich Weigand       Opcode = SystemZ::AGHI;
4125f613dfdSUlrich Weigand     else {
4135f613dfdSUlrich Weigand       Opcode = SystemZ::AGFI;
4145f613dfdSUlrich Weigand       // Make sure we maintain 8-byte stack alignment.
415fffd56ecSAlexey Samsonov       int64_t MinVal = -uint64_t(1) << 31;
4165f613dfdSUlrich Weigand       int64_t MaxVal = (int64_t(1) << 31) - 8;
4175f613dfdSUlrich Weigand       if (ThisVal < MinVal)
4185f613dfdSUlrich Weigand         ThisVal = MinVal;
4195f613dfdSUlrich Weigand       else if (ThisVal > MaxVal)
4205f613dfdSUlrich Weigand         ThisVal = MaxVal;
4215f613dfdSUlrich Weigand     }
4225f613dfdSUlrich Weigand     MachineInstr *MI = BuildMI(MBB, MBBI, DL, TII->get(Opcode), Reg)
4235f613dfdSUlrich Weigand       .addReg(Reg).addImm(ThisVal);
42414a44495SRichard Sandiford     // The CC implicit def is dead.
4255f613dfdSUlrich Weigand     MI->getOperand(3).setIsDead();
4265f613dfdSUlrich Weigand     NumBytes -= ThisVal;
4275f613dfdSUlrich Weigand   }
4285f613dfdSUlrich Weigand }
4295f613dfdSUlrich Weigand 
430515bfc66SJonas Paulsson // Add CFI for the new CFA offset.
431515bfc66SJonas Paulsson static void buildCFAOffs(MachineBasicBlock &MBB,
432515bfc66SJonas Paulsson                          MachineBasicBlock::iterator MBBI,
433515bfc66SJonas Paulsson                          const DebugLoc &DL, int Offset,
434515bfc66SJonas Paulsson                          const SystemZInstrInfo *ZII) {
435515bfc66SJonas Paulsson   unsigned CFIIndex = MBB.getParent()->addFrameInst(
436515bfc66SJonas Paulsson     MCCFIInstruction::cfiDefCfaOffset(nullptr, -Offset));
437515bfc66SJonas Paulsson   BuildMI(MBB, MBBI, DL, ZII->get(TargetOpcode::CFI_INSTRUCTION))
438515bfc66SJonas Paulsson     .addCFIIndex(CFIIndex);
439515bfc66SJonas Paulsson }
440515bfc66SJonas Paulsson 
441515bfc66SJonas Paulsson // Add CFI for the new frame location.
442515bfc66SJonas Paulsson static void buildDefCFAReg(MachineBasicBlock &MBB,
443515bfc66SJonas Paulsson                            MachineBasicBlock::iterator MBBI,
444515bfc66SJonas Paulsson                            const DebugLoc &DL, unsigned Reg,
445515bfc66SJonas Paulsson                            const SystemZInstrInfo *ZII) {
446515bfc66SJonas Paulsson   MachineFunction &MF = *MBB.getParent();
447515bfc66SJonas Paulsson   MachineModuleInfo &MMI = MF.getMMI();
448515bfc66SJonas Paulsson   const MCRegisterInfo *MRI = MMI.getContext().getRegisterInfo();
449515bfc66SJonas Paulsson   unsigned RegNum = MRI->getDwarfRegNum(Reg, true);
450515bfc66SJonas Paulsson   unsigned CFIIndex = MF.addFrameInst(
451515bfc66SJonas Paulsson                         MCCFIInstruction::createDefCfaRegister(nullptr, RegNum));
452515bfc66SJonas Paulsson   BuildMI(MBB, MBBI, DL, ZII->get(TargetOpcode::CFI_INSTRUCTION))
453515bfc66SJonas Paulsson     .addCFIIndex(CFIIndex);
454515bfc66SJonas Paulsson }
455515bfc66SJonas Paulsson 
4560782e55cSNeumann Hon void SystemZELFFrameLowering::emitPrologue(MachineFunction &MF,
45761b305edSQuentin Colombet                                            MachineBasicBlock &MBB) const {
45861b305edSQuentin Colombet   assert(&MF.front() == &MBB && "Shrink-wrapping not yet supported");
459515bfc66SJonas Paulsson   const SystemZSubtarget &STI = MF.getSubtarget<SystemZSubtarget>();
460515bfc66SJonas Paulsson   const SystemZTargetLowering &TLI = *STI.getTargetLowering();
461941a705bSMatthias Braun   MachineFrameInfo &MFFrame = MF.getFrameInfo();
462515bfc66SJonas Paulsson   auto *ZII = static_cast<const SystemZInstrInfo *>(STI.getInstrInfo());
4635f613dfdSUlrich Weigand   SystemZMachineFunctionInfo *ZFI = MF.getInfo<SystemZMachineFunctionInfo>();
4645f613dfdSUlrich Weigand   MachineBasicBlock::iterator MBBI = MBB.begin();
4655f613dfdSUlrich Weigand   MachineModuleInfo &MMI = MF.getMMI();
466bc07a890SBill Wendling   const MCRegisterInfo *MRI = MMI.getContext().getRegisterInfo();
467941a705bSMatthias Braun   const std::vector<CalleeSavedInfo> &CSI = MFFrame.getCalleeSavedInfo();
4685f613dfdSUlrich Weigand   bool HasFP = hasFP(MF);
469057c5a6bSOleg Ranevskyy 
47022f94291SUlrich Weigand   // In GHC calling convention C stack space, including the ABI-defined
47122f94291SUlrich Weigand   // 160-byte base area, is (de)allocated by GHC itself.  This stack space may
47222f94291SUlrich Weigand   // be used by LLVM as spill slots for the tail recursive GHC functions.  Thus
47322f94291SUlrich Weigand   // do not allocate stack space here, too.
47422f94291SUlrich Weigand   if (MF.getFunction().getCallingConv() == CallingConv::GHC) {
47522f94291SUlrich Weigand     if (MFFrame.getStackSize() > 2048 * sizeof(long)) {
47622f94291SUlrich Weigand       report_fatal_error(
47722f94291SUlrich Weigand           "Pre allocated stack space for GHC function is too small");
47822f94291SUlrich Weigand     }
47922f94291SUlrich Weigand     if (HasFP) {
48022f94291SUlrich Weigand       report_fatal_error(
48122f94291SUlrich Weigand           "In GHC calling convention a frame pointer is not supported");
48222f94291SUlrich Weigand     }
483023b5c1eSYusra Syeda     MFFrame.setStackSize(MFFrame.getStackSize() + SystemZMC::ELFCallFrameSize);
48422f94291SUlrich Weigand     return;
48522f94291SUlrich Weigand   }
48622f94291SUlrich Weigand 
487057c5a6bSOleg Ranevskyy   // Debug location must be unknown since the first debug location is used
488057c5a6bSOleg Ranevskyy   // to determine the end of the prologue.
489057c5a6bSOleg Ranevskyy   DebugLoc DL;
4905f613dfdSUlrich Weigand 
4915f613dfdSUlrich Weigand   // The current offset of the stack pointer from the CFA.
492023b5c1eSYusra Syeda   int64_t SPOffsetFromCFA = -SystemZMC::ELFCFAOffsetFromInitialSP;
4935f613dfdSUlrich Weigand 
49461f5ba5cSJonas Paulsson   if (ZFI->getSpillGPRRegs().LowGPR) {
4955f613dfdSUlrich Weigand     // Skip over the GPR saves.
4965f613dfdSUlrich Weigand     if (MBBI != MBB.end() && MBBI->getOpcode() == SystemZ::STMG)
4975f613dfdSUlrich Weigand       ++MBBI;
4985f613dfdSUlrich Weigand     else
4995f613dfdSUlrich Weigand       llvm_unreachable("Couldn't skip over GPR saves");
5005f613dfdSUlrich Weigand 
5015f613dfdSUlrich Weigand     // Add CFI for the GPR saves.
50228c111ecSRichard Sandiford     for (auto &Save : CSI) {
50328c111ecSRichard Sandiford       unsigned Reg = Save.getReg();
5045f613dfdSUlrich Weigand       if (SystemZ::GR64BitRegClass.contains(Reg)) {
50561f5ba5cSJonas Paulsson         int FI = Save.getFrameIdx();
50661f5ba5cSJonas Paulsson         int64_t Offset = MFFrame.getObjectOffset(FI);
507f23ef437SMatthias Braun         unsigned CFIIndex = MF.addFrameInst(MCCFIInstruction::createOffset(
508b1f25f1bSRafael Espindola             nullptr, MRI->getDwarfRegNum(Reg, true), Offset));
509b1f25f1bSRafael Espindola         BuildMI(MBB, MBBI, DL, ZII->get(TargetOpcode::CFI_INSTRUCTION))
510b1f25f1bSRafael Espindola             .addCFIIndex(CFIIndex);
5115f613dfdSUlrich Weigand       }
5125f613dfdSUlrich Weigand     }
5135f613dfdSUlrich Weigand   }
5145f613dfdSUlrich Weigand 
51532063888SUlrich Weigand   uint64_t StackSize = MFFrame.getStackSize();
51632063888SUlrich Weigand   // We need to allocate the ABI-defined 160-byte base area whenever
51732063888SUlrich Weigand   // we allocate stack space for our own use and whenever we call another
51832063888SUlrich Weigand   // function.
51961f5ba5cSJonas Paulsson   bool HasStackObject = false;
52061f5ba5cSJonas Paulsson   for (unsigned i = 0, e = MFFrame.getObjectIndexEnd(); i != e; ++i)
52161f5ba5cSJonas Paulsson     if (!MFFrame.isDeadObjectIndex(i)) {
52261f5ba5cSJonas Paulsson       HasStackObject = true;
52361f5ba5cSJonas Paulsson       break;
52432063888SUlrich Weigand     }
52561f5ba5cSJonas Paulsson   if (HasStackObject || MFFrame.hasCalls())
526023b5c1eSYusra Syeda     StackSize += SystemZMC::ELFCallFrameSize;
52761f5ba5cSJonas Paulsson   // Don't allocate the incoming reg save area.
528023b5c1eSYusra Syeda   StackSize = StackSize > SystemZMC::ELFCallFrameSize
529023b5c1eSYusra Syeda                   ? StackSize - SystemZMC::ELFCallFrameSize
53061f5ba5cSJonas Paulsson                   : 0;
53161f5ba5cSJonas Paulsson   MFFrame.setStackSize(StackSize);
53232063888SUlrich Weigand 
5335f613dfdSUlrich Weigand   if (StackSize) {
5345f613dfdSUlrich Weigand     // Allocate StackSize bytes.
5355f613dfdSUlrich Weigand     int64_t Delta = -int64_t(StackSize);
536515bfc66SJonas Paulsson     const unsigned ProbeSize = TLI.getStackProbeSize(MF);
537515bfc66SJonas Paulsson     bool FreeProbe = (ZFI->getSpillGPRRegs().GPROffset &&
538515bfc66SJonas Paulsson            (ZFI->getSpillGPRRegs().GPROffset + StackSize) < ProbeSize);
539515bfc66SJonas Paulsson     if (!FreeProbe &&
540515bfc66SJonas Paulsson         MF.getSubtarget().getTargetLowering()->hasInlineStackProbe(MF)) {
541515bfc66SJonas Paulsson       // Stack probing may involve looping, but splitting the prologue block
542515bfc66SJonas Paulsson       // is not possible at this point since it would invalidate the
543515bfc66SJonas Paulsson       // SaveBlocks / RestoreBlocks sets of PEI in the single block function
544515bfc66SJonas Paulsson       // case. Build a pseudo to be handled later by inlineStackProbe().
545515bfc66SJonas Paulsson       BuildMI(MBB, MBBI, DL, ZII->get(SystemZ::PROBED_STACKALLOC))
546515bfc66SJonas Paulsson         .addImm(StackSize);
547515bfc66SJonas Paulsson     }
548515bfc66SJonas Paulsson     else {
54942f628c8SJonas Paulsson       bool StoreBackchain = MF.getFunction().hasFnAttribute("backchain");
55042f628c8SJonas Paulsson       // If we need backchain, save current stack pointer.  R1 is free at
55142f628c8SJonas Paulsson       // this point.
55242f628c8SJonas Paulsson       if (StoreBackchain)
55342f628c8SJonas Paulsson         BuildMI(MBB, MBBI, DL, ZII->get(SystemZ::LGR))
55442f628c8SJonas Paulsson           .addReg(SystemZ::R1D, RegState::Define).addReg(SystemZ::R15D);
5555f613dfdSUlrich Weigand       emitIncrement(MBB, MBBI, DL, SystemZ::R15D, Delta, ZII);
556515bfc66SJonas Paulsson       buildCFAOffs(MBB, MBBI, DL, SPOffsetFromCFA + Delta, ZII);
557653b9769SJonas Paulsson       if (StoreBackchain)
558ad1482c6SMarcin Koscielnicki         BuildMI(MBB, MBBI, DL, ZII->get(SystemZ::STG))
55982879c29SJonas Paulsson           .addReg(SystemZ::R1D, RegState::Kill).addReg(SystemZ::R15D)
560653b9769SJonas Paulsson           .addImm(getBackchainOffset(MF)).addReg(0);
5615f613dfdSUlrich Weigand     }
56242f628c8SJonas Paulsson     SPOffsetFromCFA += Delta;
56342f628c8SJonas Paulsson   }
5645f613dfdSUlrich Weigand 
5655f613dfdSUlrich Weigand   if (HasFP) {
5665f613dfdSUlrich Weigand     // Copy the base of the frame to R11.
5675f613dfdSUlrich Weigand     BuildMI(MBB, MBBI, DL, ZII->get(SystemZ::LGR), SystemZ::R11D)
5685f613dfdSUlrich Weigand       .addReg(SystemZ::R15D);
5695f613dfdSUlrich Weigand 
5705f613dfdSUlrich Weigand     // Add CFI for the new frame location.
571515bfc66SJonas Paulsson     buildDefCFAReg(MBB, MBBI, DL, SystemZ::R11D, ZII);
5725f613dfdSUlrich Weigand 
5735f613dfdSUlrich Weigand     // Mark the FramePtr as live at the beginning of every block except
5745f613dfdSUlrich Weigand     // the entry block.  (We'll have marked R11 as live on entry when
5755f613dfdSUlrich Weigand     // saving the GPRs.)
576cfc74024SKazu Hirata     for (MachineBasicBlock &MBBJ : llvm::drop_begin(MF))
577cfc74024SKazu Hirata       MBBJ.addLiveIn(SystemZ::R11D);
5785f613dfdSUlrich Weigand   }
5795f613dfdSUlrich Weigand 
5808b19be46SUlrich Weigand   // Skip over the FPR/VR saves.
581b1f25f1bSRafael Espindola   SmallVector<unsigned, 8> CFIIndexes;
58228c111ecSRichard Sandiford   for (auto &Save : CSI) {
58328c111ecSRichard Sandiford     unsigned Reg = Save.getReg();
5845f613dfdSUlrich Weigand     if (SystemZ::FP64BitRegClass.contains(Reg)) {
5855f613dfdSUlrich Weigand       if (MBBI != MBB.end() &&
5865f613dfdSUlrich Weigand           (MBBI->getOpcode() == SystemZ::STD ||
5875f613dfdSUlrich Weigand            MBBI->getOpcode() == SystemZ::STDY))
5885f613dfdSUlrich Weigand         ++MBBI;
5895f613dfdSUlrich Weigand       else
5905f613dfdSUlrich Weigand         llvm_unreachable("Couldn't skip over FPR save");
5918b19be46SUlrich Weigand     } else if (SystemZ::VR128BitRegClass.contains(Reg)) {
5928b19be46SUlrich Weigand       if (MBBI != MBB.end() &&
5938b19be46SUlrich Weigand           MBBI->getOpcode() == SystemZ::VST)
5948b19be46SUlrich Weigand         ++MBBI;
5958b19be46SUlrich Weigand       else
5968b19be46SUlrich Weigand         llvm_unreachable("Couldn't skip over VR save");
5978b19be46SUlrich Weigand     } else
5988b19be46SUlrich Weigand       continue;
5995f613dfdSUlrich Weigand 
6005f613dfdSUlrich Weigand     // Add CFI for the this save.
60128c111ecSRichard Sandiford     unsigned DwarfReg = MRI->getDwarfRegNum(Reg, true);
6022481f26aSMatt Arsenault     Register IgnoredFrameReg;
6035567bafeSJames Y Knight     int64_t Offset =
604d57bba7cSSander de Smalen         getFrameIndexReference(MF, Save.getFrameIdx(), IgnoredFrameReg)
605d57bba7cSSander de Smalen             .getFixed();
6065567bafeSJames Y Knight 
607f23ef437SMatthias Braun     unsigned CFIIndex = MF.addFrameInst(MCCFIInstruction::createOffset(
608b1f25f1bSRafael Espindola           nullptr, DwarfReg, SPOffsetFromCFA + Offset));
609b1f25f1bSRafael Espindola     CFIIndexes.push_back(CFIIndex);
6105f613dfdSUlrich Weigand   }
6118b19be46SUlrich Weigand   // Complete the CFI for the FPR/VR saves, modelling them as taking effect
6125f613dfdSUlrich Weigand   // after the last save.
613b1f25f1bSRafael Espindola   for (auto CFIIndex : CFIIndexes) {
614b1f25f1bSRafael Espindola     BuildMI(MBB, MBBI, DL, ZII->get(TargetOpcode::CFI_INSTRUCTION))
615b1f25f1bSRafael Espindola         .addCFIIndex(CFIIndex);
616b1f25f1bSRafael Espindola   }
6175f613dfdSUlrich Weigand }
6185f613dfdSUlrich Weigand 
6190782e55cSNeumann Hon void SystemZELFFrameLowering::emitEpilogue(MachineFunction &MF,
6205f613dfdSUlrich Weigand                                            MachineBasicBlock &MBB) const {
6215f613dfdSUlrich Weigand   MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr();
622fc6de428SEric Christopher   auto *ZII =
623fc6de428SEric Christopher       static_cast<const SystemZInstrInfo *>(MF.getSubtarget().getInstrInfo());
6245f613dfdSUlrich Weigand   SystemZMachineFunctionInfo *ZFI = MF.getInfo<SystemZMachineFunctionInfo>();
62532063888SUlrich Weigand   MachineFrameInfo &MFFrame = MF.getFrameInfo();
6265f613dfdSUlrich Weigand 
6270782e55cSNeumann Hon   // See SystemZELFFrameLowering::emitPrologue
62822f94291SUlrich Weigand   if (MF.getFunction().getCallingConv() == CallingConv::GHC)
62922f94291SUlrich Weigand     return;
63022f94291SUlrich Weigand 
6315f613dfdSUlrich Weigand   // Skip the return instruction.
632709bda66SRichard Sandiford   assert(MBBI->isReturn() && "Can only insert epilogue into returning blocks");
6335f613dfdSUlrich Weigand 
63432063888SUlrich Weigand   uint64_t StackSize = MFFrame.getStackSize();
63561f5ba5cSJonas Paulsson   if (ZFI->getRestoreGPRRegs().LowGPR) {
6365f613dfdSUlrich Weigand     --MBBI;
6375f613dfdSUlrich Weigand     unsigned Opcode = MBBI->getOpcode();
6385f613dfdSUlrich Weigand     if (Opcode != SystemZ::LMG)
6395f613dfdSUlrich Weigand       llvm_unreachable("Expected to see callee-save register restore code");
6405f613dfdSUlrich Weigand 
6415f613dfdSUlrich Weigand     unsigned AddrOpNo = 2;
6425f613dfdSUlrich Weigand     DebugLoc DL = MBBI->getDebugLoc();
6435f613dfdSUlrich Weigand     uint64_t Offset = StackSize + MBBI->getOperand(AddrOpNo + 1).getImm();
6445f613dfdSUlrich Weigand     unsigned NewOpcode = ZII->getOpcodeForOffset(Opcode, Offset);
6455f613dfdSUlrich Weigand 
6465f613dfdSUlrich Weigand     // If the offset is too large, use the largest stack-aligned offset
6475f613dfdSUlrich Weigand     // and add the rest to the base register (the stack or frame pointer).
6485f613dfdSUlrich Weigand     if (!NewOpcode) {
6495f613dfdSUlrich Weigand       uint64_t NumBytes = Offset - 0x7fff8;
6505f613dfdSUlrich Weigand       emitIncrement(MBB, MBBI, DL, MBBI->getOperand(AddrOpNo).getReg(),
6515f613dfdSUlrich Weigand                     NumBytes, ZII);
6525f613dfdSUlrich Weigand       Offset -= NumBytes;
6535f613dfdSUlrich Weigand       NewOpcode = ZII->getOpcodeForOffset(Opcode, Offset);
6545f613dfdSUlrich Weigand       assert(NewOpcode && "No restore instruction available");
6555f613dfdSUlrich Weigand     }
6565f613dfdSUlrich Weigand 
6575f613dfdSUlrich Weigand     MBBI->setDesc(ZII->get(NewOpcode));
6585f613dfdSUlrich Weigand     MBBI->getOperand(AddrOpNo + 1).ChangeToImmediate(Offset);
6595f613dfdSUlrich Weigand   } else if (StackSize) {
6605f613dfdSUlrich Weigand     DebugLoc DL = MBBI->getDebugLoc();
6615f613dfdSUlrich Weigand     emitIncrement(MBB, MBBI, DL, SystemZ::R15D, StackSize, ZII);
6625f613dfdSUlrich Weigand   }
6635f613dfdSUlrich Weigand }
6645f613dfdSUlrich Weigand 
6650782e55cSNeumann Hon void SystemZELFFrameLowering::inlineStackProbe(
6660782e55cSNeumann Hon     MachineFunction &MF, MachineBasicBlock &PrologMBB) const {
667515bfc66SJonas Paulsson   auto *ZII =
668515bfc66SJonas Paulsson     static_cast<const SystemZInstrInfo *>(MF.getSubtarget().getInstrInfo());
669515bfc66SJonas Paulsson   const SystemZSubtarget &STI = MF.getSubtarget<SystemZSubtarget>();
670515bfc66SJonas Paulsson   const SystemZTargetLowering &TLI = *STI.getTargetLowering();
671515bfc66SJonas Paulsson 
672515bfc66SJonas Paulsson   MachineInstr *StackAllocMI = nullptr;
673515bfc66SJonas Paulsson   for (MachineInstr &MI : PrologMBB)
674515bfc66SJonas Paulsson     if (MI.getOpcode() == SystemZ::PROBED_STACKALLOC) {
675515bfc66SJonas Paulsson       StackAllocMI = &MI;
676515bfc66SJonas Paulsson       break;
677515bfc66SJonas Paulsson     }
678515bfc66SJonas Paulsson   if (StackAllocMI == nullptr)
679515bfc66SJonas Paulsson     return;
680515bfc66SJonas Paulsson   uint64_t StackSize = StackAllocMI->getOperand(0).getImm();
681515bfc66SJonas Paulsson   const unsigned ProbeSize = TLI.getStackProbeSize(MF);
682515bfc66SJonas Paulsson   uint64_t NumFullBlocks = StackSize / ProbeSize;
683515bfc66SJonas Paulsson   uint64_t Residual = StackSize % ProbeSize;
684023b5c1eSYusra Syeda   int64_t SPOffsetFromCFA = -SystemZMC::ELFCFAOffsetFromInitialSP;
685515bfc66SJonas Paulsson   MachineBasicBlock *MBB = &PrologMBB;
686515bfc66SJonas Paulsson   MachineBasicBlock::iterator MBBI = StackAllocMI;
687515bfc66SJonas Paulsson   const DebugLoc DL = StackAllocMI->getDebugLoc();
688515bfc66SJonas Paulsson 
689515bfc66SJonas Paulsson   // Allocate a block of Size bytes on the stack and probe it.
690515bfc66SJonas Paulsson   auto allocateAndProbe = [&](MachineBasicBlock &InsMBB,
691515bfc66SJonas Paulsson                               MachineBasicBlock::iterator InsPt, unsigned Size,
692515bfc66SJonas Paulsson                               bool EmitCFI) -> void {
693515bfc66SJonas Paulsson     emitIncrement(InsMBB, InsPt, DL, SystemZ::R15D, -int64_t(Size), ZII);
694515bfc66SJonas Paulsson     if (EmitCFI) {
695515bfc66SJonas Paulsson       SPOffsetFromCFA -= Size;
696515bfc66SJonas Paulsson       buildCFAOffs(InsMBB, InsPt, DL, SPOffsetFromCFA, ZII);
697515bfc66SJonas Paulsson     }
698515bfc66SJonas Paulsson     // Probe by means of a volatile compare.
699515bfc66SJonas Paulsson     MachineMemOperand *MMO = MF.getMachineMemOperand(MachinePointerInfo(),
700515bfc66SJonas Paulsson       MachineMemOperand::MOVolatile | MachineMemOperand::MOLoad, 8, Align(1));
701515bfc66SJonas Paulsson     BuildMI(InsMBB, InsPt, DL, ZII->get(SystemZ::CG))
702515bfc66SJonas Paulsson       .addReg(SystemZ::R0D, RegState::Undef)
703515bfc66SJonas Paulsson       .addReg(SystemZ::R15D).addImm(Size - 8).addReg(0)
704515bfc66SJonas Paulsson       .addMemOperand(MMO);
705515bfc66SJonas Paulsson   };
706515bfc66SJonas Paulsson 
70742f628c8SJonas Paulsson   bool StoreBackchain = MF.getFunction().hasFnAttribute("backchain");
70842f628c8SJonas Paulsson   if (StoreBackchain)
70942f628c8SJonas Paulsson     BuildMI(*MBB, MBBI, DL, ZII->get(SystemZ::LGR))
71042f628c8SJonas Paulsson       .addReg(SystemZ::R1D, RegState::Define).addReg(SystemZ::R15D);
71142f628c8SJonas Paulsson 
71242f628c8SJonas Paulsson   MachineBasicBlock *DoneMBB = nullptr;
71342f628c8SJonas Paulsson   MachineBasicBlock *LoopMBB = nullptr;
714515bfc66SJonas Paulsson   if (NumFullBlocks < 3) {
715515bfc66SJonas Paulsson     // Emit unrolled probe statements.
716515bfc66SJonas Paulsson     for (unsigned int i = 0; i < NumFullBlocks; i++)
717515bfc66SJonas Paulsson       allocateAndProbe(*MBB, MBBI, ProbeSize, true/*EmitCFI*/);
718515bfc66SJonas Paulsson   } else {
719515bfc66SJonas Paulsson     // Emit a loop probing the pages.
720515bfc66SJonas Paulsson     uint64_t LoopAlloc = ProbeSize * NumFullBlocks;
721515bfc66SJonas Paulsson     SPOffsetFromCFA -= LoopAlloc;
722515bfc66SJonas Paulsson 
72342f628c8SJonas Paulsson     // Use R0D to hold the exit value.
72442f628c8SJonas Paulsson     BuildMI(*MBB, MBBI, DL, ZII->get(SystemZ::LGR), SystemZ::R0D)
725515bfc66SJonas Paulsson       .addReg(SystemZ::R15D);
72642f628c8SJonas Paulsson     buildDefCFAReg(*MBB, MBBI, DL, SystemZ::R0D, ZII);
72742f628c8SJonas Paulsson     emitIncrement(*MBB, MBBI, DL, SystemZ::R0D, -int64_t(LoopAlloc), ZII);
728023b5c1eSYusra Syeda     buildCFAOffs(*MBB, MBBI, DL, -int64_t(SystemZMC::ELFCallFrameSize + LoopAlloc),
729515bfc66SJonas Paulsson                  ZII);
730515bfc66SJonas Paulsson 
73142f628c8SJonas Paulsson     DoneMBB = SystemZ::splitBlockBefore(MBBI, MBB);
73242f628c8SJonas Paulsson     LoopMBB = SystemZ::emitBlockAfter(MBB);
733515bfc66SJonas Paulsson     MBB->addSuccessor(LoopMBB);
734515bfc66SJonas Paulsson     LoopMBB->addSuccessor(LoopMBB);
735515bfc66SJonas Paulsson     LoopMBB->addSuccessor(DoneMBB);
736515bfc66SJonas Paulsson 
737515bfc66SJonas Paulsson     MBB = LoopMBB;
738515bfc66SJonas Paulsson     allocateAndProbe(*MBB, MBB->end(), ProbeSize, false/*EmitCFI*/);
739515bfc66SJonas Paulsson     BuildMI(*MBB, MBB->end(), DL, ZII->get(SystemZ::CLGR))
74042f628c8SJonas Paulsson       .addReg(SystemZ::R15D).addReg(SystemZ::R0D);
741515bfc66SJonas Paulsson     BuildMI(*MBB, MBB->end(), DL, ZII->get(SystemZ::BRC))
742515bfc66SJonas Paulsson       .addImm(SystemZ::CCMASK_ICMP).addImm(SystemZ::CCMASK_CMP_GT).addMBB(MBB);
743515bfc66SJonas Paulsson 
744515bfc66SJonas Paulsson     MBB = DoneMBB;
745515bfc66SJonas Paulsson     MBBI = DoneMBB->begin();
746515bfc66SJonas Paulsson     buildDefCFAReg(*MBB, MBBI, DL, SystemZ::R15D, ZII);
747515bfc66SJonas Paulsson   }
748515bfc66SJonas Paulsson 
749515bfc66SJonas Paulsson   if (Residual)
750515bfc66SJonas Paulsson     allocateAndProbe(*MBB, MBBI, Residual, true/*EmitCFI*/);
751515bfc66SJonas Paulsson 
752653b9769SJonas Paulsson   if (StoreBackchain)
75342f628c8SJonas Paulsson     BuildMI(*MBB, MBBI, DL, ZII->get(SystemZ::STG))
75442f628c8SJonas Paulsson       .addReg(SystemZ::R1D, RegState::Kill).addReg(SystemZ::R15D)
755653b9769SJonas Paulsson       .addImm(getBackchainOffset(MF)).addReg(0);
75642f628c8SJonas Paulsson 
757515bfc66SJonas Paulsson   StackAllocMI->eraseFromParent();
75842f628c8SJonas Paulsson   if (DoneMBB != nullptr) {
75942f628c8SJonas Paulsson     // Compute the live-in lists for the new blocks.
76042f628c8SJonas Paulsson     recomputeLiveIns(*DoneMBB);
76142f628c8SJonas Paulsson     recomputeLiveIns(*LoopMBB);
76242f628c8SJonas Paulsson   }
763515bfc66SJonas Paulsson }
764515bfc66SJonas Paulsson 
7650782e55cSNeumann Hon bool SystemZELFFrameLowering::hasFP(const MachineFunction &MF) const {
7665f613dfdSUlrich Weigand   return (MF.getTarget().Options.DisableFramePointerElim(MF) ||
767941a705bSMatthias Braun           MF.getFrameInfo().hasVarSizedObjects() ||
7685f613dfdSUlrich Weigand           MF.getInfo<SystemZMachineFunctionInfo>()->getManipulatesSP());
7695f613dfdSUlrich Weigand }
7705f613dfdSUlrich Weigand 
7710782e55cSNeumann Hon StackOffset SystemZELFFrameLowering::getFrameIndexReference(
7720782e55cSNeumann Hon     const MachineFunction &MF, int FI, Register &FrameReg) const {
773023b5c1eSYusra Syeda   // Our incoming SP is actually SystemZMC::ELFCallFrameSize below the CFA, so
77461f5ba5cSJonas Paulsson   // add that difference here.
775d57bba7cSSander de Smalen   StackOffset Offset =
77661f5ba5cSJonas Paulsson       TargetFrameLowering::getFrameIndexReference(MF, FI, FrameReg);
777023b5c1eSYusra Syeda   return Offset + StackOffset::getFixed(SystemZMC::ELFCallFrameSize);
77861f5ba5cSJonas Paulsson }
77961f5ba5cSJonas Paulsson 
7800782e55cSNeumann Hon unsigned SystemZELFFrameLowering::getRegSpillOffset(MachineFunction &MF,
7812481f26aSMatt Arsenault                                                     Register Reg) const {
78282879c29SJonas Paulsson   bool IsVarArg = MF.getFunction().isVarArg();
78382879c29SJonas Paulsson   bool BackChain = MF.getFunction().hasFnAttribute("backchain");
78482879c29SJonas Paulsson   bool SoftFloat = MF.getSubtarget<SystemZSubtarget>().hasSoftFloat();
78582879c29SJonas Paulsson   unsigned Offset = RegSpillOffsets[Reg];
78682879c29SJonas Paulsson   if (usePackedStack(MF) && !(IsVarArg && !SoftFloat)) {
78782879c29SJonas Paulsson     if (SystemZ::GR64BitRegClass.contains(Reg))
78882879c29SJonas Paulsson       // Put all GPRs at the top of the Register save area with packed
78982879c29SJonas Paulsson       // stack. Make room for the backchain if needed.
79082879c29SJonas Paulsson       Offset += BackChain ? 24 : 32;
79182879c29SJonas Paulsson     else
79282879c29SJonas Paulsson       Offset = 0;
79382879c29SJonas Paulsson   }
79482879c29SJonas Paulsson   return Offset;
79582879c29SJonas Paulsson }
79682879c29SJonas Paulsson 
7970782e55cSNeumann Hon int SystemZELFFrameLowering::getOrCreateFramePointerSaveIndex(
7980782e55cSNeumann Hon     MachineFunction &MF) const {
79961f5ba5cSJonas Paulsson   SystemZMachineFunctionInfo *ZFI = MF.getInfo<SystemZMachineFunctionInfo>();
80061f5ba5cSJonas Paulsson   int FI = ZFI->getFramePointerSaveIndex();
80161f5ba5cSJonas Paulsson   if (!FI) {
80261f5ba5cSJonas Paulsson     MachineFrameInfo &MFFrame = MF.getFrameInfo();
803023b5c1eSYusra Syeda     int Offset = getBackchainOffset(MF) - SystemZMC::ELFCallFrameSize;
80482879c29SJonas Paulsson     FI = MFFrame.CreateFixedObject(8, Offset, false);
80561f5ba5cSJonas Paulsson     ZFI->setFramePointerSaveIndex(FI);
80661f5ba5cSJonas Paulsson   }
80761f5ba5cSJonas Paulsson   return FI;
80861f5ba5cSJonas Paulsson }
80982879c29SJonas Paulsson 
8100782e55cSNeumann Hon bool SystemZELFFrameLowering::usePackedStack(MachineFunction &MF) const {
81182879c29SJonas Paulsson   bool HasPackedStackAttr = MF.getFunction().hasFnAttribute("packed-stack");
81282879c29SJonas Paulsson   bool BackChain = MF.getFunction().hasFnAttribute("backchain");
81382879c29SJonas Paulsson   bool SoftFloat = MF.getSubtarget<SystemZSubtarget>().hasSoftFloat();
81482879c29SJonas Paulsson   if (HasPackedStackAttr && BackChain && !SoftFloat)
81582879c29SJonas Paulsson     report_fatal_error("packed-stack + backchain + hard-float is unsupported.");
81682879c29SJonas Paulsson   bool CallConv = MF.getFunction().getCallingConv() != CallingConv::GHC;
81782879c29SJonas Paulsson   return HasPackedStackAttr && CallConv;
81882879c29SJonas Paulsson }
8190782e55cSNeumann Hon 
8200782e55cSNeumann Hon SystemZXPLINKFrameLowering::SystemZXPLINKFrameLowering()
8210782e55cSNeumann Hon     : SystemZFrameLowering(TargetFrameLowering::StackGrowsUp, Align(32), 128,
8220a950a2eSKai Nacke                            Align(32), /* StackRealignable */ false),
8230a950a2eSKai Nacke       RegSpillOffsets(-1) {
8240a950a2eSKai Nacke 
8250a950a2eSKai Nacke   // Create a mapping from register number to save slot offset.
8260a950a2eSKai Nacke   // These offsets are relative to the start of the local are area.
8270a950a2eSKai Nacke   RegSpillOffsets.grow(SystemZ::NUM_TARGET_REGS);
8280a950a2eSKai Nacke   for (unsigned I = 0, E = array_lengthof(XPLINKSpillOffsetTable); I != E; ++I)
8290a950a2eSKai Nacke     RegSpillOffsets[XPLINKSpillOffsetTable[I].Reg] =
8300a950a2eSKai Nacke         XPLINKSpillOffsetTable[I].Offset;
8310a950a2eSKai Nacke }
8320a950a2eSKai Nacke 
8330a950a2eSKai Nacke bool SystemZXPLINKFrameLowering::assignCalleeSavedSpillSlots(
8340a950a2eSKai Nacke     MachineFunction &MF, const TargetRegisterInfo *TRI,
8350a950a2eSKai Nacke     std::vector<CalleeSavedInfo> &CSI) const {
8360a950a2eSKai Nacke   MachineFrameInfo &MFFrame = MF.getFrameInfo();
8370a950a2eSKai Nacke   SystemZMachineFunctionInfo *MFI = MF.getInfo<SystemZMachineFunctionInfo>();
8380a950a2eSKai Nacke   const SystemZSubtarget &Subtarget = MF.getSubtarget<SystemZSubtarget>();
8390a950a2eSKai Nacke   auto &Regs = Subtarget.getSpecialRegisters<SystemZXPLINK64Registers>();
8400a950a2eSKai Nacke 
8410a950a2eSKai Nacke   // Scan the call-saved GPRs and find the bounds of the register spill area.
8420a950a2eSKai Nacke   unsigned LowGPR = 0;
8430a950a2eSKai Nacke   int LowOffset = INT32_MAX;
8440a950a2eSKai Nacke   unsigned HighGPR = LowGPR;
8450a950a2eSKai Nacke   int HighOffset = -1;
8460a950a2eSKai Nacke 
8470a950a2eSKai Nacke   unsigned RegSP = Regs.getStackPointerRegister();
8480a950a2eSKai Nacke   auto &GRRegClass = SystemZ::GR64BitRegClass;
8490a950a2eSKai Nacke   const unsigned RegSize = 8;
8500a950a2eSKai Nacke 
8510a950a2eSKai Nacke   auto ProcessCSI = [&](std::vector<CalleeSavedInfo> &CSIList) {
8520a950a2eSKai Nacke     for (auto &CS : CSIList) {
8530a950a2eSKai Nacke       unsigned Reg = CS.getReg();
8540a950a2eSKai Nacke       int Offset = RegSpillOffsets[Reg];
8550a950a2eSKai Nacke       if (Offset >= 0) {
8560a950a2eSKai Nacke         if (GRRegClass.contains(Reg)) {
8570a950a2eSKai Nacke           if (LowOffset > Offset) {
8580a950a2eSKai Nacke             LowOffset = Offset;
8590a950a2eSKai Nacke             LowGPR = Reg;
8600a950a2eSKai Nacke           }
8610a950a2eSKai Nacke 
8620a950a2eSKai Nacke           if (Offset > HighOffset) {
8630a950a2eSKai Nacke             HighOffset = Offset;
8640a950a2eSKai Nacke             HighGPR = Reg;
8650a950a2eSKai Nacke           }
8660a950a2eSKai Nacke         }
8670a950a2eSKai Nacke         int FrameIdx = MFFrame.CreateFixedSpillStackObject(RegSize, Offset);
8680a950a2eSKai Nacke         CS.setFrameIdx(FrameIdx);
8690a950a2eSKai Nacke       } else
8700a950a2eSKai Nacke         CS.setFrameIdx(INT32_MAX);
8710a950a2eSKai Nacke     }
8720a950a2eSKai Nacke   };
8730a950a2eSKai Nacke 
8740a950a2eSKai Nacke   std::vector<CalleeSavedInfo> Spills;
8750a950a2eSKai Nacke 
8760a950a2eSKai Nacke   // For non-leaf functions:
8770a950a2eSKai Nacke   // - the address of callee (entry point) register R6 must be saved
8780a950a2eSKai Nacke   Spills.push_back(CalleeSavedInfo(Regs.getAddressOfCalleeRegister()));
8790a950a2eSKai Nacke 
8800a950a2eSKai Nacke   // If the function needs a frame pointer, or if the backchain pointer should
8810a950a2eSKai Nacke   // be stored, then save the stack pointer register R4.
8820a950a2eSKai Nacke   if (hasFP(MF) || MF.getFunction().hasFnAttribute("backchain"))
8830a950a2eSKai Nacke     Spills.push_back(CalleeSavedInfo(RegSP));
8840a950a2eSKai Nacke 
8850a950a2eSKai Nacke   // Save the range of call-saved registers, for use by the
8860a950a2eSKai Nacke   // prologue/epilogue inserters.
8870a950a2eSKai Nacke   ProcessCSI(CSI);
8880a950a2eSKai Nacke   MFI->setRestoreGPRRegs(LowGPR, HighGPR, LowOffset);
8890a950a2eSKai Nacke 
8900a950a2eSKai Nacke   // Save the range of call-saved registers, for use by the epilogue inserter.
8910a950a2eSKai Nacke   ProcessCSI(Spills);
8920a950a2eSKai Nacke   MFI->setSpillGPRRegs(LowGPR, HighGPR, LowOffset);
8930a950a2eSKai Nacke 
8940a950a2eSKai Nacke   // Create spill slots for the remaining registers.
8950a950a2eSKai Nacke   for (auto &CS : CSI) {
8960a950a2eSKai Nacke     if (CS.getFrameIdx() != INT32_MAX)
8970a950a2eSKai Nacke       continue;
8980a950a2eSKai Nacke     unsigned Reg = CS.getReg();
8990a950a2eSKai Nacke     const TargetRegisterClass *RC = TRI->getMinimalPhysRegClass(Reg);
9000a950a2eSKai Nacke     Align Alignment = TRI->getSpillAlign(*RC);
9010a950a2eSKai Nacke     unsigned Size = TRI->getSpillSize(*RC);
9020a950a2eSKai Nacke     Alignment = std::min(Alignment, getStackAlign());
9030a950a2eSKai Nacke     int FrameIdx = MFFrame.CreateStackObject(Size, Alignment, true);
9040a950a2eSKai Nacke     CS.setFrameIdx(FrameIdx);
9050a950a2eSKai Nacke   }
9060a950a2eSKai Nacke 
9070a950a2eSKai Nacke   return true;
9080a950a2eSKai Nacke }
9090a950a2eSKai Nacke 
9100a950a2eSKai Nacke void SystemZXPLINKFrameLowering::determineCalleeSaves(MachineFunction &MF,
9110a950a2eSKai Nacke                                                       BitVector &SavedRegs,
9120a950a2eSKai Nacke                                                       RegScavenger *RS) const {
9130a950a2eSKai Nacke   TargetFrameLowering::determineCalleeSaves(MF, SavedRegs, RS);
9140a950a2eSKai Nacke 
9150a950a2eSKai Nacke   bool HasFP = hasFP(MF);
9160a950a2eSKai Nacke   const SystemZSubtarget &Subtarget = MF.getSubtarget<SystemZSubtarget>();
9170a950a2eSKai Nacke   auto &Regs = Subtarget.getSpecialRegisters<SystemZXPLINK64Registers>();
9180a950a2eSKai Nacke 
9190a950a2eSKai Nacke   // If the function requires a frame pointer, record that the hard
9200a950a2eSKai Nacke   // frame pointer will be clobbered.
9210a950a2eSKai Nacke   if (HasFP)
9220a950a2eSKai Nacke     SavedRegs.set(Regs.getFramePointerRegister());
9230a950a2eSKai Nacke 
9240a950a2eSKai Nacke   // If the function is not an XPLeaf function, we need to save the
9250a950a2eSKai Nacke   // return address register. We also always use that register for
9260a950a2eSKai Nacke   // the return instruction, so it needs to be restored in the
9270a950a2eSKai Nacke   // epilogue even though that register is considered to be volatile.
9280a950a2eSKai Nacke   // #TODO: Implement leaf detection.
9290a950a2eSKai Nacke   SavedRegs.set(Regs.getReturnFunctionAddressRegister());
9300a950a2eSKai Nacke }
9310a950a2eSKai Nacke 
9320a950a2eSKai Nacke bool SystemZXPLINKFrameLowering::spillCalleeSavedRegisters(
9330a950a2eSKai Nacke     MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
9340a950a2eSKai Nacke     ArrayRef<CalleeSavedInfo> CSI, const TargetRegisterInfo *TRI) const {
9350a950a2eSKai Nacke   if (CSI.empty())
9360a950a2eSKai Nacke     return true;
9370a950a2eSKai Nacke 
9380a950a2eSKai Nacke   MachineFunction &MF = *MBB.getParent();
9390a950a2eSKai Nacke   SystemZMachineFunctionInfo *ZFI = MF.getInfo<SystemZMachineFunctionInfo>();
9400a950a2eSKai Nacke   const SystemZSubtarget &Subtarget = MF.getSubtarget<SystemZSubtarget>();
9410a950a2eSKai Nacke   const TargetInstrInfo *TII = Subtarget.getInstrInfo();
9420a950a2eSKai Nacke   auto &Regs = Subtarget.getSpecialRegisters<SystemZXPLINK64Registers>();
9430a950a2eSKai Nacke   SystemZ::GPRRegs SpillGPRs = ZFI->getSpillGPRRegs();
9440a950a2eSKai Nacke   DebugLoc DL;
9450a950a2eSKai Nacke 
9460a950a2eSKai Nacke   // Save GPRs
9470a950a2eSKai Nacke   if (SpillGPRs.LowGPR) {
9480a950a2eSKai Nacke     assert(SpillGPRs.LowGPR != SpillGPRs.HighGPR &&
9490a950a2eSKai Nacke            "Should be saving multiple registers");
9500a950a2eSKai Nacke 
9510a950a2eSKai Nacke     // Build an STM/STMG instruction.
9520a950a2eSKai Nacke     MachineInstrBuilder MIB = BuildMI(MBB, MBBI, DL, TII->get(SystemZ::STMG));
9530a950a2eSKai Nacke 
9540a950a2eSKai Nacke     // Add the explicit register operands.
9550a950a2eSKai Nacke     addSavedGPR(MBB, MIB, SpillGPRs.LowGPR, false);
9560a950a2eSKai Nacke     addSavedGPR(MBB, MIB, SpillGPRs.HighGPR, false);
9570a950a2eSKai Nacke 
9580a950a2eSKai Nacke     // Add the address r4
9590a950a2eSKai Nacke     MIB.addReg(Regs.getStackPointerRegister());
9600a950a2eSKai Nacke 
9610a950a2eSKai Nacke     // Add the partial offset
9620a950a2eSKai Nacke     // We cannot add the actual offset as, at the stack is not finalized
9630a950a2eSKai Nacke     MIB.addImm(SpillGPRs.GPROffset);
9640a950a2eSKai Nacke 
9650a950a2eSKai Nacke     // Make sure all call-saved GPRs are included as operands and are
9660a950a2eSKai Nacke     // marked as live on entry.
9670a950a2eSKai Nacke     auto &GRRegClass = SystemZ::GR64BitRegClass;
968*ea5421bdSKazu Hirata     for (const CalleeSavedInfo &I : CSI) {
969*ea5421bdSKazu Hirata       unsigned Reg = I.getReg();
9700a950a2eSKai Nacke       if (GRRegClass.contains(Reg))
9710a950a2eSKai Nacke         addSavedGPR(MBB, MIB, Reg, true);
9720a950a2eSKai Nacke     }
9730a950a2eSKai Nacke   }
9740a950a2eSKai Nacke 
9750a950a2eSKai Nacke   // Spill FPRs to the stack in the normal TargetInstrInfo way
976*ea5421bdSKazu Hirata   for (const CalleeSavedInfo &I : CSI) {
977*ea5421bdSKazu Hirata     unsigned Reg = I.getReg();
9780a950a2eSKai Nacke     if (SystemZ::FP64BitRegClass.contains(Reg)) {
9790a950a2eSKai Nacke       MBB.addLiveIn(Reg);
980*ea5421bdSKazu Hirata       TII->storeRegToStackSlot(MBB, MBBI, Reg, true, I.getFrameIdx(),
9810a950a2eSKai Nacke                                &SystemZ::FP64BitRegClass, TRI);
9820a950a2eSKai Nacke     }
9830a950a2eSKai Nacke     if (SystemZ::VR128BitRegClass.contains(Reg)) {
9840a950a2eSKai Nacke       MBB.addLiveIn(Reg);
985*ea5421bdSKazu Hirata       TII->storeRegToStackSlot(MBB, MBBI, Reg, true, I.getFrameIdx(),
9860a950a2eSKai Nacke                                &SystemZ::VR128BitRegClass, TRI);
9870a950a2eSKai Nacke     }
9880a950a2eSKai Nacke   }
9890a950a2eSKai Nacke 
9900a950a2eSKai Nacke   return true;
9910a950a2eSKai Nacke }
9920782e55cSNeumann Hon 
9930782e55cSNeumann Hon void SystemZXPLINKFrameLowering::emitPrologue(MachineFunction &MF,
9940782e55cSNeumann Hon                                               MachineBasicBlock &MBB) const {}
9950782e55cSNeumann Hon 
9960782e55cSNeumann Hon void SystemZXPLINKFrameLowering::emitEpilogue(MachineFunction &MF,
9970782e55cSNeumann Hon                                               MachineBasicBlock &MBB) const {}
9980782e55cSNeumann Hon 
9990782e55cSNeumann Hon bool SystemZXPLINKFrameLowering::hasFP(const MachineFunction &MF) const {
10000782e55cSNeumann Hon   return false;
10010782e55cSNeumann Hon }
1002