1251607Sdim//===-- SystemZFrameLowering.cpp - Frame lowering for SystemZ -------------===//
2251607Sdim//
3251607Sdim//                     The LLVM Compiler Infrastructure
4251607Sdim//
5251607Sdim// This file is distributed under the University of Illinois Open Source
6251607Sdim// License. See LICENSE.TXT for details.
7251607Sdim//
8251607Sdim//===----------------------------------------------------------------------===//
9251607Sdim
10251607Sdim#include "SystemZFrameLowering.h"
11251607Sdim#include "SystemZCallingConv.h"
12251607Sdim#include "SystemZInstrBuilder.h"
13251607Sdim#include "SystemZMachineFunctionInfo.h"
14251607Sdim#include "SystemZTargetMachine.h"
15251607Sdim#include "llvm/CodeGen/MachineModuleInfo.h"
16251607Sdim#include "llvm/CodeGen/MachineRegisterInfo.h"
17263508Sdim#include "llvm/CodeGen/RegisterScavenging.h"
18251607Sdim#include "llvm/IR/Function.h"
19251607Sdim
20251607Sdimusing namespace llvm;
21251607Sdim
22263508Sdimnamespace {
23251607Sdim  // The ABI-defined register save slots, relative to the incoming stack
24251607Sdim  // pointer.
25263508Sdim  static const TargetFrameLowering::SpillSlot SpillOffsetTable[] = {
26251607Sdim    { SystemZ::R2D,  0x10 },
27251607Sdim    { SystemZ::R3D,  0x18 },
28251607Sdim    { SystemZ::R4D,  0x20 },
29251607Sdim    { SystemZ::R5D,  0x28 },
30251607Sdim    { SystemZ::R6D,  0x30 },
31251607Sdim    { SystemZ::R7D,  0x38 },
32251607Sdim    { SystemZ::R8D,  0x40 },
33251607Sdim    { SystemZ::R9D,  0x48 },
34251607Sdim    { SystemZ::R10D, 0x50 },
35251607Sdim    { SystemZ::R11D, 0x58 },
36251607Sdim    { SystemZ::R12D, 0x60 },
37251607Sdim    { SystemZ::R13D, 0x68 },
38251607Sdim    { SystemZ::R14D, 0x70 },
39251607Sdim    { SystemZ::R15D, 0x78 },
40251607Sdim    { SystemZ::F0D,  0x80 },
41251607Sdim    { SystemZ::F2D,  0x88 },
42251607Sdim    { SystemZ::F4D,  0x90 },
43251607Sdim    { SystemZ::F6D,  0x98 }
44251607Sdim  };
45263508Sdim}
46251607Sdim
47263508SdimSystemZFrameLowering::SystemZFrameLowering(const SystemZTargetMachine &tm,
48263508Sdim                                           const SystemZSubtarget &sti)
49263508Sdim  : TargetFrameLowering(TargetFrameLowering::StackGrowsDown, 8,
50263508Sdim                        -SystemZMC::CallFrameSize, 8),
51263508Sdim    TM(tm), STI(sti) {
52251607Sdim  // Create a mapping from register number to save slot offset.
53251607Sdim  RegSpillOffsets.grow(SystemZ::NUM_TARGET_REGS);
54251607Sdim  for (unsigned I = 0, E = array_lengthof(SpillOffsetTable); I != E; ++I)
55263508Sdim    RegSpillOffsets[SpillOffsetTable[I].Reg] = SpillOffsetTable[I].Offset;
56251607Sdim}
57251607Sdim
58263508Sdimconst TargetFrameLowering::SpillSlot *
59263508SdimSystemZFrameLowering::getCalleeSavedSpillSlots(unsigned &NumEntries) const {
60263508Sdim  NumEntries = array_lengthof(SpillOffsetTable);
61263508Sdim  return SpillOffsetTable;
62263508Sdim}
63263508Sdim
64251607Sdimvoid SystemZFrameLowering::
65251607SdimprocessFunctionBeforeCalleeSavedScan(MachineFunction &MF,
66251607Sdim                                     RegScavenger *RS) const {
67251607Sdim  MachineFrameInfo *MFFrame = MF.getFrameInfo();
68251607Sdim  MachineRegisterInfo &MRI = MF.getRegInfo();
69251607Sdim  const TargetRegisterInfo *TRI = MF.getTarget().getRegisterInfo();
70251607Sdim  bool HasFP = hasFP(MF);
71251607Sdim  SystemZMachineFunctionInfo *MFI = MF.getInfo<SystemZMachineFunctionInfo>();
72251607Sdim  bool IsVarArg = MF.getFunction()->isVarArg();
73251607Sdim
74251607Sdim  // va_start stores incoming FPR varargs in the normal way, but delegates
75251607Sdim  // the saving of incoming GPR varargs to spillCalleeSavedRegisters().
76251607Sdim  // Record these pending uses, which typically include the call-saved
77251607Sdim  // argument register R6D.
78251607Sdim  if (IsVarArg)
79251607Sdim    for (unsigned I = MFI->getVarArgsFirstGPR(); I < SystemZ::NumArgGPRs; ++I)
80251607Sdim      MRI.setPhysRegUsed(SystemZ::ArgGPRs[I]);
81251607Sdim
82251607Sdim  // If the function requires a frame pointer, record that the hard
83251607Sdim  // frame pointer will be clobbered.
84251607Sdim  if (HasFP)
85251607Sdim    MRI.setPhysRegUsed(SystemZ::R11D);
86251607Sdim
87251607Sdim  // If the function calls other functions, record that the return
88251607Sdim  // address register will be clobbered.
89251607Sdim  if (MFFrame->hasCalls())
90251607Sdim    MRI.setPhysRegUsed(SystemZ::R14D);
91251607Sdim
92251607Sdim  // If we are saving GPRs other than the stack pointer, we might as well
93251607Sdim  // save and restore the stack pointer at the same time, via STMG and LMG.
94251607Sdim  // This allows the deallocation to be done by the LMG, rather than needing
95251607Sdim  // a separate %r15 addition.
96251607Sdim  const uint16_t *CSRegs = TRI->getCalleeSavedRegs(&MF);
97251607Sdim  for (unsigned I = 0; CSRegs[I]; ++I) {
98251607Sdim    unsigned Reg = CSRegs[I];
99251607Sdim    if (SystemZ::GR64BitRegClass.contains(Reg) && MRI.isPhysRegUsed(Reg)) {
100251607Sdim      MRI.setPhysRegUsed(SystemZ::R15D);
101251607Sdim      break;
102251607Sdim    }
103251607Sdim  }
104251607Sdim}
105251607Sdim
106251607Sdim// Add GPR64 to the save instruction being built by MIB, which is in basic
107251607Sdim// block MBB.  IsImplicit says whether this is an explicit operand to the
108251607Sdim// instruction, or an implicit one that comes between the explicit start
109251607Sdim// and end registers.
110251607Sdimstatic void addSavedGPR(MachineBasicBlock &MBB, MachineInstrBuilder &MIB,
111251607Sdim                        const SystemZTargetMachine &TM,
112251607Sdim                        unsigned GPR64, bool IsImplicit) {
113251607Sdim  const SystemZRegisterInfo *RI = TM.getRegisterInfo();
114263508Sdim  unsigned GPR32 = RI->getSubReg(GPR64, SystemZ::subreg_l32);
115251607Sdim  bool IsLive = MBB.isLiveIn(GPR64) || MBB.isLiveIn(GPR32);
116251607Sdim  if (!IsLive || !IsImplicit) {
117251607Sdim    MIB.addReg(GPR64, getImplRegState(IsImplicit) | getKillRegState(!IsLive));
118251607Sdim    if (!IsLive)
119251607Sdim      MBB.addLiveIn(GPR64);
120251607Sdim  }
121251607Sdim}
122251607Sdim
123251607Sdimbool SystemZFrameLowering::
124251607SdimspillCalleeSavedRegisters(MachineBasicBlock &MBB,
125251607Sdim                          MachineBasicBlock::iterator MBBI,
126251607Sdim                          const std::vector<CalleeSavedInfo> &CSI,
127251607Sdim                          const TargetRegisterInfo *TRI) const {
128251607Sdim  if (CSI.empty())
129251607Sdim    return false;
130251607Sdim
131251607Sdim  MachineFunction &MF = *MBB.getParent();
132251607Sdim  const TargetInstrInfo *TII = MF.getTarget().getInstrInfo();
133251607Sdim  SystemZMachineFunctionInfo *ZFI = MF.getInfo<SystemZMachineFunctionInfo>();
134251607Sdim  bool IsVarArg = MF.getFunction()->isVarArg();
135251607Sdim  DebugLoc DL = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc();
136251607Sdim
137251607Sdim  // Scan the call-saved GPRs and find the bounds of the register spill area.
138251607Sdim  unsigned LowGPR = 0;
139251607Sdim  unsigned HighGPR = SystemZ::R15D;
140251607Sdim  unsigned StartOffset = -1U;
141251607Sdim  for (unsigned I = 0, E = CSI.size(); I != E; ++I) {
142251607Sdim    unsigned Reg = CSI[I].getReg();
143251607Sdim    if (SystemZ::GR64BitRegClass.contains(Reg)) {
144251607Sdim      unsigned Offset = RegSpillOffsets[Reg];
145251607Sdim      assert(Offset && "Unexpected GPR save");
146251607Sdim      if (StartOffset > Offset) {
147251607Sdim        LowGPR = Reg;
148251607Sdim        StartOffset = Offset;
149251607Sdim      }
150251607Sdim    }
151251607Sdim  }
152251607Sdim
153263508Sdim  // Save the range of call-saved registers, for use by the epilogue inserter.
154251607Sdim  ZFI->setLowSavedGPR(LowGPR);
155251607Sdim  ZFI->setHighSavedGPR(HighGPR);
156251607Sdim
157251607Sdim  // Include the GPR varargs, if any.  R6D is call-saved, so would
158251607Sdim  // be included by the loop above, but we also need to handle the
159251607Sdim  // call-clobbered argument registers.
160251607Sdim  if (IsVarArg) {
161251607Sdim    unsigned FirstGPR = ZFI->getVarArgsFirstGPR();
162251607Sdim    if (FirstGPR < SystemZ::NumArgGPRs) {
163251607Sdim      unsigned Reg = SystemZ::ArgGPRs[FirstGPR];
164251607Sdim      unsigned Offset = RegSpillOffsets[Reg];
165251607Sdim      if (StartOffset > Offset) {
166251607Sdim        LowGPR = Reg; StartOffset = Offset;
167251607Sdim      }
168251607Sdim    }
169251607Sdim  }
170251607Sdim
171251607Sdim  // Save GPRs
172251607Sdim  if (LowGPR) {
173251607Sdim    assert(LowGPR != HighGPR && "Should be saving %r15 and something else");
174251607Sdim
175251607Sdim    // Build an STMG instruction.
176251607Sdim    MachineInstrBuilder MIB = BuildMI(MBB, MBBI, DL, TII->get(SystemZ::STMG));
177251607Sdim
178251607Sdim    // Add the explicit register operands.
179251607Sdim    addSavedGPR(MBB, MIB, TM, LowGPR, false);
180251607Sdim    addSavedGPR(MBB, MIB, TM, HighGPR, false);
181251607Sdim
182251607Sdim    // Add the address.
183251607Sdim    MIB.addReg(SystemZ::R15D).addImm(StartOffset);
184251607Sdim
185251607Sdim    // Make sure all call-saved GPRs are included as operands and are
186251607Sdim    // marked as live on entry.
187251607Sdim    for (unsigned I = 0, E = CSI.size(); I != E; ++I) {
188251607Sdim      unsigned Reg = CSI[I].getReg();
189251607Sdim      if (SystemZ::GR64BitRegClass.contains(Reg))
190251607Sdim        addSavedGPR(MBB, MIB, TM, Reg, true);
191251607Sdim    }
192251607Sdim
193251607Sdim    // ...likewise GPR varargs.
194251607Sdim    if (IsVarArg)
195251607Sdim      for (unsigned I = ZFI->getVarArgsFirstGPR(); I < SystemZ::NumArgGPRs; ++I)
196251607Sdim        addSavedGPR(MBB, MIB, TM, SystemZ::ArgGPRs[I], true);
197251607Sdim  }
198251607Sdim
199251607Sdim  // Save FPRs in the normal TargetInstrInfo way.
200251607Sdim  for (unsigned I = 0, E = CSI.size(); I != E; ++I) {
201251607Sdim    unsigned Reg = CSI[I].getReg();
202251607Sdim    if (SystemZ::FP64BitRegClass.contains(Reg)) {
203251607Sdim      MBB.addLiveIn(Reg);
204251607Sdim      TII->storeRegToStackSlot(MBB, MBBI, Reg, true, CSI[I].getFrameIdx(),
205251607Sdim                               &SystemZ::FP64BitRegClass, TRI);
206251607Sdim    }
207251607Sdim  }
208251607Sdim
209251607Sdim  return true;
210251607Sdim}
211251607Sdim
212251607Sdimbool SystemZFrameLowering::
213251607SdimrestoreCalleeSavedRegisters(MachineBasicBlock &MBB,
214251607Sdim                            MachineBasicBlock::iterator MBBI,
215251607Sdim                            const std::vector<CalleeSavedInfo> &CSI,
216251607Sdim                            const TargetRegisterInfo *TRI) const {
217251607Sdim  if (CSI.empty())
218251607Sdim    return false;
219251607Sdim
220251607Sdim  MachineFunction &MF = *MBB.getParent();
221251607Sdim  const TargetInstrInfo *TII = MF.getTarget().getInstrInfo();
222251607Sdim  SystemZMachineFunctionInfo *ZFI = MF.getInfo<SystemZMachineFunctionInfo>();
223251607Sdim  bool HasFP = hasFP(MF);
224251607Sdim  DebugLoc DL = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc();
225251607Sdim
226251607Sdim  // Restore FPRs in the normal TargetInstrInfo way.
227251607Sdim  for (unsigned I = 0, E = CSI.size(); I != E; ++I) {
228251607Sdim    unsigned Reg = CSI[I].getReg();
229251607Sdim    if (SystemZ::FP64BitRegClass.contains(Reg))
230251607Sdim      TII->loadRegFromStackSlot(MBB, MBBI, Reg, CSI[I].getFrameIdx(),
231251607Sdim                                &SystemZ::FP64BitRegClass, TRI);
232251607Sdim  }
233251607Sdim
234251607Sdim  // Restore call-saved GPRs (but not call-clobbered varargs, which at
235251607Sdim  // this point might hold return values).
236251607Sdim  unsigned LowGPR = ZFI->getLowSavedGPR();
237251607Sdim  unsigned HighGPR = ZFI->getHighSavedGPR();
238251607Sdim  unsigned StartOffset = RegSpillOffsets[LowGPR];
239251607Sdim  if (LowGPR) {
240251607Sdim    // If we saved any of %r2-%r5 as varargs, we should also be saving
241251607Sdim    // and restoring %r6.  If we're saving %r6 or above, we should be
242251607Sdim    // restoring it too.
243251607Sdim    assert(LowGPR != HighGPR && "Should be loading %r15 and something else");
244251607Sdim
245251607Sdim    // Build an LMG instruction.
246251607Sdim    MachineInstrBuilder MIB = BuildMI(MBB, MBBI, DL, TII->get(SystemZ::LMG));
247251607Sdim
248251607Sdim    // Add the explicit register operands.
249251607Sdim    MIB.addReg(LowGPR, RegState::Define);
250251607Sdim    MIB.addReg(HighGPR, RegState::Define);
251251607Sdim
252251607Sdim    // Add the address.
253251607Sdim    MIB.addReg(HasFP ? SystemZ::R11D : SystemZ::R15D);
254251607Sdim    MIB.addImm(StartOffset);
255251607Sdim
256251607Sdim    // Do a second scan adding regs as being defined by instruction
257251607Sdim    for (unsigned I = 0, E = CSI.size(); I != E; ++I) {
258251607Sdim      unsigned Reg = CSI[I].getReg();
259251607Sdim      if (Reg != LowGPR && Reg != HighGPR)
260251607Sdim        MIB.addReg(Reg, RegState::ImplicitDefine);
261251607Sdim    }
262251607Sdim  }
263251607Sdim
264251607Sdim  return true;
265251607Sdim}
266251607Sdim
267263508Sdimvoid SystemZFrameLowering::
268263508SdimprocessFunctionBeforeFrameFinalized(MachineFunction &MF,
269263508Sdim                                    RegScavenger *RS) const {
270263508Sdim  MachineFrameInfo *MFFrame = MF.getFrameInfo();
271263508Sdim  uint64_t MaxReach = (MFFrame->estimateStackSize(MF) +
272263508Sdim                       SystemZMC::CallFrameSize * 2);
273263508Sdim  if (!isUInt<12>(MaxReach)) {
274263508Sdim    // We may need register scavenging slots if some parts of the frame
275263508Sdim    // are outside the reach of an unsigned 12-bit displacement.
276263508Sdim    // Create 2 for the case where both addresses in an MVC are
277263508Sdim    // out of range.
278263508Sdim    RS->addScavengingFrameIndex(MFFrame->CreateStackObject(8, 8, false));
279263508Sdim    RS->addScavengingFrameIndex(MFFrame->CreateStackObject(8, 8, false));
280263508Sdim  }
281263508Sdim}
282263508Sdim
283251607Sdim// Emit instructions before MBBI (in MBB) to add NumBytes to Reg.
284251607Sdimstatic void emitIncrement(MachineBasicBlock &MBB,
285251607Sdim                          MachineBasicBlock::iterator &MBBI,
286251607Sdim                          const DebugLoc &DL,
287251607Sdim                          unsigned Reg, int64_t NumBytes,
288251607Sdim                          const TargetInstrInfo *TII) {
289251607Sdim  while (NumBytes) {
290251607Sdim    unsigned Opcode;
291251607Sdim    int64_t ThisVal = NumBytes;
292251607Sdim    if (isInt<16>(NumBytes))
293251607Sdim      Opcode = SystemZ::AGHI;
294251607Sdim    else {
295251607Sdim      Opcode = SystemZ::AGFI;
296251607Sdim      // Make sure we maintain 8-byte stack alignment.
297251607Sdim      int64_t MinVal = -int64_t(1) << 31;
298251607Sdim      int64_t MaxVal = (int64_t(1) << 31) - 8;
299251607Sdim      if (ThisVal < MinVal)
300251607Sdim        ThisVal = MinVal;
301251607Sdim      else if (ThisVal > MaxVal)
302251607Sdim        ThisVal = MaxVal;
303251607Sdim    }
304251607Sdim    MachineInstr *MI = BuildMI(MBB, MBBI, DL, TII->get(Opcode), Reg)
305251607Sdim      .addReg(Reg).addImm(ThisVal);
306263508Sdim    // The CC implicit def is dead.
307251607Sdim    MI->getOperand(3).setIsDead();
308251607Sdim    NumBytes -= ThisVal;
309251607Sdim  }
310251607Sdim}
311251607Sdim
312251607Sdimvoid SystemZFrameLowering::emitPrologue(MachineFunction &MF) const {
313251607Sdim  MachineBasicBlock &MBB = MF.front();
314251607Sdim  MachineFrameInfo *MFFrame = MF.getFrameInfo();
315251607Sdim  const SystemZInstrInfo *ZII =
316251607Sdim    static_cast<const SystemZInstrInfo*>(MF.getTarget().getInstrInfo());
317251607Sdim  SystemZMachineFunctionInfo *ZFI = MF.getInfo<SystemZMachineFunctionInfo>();
318251607Sdim  MachineBasicBlock::iterator MBBI = MBB.begin();
319251607Sdim  MachineModuleInfo &MMI = MF.getMMI();
320263508Sdim  const MCRegisterInfo *MRI = MMI.getContext().getRegisterInfo();
321251607Sdim  const std::vector<CalleeSavedInfo> &CSI = MFFrame->getCalleeSavedInfo();
322251607Sdim  bool HasFP = hasFP(MF);
323251607Sdim  DebugLoc DL = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc();
324251607Sdim
325251607Sdim  // The current offset of the stack pointer from the CFA.
326251607Sdim  int64_t SPOffsetFromCFA = -SystemZMC::CFAOffsetFromInitialSP;
327251607Sdim
328251607Sdim  if (ZFI->getLowSavedGPR()) {
329251607Sdim    // Skip over the GPR saves.
330251607Sdim    if (MBBI != MBB.end() && MBBI->getOpcode() == SystemZ::STMG)
331251607Sdim      ++MBBI;
332251607Sdim    else
333251607Sdim      llvm_unreachable("Couldn't skip over GPR saves");
334251607Sdim
335251607Sdim    // Add CFI for the GPR saves.
336251607Sdim    MCSymbol *GPRSaveLabel = MMI.getContext().CreateTempSymbol();
337251607Sdim    BuildMI(MBB, MBBI, DL,
338251607Sdim            ZII->get(TargetOpcode::PROLOG_LABEL)).addSym(GPRSaveLabel);
339251607Sdim    for (std::vector<CalleeSavedInfo>::const_iterator
340251607Sdim           I = CSI.begin(), E = CSI.end(); I != E; ++I) {
341251607Sdim      unsigned Reg = I->getReg();
342251607Sdim      if (SystemZ::GR64BitRegClass.contains(Reg)) {
343251607Sdim        int64_t Offset = SPOffsetFromCFA + RegSpillOffsets[Reg];
344263508Sdim        MMI.addFrameInst(MCCFIInstruction::createOffset(
345263508Sdim            GPRSaveLabel, MRI->getDwarfRegNum(Reg, true), Offset));
346251607Sdim      }
347251607Sdim    }
348251607Sdim  }
349251607Sdim
350251607Sdim  uint64_t StackSize = getAllocatedStackSize(MF);
351251607Sdim  if (StackSize) {
352251607Sdim    // Allocate StackSize bytes.
353251607Sdim    int64_t Delta = -int64_t(StackSize);
354251607Sdim    emitIncrement(MBB, MBBI, DL, SystemZ::R15D, Delta, ZII);
355251607Sdim
356251607Sdim    // Add CFI for the allocation.
357251607Sdim    MCSymbol *AdjustSPLabel = MMI.getContext().CreateTempSymbol();
358251607Sdim    BuildMI(MBB, MBBI, DL, ZII->get(TargetOpcode::PROLOG_LABEL))
359251607Sdim      .addSym(AdjustSPLabel);
360263508Sdim    MMI.addFrameInst(MCCFIInstruction::createDefCfaOffset(
361263508Sdim        AdjustSPLabel, SPOffsetFromCFA + Delta));
362251607Sdim    SPOffsetFromCFA += Delta;
363251607Sdim  }
364251607Sdim
365251607Sdim  if (HasFP) {
366251607Sdim    // Copy the base of the frame to R11.
367251607Sdim    BuildMI(MBB, MBBI, DL, ZII->get(SystemZ::LGR), SystemZ::R11D)
368251607Sdim      .addReg(SystemZ::R15D);
369251607Sdim
370251607Sdim    // Add CFI for the new frame location.
371251607Sdim    MCSymbol *SetFPLabel = MMI.getContext().CreateTempSymbol();
372251607Sdim    BuildMI(MBB, MBBI, DL, ZII->get(TargetOpcode::PROLOG_LABEL))
373251607Sdim      .addSym(SetFPLabel);
374263508Sdim    unsigned HardFP = MRI->getDwarfRegNum(SystemZ::R11D, true);
375263508Sdim    MMI.addFrameInst(
376263508Sdim        MCCFIInstruction::createDefCfaRegister(SetFPLabel, HardFP));
377251607Sdim
378251607Sdim    // Mark the FramePtr as live at the beginning of every block except
379251607Sdim    // the entry block.  (We'll have marked R11 as live on entry when
380251607Sdim    // saving the GPRs.)
381251607Sdim    for (MachineFunction::iterator
382251607Sdim           I = llvm::next(MF.begin()), E = MF.end(); I != E; ++I)
383251607Sdim      I->addLiveIn(SystemZ::R11D);
384251607Sdim  }
385251607Sdim
386251607Sdim  // Skip over the FPR saves.
387251607Sdim  MCSymbol *FPRSaveLabel = 0;
388251607Sdim  for (std::vector<CalleeSavedInfo>::const_iterator
389251607Sdim         I = CSI.begin(), E = CSI.end(); I != E; ++I) {
390251607Sdim    unsigned Reg = I->getReg();
391251607Sdim    if (SystemZ::FP64BitRegClass.contains(Reg)) {
392251607Sdim      if (MBBI != MBB.end() &&
393251607Sdim          (MBBI->getOpcode() == SystemZ::STD ||
394251607Sdim           MBBI->getOpcode() == SystemZ::STDY))
395251607Sdim        ++MBBI;
396251607Sdim      else
397251607Sdim        llvm_unreachable("Couldn't skip over FPR save");
398251607Sdim
399251607Sdim      // Add CFI for the this save.
400251607Sdim      if (!FPRSaveLabel)
401251607Sdim        FPRSaveLabel = MMI.getContext().CreateTempSymbol();
402263508Sdim      unsigned Reg = MRI->getDwarfRegNum(I->getReg(), true);
403251607Sdim      int64_t Offset = getFrameIndexOffset(MF, I->getFrameIdx());
404263508Sdim      MMI.addFrameInst(MCCFIInstruction::createOffset(
405263508Sdim          FPRSaveLabel, Reg, SPOffsetFromCFA + Offset));
406251607Sdim    }
407251607Sdim  }
408251607Sdim  // Complete the CFI for the FPR saves, modelling them as taking effect
409251607Sdim  // after the last save.
410251607Sdim  if (FPRSaveLabel)
411251607Sdim    BuildMI(MBB, MBBI, DL, ZII->get(TargetOpcode::PROLOG_LABEL))
412251607Sdim      .addSym(FPRSaveLabel);
413251607Sdim}
414251607Sdim
415251607Sdimvoid SystemZFrameLowering::emitEpilogue(MachineFunction &MF,
416251607Sdim                                        MachineBasicBlock &MBB) const {
417251607Sdim  MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr();
418251607Sdim  const SystemZInstrInfo *ZII =
419251607Sdim    static_cast<const SystemZInstrInfo*>(MF.getTarget().getInstrInfo());
420251607Sdim  SystemZMachineFunctionInfo *ZFI = MF.getInfo<SystemZMachineFunctionInfo>();
421251607Sdim
422251607Sdim  // Skip the return instruction.
423263508Sdim  assert(MBBI->isReturn() && "Can only insert epilogue into returning blocks");
424251607Sdim
425251607Sdim  uint64_t StackSize = getAllocatedStackSize(MF);
426251607Sdim  if (ZFI->getLowSavedGPR()) {
427251607Sdim    --MBBI;
428251607Sdim    unsigned Opcode = MBBI->getOpcode();
429251607Sdim    if (Opcode != SystemZ::LMG)
430251607Sdim      llvm_unreachable("Expected to see callee-save register restore code");
431251607Sdim
432251607Sdim    unsigned AddrOpNo = 2;
433251607Sdim    DebugLoc DL = MBBI->getDebugLoc();
434251607Sdim    uint64_t Offset = StackSize + MBBI->getOperand(AddrOpNo + 1).getImm();
435251607Sdim    unsigned NewOpcode = ZII->getOpcodeForOffset(Opcode, Offset);
436251607Sdim
437251607Sdim    // If the offset is too large, use the largest stack-aligned offset
438251607Sdim    // and add the rest to the base register (the stack or frame pointer).
439251607Sdim    if (!NewOpcode) {
440251607Sdim      uint64_t NumBytes = Offset - 0x7fff8;
441251607Sdim      emitIncrement(MBB, MBBI, DL, MBBI->getOperand(AddrOpNo).getReg(),
442251607Sdim                    NumBytes, ZII);
443251607Sdim      Offset -= NumBytes;
444251607Sdim      NewOpcode = ZII->getOpcodeForOffset(Opcode, Offset);
445251607Sdim      assert(NewOpcode && "No restore instruction available");
446251607Sdim    }
447251607Sdim
448251607Sdim    MBBI->setDesc(ZII->get(NewOpcode));
449251607Sdim    MBBI->getOperand(AddrOpNo + 1).ChangeToImmediate(Offset);
450251607Sdim  } else if (StackSize) {
451251607Sdim    DebugLoc DL = MBBI->getDebugLoc();
452251607Sdim    emitIncrement(MBB, MBBI, DL, SystemZ::R15D, StackSize, ZII);
453251607Sdim  }
454251607Sdim}
455251607Sdim
456251607Sdimbool SystemZFrameLowering::hasFP(const MachineFunction &MF) const {
457251607Sdim  return (MF.getTarget().Options.DisableFramePointerElim(MF) ||
458251607Sdim          MF.getFrameInfo()->hasVarSizedObjects() ||
459251607Sdim          MF.getInfo<SystemZMachineFunctionInfo>()->getManipulatesSP());
460251607Sdim}
461251607Sdim
462251607Sdimint SystemZFrameLowering::getFrameIndexOffset(const MachineFunction &MF,
463251607Sdim                                              int FI) const {
464251607Sdim  const MachineFrameInfo *MFFrame = MF.getFrameInfo();
465251607Sdim
466251607Sdim  // Start with the offset of FI from the top of the caller-allocated frame
467251607Sdim  // (i.e. the top of the 160 bytes allocated by the caller).  This initial
468251607Sdim  // offset is therefore negative.
469251607Sdim  int64_t Offset = (MFFrame->getObjectOffset(FI) +
470251607Sdim                    MFFrame->getOffsetAdjustment());
471251607Sdim
472251607Sdim  // Make the offset relative to the incoming stack pointer.
473251607Sdim  Offset -= getOffsetOfLocalArea();
474251607Sdim
475251607Sdim  // Make the offset relative to the bottom of the frame.
476251607Sdim  Offset += getAllocatedStackSize(MF);
477251607Sdim
478251607Sdim  return Offset;
479251607Sdim}
480251607Sdim
481251607Sdimuint64_t SystemZFrameLowering::
482251607SdimgetAllocatedStackSize(const MachineFunction &MF) const {
483251607Sdim  const MachineFrameInfo *MFFrame = MF.getFrameInfo();
484251607Sdim
485251607Sdim  // Start with the size of the local variables and spill slots.
486251607Sdim  uint64_t StackSize = MFFrame->getStackSize();
487251607Sdim
488251607Sdim  // We need to allocate the ABI-defined 160-byte base area whenever
489251607Sdim  // we allocate stack space for our own use and whenever we call another
490251607Sdim  // function.
491251607Sdim  if (StackSize || MFFrame->hasVarSizedObjects() || MFFrame->hasCalls())
492251607Sdim    StackSize += SystemZMC::CallFrameSize;
493251607Sdim
494251607Sdim  return StackSize;
495251607Sdim}
496251607Sdim
497251607Sdimbool
498251607SdimSystemZFrameLowering::hasReservedCallFrame(const MachineFunction &MF) const {
499251607Sdim  // The ABI requires us to allocate 160 bytes of stack space for the callee,
500251607Sdim  // with any outgoing stack arguments being placed above that.  It seems
501251607Sdim  // better to make that area a permanent feature of the frame even if
502251607Sdim  // we're using a frame pointer.
503251607Sdim  return true;
504251607Sdim}
505251607Sdim
506251607Sdimvoid SystemZFrameLowering::
507251607SdimeliminateCallFramePseudoInstr(MachineFunction &MF,
508251607Sdim                              MachineBasicBlock &MBB,
509251607Sdim                              MachineBasicBlock::iterator MI) const {
510251607Sdim  switch (MI->getOpcode()) {
511251607Sdim  case SystemZ::ADJCALLSTACKDOWN:
512251607Sdim  case SystemZ::ADJCALLSTACKUP:
513251607Sdim    assert(hasReservedCallFrame(MF) &&
514251607Sdim           "ADJSTACKDOWN and ADJSTACKUP should be no-ops");
515251607Sdim    MBB.erase(MI);
516251607Sdim    break;
517251607Sdim
518251607Sdim  default:
519251607Sdim    llvm_unreachable("Unexpected call frame instruction");
520251607Sdim  }
521251607Sdim}
522