1239310Sdim//===-- Mips16FrameLowering.cpp - Mips16 Frame Information ----------------===//
2239310Sdim//
3239310Sdim//                     The LLVM Compiler Infrastructure
4239310Sdim//
5239310Sdim// This file is distributed under the University of Illinois Open Source
6239310Sdim// License. See LICENSE.TXT for details.
7239310Sdim//
8239310Sdim//===----------------------------------------------------------------------===//
9239310Sdim//
10239310Sdim// This file contains the Mips16 implementation of TargetFrameLowering class.
11239310Sdim//
12239310Sdim//===----------------------------------------------------------------------===//
13239310Sdim
14239310Sdim#include "Mips16FrameLowering.h"
15249423Sdim#include "MCTargetDesc/MipsBaseInfo.h"
16249423Sdim#include "Mips16InstrInfo.h"
17239310Sdim#include "MipsInstrInfo.h"
18239310Sdim#include "llvm/CodeGen/MachineFrameInfo.h"
19239310Sdim#include "llvm/CodeGen/MachineFunction.h"
20239310Sdim#include "llvm/CodeGen/MachineInstrBuilder.h"
21239310Sdim#include "llvm/CodeGen/MachineModuleInfo.h"
22239310Sdim#include "llvm/CodeGen/MachineRegisterInfo.h"
23249423Sdim#include "llvm/IR/DataLayout.h"
24249423Sdim#include "llvm/IR/Function.h"
25249423Sdim#include "llvm/Support/CommandLine.h"
26239310Sdim#include "llvm/Target/TargetOptions.h"
27239310Sdim
28239310Sdimusing namespace llvm;
29239310Sdim
30239310Sdimvoid Mips16FrameLowering::emitPrologue(MachineFunction &MF) const {
31239310Sdim  MachineBasicBlock &MBB = MF.front();
32239310Sdim  MachineFrameInfo *MFI = MF.getFrameInfo();
33249423Sdim  const Mips16InstrInfo &TII =
34249423Sdim    *static_cast<const Mips16InstrInfo*>(MF.getTarget().getInstrInfo());
35239310Sdim  MachineBasicBlock::iterator MBBI = MBB.begin();
36239310Sdim  DebugLoc dl = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc();
37239310Sdim  uint64_t StackSize = MFI->getStackSize();
38239310Sdim
39239310Sdim  // No need to allocate space on the stack.
40239310Sdim  if (StackSize == 0 && !MFI->adjustsStack()) return;
41239310Sdim
42249423Sdim  MachineModuleInfo &MMI = MF.getMMI();
43263508Sdim  const MCRegisterInfo *MRI = MMI.getContext().getRegisterInfo();
44249423Sdim  MachineLocation DstML, SrcML;
45249423Sdim
46239310Sdim  // Adjust stack.
47249423Sdim  TII.makeFrame(Mips::SP, StackSize, MBB, MBBI);
48243830Sdim
49249423Sdim  // emit ".cfi_def_cfa_offset StackSize"
50249423Sdim  MCSymbol *AdjustSPLabel = MMI.getContext().CreateTempSymbol();
51249423Sdim  BuildMI(MBB, MBBI, dl,
52249423Sdim          TII.get(TargetOpcode::PROLOG_LABEL)).addSym(AdjustSPLabel);
53263508Sdim  MMI.addFrameInst(
54263508Sdim      MCCFIInstruction::createDefCfaOffset(AdjustSPLabel, -StackSize));
55249423Sdim
56249423Sdim  MCSymbol *CSLabel = MMI.getContext().CreateTempSymbol();
57249423Sdim  BuildMI(MBB, MBBI, dl,
58249423Sdim          TII.get(TargetOpcode::PROLOG_LABEL)).addSym(CSLabel);
59263508Sdim  unsigned S2 = MRI->getDwarfRegNum(Mips::S2, true);
60263508Sdim  MMI.addFrameInst(MCCFIInstruction::createOffset(CSLabel, S2, -8));
61249423Sdim
62263508Sdim  unsigned S1 = MRI->getDwarfRegNum(Mips::S1, true);
63263508Sdim  MMI.addFrameInst(MCCFIInstruction::createOffset(CSLabel, S1, -12));
64249423Sdim
65263508Sdim  unsigned S0 = MRI->getDwarfRegNum(Mips::S0, true);
66263508Sdim  MMI.addFrameInst(MCCFIInstruction::createOffset(CSLabel, S0, -16));
67249423Sdim
68263508Sdim  unsigned RA = MRI->getDwarfRegNum(Mips::RA, true);
69263508Sdim  MMI.addFrameInst(MCCFIInstruction::createOffset(CSLabel, RA, -4));
70263508Sdim
71243830Sdim  if (hasFP(MF))
72243830Sdim    BuildMI(MBB, MBBI, dl, TII.get(Mips::MoveR3216), Mips::S0)
73243830Sdim      .addReg(Mips::SP);
74243830Sdim
75239310Sdim}
76239310Sdim
77239310Sdimvoid Mips16FrameLowering::emitEpilogue(MachineFunction &MF,
78239310Sdim                                 MachineBasicBlock &MBB) const {
79239310Sdim  MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr();
80239310Sdim  MachineFrameInfo *MFI = MF.getFrameInfo();
81249423Sdim  const Mips16InstrInfo &TII =
82249423Sdim    *static_cast<const Mips16InstrInfo*>(MF.getTarget().getInstrInfo());
83239310Sdim  DebugLoc dl = MBBI->getDebugLoc();
84239310Sdim  uint64_t StackSize = MFI->getStackSize();
85239310Sdim
86239310Sdim  if (!StackSize)
87239310Sdim    return;
88239310Sdim
89243830Sdim  if (hasFP(MF))
90243830Sdim    BuildMI(MBB, MBBI, dl, TII.get(Mips::Move32R16), Mips::SP)
91243830Sdim      .addReg(Mips::S0);
92243830Sdim
93239310Sdim  // Adjust stack.
94249423Sdim  // assumes stacksize multiple of 8
95249423Sdim  TII.restoreFrame(Mips::SP, StackSize, MBB, MBBI);
96239310Sdim}
97239310Sdim
98239310Sdimbool Mips16FrameLowering::
99239310SdimspillCalleeSavedRegisters(MachineBasicBlock &MBB,
100239310Sdim                          MachineBasicBlock::iterator MI,
101239310Sdim                          const std::vector<CalleeSavedInfo> &CSI,
102239310Sdim                          const TargetRegisterInfo *TRI) const {
103243830Sdim  MachineFunction *MF = MBB.getParent();
104243830Sdim  MachineBasicBlock *EntryBlock = MF->begin();
105243830Sdim
106243830Sdim  //
107243830Sdim  // Registers RA, S0,S1 are the callee saved registers and they
108243830Sdim  // will be saved with the "save" instruction
109243830Sdim  // during emitPrologue
110243830Sdim  //
111243830Sdim  for (unsigned i = 0, e = CSI.size(); i != e; ++i) {
112243830Sdim    // Add the callee-saved register as live-in. Do not add if the register is
113243830Sdim    // RA and return address is taken, because it has already been added in
114243830Sdim    // method MipsTargetLowering::LowerRETURNADDR.
115243830Sdim    // It's killed at the spill, unless the register is RA and return address
116243830Sdim    // is taken.
117243830Sdim    unsigned Reg = CSI[i].getReg();
118243830Sdim    bool IsRAAndRetAddrIsTaken = (Reg == Mips::RA)
119243830Sdim      && MF->getFrameInfo()->isReturnAddressTaken();
120243830Sdim    if (!IsRAAndRetAddrIsTaken)
121243830Sdim      EntryBlock->addLiveIn(Reg);
122243830Sdim  }
123243830Sdim
124239310Sdim  return true;
125239310Sdim}
126239310Sdim
127243830Sdimbool Mips16FrameLowering::restoreCalleeSavedRegisters(MachineBasicBlock &MBB,
128243830Sdim                                          MachineBasicBlock::iterator MI,
129243830Sdim                                       const std::vector<CalleeSavedInfo> &CSI,
130243830Sdim                                       const TargetRegisterInfo *TRI) const {
131243830Sdim  //
132243830Sdim  // Registers RA,S0,S1 are the callee saved registers and they will be restored
133243830Sdim  // with the restore instruction during emitEpilogue.
134243830Sdim  // We need to override this virtual function, otherwise llvm will try and
135243830Sdim  // restore the registers on it's on from the stack.
136243830Sdim  //
137243830Sdim
138243830Sdim  return true;
139243830Sdim}
140243830Sdim
141249423Sdim// Eliminate ADJCALLSTACKDOWN, ADJCALLSTACKUP pseudo instructions
142249423Sdimvoid Mips16FrameLowering::
143249423SdimeliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB,
144249423Sdim                              MachineBasicBlock::iterator I) const {
145249423Sdim  if (!hasReservedCallFrame(MF)) {
146249423Sdim    int64_t Amount = I->getOperand(0).getImm();
147249423Sdim
148249423Sdim    if (I->getOpcode() == Mips::ADJCALLSTACKDOWN)
149249423Sdim      Amount = -Amount;
150249423Sdim
151249423Sdim    const Mips16InstrInfo &TII =
152249423Sdim      *static_cast<const Mips16InstrInfo*>(MF.getTarget().getInstrInfo());
153249423Sdim
154249423Sdim    TII.adjustStackPtr(Mips::SP, Amount, MBB, I);
155249423Sdim  }
156249423Sdim
157249423Sdim  MBB.erase(I);
158249423Sdim}
159249423Sdim
160239310Sdimbool
161239310SdimMips16FrameLowering::hasReservedCallFrame(const MachineFunction &MF) const {
162243830Sdim  const MachineFrameInfo *MFI = MF.getFrameInfo();
163243830Sdim  // Reserve call frame if the size of the maximum call frame fits into 15-bit
164243830Sdim  // immediate field and there are no variable sized objects on the stack.
165243830Sdim  return isInt<15>(MFI->getMaxCallFrameSize()) && !MFI->hasVarSizedObjects();
166239310Sdim}
167239310Sdim
168239310Sdimvoid Mips16FrameLowering::
169239310SdimprocessFunctionBeforeCalleeSavedScan(MachineFunction &MF,
170239310Sdim                                     RegScavenger *RS) const {
171243830Sdim  MF.getRegInfo().setPhysRegUsed(Mips::RA);
172243830Sdim  MF.getRegInfo().setPhysRegUsed(Mips::S0);
173243830Sdim  MF.getRegInfo().setPhysRegUsed(Mips::S1);
174263508Sdim  MF.getRegInfo().setPhysRegUsed(Mips::S2);
175239310Sdim}
176239310Sdim
177239310Sdimconst MipsFrameLowering *
178239310Sdimllvm::createMips16FrameLowering(const MipsSubtarget &ST) {
179239310Sdim  return new Mips16FrameLowering(ST);
180239310Sdim}
181