1234353Sdim//===-- MSP430FrameLowering.cpp - MSP430 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 MSP430 implementation of TargetFrameLowering class.
11218885Sdim//
12218885Sdim//===----------------------------------------------------------------------===//
13218885Sdim
14218885Sdim#include "MSP430FrameLowering.h"
15218885Sdim#include "MSP430InstrInfo.h"
16218885Sdim#include "MSP430MachineFunctionInfo.h"
17218885Sdim#include "llvm/CodeGen/MachineFrameInfo.h"
18218885Sdim#include "llvm/CodeGen/MachineFunction.h"
19218885Sdim#include "llvm/CodeGen/MachineInstrBuilder.h"
20218885Sdim#include "llvm/CodeGen/MachineModuleInfo.h"
21218885Sdim#include "llvm/CodeGen/MachineRegisterInfo.h"
22249423Sdim#include "llvm/IR/DataLayout.h"
23249423Sdim#include "llvm/IR/Function.h"
24249423Sdim#include "llvm/Support/CommandLine.h"
25218885Sdim#include "llvm/Target/TargetOptions.h"
26218885Sdim
27218885Sdimusing namespace llvm;
28218885Sdim
29218885Sdimbool MSP430FrameLowering::hasFP(const MachineFunction &MF) const {
30218885Sdim  const MachineFrameInfo *MFI = MF.getFrameInfo();
31218885Sdim
32234353Sdim  return (MF.getTarget().Options.DisableFramePointerElim(MF) ||
33218885Sdim          MF.getFrameInfo()->hasVarSizedObjects() ||
34218885Sdim          MFI->isFrameAddressTaken());
35218885Sdim}
36218885Sdim
37218885Sdimbool MSP430FrameLowering::hasReservedCallFrame(const MachineFunction &MF) const {
38218885Sdim  return !MF.getFrameInfo()->hasVarSizedObjects();
39218885Sdim}
40218885Sdim
41218885Sdimvoid MSP430FrameLowering::emitPrologue(MachineFunction &MF) const {
42218885Sdim  MachineBasicBlock &MBB = MF.front();   // Prolog goes in entry BB
43218885Sdim  MachineFrameInfo *MFI = MF.getFrameInfo();
44218885Sdim  MSP430MachineFunctionInfo *MSP430FI = MF.getInfo<MSP430MachineFunctionInfo>();
45218885Sdim  const MSP430InstrInfo &TII =
46218885Sdim    *static_cast<const MSP430InstrInfo*>(MF.getTarget().getInstrInfo());
47218885Sdim
48218885Sdim  MachineBasicBlock::iterator MBBI = MBB.begin();
49218885Sdim  DebugLoc DL = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc();
50218885Sdim
51218885Sdim  // Get the number of bytes to allocate from the FrameInfo.
52218885Sdim  uint64_t StackSize = MFI->getStackSize();
53218885Sdim
54218885Sdim  uint64_t NumBytes = 0;
55218885Sdim  if (hasFP(MF)) {
56218885Sdim    // Calculate required stack adjustment
57218885Sdim    uint64_t FrameSize = StackSize - 2;
58218885Sdim    NumBytes = FrameSize - MSP430FI->getCalleeSavedFrameSize();
59218885Sdim
60218885Sdim    // Get the offset of the stack slot for the EBP register... which is
61218885Sdim    // guaranteed to be the last slot by processFunctionBeforeFrameFinalized.
62218885Sdim    // Update the frame offset adjustment.
63218885Sdim    MFI->setOffsetAdjustment(-NumBytes);
64218885Sdim
65218885Sdim    // Save FPW into the appropriate stack slot...
66218885Sdim    BuildMI(MBB, MBBI, DL, TII.get(MSP430::PUSH16r))
67218885Sdim      .addReg(MSP430::FPW, RegState::Kill);
68218885Sdim
69218885Sdim    // Update FPW with the new base value...
70218885Sdim    BuildMI(MBB, MBBI, DL, TII.get(MSP430::MOV16rr), MSP430::FPW)
71218885Sdim      .addReg(MSP430::SPW);
72218885Sdim
73218885Sdim    // Mark the FramePtr as live-in in every block except the entry.
74218885Sdim    for (MachineFunction::iterator I = llvm::next(MF.begin()), E = MF.end();
75218885Sdim         I != E; ++I)
76218885Sdim      I->addLiveIn(MSP430::FPW);
77218885Sdim
78218885Sdim  } else
79218885Sdim    NumBytes = StackSize - MSP430FI->getCalleeSavedFrameSize();
80218885Sdim
81218885Sdim  // Skip the callee-saved push instructions.
82218885Sdim  while (MBBI != MBB.end() && (MBBI->getOpcode() == MSP430::PUSH16r))
83218885Sdim    ++MBBI;
84218885Sdim
85218885Sdim  if (MBBI != MBB.end())
86218885Sdim    DL = MBBI->getDebugLoc();
87218885Sdim
88218885Sdim  if (NumBytes) { // adjust stack pointer: SPW -= numbytes
89218885Sdim    // If there is an SUB16ri of SPW immediately before this instruction, merge
90218885Sdim    // the two.
91218885Sdim    //NumBytes -= mergeSPUpdates(MBB, MBBI, true);
92218885Sdim    // If there is an ADD16ri or SUB16ri of SPW immediately after this
93218885Sdim    // instruction, merge the two instructions.
94218885Sdim    // mergeSPUpdatesDown(MBB, MBBI, &NumBytes);
95218885Sdim
96218885Sdim    if (NumBytes) {
97218885Sdim      MachineInstr *MI =
98218885Sdim        BuildMI(MBB, MBBI, DL, TII.get(MSP430::SUB16ri), MSP430::SPW)
99218885Sdim        .addReg(MSP430::SPW).addImm(NumBytes);
100218885Sdim      // The SRW implicit def is dead.
101218885Sdim      MI->getOperand(3).setIsDead();
102218885Sdim    }
103218885Sdim  }
104218885Sdim}
105218885Sdim
106218885Sdimvoid MSP430FrameLowering::emitEpilogue(MachineFunction &MF,
107218885Sdim                                       MachineBasicBlock &MBB) const {
108218885Sdim  const MachineFrameInfo *MFI = MF.getFrameInfo();
109218885Sdim  MSP430MachineFunctionInfo *MSP430FI = MF.getInfo<MSP430MachineFunctionInfo>();
110218885Sdim  const MSP430InstrInfo &TII =
111218885Sdim    *static_cast<const MSP430InstrInfo*>(MF.getTarget().getInstrInfo());
112218885Sdim
113218885Sdim  MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr();
114218885Sdim  unsigned RetOpcode = MBBI->getOpcode();
115218885Sdim  DebugLoc DL = MBBI->getDebugLoc();
116218885Sdim
117218885Sdim  switch (RetOpcode) {
118218885Sdim  case MSP430::RET:
119218885Sdim  case MSP430::RETI: break;  // These are ok
120218885Sdim  default:
121218885Sdim    llvm_unreachable("Can only insert epilog into returning blocks");
122218885Sdim  }
123218885Sdim
124218885Sdim  // Get the number of bytes to allocate from the FrameInfo
125218885Sdim  uint64_t StackSize = MFI->getStackSize();
126218885Sdim  unsigned CSSize = MSP430FI->getCalleeSavedFrameSize();
127218885Sdim  uint64_t NumBytes = 0;
128218885Sdim
129218885Sdim  if (hasFP(MF)) {
130218885Sdim    // Calculate required stack adjustment
131218885Sdim    uint64_t FrameSize = StackSize - 2;
132218885Sdim    NumBytes = FrameSize - CSSize;
133218885Sdim
134218885Sdim    // pop FPW.
135218885Sdim    BuildMI(MBB, MBBI, DL, TII.get(MSP430::POP16r), MSP430::FPW);
136218885Sdim  } else
137218885Sdim    NumBytes = StackSize - CSSize;
138218885Sdim
139218885Sdim  // Skip the callee-saved pop instructions.
140218885Sdim  while (MBBI != MBB.begin()) {
141218885Sdim    MachineBasicBlock::iterator PI = prior(MBBI);
142218885Sdim    unsigned Opc = PI->getOpcode();
143234353Sdim    if (Opc != MSP430::POP16r && !PI->isTerminator())
144218885Sdim      break;
145218885Sdim    --MBBI;
146218885Sdim  }
147218885Sdim
148218885Sdim  DL = MBBI->getDebugLoc();
149218885Sdim
150218885Sdim  // If there is an ADD16ri or SUB16ri of SPW immediately before this
151218885Sdim  // instruction, merge the two instructions.
152218885Sdim  //if (NumBytes || MFI->hasVarSizedObjects())
153218885Sdim  //  mergeSPUpdatesUp(MBB, MBBI, StackPtr, &NumBytes);
154218885Sdim
155218885Sdim  if (MFI->hasVarSizedObjects()) {
156218885Sdim    BuildMI(MBB, MBBI, DL,
157218885Sdim            TII.get(MSP430::MOV16rr), MSP430::SPW).addReg(MSP430::FPW);
158218885Sdim    if (CSSize) {
159218885Sdim      MachineInstr *MI =
160218885Sdim        BuildMI(MBB, MBBI, DL,
161218885Sdim                TII.get(MSP430::SUB16ri), MSP430::SPW)
162218885Sdim        .addReg(MSP430::SPW).addImm(CSSize);
163218885Sdim      // The SRW implicit def is dead.
164218885Sdim      MI->getOperand(3).setIsDead();
165218885Sdim    }
166218885Sdim  } else {
167218885Sdim    // adjust stack pointer back: SPW += numbytes
168218885Sdim    if (NumBytes) {
169218885Sdim      MachineInstr *MI =
170218885Sdim        BuildMI(MBB, MBBI, DL, TII.get(MSP430::ADD16ri), MSP430::SPW)
171218885Sdim        .addReg(MSP430::SPW).addImm(NumBytes);
172218885Sdim      // The SRW implicit def is dead.
173218885Sdim      MI->getOperand(3).setIsDead();
174218885Sdim    }
175218885Sdim  }
176218885Sdim}
177218885Sdim
178218885Sdim// FIXME: Can we eleminate these in favour of generic code?
179218885Sdimbool
180218885SdimMSP430FrameLowering::spillCalleeSavedRegisters(MachineBasicBlock &MBB,
181218885Sdim                                           MachineBasicBlock::iterator MI,
182218885Sdim                                        const std::vector<CalleeSavedInfo> &CSI,
183218885Sdim                                        const TargetRegisterInfo *TRI) const {
184218885Sdim  if (CSI.empty())
185218885Sdim    return false;
186218885Sdim
187218885Sdim  DebugLoc DL;
188218885Sdim  if (MI != MBB.end()) DL = MI->getDebugLoc();
189218885Sdim
190218885Sdim  MachineFunction &MF = *MBB.getParent();
191218885Sdim  const TargetInstrInfo &TII = *MF.getTarget().getInstrInfo();
192218885Sdim  MSP430MachineFunctionInfo *MFI = MF.getInfo<MSP430MachineFunctionInfo>();
193218885Sdim  MFI->setCalleeSavedFrameSize(CSI.size() * 2);
194218885Sdim
195218885Sdim  for (unsigned i = CSI.size(); i != 0; --i) {
196218885Sdim    unsigned Reg = CSI[i-1].getReg();
197218885Sdim    // Add the callee-saved register as live-in. It's killed at the spill.
198218885Sdim    MBB.addLiveIn(Reg);
199218885Sdim    BuildMI(MBB, MI, DL, TII.get(MSP430::PUSH16r))
200218885Sdim      .addReg(Reg, RegState::Kill);
201218885Sdim  }
202218885Sdim  return true;
203218885Sdim}
204218885Sdim
205218885Sdimbool
206218885SdimMSP430FrameLowering::restoreCalleeSavedRegisters(MachineBasicBlock &MBB,
207218885Sdim                                                 MachineBasicBlock::iterator MI,
208218885Sdim                                        const std::vector<CalleeSavedInfo> &CSI,
209218885Sdim                                        const TargetRegisterInfo *TRI) const {
210218885Sdim  if (CSI.empty())
211218885Sdim    return false;
212218885Sdim
213218885Sdim  DebugLoc DL;
214218885Sdim  if (MI != MBB.end()) DL = MI->getDebugLoc();
215218885Sdim
216218885Sdim  MachineFunction &MF = *MBB.getParent();
217218885Sdim  const TargetInstrInfo &TII = *MF.getTarget().getInstrInfo();
218218885Sdim
219218885Sdim  for (unsigned i = 0, e = CSI.size(); i != e; ++i)
220218885Sdim    BuildMI(MBB, MI, DL, TII.get(MSP430::POP16r), CSI[i].getReg());
221218885Sdim
222218885Sdim  return true;
223218885Sdim}
224243830Sdim
225249423Sdimvoid MSP430FrameLowering::
226249423SdimeliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB,
227249423Sdim                              MachineBasicBlock::iterator I) const {
228249423Sdim  const MSP430InstrInfo &TII =
229249423Sdim    *static_cast<const MSP430InstrInfo*>(MF.getTarget().getInstrInfo());
230249423Sdim  unsigned StackAlign = getStackAlignment();
231249423Sdim
232249423Sdim  if (!hasReservedCallFrame(MF)) {
233249423Sdim    // If the stack pointer can be changed after prologue, turn the
234249423Sdim    // adjcallstackup instruction into a 'sub SPW, <amt>' and the
235249423Sdim    // adjcallstackdown instruction into 'add SPW, <amt>'
236249423Sdim    // TODO: consider using push / pop instead of sub + store / add
237249423Sdim    MachineInstr *Old = I;
238249423Sdim    uint64_t Amount = Old->getOperand(0).getImm();
239249423Sdim    if (Amount != 0) {
240249423Sdim      // We need to keep the stack aligned properly.  To do this, we round the
241249423Sdim      // amount of space needed for the outgoing arguments up to the next
242249423Sdim      // alignment boundary.
243249423Sdim      Amount = (Amount+StackAlign-1)/StackAlign*StackAlign;
244249423Sdim
245249423Sdim      MachineInstr *New = 0;
246249423Sdim      if (Old->getOpcode() == TII.getCallFrameSetupOpcode()) {
247249423Sdim        New = BuildMI(MF, Old->getDebugLoc(),
248249423Sdim                      TII.get(MSP430::SUB16ri), MSP430::SPW)
249249423Sdim          .addReg(MSP430::SPW).addImm(Amount);
250249423Sdim      } else {
251249423Sdim        assert(Old->getOpcode() == TII.getCallFrameDestroyOpcode());
252249423Sdim        // factor out the amount the callee already popped.
253249423Sdim        uint64_t CalleeAmt = Old->getOperand(1).getImm();
254249423Sdim        Amount -= CalleeAmt;
255249423Sdim        if (Amount)
256249423Sdim          New = BuildMI(MF, Old->getDebugLoc(),
257249423Sdim                        TII.get(MSP430::ADD16ri), MSP430::SPW)
258249423Sdim            .addReg(MSP430::SPW).addImm(Amount);
259249423Sdim      }
260249423Sdim
261249423Sdim      if (New) {
262249423Sdim        // The SRW implicit def is dead.
263249423Sdim        New->getOperand(3).setIsDead();
264249423Sdim
265249423Sdim        // Replace the pseudo instruction with a new instruction...
266249423Sdim        MBB.insert(I, New);
267249423Sdim      }
268249423Sdim    }
269249423Sdim  } else if (I->getOpcode() == TII.getCallFrameDestroyOpcode()) {
270249423Sdim    // If we are performing frame pointer elimination and if the callee pops
271249423Sdim    // something off the stack pointer, add it back.
272249423Sdim    if (uint64_t CalleeAmt = I->getOperand(1).getImm()) {
273249423Sdim      MachineInstr *Old = I;
274249423Sdim      MachineInstr *New =
275249423Sdim        BuildMI(MF, Old->getDebugLoc(), TII.get(MSP430::SUB16ri),
276249423Sdim                MSP430::SPW).addReg(MSP430::SPW).addImm(CalleeAmt);
277249423Sdim      // The SRW implicit def is dead.
278249423Sdim      New->getOperand(3).setIsDead();
279249423Sdim
280249423Sdim      MBB.insert(I, New);
281249423Sdim    }
282249423Sdim  }
283249423Sdim
284249423Sdim  MBB.erase(I);
285249423Sdim}
286249423Sdim
287243830Sdimvoid
288249423SdimMSP430FrameLowering::processFunctionBeforeFrameFinalized(MachineFunction &MF,
289249423Sdim                                                         RegScavenger *) const {
290243830Sdim  // Create a frame entry for the FPW register that must be saved.
291249423Sdim  if (hasFP(MF)) {
292243830Sdim    int FrameIdx = MF.getFrameInfo()->CreateFixedObject(2, -4, true);
293243830Sdim    (void)FrameIdx;
294243830Sdim    assert(FrameIdx == MF.getFrameInfo()->getObjectIndexBegin() &&
295243830Sdim           "Slot for FPW register must be last in order to be found!");
296243830Sdim  }
297243830Sdim}
298