1112758Ssam//===-- MSP430FrameLowering.cpp - MSP430 Frame Information ----------------===//
2112758Ssam//
3112758Ssam//                     The LLVM Compiler Infrastructure
4112758Ssam//
5112758Ssam// This file is distributed under the University of Illinois Open Source
6112758Ssam// License. See LICENSE.TXT for details.
7112758Ssam//
8112758Ssam//===----------------------------------------------------------------------===//
9112758Ssam//
10112758Ssam// This file contains the MSP430 implementation of TargetFrameLowering class.
11112758Ssam//
12112758Ssam//===----------------------------------------------------------------------===//
13112758Ssam
14112758Ssam#include "MSP430FrameLowering.h"
15112758Ssam#include "MSP430InstrInfo.h"
16112758Ssam#include "MSP430MachineFunctionInfo.h"
17112758Ssam#include "llvm/CodeGen/MachineFrameInfo.h"
18112758Ssam#include "llvm/CodeGen/MachineFunction.h"
19112758Ssam#include "llvm/CodeGen/MachineInstrBuilder.h"
20112758Ssam#include "llvm/CodeGen/MachineModuleInfo.h"
21112758Ssam#include "llvm/CodeGen/MachineRegisterInfo.h"
22112758Ssam#include "llvm/IR/DataLayout.h"
23112758Ssam#include "llvm/IR/Function.h"
24112758Ssam#include "llvm/Support/CommandLine.h"
25112758Ssam#include "llvm/Target/TargetOptions.h"
26112758Ssam
27112758Ssamusing namespace llvm;
28105197Ssam
29105197Ssambool MSP430FrameLowering::hasFP(const MachineFunction &MF) const {
30105197Ssam  const MachineFrameInfo *MFI = MF.getFrameInfo();
31105197Ssam
32105197Ssam  return (MF.getTarget().Options.DisableFramePointerElim(MF) ||
33105197Ssam          MF.getFrameInfo()->hasVarSizedObjects() ||
34105197Ssam          MFI->isFrameAddressTaken());
35159965Sthompsa}
36105197Ssam
37105197Ssambool MSP430FrameLowering::hasReservedCallFrame(const MachineFunction &MF) const {
38105197Ssam  return !MF.getFrameInfo()->hasVarSizedObjects();
39105197Ssam}
40105197Ssam
41105197Ssamvoid MSP430FrameLowering::emitPrologue(MachineFunction &MF) const {
42105197Ssam  MachineBasicBlock &MBB = MF.front();   // Prolog goes in entry BB
43105197Ssam  MachineFrameInfo *MFI = MF.getFrameInfo();
44105197Ssam  MSP430MachineFunctionInfo *MSP430FI = MF.getInfo<MSP430MachineFunctionInfo>();
45105197Ssam  const MSP430InstrInfo &TII =
46105197Ssam    *static_cast<const MSP430InstrInfo*>(MF.getTarget().getInstrInfo());
47257176Sglebius
48171497Sbz  MachineBasicBlock::iterator MBBI = MBB.begin();
49195699Srwatson  DebugLoc DL = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc();
50105197Ssam
51105197Ssam  // Get the number of bytes to allocate from the FrameInfo.
52105197Ssam  uint64_t StackSize = MFI->getStackSize();
53105197Ssam
54105197Ssam  uint64_t NumBytes = 0;
55105197Ssam  if (hasFP(MF)) {
56105197Ssam    // Calculate required stack adjustment
57105197Ssam    uint64_t FrameSize = StackSize - 2;
58105197Ssam    NumBytes = FrameSize - MSP430FI->getCalleeSavedFrameSize();
59105197Ssam
60105197Ssam    // Get the offset of the stack slot for the EBP register... which is
61105197Ssam    // guaranteed to be the last slot by processFunctionBeforeFrameFinalized.
62105197Ssam    // Update the frame offset adjustment.
63105197Ssam    MFI->setOffsetAdjustment(-NumBytes);
64281692Sae
65105197Ssam    // Save FPW into the appropriate stack slot...
66105197Ssam    BuildMI(MBB, MBBI, DL, TII.get(MSP430::PUSH16r))
67105197Ssam      .addReg(MSP430::FPW, RegState::Kill);
68105197Ssam
69105197Ssam    // Update FPW with the new base value...
70105197Ssam    BuildMI(MBB, MBBI, DL, TII.get(MSP430::MOV16rr), MSP430::FPW)
71105197Ssam      .addReg(MSP430::SPW);
72105197Ssam
73105197Ssam    // Mark the FramePtr as live-in in every block except the entry.
74105197Ssam    for (MachineFunction::iterator I = llvm::next(MF.begin()), E = MF.end();
75105197Ssam         I != E; ++I)
76105197Ssam      I->addLiveIn(MSP430::FPW);
77105197Ssam
78105197Ssam  } else
79105197Ssam    NumBytes = StackSize - MSP430FI->getCalleeSavedFrameSize();
80105197Ssam
81105197Ssam  // Skip the callee-saved push instructions.
82105197Ssam  while (MBBI != MBB.end() && (MBBI->getOpcode() == MSP430::PUSH16r))
83105197Ssam    ++MBBI;
84105197Ssam
85105197Ssam  if (MBBI != MBB.end())
86105197Ssam    DL = MBBI->getDebugLoc();
87194062Svanhu
88194062Svanhu  if (NumBytes) { // adjust stack pointer: SPW -= numbytes
89194062Svanhu    // If there is an SUB16ri of SPW immediately before this instruction, merge
90194062Svanhu    // the two.
91181627Svanhu    //NumBytes -= mergeSPUpdates(MBB, MBBI, true);
92181627Svanhu    // If there is an ADD16ri or SUB16ri of SPW immediately after this
93181627Svanhu    // instruction, merge the two instructions.
94181627Svanhu    // mergeSPUpdatesDown(MBB, MBBI, &NumBytes);
95181627Svanhu
96105197Ssam    if (NumBytes) {
97105197Ssam      MachineInstr *MI =
98105197Ssam        BuildMI(MBB, MBBI, DL, TII.get(MSP430::SUB16ri), MSP430::SPW)
99105197Ssam        .addReg(MSP430::SPW).addImm(NumBytes);
100105197Ssam      // The SRW implicit def is dead.
101105197Ssam      MI->getOperand(3).setIsDead();
102105197Ssam    }
103105197Ssam  }
104105197Ssam}
105120585Ssam
106120585Ssamvoid MSP430FrameLowering::emitEpilogue(MachineFunction &MF,
107282046Sae                                       MachineBasicBlock &MBB) const {
108105197Ssam  const MachineFrameInfo *MFI = MF.getFrameInfo();
109120585Ssam  MSP430MachineFunctionInfo *MSP430FI = MF.getInfo<MSP430MachineFunctionInfo>();
110120585Ssam  const MSP430InstrInfo &TII =
111105197Ssam    *static_cast<const MSP430InstrInfo*>(MF.getTarget().getInstrInfo());
112105197Ssam
113105197Ssam  MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr();
114105197Ssam  unsigned RetOpcode = MBBI->getOpcode();
115105197Ssam  DebugLoc DL = MBBI->getDebugLoc();
116105197Ssam
117105197Ssam  switch (RetOpcode) {
118105197Ssam  case MSP430::RET:
119105197Ssam  case MSP430::RETI: break;  // These are ok
120105197Ssam  default:
121105197Ssam    llvm_unreachable("Can only insert epilog into returning blocks");
122105197Ssam  }
123105197Ssam
124105197Ssam  // Get the number of bytes to allocate from the FrameInfo
125105197Ssam  uint64_t StackSize = MFI->getStackSize();
126105197Ssam  unsigned CSSize = MSP430FI->getCalleeSavedFrameSize();
127105197Ssam  uint64_t NumBytes = 0;
128105197Ssam
129105197Ssam  if (hasFP(MF)) {
130105197Ssam    // Calculate required stack adjustment
131105197Ssam    uint64_t FrameSize = StackSize - 2;
132105197Ssam    NumBytes = FrameSize - CSSize;
133105197Ssam
134105197Ssam    // pop FPW.
135105197Ssam    BuildMI(MBB, MBBI, DL, TII.get(MSP430::POP16r), MSP430::FPW);
136105197Ssam  } else
137120585Ssam    NumBytes = StackSize - CSSize;
138105197Ssam
139105197Ssam  // Skip the callee-saved pop instructions.
140105197Ssam  while (MBBI != MBB.begin()) {
141105197Ssam    MachineBasicBlock::iterator PI = prior(MBBI);
142105197Ssam    unsigned Opc = PI->getOpcode();
143105197Ssam    if (Opc != MSP430::POP16r && !PI->isTerminator())
144105197Ssam      break;
145105197Ssam    --MBBI;
146105197Ssam  }
147105197Ssam
148105197Ssam  DL = MBBI->getDebugLoc();
149105197Ssam
150120585Ssam  // If there is an ADD16ri or SUB16ri of SPW immediately before this
151105197Ssam  // instruction, merge the two instructions.
152105197Ssam  //if (NumBytes || MFI->hasVarSizedObjects())
153105197Ssam  //  mergeSPUpdatesUp(MBB, MBBI, StackPtr, &NumBytes);
154105197Ssam
155105197Ssam  if (MFI->hasVarSizedObjects()) {
156105197Ssam    BuildMI(MBB, MBBI, DL,
157105197Ssam            TII.get(MSP430::MOV16rr), MSP430::SPW).addReg(MSP430::FPW);
158105197Ssam    if (CSSize) {
159105197Ssam      MachineInstr *MI =
160105197Ssam        BuildMI(MBB, MBBI, DL,
161105197Ssam                TII.get(MSP430::SUB16ri), MSP430::SPW)
162105197Ssam        .addReg(MSP430::SPW).addImm(CSSize);
163105197Ssam      // The SRW implicit def is dead.
164105197Ssam      MI->getOperand(3).setIsDead();
165105197Ssam    }
166105197Ssam  } else {
167282046Sae    // adjust stack pointer back: SPW += numbytes
168282046Sae    if (NumBytes) {
169282046Sae      MachineInstr *MI =
170282046Sae        BuildMI(MBB, MBBI, DL, TII.get(MSP430::ADD16ri), MSP430::SPW)
171105197Ssam        .addReg(MSP430::SPW).addImm(NumBytes);
172105197Ssam      // The SRW implicit def is dead.
173238700Sbz      MI->getOperand(3).setIsDead();
174221129Sbz    }
175221129Sbz  }
176221129Sbz}
177274467Sae
178282046Sae// FIXME: Can we eleminate these in favour of generic code?
179282046Saebool
180282046SaeMSP430FrameLowering::spillCalleeSavedRegisters(MachineBasicBlock &MBB,
181282046Sae                                           MachineBasicBlock::iterator MI,
182282046Sae                                        const std::vector<CalleeSavedInfo> &CSI,
183221129Sbz                                        const TargetRegisterInfo *TRI) const {
184221129Sbz  if (CSI.empty())
185221129Sbz    return false;
186221129Sbz
187221129Sbz  DebugLoc DL;
188221129Sbz  if (MI != MBB.end()) DL = MI->getDebugLoc();
189274467Sae
190282046Sae  MachineFunction &MF = *MBB.getParent();
191282046Sae  const TargetInstrInfo &TII = *MF.getTarget().getInstrInfo();
192282046Sae  MSP430MachineFunctionInfo *MFI = MF.getInfo<MSP430MachineFunctionInfo>();
193282046Sae  MFI->setCalleeSavedFrameSize(CSI.size() * 2);
194282046Sae
195221129Sbz  for (unsigned i = CSI.size(); i != 0; --i) {
196221129Sbz    unsigned Reg = CSI[i-1].getReg();
197221129Sbz    // Add the callee-saved register as live-in. It's killed at the spill.
198221129Sbz    MBB.addLiveIn(Reg);
199221129Sbz    BuildMI(MBB, MI, DL, TII.get(MSP430::PUSH16r))
200221129Sbz      .addReg(Reg, RegState::Kill);
201221129Sbz  }
202221129Sbz  return true;
203221129Sbz}
204105197Ssam
205117056Ssambool
206105197SsamMSP430FrameLowering::restoreCalleeSavedRegisters(MachineBasicBlock &MBB,
207105197Ssam                                                 MachineBasicBlock::iterator MI,
208105197Ssam                                        const std::vector<CalleeSavedInfo> &CSI,
209105197Ssam                                        const TargetRegisterInfo *TRI) const {
210105197Ssam  if (CSI.empty())
211105197Ssam    return false;
212105197Ssam
213105197Ssam  DebugLoc DL;
214105197Ssam  if (MI != MBB.end()) DL = MI->getDebugLoc();
215194062Svanhu
216194062Svanhu  MachineFunction &MF = *MBB.getParent();
217194062Svanhu  const TargetInstrInfo &TII = *MF.getTarget().getInstrInfo();
218194062Svanhu
219194062Svanhu  for (unsigned i = 0, e = CSI.size(); i != e; ++i)
220194062Svanhu    BuildMI(MBB, MI, DL, TII.get(MSP430::POP16r), CSI[i].getReg());
221241919Sglebius
222194062Svanhu  return true;
223194062Svanhu}
224194062Svanhu
225194062Svanhuvoid MSP430FrameLowering::
226194062SvanhueliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB,
227194062Svanhu                              MachineBasicBlock::iterator I) const {
228194062Svanhu  const MSP430InstrInfo &TII =
229194062Svanhu    *static_cast<const MSP430InstrInfo*>(MF.getTarget().getInstrInfo());
230194062Svanhu  unsigned StackAlign = getStackAlignment();
231194062Svanhu
232194062Svanhu  if (!hasReservedCallFrame(MF)) {
233194062Svanhu    // If the stack pointer can be changed after prologue, turn the
234194062Svanhu    // adjcallstackup instruction into a 'sub SPW, <amt>' and the
235194062Svanhu    // adjcallstackdown instruction into 'add SPW, <amt>'
236194062Svanhu    // TODO: consider using push / pop instead of sub + store / add
237194062Svanhu    MachineInstr *Old = I;
238194062Svanhu    uint64_t Amount = Old->getOperand(0).getImm();
239194062Svanhu    if (Amount != 0) {
240194062Svanhu      // We need to keep the stack aligned properly.  To do this, we round the
241194062Svanhu      // amount of space needed for the outgoing arguments up to the next
242194062Svanhu      // alignment boundary.
243194062Svanhu      Amount = (Amount+StackAlign-1)/StackAlign*StackAlign;
244194062Svanhu
245194062Svanhu      MachineInstr *New = 0;
246194062Svanhu      if (Old->getOpcode() == TII.getCallFrameSetupOpcode()) {
247194062Svanhu        New = BuildMI(MF, Old->getDebugLoc(),
248194062Svanhu                      TII.get(MSP430::SUB16ri), MSP430::SPW)
249194062Svanhu          .addReg(MSP430::SPW).addImm(Amount);
250194062Svanhu      } else {
251194062Svanhu        assert(Old->getOpcode() == TII.getCallFrameDestroyOpcode());
252194062Svanhu        // factor out the amount the callee already popped.
253194062Svanhu        uint64_t CalleeAmt = Old->getOperand(1).getImm();
254194062Svanhu        Amount -= CalleeAmt;
255241919Sglebius        if (Amount)
256194062Svanhu          New = BuildMI(MF, Old->getDebugLoc(),
257194062Svanhu                        TII.get(MSP430::ADD16ri), MSP430::SPW)
258194062Svanhu            .addReg(MSP430::SPW).addImm(Amount);
259194062Svanhu      }
260194062Svanhu
261194062Svanhu      if (New) {
262194062Svanhu        // The SRW implicit def is dead.
263105197Ssam        New->getOperand(3).setIsDead();
264105197Ssam
265105197Ssam        // Replace the pseudo instruction with a new instruction...
266105197Ssam        MBB.insert(I, New);
267105197Ssam      }
268105197Ssam    }
269105197Ssam  } else if (I->getOpcode() == TII.getCallFrameDestroyOpcode()) {
270105197Ssam    // If we are performing frame pointer elimination and if the callee pops
271105197Ssam    // something off the stack pointer, add it back.
272105197Ssam    if (uint64_t CalleeAmt = I->getOperand(1).getImm()) {
273105197Ssam      MachineInstr *Old = I;
274105197Ssam      MachineInstr *New =
275105197Ssam        BuildMI(MF, Old->getDebugLoc(), TII.get(MSP430::SUB16ri),
276105197Ssam                MSP430::SPW).addReg(MSP430::SPW).addImm(CalleeAmt);
277105197Ssam      // The SRW implicit def is dead.
278105197Ssam      New->getOperand(3).setIsDead();
279105197Ssam
280105197Ssam      MBB.insert(I, New);
281105197Ssam    }
282105197Ssam  }
283105197Ssam
284105197Ssam  MBB.erase(I);
285105197Ssam}
286105197Ssam
287105197Ssamvoid
288105197SsamMSP430FrameLowering::processFunctionBeforeFrameFinalized(MachineFunction &MF,
289252028Sae                                                         RegScavenger *) const {
290252028Sae  // Create a frame entry for the FPW register that must be saved.
291252028Sae  if (hasFP(MF)) {
292252028Sae    int FrameIdx = MF.getFrameInfo()->CreateFixedObject(2, -4, true);
293252028Sae    (void)FrameIdx;
294252028Sae    assert(FrameIdx == MF.getFrameInfo()->getObjectIndexBegin() &&
295252028Sae           "Slot for FPW register must be last in order to be found!");
296252028Sae  }
297105197Ssam}
298105197Ssam