xref: /freebsd/contrib/llvm-project/llvm/lib/Target/MSP430/MSP430FrameLowering.cpp (revision 06c3fb2749bda94cb5201f81ffdb8fa6c3161b2e)
10b57cec5SDimitry Andric //===-- MSP430FrameLowering.cpp - MSP430 Frame Information ----------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // This file contains the MSP430 implementation of TargetFrameLowering class.
100b57cec5SDimitry Andric //
110b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
120b57cec5SDimitry Andric 
130b57cec5SDimitry Andric #include "MSP430FrameLowering.h"
140b57cec5SDimitry Andric #include "MSP430InstrInfo.h"
150b57cec5SDimitry Andric #include "MSP430MachineFunctionInfo.h"
160b57cec5SDimitry Andric #include "MSP430Subtarget.h"
170b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFrameInfo.h"
180b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFunction.h"
190b57cec5SDimitry Andric #include "llvm/CodeGen/MachineInstrBuilder.h"
200b57cec5SDimitry Andric #include "llvm/CodeGen/MachineModuleInfo.h"
210b57cec5SDimitry Andric #include "llvm/CodeGen/MachineRegisterInfo.h"
220b57cec5SDimitry Andric #include "llvm/IR/DataLayout.h"
230b57cec5SDimitry Andric #include "llvm/IR/Function.h"
240b57cec5SDimitry Andric #include "llvm/Target/TargetOptions.h"
250b57cec5SDimitry Andric 
260b57cec5SDimitry Andric using namespace llvm;
270b57cec5SDimitry Andric 
28*06c3fb27SDimitry Andric MSP430FrameLowering::MSP430FrameLowering(const MSP430Subtarget &STI)
29*06c3fb27SDimitry Andric     : TargetFrameLowering(TargetFrameLowering::StackGrowsDown, Align(2), -2,
30*06c3fb27SDimitry Andric                           Align(2)),
31*06c3fb27SDimitry Andric       STI(STI), TII(*STI.getInstrInfo()), TRI(STI.getRegisterInfo()) {}
32*06c3fb27SDimitry Andric 
330b57cec5SDimitry Andric bool MSP430FrameLowering::hasFP(const MachineFunction &MF) const {
340b57cec5SDimitry Andric   const MachineFrameInfo &MFI = MF.getFrameInfo();
350b57cec5SDimitry Andric 
360b57cec5SDimitry Andric   return (MF.getTarget().Options.DisableFramePointerElim(MF) ||
370b57cec5SDimitry Andric           MF.getFrameInfo().hasVarSizedObjects() ||
380b57cec5SDimitry Andric           MFI.isFrameAddressTaken());
390b57cec5SDimitry Andric }
400b57cec5SDimitry Andric 
410b57cec5SDimitry Andric bool MSP430FrameLowering::hasReservedCallFrame(const MachineFunction &MF) const {
420b57cec5SDimitry Andric   return !MF.getFrameInfo().hasVarSizedObjects();
430b57cec5SDimitry Andric }
440b57cec5SDimitry Andric 
45*06c3fb27SDimitry Andric void MSP430FrameLowering::BuildCFI(MachineBasicBlock &MBB,
46*06c3fb27SDimitry Andric                                    MachineBasicBlock::iterator MBBI,
47*06c3fb27SDimitry Andric                                    const DebugLoc &DL,
48*06c3fb27SDimitry Andric                                    const MCCFIInstruction &CFIInst,
49*06c3fb27SDimitry Andric                                    MachineInstr::MIFlag Flag) const {
50*06c3fb27SDimitry Andric   MachineFunction &MF = *MBB.getParent();
51*06c3fb27SDimitry Andric   unsigned CFIIndex = MF.addFrameInst(CFIInst);
52*06c3fb27SDimitry Andric   BuildMI(MBB, MBBI, DL, TII.get(TargetOpcode::CFI_INSTRUCTION))
53*06c3fb27SDimitry Andric       .addCFIIndex(CFIIndex)
54*06c3fb27SDimitry Andric       .setMIFlag(Flag);
55*06c3fb27SDimitry Andric }
56*06c3fb27SDimitry Andric 
57*06c3fb27SDimitry Andric void MSP430FrameLowering::emitCalleeSavedFrameMoves(
58*06c3fb27SDimitry Andric     MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
59*06c3fb27SDimitry Andric     const DebugLoc &DL, bool IsPrologue) const {
60*06c3fb27SDimitry Andric   MachineFunction &MF = *MBB.getParent();
61*06c3fb27SDimitry Andric   MachineFrameInfo &MFI = MF.getFrameInfo();
62*06c3fb27SDimitry Andric   MachineModuleInfo &MMI = MF.getMMI();
63*06c3fb27SDimitry Andric   const MCRegisterInfo *MRI = MMI.getContext().getRegisterInfo();
64*06c3fb27SDimitry Andric 
65*06c3fb27SDimitry Andric   // Add callee saved registers to move list.
66*06c3fb27SDimitry Andric   const std::vector<CalleeSavedInfo> &CSI = MFI.getCalleeSavedInfo();
67*06c3fb27SDimitry Andric 
68*06c3fb27SDimitry Andric   // Calculate offsets.
69*06c3fb27SDimitry Andric   for (const CalleeSavedInfo &I : CSI) {
70*06c3fb27SDimitry Andric     int64_t Offset = MFI.getObjectOffset(I.getFrameIdx());
71*06c3fb27SDimitry Andric     Register Reg = I.getReg();
72*06c3fb27SDimitry Andric     unsigned DwarfReg = MRI->getDwarfRegNum(Reg, true);
73*06c3fb27SDimitry Andric 
74*06c3fb27SDimitry Andric     if (IsPrologue) {
75*06c3fb27SDimitry Andric       BuildCFI(MBB, MBBI, DL,
76*06c3fb27SDimitry Andric                MCCFIInstruction::createOffset(nullptr, DwarfReg, Offset));
77*06c3fb27SDimitry Andric     } else {
78*06c3fb27SDimitry Andric       BuildCFI(MBB, MBBI, DL,
79*06c3fb27SDimitry Andric                MCCFIInstruction::createRestore(nullptr, DwarfReg));
80*06c3fb27SDimitry Andric     }
81*06c3fb27SDimitry Andric   }
82*06c3fb27SDimitry Andric }
83*06c3fb27SDimitry Andric 
840b57cec5SDimitry Andric void MSP430FrameLowering::emitPrologue(MachineFunction &MF,
850b57cec5SDimitry Andric                                        MachineBasicBlock &MBB) const {
860b57cec5SDimitry Andric   assert(&MF.front() == &MBB && "Shrink-wrapping not yet supported");
870b57cec5SDimitry Andric   MachineFrameInfo &MFI = MF.getFrameInfo();
880b57cec5SDimitry Andric   MSP430MachineFunctionInfo *MSP430FI = MF.getInfo<MSP430MachineFunctionInfo>();
890b57cec5SDimitry Andric   const MSP430InstrInfo &TII =
900b57cec5SDimitry Andric       *static_cast<const MSP430InstrInfo *>(MF.getSubtarget().getInstrInfo());
910b57cec5SDimitry Andric 
920b57cec5SDimitry Andric   MachineBasicBlock::iterator MBBI = MBB.begin();
930b57cec5SDimitry Andric   DebugLoc DL = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc();
940b57cec5SDimitry Andric 
950b57cec5SDimitry Andric   // Get the number of bytes to allocate from the FrameInfo.
960b57cec5SDimitry Andric   uint64_t StackSize = MFI.getStackSize();
97*06c3fb27SDimitry Andric   int stackGrowth = -2;
980b57cec5SDimitry Andric 
990b57cec5SDimitry Andric   uint64_t NumBytes = 0;
1000b57cec5SDimitry Andric   if (hasFP(MF)) {
1010b57cec5SDimitry Andric     // Calculate required stack adjustment
1020b57cec5SDimitry Andric     uint64_t FrameSize = StackSize - 2;
1030b57cec5SDimitry Andric     NumBytes = FrameSize - MSP430FI->getCalleeSavedFrameSize();
1040b57cec5SDimitry Andric 
1050b57cec5SDimitry Andric     // Get the offset of the stack slot for the EBP register... which is
1060b57cec5SDimitry Andric     // guaranteed to be the last slot by processFunctionBeforeFrameFinalized.
1070b57cec5SDimitry Andric     // Update the frame offset adjustment.
1080b57cec5SDimitry Andric     MFI.setOffsetAdjustment(-NumBytes);
1090b57cec5SDimitry Andric 
1100b57cec5SDimitry Andric     // Save FP into the appropriate stack slot...
1110b57cec5SDimitry Andric     BuildMI(MBB, MBBI, DL, TII.get(MSP430::PUSH16r))
112*06c3fb27SDimitry Andric         .addReg(MSP430::R4, RegState::Kill)
113*06c3fb27SDimitry Andric         .setMIFlag(MachineInstr::FrameSetup);
114*06c3fb27SDimitry Andric 
115*06c3fb27SDimitry Andric     // Mark the place where FP was saved.
116*06c3fb27SDimitry Andric     // Define the current CFA rule to use the provided offset.
117*06c3fb27SDimitry Andric     BuildCFI(MBB, MBBI, DL,
118*06c3fb27SDimitry Andric              MCCFIInstruction::cfiDefCfaOffset(nullptr, -2 * stackGrowth),
119*06c3fb27SDimitry Andric              MachineInstr::FrameSetup);
120*06c3fb27SDimitry Andric 
121*06c3fb27SDimitry Andric     // Change the rule for the FramePtr to be an "offset" rule.
122*06c3fb27SDimitry Andric     unsigned DwarfFramePtr = TRI->getDwarfRegNum(MSP430::R4, true);
123*06c3fb27SDimitry Andric     BuildCFI(
124*06c3fb27SDimitry Andric         MBB, MBBI, DL,
125*06c3fb27SDimitry Andric         MCCFIInstruction::createOffset(nullptr, DwarfFramePtr, 2 * stackGrowth),
126*06c3fb27SDimitry Andric         MachineInstr::FrameSetup);
1270b57cec5SDimitry Andric 
1280b57cec5SDimitry Andric     // Update FP with the new base value...
1295ffd83dbSDimitry Andric     BuildMI(MBB, MBBI, DL, TII.get(MSP430::MOV16rr), MSP430::R4)
130*06c3fb27SDimitry Andric         .addReg(MSP430::SP)
131*06c3fb27SDimitry Andric         .setMIFlag(MachineInstr::FrameSetup);
132*06c3fb27SDimitry Andric 
133*06c3fb27SDimitry Andric     // Mark effective beginning of when frame pointer becomes valid.
134*06c3fb27SDimitry Andric     // Define the current CFA to use the FP register.
135*06c3fb27SDimitry Andric     BuildCFI(MBB, MBBI, DL,
136*06c3fb27SDimitry Andric              MCCFIInstruction::createDefCfaRegister(nullptr, DwarfFramePtr),
137*06c3fb27SDimitry Andric              MachineInstr::FrameSetup);
1380b57cec5SDimitry Andric 
1390b57cec5SDimitry Andric     // Mark the FramePtr as live-in in every block except the entry.
140349cc55cSDimitry Andric     for (MachineBasicBlock &MBBJ : llvm::drop_begin(MF))
141349cc55cSDimitry Andric       MBBJ.addLiveIn(MSP430::R4);
1420b57cec5SDimitry Andric   } else
1430b57cec5SDimitry Andric     NumBytes = StackSize - MSP430FI->getCalleeSavedFrameSize();
1440b57cec5SDimitry Andric 
1450b57cec5SDimitry Andric   // Skip the callee-saved push instructions.
146*06c3fb27SDimitry Andric   int StackOffset = 2 * stackGrowth;
147*06c3fb27SDimitry Andric   while (MBBI != MBB.end() && MBBI->getFlag(MachineInstr::FrameSetup) &&
148*06c3fb27SDimitry Andric          (MBBI->getOpcode() == MSP430::PUSH16r)) {
1490b57cec5SDimitry Andric     ++MBBI;
1500b57cec5SDimitry Andric 
151*06c3fb27SDimitry Andric     if (!hasFP(MF)) {
152*06c3fb27SDimitry Andric       // Mark callee-saved push instruction.
153*06c3fb27SDimitry Andric       // Define the current CFA rule to use the provided offset.
154*06c3fb27SDimitry Andric       assert(StackSize && "Expected stack frame");
155*06c3fb27SDimitry Andric       BuildCFI(MBB, MBBI, DL,
156*06c3fb27SDimitry Andric                MCCFIInstruction::cfiDefCfaOffset(nullptr, -StackOffset),
157*06c3fb27SDimitry Andric                MachineInstr::FrameSetup);
158*06c3fb27SDimitry Andric       StackOffset += stackGrowth;
159*06c3fb27SDimitry Andric     }
160*06c3fb27SDimitry Andric   }
161*06c3fb27SDimitry Andric 
1620b57cec5SDimitry Andric   if (MBBI != MBB.end())
1630b57cec5SDimitry Andric     DL = MBBI->getDebugLoc();
1640b57cec5SDimitry Andric 
1650b57cec5SDimitry Andric   if (NumBytes) { // adjust stack pointer: SP -= numbytes
1660b57cec5SDimitry Andric     // If there is an SUB16ri of SP immediately before this instruction, merge
1670b57cec5SDimitry Andric     // the two.
1680b57cec5SDimitry Andric     //NumBytes -= mergeSPUpdates(MBB, MBBI, true);
1690b57cec5SDimitry Andric     // If there is an ADD16ri or SUB16ri of SP immediately after this
1700b57cec5SDimitry Andric     // instruction, merge the two instructions.
1710b57cec5SDimitry Andric     // mergeSPUpdatesDown(MBB, MBBI, &NumBytes);
1720b57cec5SDimitry Andric 
1730b57cec5SDimitry Andric     if (NumBytes) {
1740b57cec5SDimitry Andric       MachineInstr *MI =
1750b57cec5SDimitry Andric           BuildMI(MBB, MBBI, DL, TII.get(MSP430::SUB16ri), MSP430::SP)
176*06c3fb27SDimitry Andric               .addReg(MSP430::SP)
177*06c3fb27SDimitry Andric               .addImm(NumBytes)
178*06c3fb27SDimitry Andric               .setMIFlag(MachineInstr::FrameSetup);
1790b57cec5SDimitry Andric       // The SRW implicit def is dead.
1800b57cec5SDimitry Andric       MI->getOperand(3).setIsDead();
1810b57cec5SDimitry Andric     }
182*06c3fb27SDimitry Andric     if (!hasFP(MF)) {
183*06c3fb27SDimitry Andric       // Adjust the previous CFA value if CFA was not redefined by FP
184*06c3fb27SDimitry Andric       BuildCFI(
185*06c3fb27SDimitry Andric           MBB, MBBI, DL,
186*06c3fb27SDimitry Andric           MCCFIInstruction::cfiDefCfaOffset(nullptr, StackSize - stackGrowth),
187*06c3fb27SDimitry Andric           MachineInstr::FrameSetup);
1880b57cec5SDimitry Andric     }
1890b57cec5SDimitry Andric   }
1900b57cec5SDimitry Andric 
191*06c3fb27SDimitry Andric   emitCalleeSavedFrameMoves(MBB, MBBI, DL, true);
192*06c3fb27SDimitry Andric }
193*06c3fb27SDimitry Andric 
1940b57cec5SDimitry Andric void MSP430FrameLowering::emitEpilogue(MachineFunction &MF,
1950b57cec5SDimitry Andric                                        MachineBasicBlock &MBB) const {
1960b57cec5SDimitry Andric   const MachineFrameInfo &MFI = MF.getFrameInfo();
1970b57cec5SDimitry Andric   MSP430MachineFunctionInfo *MSP430FI = MF.getInfo<MSP430MachineFunctionInfo>();
1980b57cec5SDimitry Andric   const MSP430InstrInfo &TII =
1990b57cec5SDimitry Andric       *static_cast<const MSP430InstrInfo *>(MF.getSubtarget().getInstrInfo());
2000b57cec5SDimitry Andric 
2010b57cec5SDimitry Andric   MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr();
2020b57cec5SDimitry Andric   unsigned RetOpcode = MBBI->getOpcode();
2030b57cec5SDimitry Andric   DebugLoc DL = MBBI->getDebugLoc();
2040b57cec5SDimitry Andric 
2050b57cec5SDimitry Andric   switch (RetOpcode) {
2060b57cec5SDimitry Andric   case MSP430::RET:
2070b57cec5SDimitry Andric   case MSP430::RETI: break;  // These are ok
2080b57cec5SDimitry Andric   default:
2090b57cec5SDimitry Andric     llvm_unreachable("Can only insert epilog into returning blocks");
2100b57cec5SDimitry Andric   }
2110b57cec5SDimitry Andric 
2120b57cec5SDimitry Andric   // Get the number of bytes to allocate from the FrameInfo
2130b57cec5SDimitry Andric   uint64_t StackSize = MFI.getStackSize();
2140b57cec5SDimitry Andric   unsigned CSSize = MSP430FI->getCalleeSavedFrameSize();
2150b57cec5SDimitry Andric   uint64_t NumBytes = 0;
2160b57cec5SDimitry Andric 
217*06c3fb27SDimitry Andric   MachineBasicBlock::iterator AfterPop = MBBI;
2180b57cec5SDimitry Andric   if (hasFP(MF)) {
2190b57cec5SDimitry Andric     // Calculate required stack adjustment
2200b57cec5SDimitry Andric     uint64_t FrameSize = StackSize - 2;
2210b57cec5SDimitry Andric     NumBytes = FrameSize - CSSize;
2220b57cec5SDimitry Andric 
2230b57cec5SDimitry Andric     // pop FP.
224*06c3fb27SDimitry Andric     BuildMI(MBB, MBBI, DL, TII.get(MSP430::POP16r), MSP430::R4)
225*06c3fb27SDimitry Andric         .setMIFlag(MachineInstr::FrameDestroy);
226*06c3fb27SDimitry Andric     unsigned DwarfStackPtr = TRI->getDwarfRegNum(MSP430::SP, true);
227*06c3fb27SDimitry Andric     BuildCFI(MBB, MBBI, DL,
228*06c3fb27SDimitry Andric              MCCFIInstruction::cfiDefCfa(nullptr, DwarfStackPtr, 2),
229*06c3fb27SDimitry Andric              MachineInstr::FrameDestroy);
230*06c3fb27SDimitry Andric     --MBBI;
231*06c3fb27SDimitry Andric     if (!MBB.succ_empty() && !MBB.isReturnBlock()) {
232*06c3fb27SDimitry Andric       unsigned DwarfFramePtr = TRI->getDwarfRegNum(MSP430::R4, true);
233*06c3fb27SDimitry Andric       BuildCFI(MBB, AfterPop, DL,
234*06c3fb27SDimitry Andric                MCCFIInstruction::createRestore(nullptr, DwarfFramePtr),
235*06c3fb27SDimitry Andric                MachineInstr::FrameDestroy);
236*06c3fb27SDimitry Andric       --MBBI;
237*06c3fb27SDimitry Andric       --AfterPop;
238*06c3fb27SDimitry Andric     }
2390b57cec5SDimitry Andric   } else
2400b57cec5SDimitry Andric     NumBytes = StackSize - CSSize;
2410b57cec5SDimitry Andric 
2420b57cec5SDimitry Andric   // Skip the callee-saved pop instructions.
243*06c3fb27SDimitry Andric   MachineBasicBlock::iterator FirstCSPop = MBBI;
2440b57cec5SDimitry Andric   while (MBBI != MBB.begin()) {
2450b57cec5SDimitry Andric     MachineBasicBlock::iterator PI = std::prev(MBBI);
2460b57cec5SDimitry Andric     unsigned Opc = PI->getOpcode();
247*06c3fb27SDimitry Andric     if ((Opc != MSP430::POP16r || !PI->getFlag(MachineInstr::FrameDestroy)) &&
248*06c3fb27SDimitry Andric         !PI->isTerminator())
2490b57cec5SDimitry Andric       break;
250*06c3fb27SDimitry Andric     FirstCSPop = PI;
2510b57cec5SDimitry Andric     --MBBI;
2520b57cec5SDimitry Andric   }
253*06c3fb27SDimitry Andric   MBBI = FirstCSPop;
2540b57cec5SDimitry Andric 
2550b57cec5SDimitry Andric   DL = MBBI->getDebugLoc();
2560b57cec5SDimitry Andric 
2570b57cec5SDimitry Andric   // If there is an ADD16ri or SUB16ri of SP immediately before this
2580b57cec5SDimitry Andric   // instruction, merge the two instructions.
2590b57cec5SDimitry Andric   //if (NumBytes || MFI.hasVarSizedObjects())
2600b57cec5SDimitry Andric   //  mergeSPUpdatesUp(MBB, MBBI, StackPtr, &NumBytes);
2610b57cec5SDimitry Andric 
2620b57cec5SDimitry Andric   if (MFI.hasVarSizedObjects()) {
263*06c3fb27SDimitry Andric     BuildMI(MBB, MBBI, DL, TII.get(MSP430::MOV16rr), MSP430::SP)
264*06c3fb27SDimitry Andric         .addReg(MSP430::R4)
265*06c3fb27SDimitry Andric         .setMIFlag(MachineInstr::FrameDestroy);
2660b57cec5SDimitry Andric     if (CSSize) {
2670b57cec5SDimitry Andric       MachineInstr *MI =
268*06c3fb27SDimitry Andric           BuildMI(MBB, MBBI, DL, TII.get(MSP430::SUB16ri), MSP430::SP)
269*06c3fb27SDimitry Andric               .addReg(MSP430::SP)
270*06c3fb27SDimitry Andric               .addImm(CSSize)
271*06c3fb27SDimitry Andric               .setMIFlag(MachineInstr::FrameDestroy);
2720b57cec5SDimitry Andric       // The SRW implicit def is dead.
2730b57cec5SDimitry Andric       MI->getOperand(3).setIsDead();
2740b57cec5SDimitry Andric     }
2750b57cec5SDimitry Andric   } else {
2760b57cec5SDimitry Andric     // adjust stack pointer back: SP += numbytes
2770b57cec5SDimitry Andric     if (NumBytes) {
2780b57cec5SDimitry Andric       MachineInstr *MI =
2790b57cec5SDimitry Andric           BuildMI(MBB, MBBI, DL, TII.get(MSP430::ADD16ri), MSP430::SP)
280*06c3fb27SDimitry Andric               .addReg(MSP430::SP)
281*06c3fb27SDimitry Andric               .addImm(NumBytes)
282*06c3fb27SDimitry Andric               .setMIFlag(MachineInstr::FrameDestroy);
2830b57cec5SDimitry Andric       // The SRW implicit def is dead.
2840b57cec5SDimitry Andric       MI->getOperand(3).setIsDead();
285*06c3fb27SDimitry Andric 
286*06c3fb27SDimitry Andric       if (!hasFP(MF)) {
287*06c3fb27SDimitry Andric         // Adjust CFA value if it was defined by SP
288*06c3fb27SDimitry Andric         BuildCFI(MBB, MBBI, DL,
289*06c3fb27SDimitry Andric                  MCCFIInstruction::cfiDefCfaOffset(nullptr, CSSize + 2),
290*06c3fb27SDimitry Andric                  MachineInstr::FrameDestroy);
2910b57cec5SDimitry Andric       }
2920b57cec5SDimitry Andric     }
2930b57cec5SDimitry Andric   }
2940b57cec5SDimitry Andric 
295*06c3fb27SDimitry Andric   if (!hasFP(MF)) {
296*06c3fb27SDimitry Andric     MBBI = FirstCSPop;
297*06c3fb27SDimitry Andric     int64_t Offset = -CSSize - 2;
298*06c3fb27SDimitry Andric     // Mark callee-saved pop instruction.
299*06c3fb27SDimitry Andric     // Define the current CFA rule to use the provided offset.
300*06c3fb27SDimitry Andric     while (MBBI != MBB.end()) {
301*06c3fb27SDimitry Andric       MachineBasicBlock::iterator PI = MBBI;
302*06c3fb27SDimitry Andric       unsigned Opc = PI->getOpcode();
303*06c3fb27SDimitry Andric       ++MBBI;
304*06c3fb27SDimitry Andric       if (Opc == MSP430::POP16r) {
305*06c3fb27SDimitry Andric         Offset += 2;
306*06c3fb27SDimitry Andric         BuildCFI(MBB, MBBI, DL,
307*06c3fb27SDimitry Andric                  MCCFIInstruction::cfiDefCfaOffset(nullptr, -Offset),
308*06c3fb27SDimitry Andric                  MachineInstr::FrameDestroy);
309*06c3fb27SDimitry Andric       }
310*06c3fb27SDimitry Andric     }
311*06c3fb27SDimitry Andric   }
312*06c3fb27SDimitry Andric   emitCalleeSavedFrameMoves(MBB, AfterPop, DL, false);
313*06c3fb27SDimitry Andric }
314*06c3fb27SDimitry Andric 
3150b57cec5SDimitry Andric // FIXME: Can we eleminate these in favour of generic code?
3165ffd83dbSDimitry Andric bool MSP430FrameLowering::spillCalleeSavedRegisters(
3175ffd83dbSDimitry Andric     MachineBasicBlock &MBB, MachineBasicBlock::iterator MI,
3185ffd83dbSDimitry Andric     ArrayRef<CalleeSavedInfo> CSI, const TargetRegisterInfo *TRI) const {
3190b57cec5SDimitry Andric   if (CSI.empty())
3200b57cec5SDimitry Andric     return false;
3210b57cec5SDimitry Andric 
3220b57cec5SDimitry Andric   DebugLoc DL;
3230b57cec5SDimitry Andric   if (MI != MBB.end()) DL = MI->getDebugLoc();
3240b57cec5SDimitry Andric 
3250b57cec5SDimitry Andric   MachineFunction &MF = *MBB.getParent();
3260b57cec5SDimitry Andric   const TargetInstrInfo &TII = *MF.getSubtarget().getInstrInfo();
3270b57cec5SDimitry Andric   MSP430MachineFunctionInfo *MFI = MF.getInfo<MSP430MachineFunctionInfo>();
3280b57cec5SDimitry Andric   MFI->setCalleeSavedFrameSize(CSI.size() * 2);
3290b57cec5SDimitry Andric 
330*06c3fb27SDimitry Andric   for (const CalleeSavedInfo &I : CSI) {
33104eeddc0SDimitry Andric     Register Reg = I.getReg();
3320b57cec5SDimitry Andric     // Add the callee-saved register as live-in. It's killed at the spill.
3330b57cec5SDimitry Andric     MBB.addLiveIn(Reg);
3340b57cec5SDimitry Andric     BuildMI(MBB, MI, DL, TII.get(MSP430::PUSH16r))
335*06c3fb27SDimitry Andric         .addReg(Reg, RegState::Kill)
336*06c3fb27SDimitry Andric         .setMIFlag(MachineInstr::FrameSetup);
3370b57cec5SDimitry Andric   }
3380b57cec5SDimitry Andric   return true;
3390b57cec5SDimitry Andric }
3400b57cec5SDimitry Andric 
3415ffd83dbSDimitry Andric bool MSP430FrameLowering::restoreCalleeSavedRegisters(
3425ffd83dbSDimitry Andric     MachineBasicBlock &MBB, MachineBasicBlock::iterator MI,
3435ffd83dbSDimitry Andric     MutableArrayRef<CalleeSavedInfo> CSI, const TargetRegisterInfo *TRI) const {
3440b57cec5SDimitry Andric   if (CSI.empty())
3450b57cec5SDimitry Andric     return false;
3460b57cec5SDimitry Andric 
3470b57cec5SDimitry Andric   DebugLoc DL;
3480b57cec5SDimitry Andric   if (MI != MBB.end()) DL = MI->getDebugLoc();
3490b57cec5SDimitry Andric 
3500b57cec5SDimitry Andric   MachineFunction &MF = *MBB.getParent();
3510b57cec5SDimitry Andric   const TargetInstrInfo &TII = *MF.getSubtarget().getInstrInfo();
3520b57cec5SDimitry Andric 
353*06c3fb27SDimitry Andric   for (const CalleeSavedInfo &I : llvm::reverse(CSI))
354*06c3fb27SDimitry Andric     BuildMI(MBB, MI, DL, TII.get(MSP430::POP16r), I.getReg())
355*06c3fb27SDimitry Andric         .setMIFlag(MachineInstr::FrameDestroy);
3560b57cec5SDimitry Andric 
3570b57cec5SDimitry Andric   return true;
3580b57cec5SDimitry Andric }
3590b57cec5SDimitry Andric 
3600b57cec5SDimitry Andric MachineBasicBlock::iterator MSP430FrameLowering::eliminateCallFramePseudoInstr(
3610b57cec5SDimitry Andric     MachineFunction &MF, MachineBasicBlock &MBB,
3620b57cec5SDimitry Andric     MachineBasicBlock::iterator I) const {
3630b57cec5SDimitry Andric   const MSP430InstrInfo &TII =
3640b57cec5SDimitry Andric       *static_cast<const MSP430InstrInfo *>(MF.getSubtarget().getInstrInfo());
3650b57cec5SDimitry Andric   if (!hasReservedCallFrame(MF)) {
3660b57cec5SDimitry Andric     // If the stack pointer can be changed after prologue, turn the
3670b57cec5SDimitry Andric     // adjcallstackup instruction into a 'sub SP, <amt>' and the
3680b57cec5SDimitry Andric     // adjcallstackdown instruction into 'add SP, <amt>'
3690b57cec5SDimitry Andric     // TODO: consider using push / pop instead of sub + store / add
3700b57cec5SDimitry Andric     MachineInstr &Old = *I;
3710b57cec5SDimitry Andric     uint64_t Amount = TII.getFrameSize(Old);
3720b57cec5SDimitry Andric     if (Amount != 0) {
3730b57cec5SDimitry Andric       // We need to keep the stack aligned properly.  To do this, we round the
3740b57cec5SDimitry Andric       // amount of space needed for the outgoing arguments up to the next
3750b57cec5SDimitry Andric       // alignment boundary.
3765ffd83dbSDimitry Andric       Amount = alignTo(Amount, getStackAlign());
3770b57cec5SDimitry Andric 
3780b57cec5SDimitry Andric       MachineInstr *New = nullptr;
3790b57cec5SDimitry Andric       if (Old.getOpcode() == TII.getCallFrameSetupOpcode()) {
3800b57cec5SDimitry Andric         New =
3810b57cec5SDimitry Andric             BuildMI(MF, Old.getDebugLoc(), TII.get(MSP430::SUB16ri), MSP430::SP)
3820b57cec5SDimitry Andric                 .addReg(MSP430::SP)
3830b57cec5SDimitry Andric                 .addImm(Amount);
3840b57cec5SDimitry Andric       } else {
3850b57cec5SDimitry Andric         assert(Old.getOpcode() == TII.getCallFrameDestroyOpcode());
3860b57cec5SDimitry Andric         // factor out the amount the callee already popped.
3870b57cec5SDimitry Andric         Amount -= TII.getFramePoppedByCallee(Old);
3880b57cec5SDimitry Andric         if (Amount)
3890b57cec5SDimitry Andric           New = BuildMI(MF, Old.getDebugLoc(), TII.get(MSP430::ADD16ri),
3900b57cec5SDimitry Andric                         MSP430::SP)
3910b57cec5SDimitry Andric                     .addReg(MSP430::SP)
3920b57cec5SDimitry Andric                     .addImm(Amount);
3930b57cec5SDimitry Andric       }
3940b57cec5SDimitry Andric 
3950b57cec5SDimitry Andric       if (New) {
3960b57cec5SDimitry Andric         // The SRW implicit def is dead.
3970b57cec5SDimitry Andric         New->getOperand(3).setIsDead();
3980b57cec5SDimitry Andric 
3990b57cec5SDimitry Andric         // Replace the pseudo instruction with a new instruction...
4000b57cec5SDimitry Andric         MBB.insert(I, New);
4010b57cec5SDimitry Andric       }
4020b57cec5SDimitry Andric     }
4030b57cec5SDimitry Andric   } else if (I->getOpcode() == TII.getCallFrameDestroyOpcode()) {
4040b57cec5SDimitry Andric     // If we are performing frame pointer elimination and if the callee pops
4050b57cec5SDimitry Andric     // something off the stack pointer, add it back.
4060b57cec5SDimitry Andric     if (uint64_t CalleeAmt = TII.getFramePoppedByCallee(*I)) {
4070b57cec5SDimitry Andric       MachineInstr &Old = *I;
4080b57cec5SDimitry Andric       MachineInstr *New =
4090b57cec5SDimitry Andric           BuildMI(MF, Old.getDebugLoc(), TII.get(MSP430::SUB16ri), MSP430::SP)
4100b57cec5SDimitry Andric               .addReg(MSP430::SP)
4110b57cec5SDimitry Andric               .addImm(CalleeAmt);
412*06c3fb27SDimitry Andric       if (!hasFP(MF)) {
413*06c3fb27SDimitry Andric         DebugLoc DL = I->getDebugLoc();
414*06c3fb27SDimitry Andric         BuildCFI(MBB, I, DL,
415*06c3fb27SDimitry Andric                  MCCFIInstruction::createAdjustCfaOffset(nullptr, CalleeAmt));
416*06c3fb27SDimitry Andric       }
4170b57cec5SDimitry Andric       // The SRW implicit def is dead.
4180b57cec5SDimitry Andric       New->getOperand(3).setIsDead();
4190b57cec5SDimitry Andric 
4200b57cec5SDimitry Andric       MBB.insert(I, New);
4210b57cec5SDimitry Andric     }
4220b57cec5SDimitry Andric   }
4230b57cec5SDimitry Andric 
4240b57cec5SDimitry Andric   return MBB.erase(I);
4250b57cec5SDimitry Andric }
4260b57cec5SDimitry Andric 
4270b57cec5SDimitry Andric void
4280b57cec5SDimitry Andric MSP430FrameLowering::processFunctionBeforeFrameFinalized(MachineFunction &MF,
4290b57cec5SDimitry Andric                                                          RegScavenger *) const {
4300b57cec5SDimitry Andric   // Create a frame entry for the FP register that must be saved.
4310b57cec5SDimitry Andric   if (hasFP(MF)) {
4320b57cec5SDimitry Andric     int FrameIdx = MF.getFrameInfo().CreateFixedObject(2, -4, true);
4330b57cec5SDimitry Andric     (void)FrameIdx;
4340b57cec5SDimitry Andric     assert(FrameIdx == MF.getFrameInfo().getObjectIndexBegin() &&
4350b57cec5SDimitry Andric            "Slot for FP register must be last in order to be found!");
4360b57cec5SDimitry Andric   }
4370b57cec5SDimitry Andric }
438