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