1*5f613dfdSUlrich Weigand //===-- SystemZFrameLowering.cpp - Frame lowering for SystemZ -------------===//
2*5f613dfdSUlrich Weigand //
3*5f613dfdSUlrich Weigand //                     The LLVM Compiler Infrastructure
4*5f613dfdSUlrich Weigand //
5*5f613dfdSUlrich Weigand // This file is distributed under the University of Illinois Open Source
6*5f613dfdSUlrich Weigand // License. See LICENSE.TXT for details.
7*5f613dfdSUlrich Weigand //
8*5f613dfdSUlrich Weigand //===----------------------------------------------------------------------===//
9*5f613dfdSUlrich Weigand 
10*5f613dfdSUlrich Weigand #include "SystemZFrameLowering.h"
11*5f613dfdSUlrich Weigand #include "SystemZCallingConv.h"
12*5f613dfdSUlrich Weigand #include "SystemZInstrBuilder.h"
13*5f613dfdSUlrich Weigand #include "SystemZMachineFunctionInfo.h"
14*5f613dfdSUlrich Weigand #include "SystemZTargetMachine.h"
15*5f613dfdSUlrich Weigand #include "llvm/CodeGen/MachineModuleInfo.h"
16*5f613dfdSUlrich Weigand #include "llvm/CodeGen/MachineRegisterInfo.h"
17*5f613dfdSUlrich Weigand #include "llvm/IR/Function.h"
18*5f613dfdSUlrich Weigand 
19*5f613dfdSUlrich Weigand using namespace llvm;
20*5f613dfdSUlrich Weigand 
21*5f613dfdSUlrich Weigand SystemZFrameLowering::SystemZFrameLowering(const SystemZTargetMachine &tm,
22*5f613dfdSUlrich Weigand                                            const SystemZSubtarget &sti)
23*5f613dfdSUlrich Weigand   : TargetFrameLowering(TargetFrameLowering::StackGrowsDown, 8,
24*5f613dfdSUlrich Weigand                         -SystemZMC::CallFrameSize),
25*5f613dfdSUlrich Weigand     TM(tm),
26*5f613dfdSUlrich Weigand     STI(sti) {
27*5f613dfdSUlrich Weigand   // The ABI-defined register save slots, relative to the incoming stack
28*5f613dfdSUlrich Weigand   // pointer.
29*5f613dfdSUlrich Weigand   static const unsigned SpillOffsetTable[][2] = {
30*5f613dfdSUlrich Weigand     { SystemZ::R2D,  0x10 },
31*5f613dfdSUlrich Weigand     { SystemZ::R3D,  0x18 },
32*5f613dfdSUlrich Weigand     { SystemZ::R4D,  0x20 },
33*5f613dfdSUlrich Weigand     { SystemZ::R5D,  0x28 },
34*5f613dfdSUlrich Weigand     { SystemZ::R6D,  0x30 },
35*5f613dfdSUlrich Weigand     { SystemZ::R7D,  0x38 },
36*5f613dfdSUlrich Weigand     { SystemZ::R8D,  0x40 },
37*5f613dfdSUlrich Weigand     { SystemZ::R9D,  0x48 },
38*5f613dfdSUlrich Weigand     { SystemZ::R10D, 0x50 },
39*5f613dfdSUlrich Weigand     { SystemZ::R11D, 0x58 },
40*5f613dfdSUlrich Weigand     { SystemZ::R12D, 0x60 },
41*5f613dfdSUlrich Weigand     { SystemZ::R13D, 0x68 },
42*5f613dfdSUlrich Weigand     { SystemZ::R14D, 0x70 },
43*5f613dfdSUlrich Weigand     { SystemZ::R15D, 0x78 },
44*5f613dfdSUlrich Weigand     { SystemZ::F0D,  0x80 },
45*5f613dfdSUlrich Weigand     { SystemZ::F2D,  0x88 },
46*5f613dfdSUlrich Weigand     { SystemZ::F4D,  0x90 },
47*5f613dfdSUlrich Weigand     { SystemZ::F6D,  0x98 }
48*5f613dfdSUlrich Weigand   };
49*5f613dfdSUlrich Weigand 
50*5f613dfdSUlrich Weigand   // Create a mapping from register number to save slot offset.
51*5f613dfdSUlrich Weigand   RegSpillOffsets.grow(SystemZ::NUM_TARGET_REGS);
52*5f613dfdSUlrich Weigand   for (unsigned I = 0, E = array_lengthof(SpillOffsetTable); I != E; ++I)
53*5f613dfdSUlrich Weigand     RegSpillOffsets[SpillOffsetTable[I][0]] = SpillOffsetTable[I][1];
54*5f613dfdSUlrich Weigand }
55*5f613dfdSUlrich Weigand 
56*5f613dfdSUlrich Weigand void SystemZFrameLowering::
57*5f613dfdSUlrich Weigand processFunctionBeforeCalleeSavedScan(MachineFunction &MF,
58*5f613dfdSUlrich Weigand                                      RegScavenger *RS) const {
59*5f613dfdSUlrich Weigand   MachineFrameInfo *MFFrame = MF.getFrameInfo();
60*5f613dfdSUlrich Weigand   MachineRegisterInfo &MRI = MF.getRegInfo();
61*5f613dfdSUlrich Weigand   const TargetRegisterInfo *TRI = MF.getTarget().getRegisterInfo();
62*5f613dfdSUlrich Weigand   bool HasFP = hasFP(MF);
63*5f613dfdSUlrich Weigand   SystemZMachineFunctionInfo *MFI = MF.getInfo<SystemZMachineFunctionInfo>();
64*5f613dfdSUlrich Weigand   bool IsVarArg = MF.getFunction()->isVarArg();
65*5f613dfdSUlrich Weigand 
66*5f613dfdSUlrich Weigand   // va_start stores incoming FPR varargs in the normal way, but delegates
67*5f613dfdSUlrich Weigand   // the saving of incoming GPR varargs to spillCalleeSavedRegisters().
68*5f613dfdSUlrich Weigand   // Record these pending uses, which typically include the call-saved
69*5f613dfdSUlrich Weigand   // argument register R6D.
70*5f613dfdSUlrich Weigand   if (IsVarArg)
71*5f613dfdSUlrich Weigand     for (unsigned I = MFI->getVarArgsFirstGPR(); I < SystemZ::NumArgGPRs; ++I)
72*5f613dfdSUlrich Weigand       MRI.setPhysRegUsed(SystemZ::ArgGPRs[I]);
73*5f613dfdSUlrich Weigand 
74*5f613dfdSUlrich Weigand   // If the function requires a frame pointer, record that the hard
75*5f613dfdSUlrich Weigand   // frame pointer will be clobbered.
76*5f613dfdSUlrich Weigand   if (HasFP)
77*5f613dfdSUlrich Weigand     MRI.setPhysRegUsed(SystemZ::R11D);
78*5f613dfdSUlrich Weigand 
79*5f613dfdSUlrich Weigand   // If the function calls other functions, record that the return
80*5f613dfdSUlrich Weigand   // address register will be clobbered.
81*5f613dfdSUlrich Weigand   if (MFFrame->hasCalls())
82*5f613dfdSUlrich Weigand     MRI.setPhysRegUsed(SystemZ::R14D);
83*5f613dfdSUlrich Weigand 
84*5f613dfdSUlrich Weigand   // If we are saving GPRs other than the stack pointer, we might as well
85*5f613dfdSUlrich Weigand   // save and restore the stack pointer at the same time, via STMG and LMG.
86*5f613dfdSUlrich Weigand   // This allows the deallocation to be done by the LMG, rather than needing
87*5f613dfdSUlrich Weigand   // a separate %r15 addition.
88*5f613dfdSUlrich Weigand   const uint16_t *CSRegs = TRI->getCalleeSavedRegs(&MF);
89*5f613dfdSUlrich Weigand   for (unsigned I = 0; CSRegs[I]; ++I) {
90*5f613dfdSUlrich Weigand     unsigned Reg = CSRegs[I];
91*5f613dfdSUlrich Weigand     if (SystemZ::GR64BitRegClass.contains(Reg) && MRI.isPhysRegUsed(Reg)) {
92*5f613dfdSUlrich Weigand       MRI.setPhysRegUsed(SystemZ::R15D);
93*5f613dfdSUlrich Weigand       break;
94*5f613dfdSUlrich Weigand     }
95*5f613dfdSUlrich Weigand   }
96*5f613dfdSUlrich Weigand }
97*5f613dfdSUlrich Weigand 
98*5f613dfdSUlrich Weigand // Add GPR64 to the save instruction being built by MIB, which is in basic
99*5f613dfdSUlrich Weigand // block MBB.  IsImplicit says whether this is an explicit operand to the
100*5f613dfdSUlrich Weigand // instruction, or an implicit one that comes between the explicit start
101*5f613dfdSUlrich Weigand // and end registers.
102*5f613dfdSUlrich Weigand static void addSavedGPR(MachineBasicBlock &MBB, MachineInstrBuilder &MIB,
103*5f613dfdSUlrich Weigand                         const SystemZTargetMachine &TM,
104*5f613dfdSUlrich Weigand                         unsigned GPR64, bool IsImplicit) {
105*5f613dfdSUlrich Weigand   const SystemZRegisterInfo *RI = TM.getRegisterInfo();
106*5f613dfdSUlrich Weigand   unsigned GPR32 = RI->getSubReg(GPR64, SystemZ::subreg_32bit);
107*5f613dfdSUlrich Weigand   bool IsLive = MBB.isLiveIn(GPR64) || MBB.isLiveIn(GPR32);
108*5f613dfdSUlrich Weigand   if (!IsLive || !IsImplicit) {
109*5f613dfdSUlrich Weigand     MIB.addReg(GPR64, getImplRegState(IsImplicit) | getKillRegState(!IsLive));
110*5f613dfdSUlrich Weigand     if (!IsLive)
111*5f613dfdSUlrich Weigand       MBB.addLiveIn(GPR64);
112*5f613dfdSUlrich Weigand   }
113*5f613dfdSUlrich Weigand }
114*5f613dfdSUlrich Weigand 
115*5f613dfdSUlrich Weigand bool SystemZFrameLowering::
116*5f613dfdSUlrich Weigand spillCalleeSavedRegisters(MachineBasicBlock &MBB,
117*5f613dfdSUlrich Weigand                           MachineBasicBlock::iterator MBBI,
118*5f613dfdSUlrich Weigand                           const std::vector<CalleeSavedInfo> &CSI,
119*5f613dfdSUlrich Weigand                           const TargetRegisterInfo *TRI) const {
120*5f613dfdSUlrich Weigand   if (CSI.empty())
121*5f613dfdSUlrich Weigand     return false;
122*5f613dfdSUlrich Weigand 
123*5f613dfdSUlrich Weigand   MachineFunction &MF = *MBB.getParent();
124*5f613dfdSUlrich Weigand   const TargetInstrInfo *TII = MF.getTarget().getInstrInfo();
125*5f613dfdSUlrich Weigand   SystemZMachineFunctionInfo *ZFI = MF.getInfo<SystemZMachineFunctionInfo>();
126*5f613dfdSUlrich Weigand   bool IsVarArg = MF.getFunction()->isVarArg();
127*5f613dfdSUlrich Weigand   DebugLoc DL = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc();
128*5f613dfdSUlrich Weigand 
129*5f613dfdSUlrich Weigand   // Scan the call-saved GPRs and find the bounds of the register spill area.
130*5f613dfdSUlrich Weigand   unsigned SavedGPRFrameSize = 0;
131*5f613dfdSUlrich Weigand   unsigned LowGPR = 0;
132*5f613dfdSUlrich Weigand   unsigned HighGPR = SystemZ::R15D;
133*5f613dfdSUlrich Weigand   unsigned StartOffset = -1U;
134*5f613dfdSUlrich Weigand   for (unsigned I = 0, E = CSI.size(); I != E; ++I) {
135*5f613dfdSUlrich Weigand     unsigned Reg = CSI[I].getReg();
136*5f613dfdSUlrich Weigand     if (SystemZ::GR64BitRegClass.contains(Reg)) {
137*5f613dfdSUlrich Weigand       SavedGPRFrameSize += 8;
138*5f613dfdSUlrich Weigand       unsigned Offset = RegSpillOffsets[Reg];
139*5f613dfdSUlrich Weigand       assert(Offset && "Unexpected GPR save");
140*5f613dfdSUlrich Weigand       if (StartOffset > Offset) {
141*5f613dfdSUlrich Weigand         LowGPR = Reg;
142*5f613dfdSUlrich Weigand         StartOffset = Offset;
143*5f613dfdSUlrich Weigand       }
144*5f613dfdSUlrich Weigand     }
145*5f613dfdSUlrich Weigand   }
146*5f613dfdSUlrich Weigand 
147*5f613dfdSUlrich Weigand   // Save information about the range and location of the call-saved
148*5f613dfdSUlrich Weigand   // registers, for use by the epilogue inserter.
149*5f613dfdSUlrich Weigand   ZFI->setSavedGPRFrameSize(SavedGPRFrameSize);
150*5f613dfdSUlrich Weigand   ZFI->setLowSavedGPR(LowGPR);
151*5f613dfdSUlrich Weigand   ZFI->setHighSavedGPR(HighGPR);
152*5f613dfdSUlrich Weigand 
153*5f613dfdSUlrich Weigand   // Include the GPR varargs, if any.  R6D is call-saved, so would
154*5f613dfdSUlrich Weigand   // be included by the loop above, but we also need to handle the
155*5f613dfdSUlrich Weigand   // call-clobbered argument registers.
156*5f613dfdSUlrich Weigand   if (IsVarArg) {
157*5f613dfdSUlrich Weigand     unsigned FirstGPR = ZFI->getVarArgsFirstGPR();
158*5f613dfdSUlrich Weigand     if (FirstGPR < SystemZ::NumArgGPRs) {
159*5f613dfdSUlrich Weigand       unsigned Reg = SystemZ::ArgGPRs[FirstGPR];
160*5f613dfdSUlrich Weigand       unsigned Offset = RegSpillOffsets[Reg];
161*5f613dfdSUlrich Weigand       if (StartOffset > Offset) {
162*5f613dfdSUlrich Weigand         LowGPR = Reg; StartOffset = Offset;
163*5f613dfdSUlrich Weigand       }
164*5f613dfdSUlrich Weigand     }
165*5f613dfdSUlrich Weigand   }
166*5f613dfdSUlrich Weigand 
167*5f613dfdSUlrich Weigand   // Save GPRs
168*5f613dfdSUlrich Weigand   if (LowGPR) {
169*5f613dfdSUlrich Weigand     assert(LowGPR != HighGPR && "Should be saving %r15 and something else");
170*5f613dfdSUlrich Weigand 
171*5f613dfdSUlrich Weigand     // Build an STMG instruction.
172*5f613dfdSUlrich Weigand     MachineInstrBuilder MIB = BuildMI(MBB, MBBI, DL, TII->get(SystemZ::STMG));
173*5f613dfdSUlrich Weigand 
174*5f613dfdSUlrich Weigand     // Add the explicit register operands.
175*5f613dfdSUlrich Weigand     addSavedGPR(MBB, MIB, TM, LowGPR, false);
176*5f613dfdSUlrich Weigand     addSavedGPR(MBB, MIB, TM, HighGPR, false);
177*5f613dfdSUlrich Weigand 
178*5f613dfdSUlrich Weigand     // Add the address.
179*5f613dfdSUlrich Weigand     MIB.addReg(SystemZ::R15D).addImm(StartOffset);
180*5f613dfdSUlrich Weigand 
181*5f613dfdSUlrich Weigand     // Make sure all call-saved GPRs are included as operands and are
182*5f613dfdSUlrich Weigand     // marked as live on entry.
183*5f613dfdSUlrich Weigand     for (unsigned I = 0, E = CSI.size(); I != E; ++I) {
184*5f613dfdSUlrich Weigand       unsigned Reg = CSI[I].getReg();
185*5f613dfdSUlrich Weigand       if (SystemZ::GR64BitRegClass.contains(Reg))
186*5f613dfdSUlrich Weigand         addSavedGPR(MBB, MIB, TM, Reg, true);
187*5f613dfdSUlrich Weigand     }
188*5f613dfdSUlrich Weigand 
189*5f613dfdSUlrich Weigand     // ...likewise GPR varargs.
190*5f613dfdSUlrich Weigand     if (IsVarArg)
191*5f613dfdSUlrich Weigand       for (unsigned I = ZFI->getVarArgsFirstGPR(); I < SystemZ::NumArgGPRs; ++I)
192*5f613dfdSUlrich Weigand         addSavedGPR(MBB, MIB, TM, SystemZ::ArgGPRs[I], true);
193*5f613dfdSUlrich Weigand   }
194*5f613dfdSUlrich Weigand 
195*5f613dfdSUlrich Weigand   // Save FPRs in the normal TargetInstrInfo way.
196*5f613dfdSUlrich Weigand   for (unsigned I = 0, E = CSI.size(); I != E; ++I) {
197*5f613dfdSUlrich Weigand     unsigned Reg = CSI[I].getReg();
198*5f613dfdSUlrich Weigand     if (SystemZ::FP64BitRegClass.contains(Reg)) {
199*5f613dfdSUlrich Weigand       MBB.addLiveIn(Reg);
200*5f613dfdSUlrich Weigand       TII->storeRegToStackSlot(MBB, MBBI, Reg, true, CSI[I].getFrameIdx(),
201*5f613dfdSUlrich Weigand                                &SystemZ::FP64BitRegClass, TRI);
202*5f613dfdSUlrich Weigand     }
203*5f613dfdSUlrich Weigand   }
204*5f613dfdSUlrich Weigand 
205*5f613dfdSUlrich Weigand   return true;
206*5f613dfdSUlrich Weigand }
207*5f613dfdSUlrich Weigand 
208*5f613dfdSUlrich Weigand bool SystemZFrameLowering::
209*5f613dfdSUlrich Weigand restoreCalleeSavedRegisters(MachineBasicBlock &MBB,
210*5f613dfdSUlrich Weigand                             MachineBasicBlock::iterator MBBI,
211*5f613dfdSUlrich Weigand                             const std::vector<CalleeSavedInfo> &CSI,
212*5f613dfdSUlrich Weigand                             const TargetRegisterInfo *TRI) const {
213*5f613dfdSUlrich Weigand   if (CSI.empty())
214*5f613dfdSUlrich Weigand     return false;
215*5f613dfdSUlrich Weigand 
216*5f613dfdSUlrich Weigand   MachineFunction &MF = *MBB.getParent();
217*5f613dfdSUlrich Weigand   const TargetInstrInfo *TII = MF.getTarget().getInstrInfo();
218*5f613dfdSUlrich Weigand   SystemZMachineFunctionInfo *ZFI = MF.getInfo<SystemZMachineFunctionInfo>();
219*5f613dfdSUlrich Weigand   bool HasFP = hasFP(MF);
220*5f613dfdSUlrich Weigand   DebugLoc DL = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc();
221*5f613dfdSUlrich Weigand 
222*5f613dfdSUlrich Weigand   // Restore FPRs in the normal TargetInstrInfo way.
223*5f613dfdSUlrich Weigand   for (unsigned I = 0, E = CSI.size(); I != E; ++I) {
224*5f613dfdSUlrich Weigand     unsigned Reg = CSI[I].getReg();
225*5f613dfdSUlrich Weigand     if (SystemZ::FP64BitRegClass.contains(Reg))
226*5f613dfdSUlrich Weigand       TII->loadRegFromStackSlot(MBB, MBBI, Reg, CSI[I].getFrameIdx(),
227*5f613dfdSUlrich Weigand                                 &SystemZ::FP64BitRegClass, TRI);
228*5f613dfdSUlrich Weigand   }
229*5f613dfdSUlrich Weigand 
230*5f613dfdSUlrich Weigand   // Restore call-saved GPRs (but not call-clobbered varargs, which at
231*5f613dfdSUlrich Weigand   // this point might hold return values).
232*5f613dfdSUlrich Weigand   unsigned LowGPR = ZFI->getLowSavedGPR();
233*5f613dfdSUlrich Weigand   unsigned HighGPR = ZFI->getHighSavedGPR();
234*5f613dfdSUlrich Weigand   unsigned StartOffset = RegSpillOffsets[LowGPR];
235*5f613dfdSUlrich Weigand   if (LowGPR) {
236*5f613dfdSUlrich Weigand     // If we saved any of %r2-%r5 as varargs, we should also be saving
237*5f613dfdSUlrich Weigand     // and restoring %r6.  If we're saving %r6 or above, we should be
238*5f613dfdSUlrich Weigand     // restoring it too.
239*5f613dfdSUlrich Weigand     assert(LowGPR != HighGPR && "Should be loading %r15 and something else");
240*5f613dfdSUlrich Weigand 
241*5f613dfdSUlrich Weigand     // Build an LMG instruction.
242*5f613dfdSUlrich Weigand     MachineInstrBuilder MIB = BuildMI(MBB, MBBI, DL, TII->get(SystemZ::LMG));
243*5f613dfdSUlrich Weigand 
244*5f613dfdSUlrich Weigand     // Add the explicit register operands.
245*5f613dfdSUlrich Weigand     MIB.addReg(LowGPR, RegState::Define);
246*5f613dfdSUlrich Weigand     MIB.addReg(HighGPR, RegState::Define);
247*5f613dfdSUlrich Weigand 
248*5f613dfdSUlrich Weigand     // Add the address.
249*5f613dfdSUlrich Weigand     MIB.addReg(HasFP ? SystemZ::R11D : SystemZ::R15D);
250*5f613dfdSUlrich Weigand     MIB.addImm(StartOffset);
251*5f613dfdSUlrich Weigand 
252*5f613dfdSUlrich Weigand     // Do a second scan adding regs as being defined by instruction
253*5f613dfdSUlrich Weigand     for (unsigned I = 0, E = CSI.size(); I != E; ++I) {
254*5f613dfdSUlrich Weigand       unsigned Reg = CSI[I].getReg();
255*5f613dfdSUlrich Weigand       if (Reg != LowGPR && Reg != HighGPR)
256*5f613dfdSUlrich Weigand         MIB.addReg(Reg, RegState::ImplicitDefine);
257*5f613dfdSUlrich Weigand     }
258*5f613dfdSUlrich Weigand   }
259*5f613dfdSUlrich Weigand 
260*5f613dfdSUlrich Weigand   return true;
261*5f613dfdSUlrich Weigand }
262*5f613dfdSUlrich Weigand 
263*5f613dfdSUlrich Weigand // Emit instructions before MBBI (in MBB) to add NumBytes to Reg.
264*5f613dfdSUlrich Weigand static void emitIncrement(MachineBasicBlock &MBB,
265*5f613dfdSUlrich Weigand                           MachineBasicBlock::iterator &MBBI,
266*5f613dfdSUlrich Weigand                           const DebugLoc &DL,
267*5f613dfdSUlrich Weigand                           unsigned Reg, int64_t NumBytes,
268*5f613dfdSUlrich Weigand                           const TargetInstrInfo *TII) {
269*5f613dfdSUlrich Weigand   while (NumBytes) {
270*5f613dfdSUlrich Weigand     unsigned Opcode;
271*5f613dfdSUlrich Weigand     int64_t ThisVal = NumBytes;
272*5f613dfdSUlrich Weigand     if (isInt<16>(NumBytes))
273*5f613dfdSUlrich Weigand       Opcode = SystemZ::AGHI;
274*5f613dfdSUlrich Weigand     else {
275*5f613dfdSUlrich Weigand       Opcode = SystemZ::AGFI;
276*5f613dfdSUlrich Weigand       // Make sure we maintain 8-byte stack alignment.
277*5f613dfdSUlrich Weigand       int64_t MinVal = -int64_t(1) << 31;
278*5f613dfdSUlrich Weigand       int64_t MaxVal = (int64_t(1) << 31) - 8;
279*5f613dfdSUlrich Weigand       if (ThisVal < MinVal)
280*5f613dfdSUlrich Weigand         ThisVal = MinVal;
281*5f613dfdSUlrich Weigand       else if (ThisVal > MaxVal)
282*5f613dfdSUlrich Weigand         ThisVal = MaxVal;
283*5f613dfdSUlrich Weigand     }
284*5f613dfdSUlrich Weigand     MachineInstr *MI = BuildMI(MBB, MBBI, DL, TII->get(Opcode), Reg)
285*5f613dfdSUlrich Weigand       .addReg(Reg).addImm(ThisVal);
286*5f613dfdSUlrich Weigand     // The PSW implicit def is dead.
287*5f613dfdSUlrich Weigand     MI->getOperand(3).setIsDead();
288*5f613dfdSUlrich Weigand     NumBytes -= ThisVal;
289*5f613dfdSUlrich Weigand   }
290*5f613dfdSUlrich Weigand }
291*5f613dfdSUlrich Weigand 
292*5f613dfdSUlrich Weigand void SystemZFrameLowering::emitPrologue(MachineFunction &MF) const {
293*5f613dfdSUlrich Weigand   MachineBasicBlock &MBB = MF.front();
294*5f613dfdSUlrich Weigand   MachineFrameInfo *MFFrame = MF.getFrameInfo();
295*5f613dfdSUlrich Weigand   const SystemZInstrInfo *ZII =
296*5f613dfdSUlrich Weigand     static_cast<const SystemZInstrInfo*>(MF.getTarget().getInstrInfo());
297*5f613dfdSUlrich Weigand   SystemZMachineFunctionInfo *ZFI = MF.getInfo<SystemZMachineFunctionInfo>();
298*5f613dfdSUlrich Weigand   MachineBasicBlock::iterator MBBI = MBB.begin();
299*5f613dfdSUlrich Weigand   MachineModuleInfo &MMI = MF.getMMI();
300*5f613dfdSUlrich Weigand   std::vector<MachineMove> &Moves = MMI.getFrameMoves();
301*5f613dfdSUlrich Weigand   const std::vector<CalleeSavedInfo> &CSI = MFFrame->getCalleeSavedInfo();
302*5f613dfdSUlrich Weigand   bool HasFP = hasFP(MF);
303*5f613dfdSUlrich Weigand   DebugLoc DL = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc();
304*5f613dfdSUlrich Weigand 
305*5f613dfdSUlrich Weigand   // The current offset of the stack pointer from the CFA.
306*5f613dfdSUlrich Weigand   int64_t SPOffsetFromCFA = -SystemZMC::CFAOffsetFromInitialSP;
307*5f613dfdSUlrich Weigand 
308*5f613dfdSUlrich Weigand   if (ZFI->getLowSavedGPR()) {
309*5f613dfdSUlrich Weigand     // Skip over the GPR saves.
310*5f613dfdSUlrich Weigand     if (MBBI != MBB.end() && MBBI->getOpcode() == SystemZ::STMG)
311*5f613dfdSUlrich Weigand       ++MBBI;
312*5f613dfdSUlrich Weigand     else
313*5f613dfdSUlrich Weigand       llvm_unreachable("Couldn't skip over GPR saves");
314*5f613dfdSUlrich Weigand 
315*5f613dfdSUlrich Weigand     // Add CFI for the GPR saves.
316*5f613dfdSUlrich Weigand     MCSymbol *GPRSaveLabel = MMI.getContext().CreateTempSymbol();
317*5f613dfdSUlrich Weigand     BuildMI(MBB, MBBI, DL,
318*5f613dfdSUlrich Weigand             ZII->get(TargetOpcode::PROLOG_LABEL)).addSym(GPRSaveLabel);
319*5f613dfdSUlrich Weigand     for (std::vector<CalleeSavedInfo>::const_iterator
320*5f613dfdSUlrich Weigand            I = CSI.begin(), E = CSI.end(); I != E; ++I) {
321*5f613dfdSUlrich Weigand       unsigned Reg = I->getReg();
322*5f613dfdSUlrich Weigand       if (SystemZ::GR64BitRegClass.contains(Reg)) {
323*5f613dfdSUlrich Weigand         int64_t Offset = SPOffsetFromCFA + RegSpillOffsets[Reg];
324*5f613dfdSUlrich Weigand         MachineLocation StackSlot(MachineLocation::VirtualFP, Offset);
325*5f613dfdSUlrich Weigand         MachineLocation RegValue(Reg);
326*5f613dfdSUlrich Weigand         Moves.push_back(MachineMove(GPRSaveLabel, StackSlot, RegValue));
327*5f613dfdSUlrich Weigand       }
328*5f613dfdSUlrich Weigand     }
329*5f613dfdSUlrich Weigand   }
330*5f613dfdSUlrich Weigand 
331*5f613dfdSUlrich Weigand   uint64_t StackSize = getAllocatedStackSize(MF);
332*5f613dfdSUlrich Weigand   if (StackSize) {
333*5f613dfdSUlrich Weigand     // Allocate StackSize bytes.
334*5f613dfdSUlrich Weigand     int64_t Delta = -int64_t(StackSize);
335*5f613dfdSUlrich Weigand     emitIncrement(MBB, MBBI, DL, SystemZ::R15D, Delta, ZII);
336*5f613dfdSUlrich Weigand 
337*5f613dfdSUlrich Weigand     // Add CFI for the allocation.
338*5f613dfdSUlrich Weigand     MCSymbol *AdjustSPLabel = MMI.getContext().CreateTempSymbol();
339*5f613dfdSUlrich Weigand     BuildMI(MBB, MBBI, DL, ZII->get(TargetOpcode::PROLOG_LABEL))
340*5f613dfdSUlrich Weigand       .addSym(AdjustSPLabel);
341*5f613dfdSUlrich Weigand     MachineLocation FPDest(MachineLocation::VirtualFP);
342*5f613dfdSUlrich Weigand     MachineLocation FPSrc(MachineLocation::VirtualFP, SPOffsetFromCFA + Delta);
343*5f613dfdSUlrich Weigand     Moves.push_back(MachineMove(AdjustSPLabel, FPDest, FPSrc));
344*5f613dfdSUlrich Weigand     SPOffsetFromCFA += Delta;
345*5f613dfdSUlrich Weigand   }
346*5f613dfdSUlrich Weigand 
347*5f613dfdSUlrich Weigand   if (HasFP) {
348*5f613dfdSUlrich Weigand     // Copy the base of the frame to R11.
349*5f613dfdSUlrich Weigand     BuildMI(MBB, MBBI, DL, ZII->get(SystemZ::LGR), SystemZ::R11D)
350*5f613dfdSUlrich Weigand       .addReg(SystemZ::R15D);
351*5f613dfdSUlrich Weigand 
352*5f613dfdSUlrich Weigand     // Add CFI for the new frame location.
353*5f613dfdSUlrich Weigand     MCSymbol *SetFPLabel = MMI.getContext().CreateTempSymbol();
354*5f613dfdSUlrich Weigand     BuildMI(MBB, MBBI, DL, ZII->get(TargetOpcode::PROLOG_LABEL))
355*5f613dfdSUlrich Weigand       .addSym(SetFPLabel);
356*5f613dfdSUlrich Weigand     MachineLocation HardFP(SystemZ::R11D);
357*5f613dfdSUlrich Weigand     MachineLocation VirtualFP(MachineLocation::VirtualFP);
358*5f613dfdSUlrich Weigand     Moves.push_back(MachineMove(SetFPLabel, HardFP, VirtualFP));
359*5f613dfdSUlrich Weigand 
360*5f613dfdSUlrich Weigand     // Mark the FramePtr as live at the beginning of every block except
361*5f613dfdSUlrich Weigand     // the entry block.  (We'll have marked R11 as live on entry when
362*5f613dfdSUlrich Weigand     // saving the GPRs.)
363*5f613dfdSUlrich Weigand     for (MachineFunction::iterator
364*5f613dfdSUlrich Weigand            I = llvm::next(MF.begin()), E = MF.end(); I != E; ++I)
365*5f613dfdSUlrich Weigand       I->addLiveIn(SystemZ::R11D);
366*5f613dfdSUlrich Weigand   }
367*5f613dfdSUlrich Weigand 
368*5f613dfdSUlrich Weigand   // Skip over the FPR saves.
369*5f613dfdSUlrich Weigand   MCSymbol *FPRSaveLabel = 0;
370*5f613dfdSUlrich Weigand   for (std::vector<CalleeSavedInfo>::const_iterator
371*5f613dfdSUlrich Weigand          I = CSI.begin(), E = CSI.end(); I != E; ++I) {
372*5f613dfdSUlrich Weigand     unsigned Reg = I->getReg();
373*5f613dfdSUlrich Weigand     if (SystemZ::FP64BitRegClass.contains(Reg)) {
374*5f613dfdSUlrich Weigand       if (MBBI != MBB.end() &&
375*5f613dfdSUlrich Weigand           (MBBI->getOpcode() == SystemZ::STD ||
376*5f613dfdSUlrich Weigand            MBBI->getOpcode() == SystemZ::STDY))
377*5f613dfdSUlrich Weigand         ++MBBI;
378*5f613dfdSUlrich Weigand       else
379*5f613dfdSUlrich Weigand         llvm_unreachable("Couldn't skip over FPR save");
380*5f613dfdSUlrich Weigand 
381*5f613dfdSUlrich Weigand       // Add CFI for the this save.
382*5f613dfdSUlrich Weigand       if (!FPRSaveLabel)
383*5f613dfdSUlrich Weigand         FPRSaveLabel = MMI.getContext().CreateTempSymbol();
384*5f613dfdSUlrich Weigand       unsigned Reg = I->getReg();
385*5f613dfdSUlrich Weigand       int64_t Offset = getFrameIndexOffset(MF, I->getFrameIdx());
386*5f613dfdSUlrich Weigand       MachineLocation Slot(MachineLocation::VirtualFP,
387*5f613dfdSUlrich Weigand                            SPOffsetFromCFA + Offset);
388*5f613dfdSUlrich Weigand       MachineLocation RegValue(Reg);
389*5f613dfdSUlrich Weigand       Moves.push_back(MachineMove(FPRSaveLabel, Slot, RegValue));
390*5f613dfdSUlrich Weigand     }
391*5f613dfdSUlrich Weigand   }
392*5f613dfdSUlrich Weigand   // Complete the CFI for the FPR saves, modelling them as taking effect
393*5f613dfdSUlrich Weigand   // after the last save.
394*5f613dfdSUlrich Weigand   if (FPRSaveLabel)
395*5f613dfdSUlrich Weigand     BuildMI(MBB, MBBI, DL, ZII->get(TargetOpcode::PROLOG_LABEL))
396*5f613dfdSUlrich Weigand       .addSym(FPRSaveLabel);
397*5f613dfdSUlrich Weigand }
398*5f613dfdSUlrich Weigand 
399*5f613dfdSUlrich Weigand void SystemZFrameLowering::emitEpilogue(MachineFunction &MF,
400*5f613dfdSUlrich Weigand                                         MachineBasicBlock &MBB) const {
401*5f613dfdSUlrich Weigand   MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr();
402*5f613dfdSUlrich Weigand   const SystemZInstrInfo *ZII =
403*5f613dfdSUlrich Weigand     static_cast<const SystemZInstrInfo*>(MF.getTarget().getInstrInfo());
404*5f613dfdSUlrich Weigand   SystemZMachineFunctionInfo *ZFI = MF.getInfo<SystemZMachineFunctionInfo>();
405*5f613dfdSUlrich Weigand 
406*5f613dfdSUlrich Weigand   // Skip the return instruction.
407*5f613dfdSUlrich Weigand   assert(MBBI->getOpcode() == SystemZ::RET &&
408*5f613dfdSUlrich Weigand          "Can only insert epilogue into returning blocks");
409*5f613dfdSUlrich Weigand 
410*5f613dfdSUlrich Weigand   uint64_t StackSize = getAllocatedStackSize(MF);
411*5f613dfdSUlrich Weigand   if (ZFI->getLowSavedGPR()) {
412*5f613dfdSUlrich Weigand     --MBBI;
413*5f613dfdSUlrich Weigand     unsigned Opcode = MBBI->getOpcode();
414*5f613dfdSUlrich Weigand     if (Opcode != SystemZ::LMG)
415*5f613dfdSUlrich Weigand       llvm_unreachable("Expected to see callee-save register restore code");
416*5f613dfdSUlrich Weigand 
417*5f613dfdSUlrich Weigand     unsigned AddrOpNo = 2;
418*5f613dfdSUlrich Weigand     DebugLoc DL = MBBI->getDebugLoc();
419*5f613dfdSUlrich Weigand     uint64_t Offset = StackSize + MBBI->getOperand(AddrOpNo + 1).getImm();
420*5f613dfdSUlrich Weigand     unsigned NewOpcode = ZII->getOpcodeForOffset(Opcode, Offset);
421*5f613dfdSUlrich Weigand 
422*5f613dfdSUlrich Weigand     // If the offset is too large, use the largest stack-aligned offset
423*5f613dfdSUlrich Weigand     // and add the rest to the base register (the stack or frame pointer).
424*5f613dfdSUlrich Weigand     if (!NewOpcode) {
425*5f613dfdSUlrich Weigand       uint64_t NumBytes = Offset - 0x7fff8;
426*5f613dfdSUlrich Weigand       emitIncrement(MBB, MBBI, DL, MBBI->getOperand(AddrOpNo).getReg(),
427*5f613dfdSUlrich Weigand                     NumBytes, ZII);
428*5f613dfdSUlrich Weigand       Offset -= NumBytes;
429*5f613dfdSUlrich Weigand       NewOpcode = ZII->getOpcodeForOffset(Opcode, Offset);
430*5f613dfdSUlrich Weigand       assert(NewOpcode && "No restore instruction available");
431*5f613dfdSUlrich Weigand     }
432*5f613dfdSUlrich Weigand 
433*5f613dfdSUlrich Weigand     MBBI->setDesc(ZII->get(NewOpcode));
434*5f613dfdSUlrich Weigand     MBBI->getOperand(AddrOpNo + 1).ChangeToImmediate(Offset);
435*5f613dfdSUlrich Weigand   } else if (StackSize) {
436*5f613dfdSUlrich Weigand     DebugLoc DL = MBBI->getDebugLoc();
437*5f613dfdSUlrich Weigand     emitIncrement(MBB, MBBI, DL, SystemZ::R15D, StackSize, ZII);
438*5f613dfdSUlrich Weigand   }
439*5f613dfdSUlrich Weigand }
440*5f613dfdSUlrich Weigand 
441*5f613dfdSUlrich Weigand bool SystemZFrameLowering::hasFP(const MachineFunction &MF) const {
442*5f613dfdSUlrich Weigand   return (MF.getTarget().Options.DisableFramePointerElim(MF) ||
443*5f613dfdSUlrich Weigand           MF.getFrameInfo()->hasVarSizedObjects() ||
444*5f613dfdSUlrich Weigand           MF.getInfo<SystemZMachineFunctionInfo>()->getManipulatesSP());
445*5f613dfdSUlrich Weigand }
446*5f613dfdSUlrich Weigand 
447*5f613dfdSUlrich Weigand int SystemZFrameLowering::getFrameIndexOffset(const MachineFunction &MF,
448*5f613dfdSUlrich Weigand                                               int FI) const {
449*5f613dfdSUlrich Weigand   const MachineFrameInfo *MFFrame = MF.getFrameInfo();
450*5f613dfdSUlrich Weigand 
451*5f613dfdSUlrich Weigand   // Start with the offset of FI from the top of the caller-allocated frame
452*5f613dfdSUlrich Weigand   // (i.e. the top of the 160 bytes allocated by the caller).  This initial
453*5f613dfdSUlrich Weigand   // offset is therefore negative.
454*5f613dfdSUlrich Weigand   int64_t Offset = (MFFrame->getObjectOffset(FI) +
455*5f613dfdSUlrich Weigand                     MFFrame->getOffsetAdjustment());
456*5f613dfdSUlrich Weigand   if (FI >= 0)
457*5f613dfdSUlrich Weigand     // Non-fixed objects are allocated below the incoming stack pointer.
458*5f613dfdSUlrich Weigand     // Account for the space at the top of the frame that we choose not
459*5f613dfdSUlrich Weigand     // to allocate.
460*5f613dfdSUlrich Weigand     Offset += getUnallocatedTopBytes(MF);
461*5f613dfdSUlrich Weigand 
462*5f613dfdSUlrich Weigand   // Make the offset relative to the incoming stack pointer.
463*5f613dfdSUlrich Weigand   Offset -= getOffsetOfLocalArea();
464*5f613dfdSUlrich Weigand 
465*5f613dfdSUlrich Weigand   // Make the offset relative to the bottom of the frame.
466*5f613dfdSUlrich Weigand   Offset += getAllocatedStackSize(MF);
467*5f613dfdSUlrich Weigand 
468*5f613dfdSUlrich Weigand   return Offset;
469*5f613dfdSUlrich Weigand }
470*5f613dfdSUlrich Weigand 
471*5f613dfdSUlrich Weigand uint64_t SystemZFrameLowering::
472*5f613dfdSUlrich Weigand getUnallocatedTopBytes(const MachineFunction &MF) const {
473*5f613dfdSUlrich Weigand   return MF.getInfo<SystemZMachineFunctionInfo>()->getSavedGPRFrameSize();
474*5f613dfdSUlrich Weigand }
475*5f613dfdSUlrich Weigand 
476*5f613dfdSUlrich Weigand uint64_t SystemZFrameLowering::
477*5f613dfdSUlrich Weigand getAllocatedStackSize(const MachineFunction &MF) const {
478*5f613dfdSUlrich Weigand   const MachineFrameInfo *MFFrame = MF.getFrameInfo();
479*5f613dfdSUlrich Weigand 
480*5f613dfdSUlrich Weigand   // Start with the size of the local variables and spill slots.
481*5f613dfdSUlrich Weigand   uint64_t StackSize = MFFrame->getStackSize();
482*5f613dfdSUlrich Weigand 
483*5f613dfdSUlrich Weigand   // Remove any bytes that we choose not to allocate.
484*5f613dfdSUlrich Weigand   StackSize -= getUnallocatedTopBytes(MF);
485*5f613dfdSUlrich Weigand 
486*5f613dfdSUlrich Weigand   // Include space for an emergency spill slot, if one might be needed.
487*5f613dfdSUlrich Weigand   StackSize += getEmergencySpillSlotSize(MF);
488*5f613dfdSUlrich Weigand 
489*5f613dfdSUlrich Weigand   // We need to allocate the ABI-defined 160-byte base area whenever
490*5f613dfdSUlrich Weigand   // we allocate stack space for our own use and whenever we call another
491*5f613dfdSUlrich Weigand   // function.
492*5f613dfdSUlrich Weigand   if (StackSize || MFFrame->hasVarSizedObjects() || MFFrame->hasCalls())
493*5f613dfdSUlrich Weigand     StackSize += SystemZMC::CallFrameSize;
494*5f613dfdSUlrich Weigand 
495*5f613dfdSUlrich Weigand   return StackSize;
496*5f613dfdSUlrich Weigand }
497*5f613dfdSUlrich Weigand 
498*5f613dfdSUlrich Weigand unsigned SystemZFrameLowering::
499*5f613dfdSUlrich Weigand getEmergencySpillSlotSize(const MachineFunction &MF) const {
500*5f613dfdSUlrich Weigand   const MachineFrameInfo *MFFrame = MF.getFrameInfo();
501*5f613dfdSUlrich Weigand   uint64_t MaxReach = MFFrame->getStackSize() + SystemZMC::CallFrameSize * 2;
502*5f613dfdSUlrich Weigand   return isUInt<12>(MaxReach) ? 0 : 8;
503*5f613dfdSUlrich Weigand }
504*5f613dfdSUlrich Weigand 
505*5f613dfdSUlrich Weigand unsigned SystemZFrameLowering::
506*5f613dfdSUlrich Weigand getEmergencySpillSlotOffset(const MachineFunction &MF) const {
507*5f613dfdSUlrich Weigand   assert(getEmergencySpillSlotSize(MF) && "No emergency spill slot");
508*5f613dfdSUlrich Weigand   return SystemZMC::CallFrameSize;
509*5f613dfdSUlrich Weigand }
510*5f613dfdSUlrich Weigand 
511*5f613dfdSUlrich Weigand bool
512*5f613dfdSUlrich Weigand SystemZFrameLowering::hasReservedCallFrame(const MachineFunction &MF) const {
513*5f613dfdSUlrich Weigand   // The ABI requires us to allocate 160 bytes of stack space for the callee,
514*5f613dfdSUlrich Weigand   // with any outgoing stack arguments being placed above that.  It seems
515*5f613dfdSUlrich Weigand   // better to make that area a permanent feature of the frame even if
516*5f613dfdSUlrich Weigand   // we're using a frame pointer.
517*5f613dfdSUlrich Weigand   return true;
518*5f613dfdSUlrich Weigand }
519*5f613dfdSUlrich Weigand 
520*5f613dfdSUlrich Weigand void SystemZFrameLowering::
521*5f613dfdSUlrich Weigand eliminateCallFramePseudoInstr(MachineFunction &MF,
522*5f613dfdSUlrich Weigand                               MachineBasicBlock &MBB,
523*5f613dfdSUlrich Weigand                               MachineBasicBlock::iterator MI) const {
524*5f613dfdSUlrich Weigand   switch (MI->getOpcode()) {
525*5f613dfdSUlrich Weigand   case SystemZ::ADJCALLSTACKDOWN:
526*5f613dfdSUlrich Weigand   case SystemZ::ADJCALLSTACKUP:
527*5f613dfdSUlrich Weigand     assert(hasReservedCallFrame(MF) &&
528*5f613dfdSUlrich Weigand            "ADJSTACKDOWN and ADJSTACKUP should be no-ops");
529*5f613dfdSUlrich Weigand     MBB.erase(MI);
530*5f613dfdSUlrich Weigand     break;
531*5f613dfdSUlrich Weigand 
532*5f613dfdSUlrich Weigand   default:
533*5f613dfdSUlrich Weigand     llvm_unreachable("Unexpected call frame instruction");
534*5f613dfdSUlrich Weigand   }
535*5f613dfdSUlrich Weigand }
536