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"
15252723Sdim#include "MCTargetDesc/MipsBaseInfo.h"
16252723Sdim#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"
23252723Sdim#include "llvm/IR/DataLayout.h"
24252723Sdim#include "llvm/IR/Function.h"
25252723Sdim#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();
33252723Sdim  const Mips16InstrInfo &TII =
34252723Sdim    *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
42252723Sdim  MachineModuleInfo &MMI = MF.getMMI();
43263509Sdim  const MCRegisterInfo *MRI = MMI.getContext().getRegisterInfo();
44252723Sdim  MachineLocation DstML, SrcML;
45252723Sdim
46239310Sdim  // Adjust stack.
47252723Sdim  TII.makeFrame(Mips::SP, StackSize, MBB, MBBI);
48245431Sdim
49252723Sdim  // emit ".cfi_def_cfa_offset StackSize"
50252723Sdim  MCSymbol *AdjustSPLabel = MMI.getContext().CreateTempSymbol();
51252723Sdim  BuildMI(MBB, MBBI, dl,
52252723Sdim          TII.get(TargetOpcode::PROLOG_LABEL)).addSym(AdjustSPLabel);
53263509Sdim  MMI.addFrameInst(
54263509Sdim      MCCFIInstruction::createDefCfaOffset(AdjustSPLabel, -StackSize));
55252723Sdim
56252723Sdim  MCSymbol *CSLabel = MMI.getContext().CreateTempSymbol();
57252723Sdim  BuildMI(MBB, MBBI, dl,
58252723Sdim          TII.get(TargetOpcode::PROLOG_LABEL)).addSym(CSLabel);
59263509Sdim  unsigned S2 = MRI->getDwarfRegNum(Mips::S2, true);
60263509Sdim  MMI.addFrameInst(MCCFIInstruction::createOffset(CSLabel, S2, -8));
61252723Sdim
62263509Sdim  unsigned S1 = MRI->getDwarfRegNum(Mips::S1, true);
63263509Sdim  MMI.addFrameInst(MCCFIInstruction::createOffset(CSLabel, S1, -12));
64252723Sdim
65263509Sdim  unsigned S0 = MRI->getDwarfRegNum(Mips::S0, true);
66263509Sdim  MMI.addFrameInst(MCCFIInstruction::createOffset(CSLabel, S0, -16));
67252723Sdim
68263509Sdim  unsigned RA = MRI->getDwarfRegNum(Mips::RA, true);
69263509Sdim  MMI.addFrameInst(MCCFIInstruction::createOffset(CSLabel, RA, -4));
70263509Sdim
71245431Sdim  if (hasFP(MF))
72245431Sdim    BuildMI(MBB, MBBI, dl, TII.get(Mips::MoveR3216), Mips::S0)
73245431Sdim      .addReg(Mips::SP);
74245431Sdim
75239310Sdim}
76239310Sdim
77239310Sdimvoid Mips16FrameLowering::emitEpilogue(MachineFunction &MF,
78239310Sdim                                 MachineBasicBlock &MBB) const {
79239310Sdim  MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr();
80239310Sdim  MachineFrameInfo *MFI = MF.getFrameInfo();
81252723Sdim  const Mips16InstrInfo &TII =
82252723Sdim    *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
89245431Sdim  if (hasFP(MF))
90245431Sdim    BuildMI(MBB, MBBI, dl, TII.get(Mips::Move32R16), Mips::SP)
91245431Sdim      .addReg(Mips::S0);
92245431Sdim
93239310Sdim  // Adjust stack.
94252723Sdim  // assumes stacksize multiple of 8
95252723Sdim  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 {
103245431Sdim  MachineFunction *MF = MBB.getParent();
104245431Sdim  MachineBasicBlock *EntryBlock = MF->begin();
105245431Sdim
106245431Sdim  //
107245431Sdim  // Registers RA, S0,S1 are the callee saved registers and they
108245431Sdim  // will be saved with the "save" instruction
109245431Sdim  // during emitPrologue
110245431Sdim  //
111245431Sdim  for (unsigned i = 0, e = CSI.size(); i != e; ++i) {
112245431Sdim    // Add the callee-saved register as live-in. Do not add if the register is
113245431Sdim    // RA and return address is taken, because it has already been added in
114245431Sdim    // method MipsTargetLowering::LowerRETURNADDR.
115245431Sdim    // It's killed at the spill, unless the register is RA and return address
116245431Sdim    // is taken.
117245431Sdim    unsigned Reg = CSI[i].getReg();
118245431Sdim    bool IsRAAndRetAddrIsTaken = (Reg == Mips::RA)
119245431Sdim      && MF->getFrameInfo()->isReturnAddressTaken();
120245431Sdim    if (!IsRAAndRetAddrIsTaken)
121245431Sdim      EntryBlock->addLiveIn(Reg);
122245431Sdim  }
123245431Sdim
124239310Sdim  return true;
125239310Sdim}
126239310Sdim
127245431Sdimbool Mips16FrameLowering::restoreCalleeSavedRegisters(MachineBasicBlock &MBB,
128245431Sdim                                          MachineBasicBlock::iterator MI,
129245431Sdim                                       const std::vector<CalleeSavedInfo> &CSI,
130245431Sdim                                       const TargetRegisterInfo *TRI) const {
131245431Sdim  //
132245431Sdim  // Registers RA,S0,S1 are the callee saved registers and they will be restored
133245431Sdim  // with the restore instruction during emitEpilogue.
134245431Sdim  // We need to override this virtual function, otherwise llvm will try and
135245431Sdim  // restore the registers on it's on from the stack.
136245431Sdim  //
137245431Sdim
138245431Sdim  return true;
139245431Sdim}
140245431Sdim
141252723Sdim// Eliminate ADJCALLSTACKDOWN, ADJCALLSTACKUP pseudo instructions
142252723Sdimvoid Mips16FrameLowering::
143252723SdimeliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB,
144252723Sdim                              MachineBasicBlock::iterator I) const {
145252723Sdim  if (!hasReservedCallFrame(MF)) {
146252723Sdim    int64_t Amount = I->getOperand(0).getImm();
147252723Sdim
148252723Sdim    if (I->getOpcode() == Mips::ADJCALLSTACKDOWN)
149252723Sdim      Amount = -Amount;
150252723Sdim
151252723Sdim    const Mips16InstrInfo &TII =
152252723Sdim      *static_cast<const Mips16InstrInfo*>(MF.getTarget().getInstrInfo());
153252723Sdim
154252723Sdim    TII.adjustStackPtr(Mips::SP, Amount, MBB, I);
155252723Sdim  }
156252723Sdim
157252723Sdim  MBB.erase(I);
158252723Sdim}
159252723Sdim
160239310Sdimbool
161239310SdimMips16FrameLowering::hasReservedCallFrame(const MachineFunction &MF) const {
162245431Sdim  const MachineFrameInfo *MFI = MF.getFrameInfo();
163245431Sdim  // Reserve call frame if the size of the maximum call frame fits into 15-bit
164245431Sdim  // immediate field and there are no variable sized objects on the stack.
165245431Sdim  return isInt<15>(MFI->getMaxCallFrameSize()) && !MFI->hasVarSizedObjects();
166239310Sdim}
167239310Sdim
168239310Sdimvoid Mips16FrameLowering::
169239310SdimprocessFunctionBeforeCalleeSavedScan(MachineFunction &MF,
170239310Sdim                                     RegScavenger *RS) const {
171245431Sdim  MF.getRegInfo().setPhysRegUsed(Mips::RA);
172245431Sdim  MF.getRegInfo().setPhysRegUsed(Mips::S0);
173245431Sdim  MF.getRegInfo().setPhysRegUsed(Mips::S1);
174263509Sdim  MF.getRegInfo().setPhysRegUsed(Mips::S2);
175239310Sdim}
176239310Sdim
177239310Sdimconst MipsFrameLowering *
178239310Sdimllvm::createMips16FrameLowering(const MipsSubtarget &ST) {
179239310Sdim  return new Mips16FrameLowering(ST);
180239310Sdim}
181