1235633Sdim//===-- PPCFrameLowering.h - Define frame lowering for PowerPC --*- C++ -*-===//
2218885Sdim//
3218885Sdim//                     The LLVM Compiler Infrastructure
4218885Sdim//
5218885Sdim// This file is distributed under the University of Illinois Open Source
6218885Sdim// License. See LICENSE.TXT for details.
7218885Sdim//
8218885Sdim//===----------------------------------------------------------------------===//
9218885Sdim//
10218885Sdim//
11218885Sdim//===----------------------------------------------------------------------===//
12218885Sdim
13218885Sdim#ifndef POWERPC_FRAMEINFO_H
14218885Sdim#define POWERPC_FRAMEINFO_H
15218885Sdim
16218885Sdim#include "PPC.h"
17218885Sdim#include "PPCSubtarget.h"
18252723Sdim#include "llvm/ADT/STLExtras.h"
19218885Sdim#include "llvm/Target/TargetFrameLowering.h"
20218885Sdim#include "llvm/Target/TargetMachine.h"
21218885Sdim
22218885Sdimnamespace llvm {
23218885Sdim  class PPCSubtarget;
24218885Sdim
25218885Sdimclass PPCFrameLowering: public TargetFrameLowering {
26218885Sdim  const PPCSubtarget &Subtarget;
27218885Sdim
28218885Sdimpublic:
29218885Sdim  PPCFrameLowering(const PPCSubtarget &sti)
30252723Sdim    : TargetFrameLowering(TargetFrameLowering::StackGrowsDown,
31252723Sdim        (sti.hasQPX() || sti.isBGQ()) ? 32 : 16, 0),
32218885Sdim      Subtarget(sti) {
33218885Sdim  }
34218885Sdim
35252723Sdim  unsigned determineFrameLayout(MachineFunction &MF,
36252723Sdim                                bool UpdateMF = true,
37252723Sdim                                bool UseEstimate = false) const;
38218885Sdim
39218885Sdim  /// emitProlog/emitEpilog - These methods insert prolog and epilog code into
40218885Sdim  /// the function.
41218885Sdim  void emitPrologue(MachineFunction &MF) const;
42218885Sdim  void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const;
43218885Sdim
44218885Sdim  bool hasFP(const MachineFunction &MF) const;
45218885Sdim  bool needsFP(const MachineFunction &MF) const;
46252723Sdim  void replaceFPWithRealFP(MachineFunction &MF) const;
47218885Sdim
48218885Sdim  void processFunctionBeforeCalleeSavedScan(MachineFunction &MF,
49218885Sdim                                            RegScavenger *RS = NULL) const;
50252723Sdim  void processFunctionBeforeFrameFinalized(MachineFunction &MF,
51252723Sdim                                       RegScavenger *RS = NULL) const;
52252723Sdim  void addScavengingSpillSlot(MachineFunction &MF, RegScavenger *RS) const;
53218885Sdim
54245431Sdim  bool spillCalleeSavedRegisters(MachineBasicBlock &MBB,
55245431Sdim                                 MachineBasicBlock::iterator MI,
56245431Sdim                                 const std::vector<CalleeSavedInfo> &CSI,
57245431Sdim                                 const TargetRegisterInfo *TRI) const;
58245431Sdim
59252723Sdim  void eliminateCallFramePseudoInstr(MachineFunction &MF,
60252723Sdim                                     MachineBasicBlock &MBB,
61252723Sdim                                     MachineBasicBlock::iterator I) const;
62252723Sdim
63245431Sdim  bool restoreCalleeSavedRegisters(MachineBasicBlock &MBB,
64245431Sdim                                   MachineBasicBlock::iterator MI,
65245431Sdim                                   const std::vector<CalleeSavedInfo> &CSI,
66245431Sdim                                   const TargetRegisterInfo *TRI) const;
67245431Sdim
68218885Sdim  /// targetHandlesStackFrameRounding - Returns true if the target is
69218885Sdim  /// responsible for rounding up the stack frame (probably at emitPrologue
70218885Sdim  /// time).
71218885Sdim  bool targetHandlesStackFrameRounding() const { return true; }
72218885Sdim
73218885Sdim  /// getReturnSaveOffset - Return the previous frame offset to save the
74218885Sdim  /// return address.
75218885Sdim  static unsigned getReturnSaveOffset(bool isPPC64, bool isDarwinABI) {
76218885Sdim    if (isDarwinABI)
77218885Sdim      return isPPC64 ? 16 : 8;
78218885Sdim    // SVR4 ABI:
79218885Sdim    return isPPC64 ? 16 : 4;
80218885Sdim  }
81218885Sdim
82218885Sdim  /// getFramePointerSaveOffset - Return the previous frame offset to save the
83218885Sdim  /// frame pointer.
84218885Sdim  static unsigned getFramePointerSaveOffset(bool isPPC64, bool isDarwinABI) {
85218885Sdim    // For the Darwin ABI:
86218885Sdim    // We cannot use the TOC save slot (offset +20) in the PowerPC linkage area
87218885Sdim    // for saving the frame pointer (if needed.)  While the published ABI has
88218885Sdim    // not used this slot since at least MacOSX 10.2, there is older code
89218885Sdim    // around that does use it, and that needs to continue to work.
90218885Sdim    if (isDarwinABI)
91218885Sdim      return isPPC64 ? -8U : -4U;
92218885Sdim
93218885Sdim    // SVR4 ABI: First slot in the general register save area.
94218885Sdim    return isPPC64 ? -8U : -4U;
95218885Sdim  }
96218885Sdim
97263509Sdim  /// getBasePointerSaveOffset - Return the previous frame offset to save the
98263509Sdim  /// base pointer.
99263509Sdim  static unsigned getBasePointerSaveOffset(bool isPPC64, bool isDarwinABI) {
100263509Sdim    if (isDarwinABI)
101263509Sdim      return isPPC64 ? -16U : -8U;
102263509Sdim
103263509Sdim    // SVR4 ABI: First slot in the general register save area.
104263509Sdim    return isPPC64 ? -16U : -8U;
105263509Sdim  }
106263509Sdim
107218885Sdim  /// getLinkageSize - Return the size of the PowerPC ABI linkage area.
108218885Sdim  ///
109218885Sdim  static unsigned getLinkageSize(bool isPPC64, bool isDarwinABI) {
110218885Sdim    if (isDarwinABI || isPPC64)
111218885Sdim      return 6 * (isPPC64 ? 8 : 4);
112218885Sdim
113218885Sdim    // SVR4 ABI:
114218885Sdim    return 8;
115218885Sdim  }
116218885Sdim
117218885Sdim  /// getMinCallArgumentsSize - Return the size of the minium PowerPC ABI
118218885Sdim  /// argument area.
119218885Sdim  static unsigned getMinCallArgumentsSize(bool isPPC64, bool isDarwinABI) {
120218885Sdim    // For the Darwin ABI / 64-bit SVR4 ABI:
121218885Sdim    // The prolog code of the callee may store up to 8 GPR argument registers to
122218885Sdim    // the stack, allowing va_start to index over them in memory if its varargs.
123218885Sdim    // Because we cannot tell if this is needed on the caller side, we have to
124218885Sdim    // conservatively assume that it is needed.  As such, make sure we have at
125218885Sdim    // least enough stack space for the caller to store the 8 GPRs.
126218885Sdim    if (isDarwinABI || isPPC64)
127218885Sdim      return 8 * (isPPC64 ? 8 : 4);
128218885Sdim
129218885Sdim    // 32-bit SVR4 ABI:
130218885Sdim    // There is no default stack allocated for the 8 first GPR arguments.
131218885Sdim    return 0;
132218885Sdim  }
133218885Sdim
134218885Sdim  /// getMinCallFrameSize - Return the minimum size a call frame can be using
135218885Sdim  /// the PowerPC ABI.
136218885Sdim  static unsigned getMinCallFrameSize(bool isPPC64, bool isDarwinABI) {
137218885Sdim    // The call frame needs to be at least big enough for linkage and 8 args.
138218885Sdim    return getLinkageSize(isPPC64, isDarwinABI) +
139218885Sdim           getMinCallArgumentsSize(isPPC64, isDarwinABI);
140218885Sdim  }
141218885Sdim
142218885Sdim  // With the SVR4 ABI, callee-saved registers have fixed offsets on the stack.
143218885Sdim  const SpillSlot *
144218885Sdim  getCalleeSavedSpillSlots(unsigned &NumEntries) const {
145218885Sdim    if (Subtarget.isDarwinABI()) {
146218885Sdim      NumEntries = 1;
147218885Sdim      if (Subtarget.isPPC64()) {
148218885Sdim        static const SpillSlot darwin64Offsets = {PPC::X31, -8};
149218885Sdim        return &darwin64Offsets;
150218885Sdim      } else {
151218885Sdim        static const SpillSlot darwinOffsets = {PPC::R31, -4};
152218885Sdim        return &darwinOffsets;
153218885Sdim      }
154218885Sdim    }
155218885Sdim
156218885Sdim    // Early exit if not using the SVR4 ABI.
157218885Sdim    if (!Subtarget.isSVR4ABI()) {
158218885Sdim      NumEntries = 0;
159218885Sdim      return 0;
160218885Sdim    }
161218885Sdim
162252723Sdim    // Note that the offsets here overlap, but this is fixed up in
163252723Sdim    // processFunctionBeforeFrameFinalized.
164252723Sdim
165218885Sdim    static const SpillSlot Offsets[] = {
166218885Sdim      // Floating-point register save area offsets.
167218885Sdim      {PPC::F31, -8},
168218885Sdim      {PPC::F30, -16},
169218885Sdim      {PPC::F29, -24},
170218885Sdim      {PPC::F28, -32},
171218885Sdim      {PPC::F27, -40},
172218885Sdim      {PPC::F26, -48},
173218885Sdim      {PPC::F25, -56},
174218885Sdim      {PPC::F24, -64},
175218885Sdim      {PPC::F23, -72},
176218885Sdim      {PPC::F22, -80},
177218885Sdim      {PPC::F21, -88},
178218885Sdim      {PPC::F20, -96},
179218885Sdim      {PPC::F19, -104},
180218885Sdim      {PPC::F18, -112},
181218885Sdim      {PPC::F17, -120},
182218885Sdim      {PPC::F16, -128},
183218885Sdim      {PPC::F15, -136},
184218885Sdim      {PPC::F14, -144},
185218885Sdim
186218885Sdim      // General register save area offsets.
187218885Sdim      {PPC::R31, -4},
188218885Sdim      {PPC::R30, -8},
189218885Sdim      {PPC::R29, -12},
190218885Sdim      {PPC::R28, -16},
191218885Sdim      {PPC::R27, -20},
192218885Sdim      {PPC::R26, -24},
193218885Sdim      {PPC::R25, -28},
194218885Sdim      {PPC::R24, -32},
195218885Sdim      {PPC::R23, -36},
196218885Sdim      {PPC::R22, -40},
197218885Sdim      {PPC::R21, -44},
198218885Sdim      {PPC::R20, -48},
199218885Sdim      {PPC::R19, -52},
200218885Sdim      {PPC::R18, -56},
201218885Sdim      {PPC::R17, -60},
202218885Sdim      {PPC::R16, -64},
203218885Sdim      {PPC::R15, -68},
204218885Sdim      {PPC::R14, -72},
205218885Sdim
206245431Sdim      // CR save area offset.  We map each of the nonvolatile CR fields
207245431Sdim      // to the slot for CR2, which is the first of the nonvolatile CR
208245431Sdim      // fields to be assigned, so that we only allocate one save slot.
209245431Sdim      // See PPCRegisterInfo::hasReservedSpillSlot() for more information.
210245431Sdim      {PPC::CR2, -4},
211218885Sdim
212218885Sdim      // VRSAVE save area offset.
213218885Sdim      {PPC::VRSAVE, -4},
214218885Sdim
215218885Sdim      // Vector register save area
216218885Sdim      {PPC::V31, -16},
217218885Sdim      {PPC::V30, -32},
218218885Sdim      {PPC::V29, -48},
219218885Sdim      {PPC::V28, -64},
220218885Sdim      {PPC::V27, -80},
221218885Sdim      {PPC::V26, -96},
222218885Sdim      {PPC::V25, -112},
223218885Sdim      {PPC::V24, -128},
224218885Sdim      {PPC::V23, -144},
225218885Sdim      {PPC::V22, -160},
226218885Sdim      {PPC::V21, -176},
227218885Sdim      {PPC::V20, -192}
228218885Sdim    };
229218885Sdim
230218885Sdim    static const SpillSlot Offsets64[] = {
231218885Sdim      // Floating-point register save area offsets.
232218885Sdim      {PPC::F31, -8},
233218885Sdim      {PPC::F30, -16},
234218885Sdim      {PPC::F29, -24},
235218885Sdim      {PPC::F28, -32},
236218885Sdim      {PPC::F27, -40},
237218885Sdim      {PPC::F26, -48},
238218885Sdim      {PPC::F25, -56},
239218885Sdim      {PPC::F24, -64},
240218885Sdim      {PPC::F23, -72},
241218885Sdim      {PPC::F22, -80},
242218885Sdim      {PPC::F21, -88},
243218885Sdim      {PPC::F20, -96},
244218885Sdim      {PPC::F19, -104},
245218885Sdim      {PPC::F18, -112},
246218885Sdim      {PPC::F17, -120},
247218885Sdim      {PPC::F16, -128},
248218885Sdim      {PPC::F15, -136},
249218885Sdim      {PPC::F14, -144},
250218885Sdim
251218885Sdim      // General register save area offsets.
252218885Sdim      {PPC::X31, -8},
253218885Sdim      {PPC::X30, -16},
254218885Sdim      {PPC::X29, -24},
255218885Sdim      {PPC::X28, -32},
256218885Sdim      {PPC::X27, -40},
257218885Sdim      {PPC::X26, -48},
258218885Sdim      {PPC::X25, -56},
259218885Sdim      {PPC::X24, -64},
260218885Sdim      {PPC::X23, -72},
261218885Sdim      {PPC::X22, -80},
262218885Sdim      {PPC::X21, -88},
263218885Sdim      {PPC::X20, -96},
264218885Sdim      {PPC::X19, -104},
265218885Sdim      {PPC::X18, -112},
266218885Sdim      {PPC::X17, -120},
267218885Sdim      {PPC::X16, -128},
268218885Sdim      {PPC::X15, -136},
269218885Sdim      {PPC::X14, -144},
270218885Sdim
271218885Sdim      // VRSAVE save area offset.
272218885Sdim      {PPC::VRSAVE, -4},
273218885Sdim
274218885Sdim      // Vector register save area
275218885Sdim      {PPC::V31, -16},
276218885Sdim      {PPC::V30, -32},
277218885Sdim      {PPC::V29, -48},
278218885Sdim      {PPC::V28, -64},
279218885Sdim      {PPC::V27, -80},
280218885Sdim      {PPC::V26, -96},
281218885Sdim      {PPC::V25, -112},
282218885Sdim      {PPC::V24, -128},
283218885Sdim      {PPC::V23, -144},
284218885Sdim      {PPC::V22, -160},
285218885Sdim      {PPC::V21, -176},
286218885Sdim      {PPC::V20, -192}
287218885Sdim    };
288218885Sdim
289218885Sdim    if (Subtarget.isPPC64()) {
290218885Sdim      NumEntries = array_lengthof(Offsets64);
291218885Sdim
292218885Sdim      return Offsets64;
293218885Sdim    } else {
294218885Sdim      NumEntries = array_lengthof(Offsets);
295218885Sdim
296218885Sdim      return Offsets;
297218885Sdim    }
298218885Sdim  }
299218885Sdim};
300218885Sdim
301218885Sdim} // End llvm namespace
302218885Sdim
303218885Sdim#endif
304