MipsFrameLowering.cpp revision 864f66085cd9543070ef01b9f7371c110ecd7898
1//===-- MipsFrameLowering.cpp - Mips Frame Information --------------------===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file contains the Mips implementation of TargetFrameLowering class.
11//
12//===----------------------------------------------------------------------===//
13
14#include "MipsFrameLowering.h"
15#include "MipsAnalyzeImmediate.h"
16#include "MipsInstrInfo.h"
17#include "MipsMachineFunction.h"
18#include "MCTargetDesc/MipsBaseInfo.h"
19#include "llvm/Function.h"
20#include "llvm/CodeGen/MachineFrameInfo.h"
21#include "llvm/CodeGen/MachineFunction.h"
22#include "llvm/CodeGen/MachineInstrBuilder.h"
23#include "llvm/CodeGen/MachineModuleInfo.h"
24#include "llvm/CodeGen/MachineRegisterInfo.h"
25#include "llvm/Target/TargetData.h"
26#include "llvm/Target/TargetOptions.h"
27#include "llvm/Support/CommandLine.h"
28
29using namespace llvm;
30
31
32//===----------------------------------------------------------------------===//
33//
34// Stack Frame Processing methods
35// +----------------------------+
36//
37// The stack is allocated decrementing the stack pointer on
38// the first instruction of a function prologue. Once decremented,
39// all stack references are done thought a positive offset
40// from the stack/frame pointer, so the stack is considering
41// to grow up! Otherwise terrible hacks would have to be made
42// to get this stack ABI compliant :)
43//
44//  The stack frame required by the ABI (after call):
45//  Offset
46//
47//  0                 ----------
48//  4                 Args to pass
49//  .                 saved $GP  (used in PIC)
50//  .                 Alloca allocations
51//  .                 Local Area
52//  .                 CPU "Callee Saved" Registers
53//  .                 saved FP
54//  .                 saved RA
55//  .                 FPU "Callee Saved" Registers
56//  StackSize         -----------
57//
58// Offset - offset from sp after stack allocation on function prologue
59//
60// The sp is the stack pointer subtracted/added from the stack size
61// at the Prologue/Epilogue
62//
63// References to the previous stack (to obtain arguments) are done
64// with offsets that exceeds the stack size: (stacksize+(4*(num_arg-1))
65//
66// Examples:
67// - reference to the actual stack frame
68//   for any local area var there is smt like : FI >= 0, StackOffset: 4
69//     sw REGX, 4(SP)
70//
71// - reference to previous stack frame
72//   suppose there's a load to the 5th arguments : FI < 0, StackOffset: 16.
73//   The emitted instruction will be something like:
74//     lw REGX, 16+StackSize(SP)
75//
76// Since the total stack size is unknown on LowerFormalArguments, all
77// stack references (ObjectOffset) created to reference the function
78// arguments, are negative numbers. This way, on eliminateFrameIndex it's
79// possible to detect those references and the offsets are adjusted to
80// their real location.
81//
82//===----------------------------------------------------------------------===//
83
84// hasFP - Return true if the specified function should have a dedicated frame
85// pointer register.  This is true if the function has variable sized allocas or
86// if frame pointer elimination is disabled.
87bool MipsFrameLowering::hasFP(const MachineFunction &MF) const {
88  const MachineFrameInfo *MFI = MF.getFrameInfo();
89  return MF.getTarget().Options.DisableFramePointerElim(MF) ||
90      MFI->hasVarSizedObjects() || MFI->isFrameAddressTaken();
91}
92
93bool MipsFrameLowering::targetHandlesStackFrameRounding() const {
94  return true;
95}
96
97void MipsFrameLowering::emitPrologue(MachineFunction &MF) const {
98  MachineBasicBlock &MBB   = MF.front();
99  MachineFrameInfo *MFI    = MF.getFrameInfo();
100  MipsFunctionInfo *MipsFI = MF.getInfo<MipsFunctionInfo>();
101  const MipsRegisterInfo *RegInfo =
102    static_cast<const MipsRegisterInfo*>(MF.getTarget().getRegisterInfo());
103  const MipsInstrInfo &TII =
104    *static_cast<const MipsInstrInfo*>(MF.getTarget().getInstrInfo());
105  MachineBasicBlock::iterator MBBI = MBB.begin();
106  DebugLoc dl = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc();
107  unsigned SP = STI.isABI_N64() ? Mips::SP_64 : Mips::SP;
108  unsigned FP = STI.isABI_N64() ? Mips::FP_64 : Mips::FP;
109  unsigned ZERO = STI.isABI_N64() ? Mips::ZERO_64 : Mips::ZERO;
110  unsigned ADDu = STI.isABI_N64() ? Mips::DADDu : Mips::ADDu;
111  unsigned ADDiu = STI.isABI_N64() ? Mips::DADDiu : Mips::ADDiu;
112
113  // First, compute final stack size.
114  unsigned StackAlign = getStackAlignment();
115  uint64_t StackSize = MFI->getObjectOffset(MipsFI->getGlobalRegFI()) +
116    StackAlign + RoundUpToAlignment(MFI->getStackSize(), StackAlign);
117
118   // Update stack size
119  MFI->setStackSize(StackSize);
120
121  // No need to allocate space on the stack.
122  if (StackSize == 0 && !MFI->adjustsStack()) return;
123
124  MachineModuleInfo &MMI = MF.getMMI();
125  std::vector<MachineMove> &Moves = MMI.getFrameMoves();
126  MachineLocation DstML, SrcML;
127
128  // Adjust stack.
129  if (isInt<16>(-StackSize)) // addi sp, sp, (-stacksize)
130    BuildMI(MBB, MBBI, dl, TII.get(ADDiu), SP).addReg(SP).addImm(-StackSize);
131  else { // Expand immediate that doesn't fit in 16-bit.
132    unsigned ATReg = STI.isABI_N64() ? Mips::AT_64 : Mips::AT;
133
134    MF.getInfo<MipsFunctionInfo>()->setEmitNOAT();
135    Mips::loadImmediate(-StackSize, STI.isABI_N64(), TII, MBB, MBBI, dl, false,
136                        0);
137    BuildMI(MBB, MBBI, dl, TII.get(ADDu), SP).addReg(SP).addReg(ATReg);
138  }
139
140  // emit ".cfi_def_cfa_offset StackSize"
141  MCSymbol *AdjustSPLabel = MMI.getContext().CreateTempSymbol();
142  BuildMI(MBB, MBBI, dl,
143          TII.get(TargetOpcode::PROLOG_LABEL)).addSym(AdjustSPLabel);
144  DstML = MachineLocation(MachineLocation::VirtualFP);
145  SrcML = MachineLocation(MachineLocation::VirtualFP, -StackSize);
146  Moves.push_back(MachineMove(AdjustSPLabel, DstML, SrcML));
147
148  const std::vector<CalleeSavedInfo> &CSI = MFI->getCalleeSavedInfo();
149
150  if (CSI.size()) {
151    // Find the instruction past the last instruction that saves a callee-saved
152    // register to the stack.
153    for (unsigned i = 0; i < CSI.size(); ++i)
154      ++MBBI;
155
156    // Iterate over list of callee-saved registers and emit .cfi_offset
157    // directives.
158    MCSymbol *CSLabel = MMI.getContext().CreateTempSymbol();
159    BuildMI(MBB, MBBI, dl,
160            TII.get(TargetOpcode::PROLOG_LABEL)).addSym(CSLabel);
161
162    for (std::vector<CalleeSavedInfo>::const_iterator I = CSI.begin(),
163           E = CSI.end(); I != E; ++I) {
164      int64_t Offset = MFI->getObjectOffset(I->getFrameIdx());
165      unsigned Reg = I->getReg();
166
167      // If Reg is a double precision register, emit two cfa_offsets,
168      // one for each of the paired single precision registers.
169      if (Mips::AFGR64RegClass.contains(Reg)) {
170        MachineLocation DstML0(MachineLocation::VirtualFP, Offset);
171        MachineLocation DstML1(MachineLocation::VirtualFP, Offset + 4);
172        MachineLocation SrcML0(RegInfo->getSubReg(Reg, Mips::sub_fpeven));
173        MachineLocation SrcML1(RegInfo->getSubReg(Reg, Mips::sub_fpodd));
174
175        if (!STI.isLittle())
176          std::swap(SrcML0, SrcML1);
177
178        Moves.push_back(MachineMove(CSLabel, DstML0, SrcML0));
179        Moves.push_back(MachineMove(CSLabel, DstML1, SrcML1));
180      } else {
181        // Reg is either in CPURegs or FGR32.
182        DstML = MachineLocation(MachineLocation::VirtualFP, Offset);
183        SrcML = MachineLocation(Reg);
184        Moves.push_back(MachineMove(CSLabel, DstML, SrcML));
185      }
186    }
187  }
188
189  // if framepointer enabled, set it to point to the stack pointer.
190  if (hasFP(MF)) {
191    // Insert instruction "move $fp, $sp" at this location.
192    BuildMI(MBB, MBBI, dl, TII.get(ADDu), FP).addReg(SP).addReg(ZERO);
193
194    // emit ".cfi_def_cfa_register $fp"
195    MCSymbol *SetFPLabel = MMI.getContext().CreateTempSymbol();
196    BuildMI(MBB, MBBI, dl,
197            TII.get(TargetOpcode::PROLOG_LABEL)).addSym(SetFPLabel);
198    DstML = MachineLocation(FP);
199    SrcML = MachineLocation(MachineLocation::VirtualFP);
200    Moves.push_back(MachineMove(SetFPLabel, DstML, SrcML));
201  }
202}
203
204void MipsFrameLowering::emitEpilogue(MachineFunction &MF,
205                                 MachineBasicBlock &MBB) const {
206  MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr();
207  MachineFrameInfo *MFI            = MF.getFrameInfo();
208  const MipsInstrInfo &TII =
209    *static_cast<const MipsInstrInfo*>(MF.getTarget().getInstrInfo());
210  DebugLoc dl = MBBI->getDebugLoc();
211  unsigned SP = STI.isABI_N64() ? Mips::SP_64 : Mips::SP;
212  unsigned FP = STI.isABI_N64() ? Mips::FP_64 : Mips::FP;
213  unsigned ZERO = STI.isABI_N64() ? Mips::ZERO_64 : Mips::ZERO;
214  unsigned ADDu = STI.isABI_N64() ? Mips::DADDu : Mips::ADDu;
215  unsigned ADDiu = STI.isABI_N64() ? Mips::DADDiu : Mips::ADDiu;
216
217  // if framepointer enabled, restore the stack pointer.
218  if (hasFP(MF)) {
219    // Find the first instruction that restores a callee-saved register.
220    MachineBasicBlock::iterator I = MBBI;
221
222    for (unsigned i = 0; i < MFI->getCalleeSavedInfo().size(); ++i)
223      --I;
224
225    // Insert instruction "move $sp, $fp" at this location.
226    BuildMI(MBB, I, dl, TII.get(ADDu), SP).addReg(FP).addReg(ZERO);
227  }
228
229  // Get the number of bytes from FrameInfo
230  uint64_t StackSize = MFI->getStackSize();
231
232  if (!StackSize)
233    return;
234
235  // Adjust stack.
236  if (isInt<16>(StackSize)) // addi sp, sp, (-stacksize)
237    BuildMI(MBB, MBBI, dl, TII.get(ADDiu), SP).addReg(SP).addImm(StackSize);
238  else { // Expand immediate that doesn't fit in 16-bit.
239    unsigned ATReg = STI.isABI_N64() ? Mips::AT_64 : Mips::AT;
240
241    MF.getInfo<MipsFunctionInfo>()->setEmitNOAT();
242    Mips::loadImmediate(StackSize, STI.isABI_N64(), TII, MBB, MBBI, dl, false,
243                        0);
244    BuildMI(MBB, MBBI, dl, TII.get(ADDu), SP).addReg(SP).addReg(ATReg);
245  }
246}
247
248void MipsFrameLowering::
249processFunctionBeforeCalleeSavedScan(MachineFunction &MF,
250                                     RegScavenger *RS) const {
251  MachineRegisterInfo &MRI = MF.getRegInfo();
252  unsigned FP = STI.isABI_N64() ? Mips::FP_64 : Mips::FP;
253
254  // FIXME: remove this code if register allocator can correctly mark
255  //        $fp and $ra used or unused.
256
257  // Mark $fp and $ra as used or unused.
258  if (hasFP(MF))
259    MRI.setPhysRegUsed(FP);
260
261  // The register allocator might determine $ra is used after seeing
262  // instruction "jr $ra", but we do not want PrologEpilogInserter to insert
263  // instructions to save/restore $ra unless there is a function call.
264  // To correct this, $ra is explicitly marked unused if there is no
265  // function call.
266  if (MF.getFrameInfo()->hasCalls())
267    MRI.setPhysRegUsed(Mips::RA);
268  else {
269    MRI.setPhysRegUnused(Mips::RA);
270    MRI.setPhysRegUnused(Mips::RA_64);
271  }
272}
273