1//===-- MipsSEFrameLowering.cpp - Mips32/64 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 Mips32/64 implementation of TargetFrameLowering class.
11//
12//===----------------------------------------------------------------------===//
13
14#include "MipsSEFrameLowering.h"
15#include "MCTargetDesc/MipsBaseInfo.h"
16#include "MipsAnalyzeImmediate.h"
17#include "MipsMachineFunction.h"
18#include "MipsSEInstrInfo.h"
19#include "llvm/CodeGen/MachineFrameInfo.h"
20#include "llvm/CodeGen/MachineFunction.h"
21#include "llvm/CodeGen/MachineInstrBuilder.h"
22#include "llvm/CodeGen/MachineModuleInfo.h"
23#include "llvm/CodeGen/MachineRegisterInfo.h"
24#include "llvm/CodeGen/RegisterScavenging.h"
25#include "llvm/IR/DataLayout.h"
26#include "llvm/IR/Function.h"
27#include "llvm/Support/CommandLine.h"
28#include "llvm/Target/TargetOptions.h"
29
30using namespace llvm;
31
32unsigned MipsSEFrameLowering::ehDataReg(unsigned I) const {
33  static const unsigned EhDataReg[] = {
34    Mips::A0, Mips::A1, Mips::A2, Mips::A3
35  };
36  static const unsigned EhDataReg64[] = {
37    Mips::A0_64, Mips::A1_64, Mips::A2_64, Mips::A3_64
38  };
39
40  return STI.isABI_N64() ? EhDataReg64[I] : EhDataReg[I];
41}
42
43void MipsSEFrameLowering::emitPrologue(MachineFunction &MF) const {
44  MachineBasicBlock &MBB   = MF.front();
45  MachineFrameInfo *MFI    = MF.getFrameInfo();
46  MipsFunctionInfo *MipsFI = MF.getInfo<MipsFunctionInfo>();
47  const MipsRegisterInfo *RegInfo =
48    static_cast<const MipsRegisterInfo*>(MF.getTarget().getRegisterInfo());
49  const MipsSEInstrInfo &TII =
50    *static_cast<const MipsSEInstrInfo*>(MF.getTarget().getInstrInfo());
51  MachineBasicBlock::iterator MBBI = MBB.begin();
52  DebugLoc dl = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc();
53  unsigned SP = STI.isABI_N64() ? Mips::SP_64 : Mips::SP;
54  unsigned FP = STI.isABI_N64() ? Mips::FP_64 : Mips::FP;
55  unsigned ZERO = STI.isABI_N64() ? Mips::ZERO_64 : Mips::ZERO;
56  unsigned ADDu = STI.isABI_N64() ? Mips::DADDu : Mips::ADDu;
57
58  // First, compute final stack size.
59  uint64_t StackSize = MFI->getStackSize();
60
61  // No need to allocate space on the stack.
62  if (StackSize == 0 && !MFI->adjustsStack()) return;
63
64  MachineModuleInfo &MMI = MF.getMMI();
65  std::vector<MachineMove> &Moves = MMI.getFrameMoves();
66  MachineLocation DstML, SrcML;
67
68  // Adjust stack.
69  TII.adjustStackPtr(SP, -StackSize, MBB, MBBI);
70
71  // emit ".cfi_def_cfa_offset StackSize"
72  MCSymbol *AdjustSPLabel = MMI.getContext().CreateTempSymbol();
73  BuildMI(MBB, MBBI, dl,
74          TII.get(TargetOpcode::PROLOG_LABEL)).addSym(AdjustSPLabel);
75  DstML = MachineLocation(MachineLocation::VirtualFP);
76  SrcML = MachineLocation(MachineLocation::VirtualFP, -StackSize);
77  Moves.push_back(MachineMove(AdjustSPLabel, DstML, SrcML));
78
79  const std::vector<CalleeSavedInfo> &CSI = MFI->getCalleeSavedInfo();
80
81  if (CSI.size()) {
82    // Find the instruction past the last instruction that saves a callee-saved
83    // register to the stack.
84    for (unsigned i = 0; i < CSI.size(); ++i)
85      ++MBBI;
86
87    // Iterate over list of callee-saved registers and emit .cfi_offset
88    // directives.
89    MCSymbol *CSLabel = MMI.getContext().CreateTempSymbol();
90    BuildMI(MBB, MBBI, dl,
91            TII.get(TargetOpcode::PROLOG_LABEL)).addSym(CSLabel);
92
93    for (std::vector<CalleeSavedInfo>::const_iterator I = CSI.begin(),
94           E = CSI.end(); I != E; ++I) {
95      int64_t Offset = MFI->getObjectOffset(I->getFrameIdx());
96      unsigned Reg = I->getReg();
97
98      // If Reg is a double precision register, emit two cfa_offsets,
99      // one for each of the paired single precision registers.
100      if (Mips::AFGR64RegClass.contains(Reg)) {
101        MachineLocation DstML0(MachineLocation::VirtualFP, Offset);
102        MachineLocation DstML1(MachineLocation::VirtualFP, Offset + 4);
103        MachineLocation SrcML0(RegInfo->getSubReg(Reg, Mips::sub_fpeven));
104        MachineLocation SrcML1(RegInfo->getSubReg(Reg, Mips::sub_fpodd));
105
106        if (!STI.isLittle())
107          std::swap(SrcML0, SrcML1);
108
109        Moves.push_back(MachineMove(CSLabel, DstML0, SrcML0));
110        Moves.push_back(MachineMove(CSLabel, DstML1, SrcML1));
111      } else {
112        // Reg is either in CPURegs or FGR32.
113        DstML = MachineLocation(MachineLocation::VirtualFP, Offset);
114        SrcML = MachineLocation(Reg);
115        Moves.push_back(MachineMove(CSLabel, DstML, SrcML));
116      }
117    }
118  }
119
120  if (MipsFI->callsEhReturn()) {
121    const TargetRegisterClass *RC = STI.isABI_N64() ?
122        &Mips::CPU64RegsRegClass : &Mips::CPURegsRegClass;
123
124    // Insert instructions that spill eh data registers.
125    for (int I = 0; I < 4; ++I) {
126      if (!MBB.isLiveIn(ehDataReg(I)))
127        MBB.addLiveIn(ehDataReg(I));
128      TII.storeRegToStackSlot(MBB, MBBI, ehDataReg(I), false,
129                              MipsFI->getEhDataRegFI(I), RC, RegInfo);
130    }
131
132    // Emit .cfi_offset directives for eh data registers.
133    MCSymbol *CSLabel2 = MMI.getContext().CreateTempSymbol();
134    BuildMI(MBB, MBBI, dl,
135            TII.get(TargetOpcode::PROLOG_LABEL)).addSym(CSLabel2);
136    for (int I = 0; I < 4; ++I) {
137      int64_t Offset = MFI->getObjectOffset(MipsFI->getEhDataRegFI(I));
138      DstML = MachineLocation(MachineLocation::VirtualFP, Offset);
139      SrcML = MachineLocation(ehDataReg(I));
140      Moves.push_back(MachineMove(CSLabel2, DstML, SrcML));
141    }
142  }
143
144  // if framepointer enabled, set it to point to the stack pointer.
145  if (hasFP(MF)) {
146    // Insert instruction "move $fp, $sp" at this location.
147    BuildMI(MBB, MBBI, dl, TII.get(ADDu), FP).addReg(SP).addReg(ZERO);
148
149    // emit ".cfi_def_cfa_register $fp"
150    MCSymbol *SetFPLabel = MMI.getContext().CreateTempSymbol();
151    BuildMI(MBB, MBBI, dl,
152            TII.get(TargetOpcode::PROLOG_LABEL)).addSym(SetFPLabel);
153    DstML = MachineLocation(FP);
154    SrcML = MachineLocation(MachineLocation::VirtualFP);
155    Moves.push_back(MachineMove(SetFPLabel, DstML, SrcML));
156  }
157}
158
159void MipsSEFrameLowering::emitEpilogue(MachineFunction &MF,
160                                       MachineBasicBlock &MBB) const {
161  MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr();
162  MachineFrameInfo *MFI            = MF.getFrameInfo();
163  MipsFunctionInfo *MipsFI = MF.getInfo<MipsFunctionInfo>();
164  const MipsRegisterInfo *RegInfo =
165    static_cast<const MipsRegisterInfo*>(MF.getTarget().getRegisterInfo());
166  const MipsSEInstrInfo &TII =
167    *static_cast<const MipsSEInstrInfo*>(MF.getTarget().getInstrInfo());
168  DebugLoc dl = MBBI->getDebugLoc();
169  unsigned SP = STI.isABI_N64() ? Mips::SP_64 : Mips::SP;
170  unsigned FP = STI.isABI_N64() ? Mips::FP_64 : Mips::FP;
171  unsigned ZERO = STI.isABI_N64() ? Mips::ZERO_64 : Mips::ZERO;
172  unsigned ADDu = STI.isABI_N64() ? Mips::DADDu : Mips::ADDu;
173
174  // if framepointer enabled, restore the stack pointer.
175  if (hasFP(MF)) {
176    // Find the first instruction that restores a callee-saved register.
177    MachineBasicBlock::iterator I = MBBI;
178
179    for (unsigned i = 0; i < MFI->getCalleeSavedInfo().size(); ++i)
180      --I;
181
182    // Insert instruction "move $sp, $fp" at this location.
183    BuildMI(MBB, I, dl, TII.get(ADDu), SP).addReg(FP).addReg(ZERO);
184  }
185
186  if (MipsFI->callsEhReturn()) {
187    const TargetRegisterClass *RC = STI.isABI_N64() ?
188        &Mips::CPU64RegsRegClass : &Mips::CPURegsRegClass;
189
190    // Find first instruction that restores a callee-saved register.
191    MachineBasicBlock::iterator I = MBBI;
192    for (unsigned i = 0; i < MFI->getCalleeSavedInfo().size(); ++i)
193      --I;
194
195    // Insert instructions that restore eh data registers.
196    for (int J = 0; J < 4; ++J) {
197      TII.loadRegFromStackSlot(MBB, I, ehDataReg(J), MipsFI->getEhDataRegFI(J),
198                               RC, RegInfo);
199    }
200  }
201
202  // Get the number of bytes from FrameInfo
203  uint64_t StackSize = MFI->getStackSize();
204
205  if (!StackSize)
206    return;
207
208  // Adjust stack.
209  TII.adjustStackPtr(SP, StackSize, MBB, MBBI);
210}
211
212bool MipsSEFrameLowering::
213spillCalleeSavedRegisters(MachineBasicBlock &MBB,
214                          MachineBasicBlock::iterator MI,
215                          const std::vector<CalleeSavedInfo> &CSI,
216                          const TargetRegisterInfo *TRI) const {
217  MachineFunction *MF = MBB.getParent();
218  MachineBasicBlock *EntryBlock = MF->begin();
219  const TargetInstrInfo &TII = *MF->getTarget().getInstrInfo();
220
221  for (unsigned i = 0, e = CSI.size(); i != e; ++i) {
222    // Add the callee-saved register as live-in. Do not add if the register is
223    // RA and return address is taken, because it has already been added in
224    // method MipsTargetLowering::LowerRETURNADDR.
225    // It's killed at the spill, unless the register is RA and return address
226    // is taken.
227    unsigned Reg = CSI[i].getReg();
228    bool IsRAAndRetAddrIsTaken = (Reg == Mips::RA || Reg == Mips::RA_64)
229        && MF->getFrameInfo()->isReturnAddressTaken();
230    if (!IsRAAndRetAddrIsTaken)
231      EntryBlock->addLiveIn(Reg);
232
233    // Insert the spill to the stack frame.
234    bool IsKill = !IsRAAndRetAddrIsTaken;
235    const TargetRegisterClass *RC = TRI->getMinimalPhysRegClass(Reg);
236    TII.storeRegToStackSlot(*EntryBlock, MI, Reg, IsKill,
237                            CSI[i].getFrameIdx(), RC, TRI);
238  }
239
240  return true;
241}
242
243bool
244MipsSEFrameLowering::hasReservedCallFrame(const MachineFunction &MF) const {
245  const MachineFrameInfo *MFI = MF.getFrameInfo();
246
247  // Reserve call frame if the size of the maximum call frame fits into 16-bit
248  // immediate field and there are no variable sized objects on the stack.
249  return isInt<16>(MFI->getMaxCallFrameSize()) && !MFI->hasVarSizedObjects();
250}
251
252// Eliminate ADJCALLSTACKDOWN, ADJCALLSTACKUP pseudo instructions
253void MipsSEFrameLowering::
254eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB,
255                              MachineBasicBlock::iterator I) const {
256  const MipsSEInstrInfo &TII =
257    *static_cast<const MipsSEInstrInfo*>(MF.getTarget().getInstrInfo());
258
259  if (!hasReservedCallFrame(MF)) {
260    int64_t Amount = I->getOperand(0).getImm();
261
262    if (I->getOpcode() == Mips::ADJCALLSTACKDOWN)
263      Amount = -Amount;
264
265    unsigned SP = STI.isABI_N64() ? Mips::SP_64 : Mips::SP;
266    TII.adjustStackPtr(SP, Amount, MBB, I);
267  }
268
269  MBB.erase(I);
270}
271
272void MipsSEFrameLowering::
273processFunctionBeforeCalleeSavedScan(MachineFunction &MF,
274                                     RegScavenger *RS) const {
275  MachineRegisterInfo &MRI = MF.getRegInfo();
276  MipsFunctionInfo *MipsFI = MF.getInfo<MipsFunctionInfo>();
277  unsigned FP = STI.isABI_N64() ? Mips::FP_64 : Mips::FP;
278
279  // Mark $fp as used if function has dedicated frame pointer.
280  if (hasFP(MF))
281    MRI.setPhysRegUsed(FP);
282
283  // Create spill slots for eh data registers if function calls eh_return.
284  if (MipsFI->callsEhReturn())
285    MipsFI->createEhDataRegsFI();
286
287  // Set scavenging frame index if necessary.
288  uint64_t MaxSPOffset = MF.getInfo<MipsFunctionInfo>()->getIncomingArgSize() +
289    estimateStackSize(MF);
290
291  if (isInt<16>(MaxSPOffset))
292    return;
293
294  const TargetRegisterClass *RC = STI.isABI_N64() ?
295    &Mips::CPU64RegsRegClass : &Mips::CPURegsRegClass;
296  int FI = MF.getFrameInfo()->CreateStackObject(RC->getSize(),
297                                                RC->getAlignment(), false);
298  RS->setScavengingFrameIndex(FI);
299}
300
301const MipsFrameLowering *
302llvm::createMipsSEFrameLowering(const MipsSubtarget &ST) {
303  return new MipsSEFrameLowering(ST);
304}
305