1234353Sdim//===-- MipsFrameLowering.cpp - Mips Frame Information --------------------===//
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// This file contains the Mips implementation of TargetFrameLowering class.
11218885Sdim//
12218885Sdim//===----------------------------------------------------------------------===//
13218885Sdim
14218885Sdim#include "MipsFrameLowering.h"
15249423Sdim#include "MCTargetDesc/MipsBaseInfo.h"
16234353Sdim#include "MipsAnalyzeImmediate.h"
17218885Sdim#include "MipsInstrInfo.h"
18218885Sdim#include "MipsMachineFunction.h"
19239462Sdim#include "MipsTargetMachine.h"
20218885Sdim#include "llvm/CodeGen/MachineFrameInfo.h"
21218885Sdim#include "llvm/CodeGen/MachineFunction.h"
22218885Sdim#include "llvm/CodeGen/MachineInstrBuilder.h"
23218885Sdim#include "llvm/CodeGen/MachineModuleInfo.h"
24218885Sdim#include "llvm/CodeGen/MachineRegisterInfo.h"
25249423Sdim#include "llvm/IR/DataLayout.h"
26249423Sdim#include "llvm/IR/Function.h"
27249423Sdim#include "llvm/Support/CommandLine.h"
28218885Sdim#include "llvm/Target/TargetOptions.h"
29218885Sdim
30218885Sdimusing namespace llvm;
31218885Sdim
32218885Sdim
33218885Sdim//===----------------------------------------------------------------------===//
34218885Sdim//
35218885Sdim// Stack Frame Processing methods
36218885Sdim// +----------------------------+
37218885Sdim//
38218885Sdim// The stack is allocated decrementing the stack pointer on
39218885Sdim// the first instruction of a function prologue. Once decremented,
40218885Sdim// all stack references are done thought a positive offset
41218885Sdim// from the stack/frame pointer, so the stack is considering
42218885Sdim// to grow up! Otherwise terrible hacks would have to be made
43218885Sdim// to get this stack ABI compliant :)
44218885Sdim//
45218885Sdim//  The stack frame required by the ABI (after call):
46218885Sdim//  Offset
47218885Sdim//
48218885Sdim//  0                 ----------
49218885Sdim//  4                 Args to pass
50218885Sdim//  .                 saved $GP  (used in PIC)
51218885Sdim//  .                 Alloca allocations
52218885Sdim//  .                 Local Area
53218885Sdim//  .                 CPU "Callee Saved" Registers
54218885Sdim//  .                 saved FP
55218885Sdim//  .                 saved RA
56218885Sdim//  .                 FPU "Callee Saved" Registers
57218885Sdim//  StackSize         -----------
58218885Sdim//
59218885Sdim// Offset - offset from sp after stack allocation on function prologue
60218885Sdim//
61218885Sdim// The sp is the stack pointer subtracted/added from the stack size
62218885Sdim// at the Prologue/Epilogue
63218885Sdim//
64218885Sdim// References to the previous stack (to obtain arguments) are done
65218885Sdim// with offsets that exceeds the stack size: (stacksize+(4*(num_arg-1))
66218885Sdim//
67218885Sdim// Examples:
68218885Sdim// - reference to the actual stack frame
69218885Sdim//   for any local area var there is smt like : FI >= 0, StackOffset: 4
70218885Sdim//     sw REGX, 4(SP)
71218885Sdim//
72218885Sdim// - reference to previous stack frame
73218885Sdim//   suppose there's a load to the 5th arguments : FI < 0, StackOffset: 16.
74218885Sdim//   The emitted instruction will be something like:
75218885Sdim//     lw REGX, 16+StackSize(SP)
76218885Sdim//
77218885Sdim// Since the total stack size is unknown on LowerFormalArguments, all
78218885Sdim// stack references (ObjectOffset) created to reference the function
79218885Sdim// arguments, are negative numbers. This way, on eliminateFrameIndex it's
80218885Sdim// possible to detect those references and the offsets are adjusted to
81218885Sdim// their real location.
82218885Sdim//
83218885Sdim//===----------------------------------------------------------------------===//
84218885Sdim
85239462Sdimconst MipsFrameLowering *MipsFrameLowering::create(MipsTargetMachine &TM,
86239462Sdim                                                   const MipsSubtarget &ST) {
87239462Sdim  if (TM.getSubtargetImpl()->inMips16Mode())
88239462Sdim    return llvm::createMips16FrameLowering(ST);
89239462Sdim
90239462Sdim  return llvm::createMipsSEFrameLowering(ST);
91239462Sdim}
92239462Sdim
93218885Sdim// hasFP - Return true if the specified function should have a dedicated frame
94218885Sdim// pointer register.  This is true if the function has variable sized allocas or
95218885Sdim// if frame pointer elimination is disabled.
96218885Sdimbool MipsFrameLowering::hasFP(const MachineFunction &MF) const {
97218885Sdim  const MachineFrameInfo *MFI = MF.getFrameInfo();
98234353Sdim  return MF.getTarget().Options.DisableFramePointerElim(MF) ||
99234353Sdim      MFI->hasVarSizedObjects() || MFI->isFrameAddressTaken();
100218885Sdim}
101243830Sdim
102243830Sdimuint64_t MipsFrameLowering::estimateStackSize(const MachineFunction &MF) const {
103243830Sdim  const MachineFrameInfo *MFI = MF.getFrameInfo();
104243830Sdim  const TargetRegisterInfo &TRI = *MF.getTarget().getRegisterInfo();
105243830Sdim
106243830Sdim  int64_t Offset = 0;
107243830Sdim
108243830Sdim  // Iterate over fixed sized objects.
109243830Sdim  for (int I = MFI->getObjectIndexBegin(); I != 0; ++I)
110243830Sdim    Offset = std::max(Offset, -MFI->getObjectOffset(I));
111243830Sdim
112243830Sdim  // Conservatively assume all callee-saved registers will be saved.
113243830Sdim  for (const uint16_t *R = TRI.getCalleeSavedRegs(&MF); *R; ++R) {
114243830Sdim    unsigned Size = TRI.getMinimalPhysRegClass(*R)->getSize();
115243830Sdim    Offset = RoundUpToAlignment(Offset + Size, Size);
116243830Sdim  }
117243830Sdim
118243830Sdim  unsigned MaxAlign = MFI->getMaxAlignment();
119243830Sdim
120243830Sdim  // Check that MaxAlign is not zero if there is a stack object that is not a
121243830Sdim  // callee-saved spill.
122243830Sdim  assert(!MFI->getObjectIndexEnd() || MaxAlign);
123243830Sdim
124243830Sdim  // Iterate over other objects.
125243830Sdim  for (unsigned I = 0, E = MFI->getObjectIndexEnd(); I != E; ++I)
126243830Sdim    Offset = RoundUpToAlignment(Offset + MFI->getObjectSize(I), MaxAlign);
127243830Sdim
128243830Sdim  // Call frame.
129243830Sdim  if (MFI->adjustsStack() && hasReservedCallFrame(MF))
130243830Sdim    Offset = RoundUpToAlignment(Offset + MFI->getMaxCallFrameSize(),
131243830Sdim                                std::max(MaxAlign, getStackAlignment()));
132243830Sdim
133243830Sdim  return RoundUpToAlignment(Offset, getStackAlignment());
134243830Sdim}
135