xref: /freebsd-src/contrib/llvm-project/llvm/lib/Target/MSP430/MSP430FrameLowering.cpp (revision 36b606ae6aa4b24061096ba18582e0a08ccd5dba)
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 
2806c3fb27SDimitry Andric MSP430FrameLowering::MSP430FrameLowering(const MSP430Subtarget &STI)
2906c3fb27SDimitry Andric     : TargetFrameLowering(TargetFrameLowering::StackGrowsDown, Align(2), -2,
3006c3fb27SDimitry Andric                           Align(2)),
3106c3fb27SDimitry Andric       STI(STI), TII(*STI.getInstrInfo()), TRI(STI.getRegisterInfo()) {}
3206c3fb27SDimitry 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 
4506c3fb27SDimitry Andric void MSP430FrameLowering::BuildCFI(MachineBasicBlock &MBB,
4606c3fb27SDimitry Andric                                    MachineBasicBlock::iterator MBBI,
4706c3fb27SDimitry Andric                                    const DebugLoc &DL,
4806c3fb27SDimitry Andric                                    const MCCFIInstruction &CFIInst,
4906c3fb27SDimitry Andric                                    MachineInstr::MIFlag Flag) const {
5006c3fb27SDimitry Andric   MachineFunction &MF = *MBB.getParent();
5106c3fb27SDimitry Andric   unsigned CFIIndex = MF.addFrameInst(CFIInst);
5206c3fb27SDimitry Andric   BuildMI(MBB, MBBI, DL, TII.get(TargetOpcode::CFI_INSTRUCTION))
5306c3fb27SDimitry Andric       .addCFIIndex(CFIIndex)
5406c3fb27SDimitry Andric       .setMIFlag(Flag);
5506c3fb27SDimitry Andric }
5606c3fb27SDimitry Andric 
5706c3fb27SDimitry Andric void MSP430FrameLowering::emitCalleeSavedFrameMoves(
5806c3fb27SDimitry Andric     MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
5906c3fb27SDimitry Andric     const DebugLoc &DL, bool IsPrologue) const {
6006c3fb27SDimitry Andric   MachineFunction &MF = *MBB.getParent();
6106c3fb27SDimitry Andric   MachineFrameInfo &MFI = MF.getFrameInfo();
620fca6ea1SDimitry Andric   const MCRegisterInfo *MRI = MF.getContext().getRegisterInfo();
6306c3fb27SDimitry Andric 
6406c3fb27SDimitry Andric   // Add callee saved registers to move list.
6506c3fb27SDimitry Andric   const std::vector<CalleeSavedInfo> &CSI = MFI.getCalleeSavedInfo();
6606c3fb27SDimitry Andric 
6706c3fb27SDimitry Andric   // Calculate offsets.
6806c3fb27SDimitry Andric   for (const CalleeSavedInfo &I : CSI) {
6906c3fb27SDimitry Andric     int64_t Offset = MFI.getObjectOffset(I.getFrameIdx());
7006c3fb27SDimitry Andric     Register Reg = I.getReg();
7106c3fb27SDimitry Andric     unsigned DwarfReg = MRI->getDwarfRegNum(Reg, true);
7206c3fb27SDimitry Andric 
7306c3fb27SDimitry Andric     if (IsPrologue) {
7406c3fb27SDimitry Andric       BuildCFI(MBB, MBBI, DL,
7506c3fb27SDimitry Andric                MCCFIInstruction::createOffset(nullptr, DwarfReg, Offset));
7606c3fb27SDimitry Andric     } else {
7706c3fb27SDimitry Andric       BuildCFI(MBB, MBBI, DL,
7806c3fb27SDimitry Andric                MCCFIInstruction::createRestore(nullptr, DwarfReg));
7906c3fb27SDimitry Andric     }
8006c3fb27SDimitry Andric   }
8106c3fb27SDimitry Andric }
8206c3fb27SDimitry Andric 
830b57cec5SDimitry Andric void MSP430FrameLowering::emitPrologue(MachineFunction &MF,
840b57cec5SDimitry Andric                                        MachineBasicBlock &MBB) const {
850b57cec5SDimitry Andric   assert(&MF.front() == &MBB && "Shrink-wrapping not yet supported");
860b57cec5SDimitry Andric   MachineFrameInfo &MFI = MF.getFrameInfo();
870b57cec5SDimitry Andric   MSP430MachineFunctionInfo *MSP430FI = MF.getInfo<MSP430MachineFunctionInfo>();
880b57cec5SDimitry Andric   const MSP430InstrInfo &TII =
890b57cec5SDimitry Andric       *static_cast<const MSP430InstrInfo *>(MF.getSubtarget().getInstrInfo());
900b57cec5SDimitry Andric 
910b57cec5SDimitry Andric   MachineBasicBlock::iterator MBBI = MBB.begin();
920b57cec5SDimitry Andric   DebugLoc DL = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc();
930b57cec5SDimitry Andric 
940b57cec5SDimitry Andric   // Get the number of bytes to allocate from the FrameInfo.
950b57cec5SDimitry Andric   uint64_t StackSize = MFI.getStackSize();
9606c3fb27SDimitry Andric   int stackGrowth = -2;
970b57cec5SDimitry Andric 
980b57cec5SDimitry Andric   uint64_t NumBytes = 0;
990b57cec5SDimitry Andric   if (hasFP(MF)) {
1000b57cec5SDimitry Andric     // Calculate required stack adjustment
1010b57cec5SDimitry Andric     uint64_t FrameSize = StackSize - 2;
1020b57cec5SDimitry Andric     NumBytes = FrameSize - MSP430FI->getCalleeSavedFrameSize();
1030b57cec5SDimitry Andric 
1040b57cec5SDimitry Andric     // Get the offset of the stack slot for the EBP register... which is
1050b57cec5SDimitry Andric     // guaranteed to be the last slot by processFunctionBeforeFrameFinalized.
1060b57cec5SDimitry Andric     // Update the frame offset adjustment.
1070b57cec5SDimitry Andric     MFI.setOffsetAdjustment(-NumBytes);
1080b57cec5SDimitry Andric 
1090b57cec5SDimitry Andric     // Save FP into the appropriate stack slot...
1100b57cec5SDimitry Andric     BuildMI(MBB, MBBI, DL, TII.get(MSP430::PUSH16r))
11106c3fb27SDimitry Andric         .addReg(MSP430::R4, RegState::Kill)
11206c3fb27SDimitry Andric         .setMIFlag(MachineInstr::FrameSetup);
11306c3fb27SDimitry Andric 
11406c3fb27SDimitry Andric     // Mark the place where FP was saved.
11506c3fb27SDimitry Andric     // Define the current CFA rule to use the provided offset.
11606c3fb27SDimitry Andric     BuildCFI(MBB, MBBI, DL,
11706c3fb27SDimitry Andric              MCCFIInstruction::cfiDefCfaOffset(nullptr, -2 * stackGrowth),
11806c3fb27SDimitry Andric              MachineInstr::FrameSetup);
11906c3fb27SDimitry Andric 
12006c3fb27SDimitry Andric     // Change the rule for the FramePtr to be an "offset" rule.
12106c3fb27SDimitry Andric     unsigned DwarfFramePtr = TRI->getDwarfRegNum(MSP430::R4, true);
12206c3fb27SDimitry Andric     BuildCFI(
12306c3fb27SDimitry Andric         MBB, MBBI, DL,
12406c3fb27SDimitry Andric         MCCFIInstruction::createOffset(nullptr, DwarfFramePtr, 2 * stackGrowth),
12506c3fb27SDimitry Andric         MachineInstr::FrameSetup);
1260b57cec5SDimitry Andric 
1270b57cec5SDimitry Andric     // Update FP with the new base value...
1285ffd83dbSDimitry Andric     BuildMI(MBB, MBBI, DL, TII.get(MSP430::MOV16rr), MSP430::R4)
12906c3fb27SDimitry Andric         .addReg(MSP430::SP)
13006c3fb27SDimitry Andric         .setMIFlag(MachineInstr::FrameSetup);
13106c3fb27SDimitry Andric 
13206c3fb27SDimitry Andric     // Mark effective beginning of when frame pointer becomes valid.
13306c3fb27SDimitry Andric     // Define the current CFA to use the FP register.
13406c3fb27SDimitry Andric     BuildCFI(MBB, MBBI, DL,
13506c3fb27SDimitry Andric              MCCFIInstruction::createDefCfaRegister(nullptr, DwarfFramePtr),
13606c3fb27SDimitry Andric              MachineInstr::FrameSetup);
1370b57cec5SDimitry Andric 
1380b57cec5SDimitry Andric     // Mark the FramePtr as live-in in every block except the entry.
139349cc55cSDimitry Andric     for (MachineBasicBlock &MBBJ : llvm::drop_begin(MF))
140349cc55cSDimitry Andric       MBBJ.addLiveIn(MSP430::R4);
1410b57cec5SDimitry Andric   } else
1420b57cec5SDimitry Andric     NumBytes = StackSize - MSP430FI->getCalleeSavedFrameSize();
1430b57cec5SDimitry Andric 
1440b57cec5SDimitry Andric   // Skip the callee-saved push instructions.
14506c3fb27SDimitry Andric   int StackOffset = 2 * stackGrowth;
14606c3fb27SDimitry Andric   while (MBBI != MBB.end() && MBBI->getFlag(MachineInstr::FrameSetup) &&
14706c3fb27SDimitry Andric          (MBBI->getOpcode() == MSP430::PUSH16r)) {
1480b57cec5SDimitry Andric     ++MBBI;
1490b57cec5SDimitry Andric 
15006c3fb27SDimitry Andric     if (!hasFP(MF)) {
15106c3fb27SDimitry Andric       // Mark callee-saved push instruction.
15206c3fb27SDimitry Andric       // Define the current CFA rule to use the provided offset.
15306c3fb27SDimitry Andric       assert(StackSize && "Expected stack frame");
15406c3fb27SDimitry Andric       BuildCFI(MBB, MBBI, DL,
15506c3fb27SDimitry Andric                MCCFIInstruction::cfiDefCfaOffset(nullptr, -StackOffset),
15606c3fb27SDimitry Andric                MachineInstr::FrameSetup);
15706c3fb27SDimitry Andric       StackOffset += stackGrowth;
15806c3fb27SDimitry Andric     }
15906c3fb27SDimitry Andric   }
16006c3fb27SDimitry Andric 
1610b57cec5SDimitry Andric   if (MBBI != MBB.end())
1620b57cec5SDimitry Andric     DL = MBBI->getDebugLoc();
1630b57cec5SDimitry Andric 
1640b57cec5SDimitry Andric   if (NumBytes) { // adjust stack pointer: SP -= numbytes
1650b57cec5SDimitry Andric     // If there is an SUB16ri of SP immediately before this instruction, merge
1660b57cec5SDimitry Andric     // the two.
1670b57cec5SDimitry Andric     //NumBytes -= mergeSPUpdates(MBB, MBBI, true);
1680b57cec5SDimitry Andric     // If there is an ADD16ri or SUB16ri of SP immediately after this
1690b57cec5SDimitry Andric     // instruction, merge the two instructions.
1700b57cec5SDimitry Andric     // mergeSPUpdatesDown(MBB, MBBI, &NumBytes);
1710b57cec5SDimitry Andric 
1720b57cec5SDimitry Andric     if (NumBytes) {
1730b57cec5SDimitry Andric       MachineInstr *MI =
1740b57cec5SDimitry Andric           BuildMI(MBB, MBBI, DL, TII.get(MSP430::SUB16ri), MSP430::SP)
17506c3fb27SDimitry Andric               .addReg(MSP430::SP)
17606c3fb27SDimitry Andric               .addImm(NumBytes)
17706c3fb27SDimitry Andric               .setMIFlag(MachineInstr::FrameSetup);
1780b57cec5SDimitry Andric       // The SRW implicit def is dead.
1790b57cec5SDimitry Andric       MI->getOperand(3).setIsDead();
1800b57cec5SDimitry Andric     }
18106c3fb27SDimitry Andric     if (!hasFP(MF)) {
18206c3fb27SDimitry Andric       // Adjust the previous CFA value if CFA was not redefined by FP
18306c3fb27SDimitry Andric       BuildCFI(
18406c3fb27SDimitry Andric           MBB, MBBI, DL,
18506c3fb27SDimitry Andric           MCCFIInstruction::cfiDefCfaOffset(nullptr, StackSize - stackGrowth),
18606c3fb27SDimitry Andric           MachineInstr::FrameSetup);
1870b57cec5SDimitry Andric     }
1880b57cec5SDimitry Andric   }
1890b57cec5SDimitry Andric 
19006c3fb27SDimitry Andric   emitCalleeSavedFrameMoves(MBB, MBBI, DL, true);
19106c3fb27SDimitry Andric }
19206c3fb27SDimitry Andric 
1930b57cec5SDimitry Andric void MSP430FrameLowering::emitEpilogue(MachineFunction &MF,
1940b57cec5SDimitry Andric                                        MachineBasicBlock &MBB) const {
1950b57cec5SDimitry Andric   const MachineFrameInfo &MFI = MF.getFrameInfo();
1960b57cec5SDimitry Andric   MSP430MachineFunctionInfo *MSP430FI = MF.getInfo<MSP430MachineFunctionInfo>();
1970b57cec5SDimitry Andric   const MSP430InstrInfo &TII =
1980b57cec5SDimitry Andric       *static_cast<const MSP430InstrInfo *>(MF.getSubtarget().getInstrInfo());
1990b57cec5SDimitry Andric 
2000b57cec5SDimitry Andric   MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr();
2010b57cec5SDimitry Andric   unsigned RetOpcode = MBBI->getOpcode();
2020b57cec5SDimitry Andric   DebugLoc DL = MBBI->getDebugLoc();
2030b57cec5SDimitry Andric 
2040b57cec5SDimitry Andric   switch (RetOpcode) {
2050b57cec5SDimitry Andric   case MSP430::RET:
2060b57cec5SDimitry Andric   case MSP430::RETI: break;  // These are ok
2070b57cec5SDimitry Andric   default:
2080b57cec5SDimitry Andric     llvm_unreachable("Can only insert epilog into returning blocks");
2090b57cec5SDimitry Andric   }
2100b57cec5SDimitry Andric 
2110b57cec5SDimitry Andric   // Get the number of bytes to allocate from the FrameInfo
2120b57cec5SDimitry Andric   uint64_t StackSize = MFI.getStackSize();
2130b57cec5SDimitry Andric   unsigned CSSize = MSP430FI->getCalleeSavedFrameSize();
2140b57cec5SDimitry Andric   uint64_t NumBytes = 0;
2150b57cec5SDimitry Andric 
21606c3fb27SDimitry Andric   MachineBasicBlock::iterator AfterPop = MBBI;
2170b57cec5SDimitry Andric   if (hasFP(MF)) {
2180b57cec5SDimitry Andric     // Calculate required stack adjustment
2190b57cec5SDimitry Andric     uint64_t FrameSize = StackSize - 2;
2200b57cec5SDimitry Andric     NumBytes = FrameSize - CSSize;
2210b57cec5SDimitry Andric 
2220b57cec5SDimitry Andric     // pop FP.
22306c3fb27SDimitry Andric     BuildMI(MBB, MBBI, DL, TII.get(MSP430::POP16r), MSP430::R4)
22406c3fb27SDimitry Andric         .setMIFlag(MachineInstr::FrameDestroy);
22506c3fb27SDimitry Andric     unsigned DwarfStackPtr = TRI->getDwarfRegNum(MSP430::SP, true);
22606c3fb27SDimitry Andric     BuildCFI(MBB, MBBI, DL,
22706c3fb27SDimitry Andric              MCCFIInstruction::cfiDefCfa(nullptr, DwarfStackPtr, 2),
22806c3fb27SDimitry Andric              MachineInstr::FrameDestroy);
22906c3fb27SDimitry Andric     --MBBI;
23006c3fb27SDimitry Andric     if (!MBB.succ_empty() && !MBB.isReturnBlock()) {
23106c3fb27SDimitry Andric       unsigned DwarfFramePtr = TRI->getDwarfRegNum(MSP430::R4, true);
23206c3fb27SDimitry Andric       BuildCFI(MBB, AfterPop, DL,
23306c3fb27SDimitry Andric                MCCFIInstruction::createRestore(nullptr, DwarfFramePtr),
23406c3fb27SDimitry Andric                MachineInstr::FrameDestroy);
23506c3fb27SDimitry Andric       --MBBI;
23606c3fb27SDimitry Andric       --AfterPop;
23706c3fb27SDimitry Andric     }
2380b57cec5SDimitry Andric   } else
2390b57cec5SDimitry Andric     NumBytes = StackSize - CSSize;
2400b57cec5SDimitry Andric 
2410b57cec5SDimitry Andric   // Skip the callee-saved pop instructions.
24206c3fb27SDimitry Andric   MachineBasicBlock::iterator FirstCSPop = MBBI;
2430b57cec5SDimitry Andric   while (MBBI != MBB.begin()) {
2440b57cec5SDimitry Andric     MachineBasicBlock::iterator PI = std::prev(MBBI);
2450b57cec5SDimitry Andric     unsigned Opc = PI->getOpcode();
24606c3fb27SDimitry Andric     if ((Opc != MSP430::POP16r || !PI->getFlag(MachineInstr::FrameDestroy)) &&
24706c3fb27SDimitry Andric         !PI->isTerminator())
2480b57cec5SDimitry Andric       break;
24906c3fb27SDimitry Andric     FirstCSPop = PI;
2500b57cec5SDimitry Andric     --MBBI;
2510b57cec5SDimitry Andric   }
25206c3fb27SDimitry Andric   MBBI = FirstCSPop;
2530b57cec5SDimitry Andric 
2540b57cec5SDimitry Andric   DL = MBBI->getDebugLoc();
2550b57cec5SDimitry Andric 
2560b57cec5SDimitry Andric   // If there is an ADD16ri or SUB16ri of SP immediately before this
2570b57cec5SDimitry Andric   // instruction, merge the two instructions.
2580b57cec5SDimitry Andric   //if (NumBytes || MFI.hasVarSizedObjects())
2590b57cec5SDimitry Andric   //  mergeSPUpdatesUp(MBB, MBBI, StackPtr, &NumBytes);
2600b57cec5SDimitry Andric 
2610b57cec5SDimitry Andric   if (MFI.hasVarSizedObjects()) {
26206c3fb27SDimitry Andric     BuildMI(MBB, MBBI, DL, TII.get(MSP430::MOV16rr), MSP430::SP)
26306c3fb27SDimitry Andric         .addReg(MSP430::R4)
26406c3fb27SDimitry Andric         .setMIFlag(MachineInstr::FrameDestroy);
2650b57cec5SDimitry Andric     if (CSSize) {
2660b57cec5SDimitry Andric       MachineInstr *MI =
26706c3fb27SDimitry Andric           BuildMI(MBB, MBBI, DL, TII.get(MSP430::SUB16ri), MSP430::SP)
26806c3fb27SDimitry Andric               .addReg(MSP430::SP)
26906c3fb27SDimitry Andric               .addImm(CSSize)
27006c3fb27SDimitry Andric               .setMIFlag(MachineInstr::FrameDestroy);
2710b57cec5SDimitry Andric       // The SRW implicit def is dead.
2720b57cec5SDimitry Andric       MI->getOperand(3).setIsDead();
2730b57cec5SDimitry Andric     }
2740b57cec5SDimitry Andric   } else {
2750b57cec5SDimitry Andric     // adjust stack pointer back: SP += numbytes
2760b57cec5SDimitry Andric     if (NumBytes) {
2770b57cec5SDimitry Andric       MachineInstr *MI =
2780b57cec5SDimitry Andric           BuildMI(MBB, MBBI, DL, TII.get(MSP430::ADD16ri), MSP430::SP)
27906c3fb27SDimitry Andric               .addReg(MSP430::SP)
28006c3fb27SDimitry Andric               .addImm(NumBytes)
28106c3fb27SDimitry Andric               .setMIFlag(MachineInstr::FrameDestroy);
2820b57cec5SDimitry Andric       // The SRW implicit def is dead.
2830b57cec5SDimitry Andric       MI->getOperand(3).setIsDead();
28406c3fb27SDimitry Andric 
28506c3fb27SDimitry Andric       if (!hasFP(MF)) {
28606c3fb27SDimitry Andric         // Adjust CFA value if it was defined by SP
28706c3fb27SDimitry Andric         BuildCFI(MBB, MBBI, DL,
28806c3fb27SDimitry Andric                  MCCFIInstruction::cfiDefCfaOffset(nullptr, CSSize + 2),
28906c3fb27SDimitry Andric                  MachineInstr::FrameDestroy);
2900b57cec5SDimitry Andric       }
2910b57cec5SDimitry Andric     }
2920b57cec5SDimitry Andric   }
2930b57cec5SDimitry Andric 
29406c3fb27SDimitry Andric   if (!hasFP(MF)) {
29506c3fb27SDimitry Andric     MBBI = FirstCSPop;
296*36b606aeSDimitry Andric     int64_t Offset = -(int64_t)CSSize - 2;
29706c3fb27SDimitry Andric     // Mark callee-saved pop instruction.
29806c3fb27SDimitry Andric     // Define the current CFA rule to use the provided offset.
29906c3fb27SDimitry Andric     while (MBBI != MBB.end()) {
30006c3fb27SDimitry Andric       MachineBasicBlock::iterator PI = MBBI;
30106c3fb27SDimitry Andric       unsigned Opc = PI->getOpcode();
30206c3fb27SDimitry Andric       ++MBBI;
30306c3fb27SDimitry Andric       if (Opc == MSP430::POP16r) {
30406c3fb27SDimitry Andric         Offset += 2;
30506c3fb27SDimitry Andric         BuildCFI(MBB, MBBI, DL,
30606c3fb27SDimitry Andric                  MCCFIInstruction::cfiDefCfaOffset(nullptr, -Offset),
30706c3fb27SDimitry Andric                  MachineInstr::FrameDestroy);
30806c3fb27SDimitry Andric       }
30906c3fb27SDimitry Andric     }
31006c3fb27SDimitry Andric   }
31106c3fb27SDimitry Andric   emitCalleeSavedFrameMoves(MBB, AfterPop, DL, false);
31206c3fb27SDimitry Andric }
31306c3fb27SDimitry Andric 
3140b57cec5SDimitry Andric // FIXME: Can we eleminate these in favour of generic code?
3155ffd83dbSDimitry Andric bool MSP430FrameLowering::spillCalleeSavedRegisters(
3165ffd83dbSDimitry Andric     MachineBasicBlock &MBB, MachineBasicBlock::iterator MI,
3175ffd83dbSDimitry Andric     ArrayRef<CalleeSavedInfo> CSI, const TargetRegisterInfo *TRI) const {
3180b57cec5SDimitry Andric   if (CSI.empty())
3190b57cec5SDimitry Andric     return false;
3200b57cec5SDimitry Andric 
3210b57cec5SDimitry Andric   DebugLoc DL;
3220b57cec5SDimitry Andric   if (MI != MBB.end()) DL = MI->getDebugLoc();
3230b57cec5SDimitry Andric 
3240b57cec5SDimitry Andric   MachineFunction &MF = *MBB.getParent();
3250b57cec5SDimitry Andric   const TargetInstrInfo &TII = *MF.getSubtarget().getInstrInfo();
3260b57cec5SDimitry Andric   MSP430MachineFunctionInfo *MFI = MF.getInfo<MSP430MachineFunctionInfo>();
3270b57cec5SDimitry Andric   MFI->setCalleeSavedFrameSize(CSI.size() * 2);
3280b57cec5SDimitry Andric 
32906c3fb27SDimitry Andric   for (const CalleeSavedInfo &I : CSI) {
33004eeddc0SDimitry Andric     Register Reg = I.getReg();
3310b57cec5SDimitry Andric     // Add the callee-saved register as live-in. It's killed at the spill.
3320b57cec5SDimitry Andric     MBB.addLiveIn(Reg);
3330b57cec5SDimitry Andric     BuildMI(MBB, MI, DL, TII.get(MSP430::PUSH16r))
33406c3fb27SDimitry Andric         .addReg(Reg, RegState::Kill)
33506c3fb27SDimitry Andric         .setMIFlag(MachineInstr::FrameSetup);
3360b57cec5SDimitry Andric   }
3370b57cec5SDimitry Andric   return true;
3380b57cec5SDimitry Andric }
3390b57cec5SDimitry Andric 
3405ffd83dbSDimitry Andric bool MSP430FrameLowering::restoreCalleeSavedRegisters(
3415ffd83dbSDimitry Andric     MachineBasicBlock &MBB, MachineBasicBlock::iterator MI,
3425ffd83dbSDimitry Andric     MutableArrayRef<CalleeSavedInfo> CSI, const TargetRegisterInfo *TRI) const {
3430b57cec5SDimitry Andric   if (CSI.empty())
3440b57cec5SDimitry Andric     return false;
3450b57cec5SDimitry Andric 
3460b57cec5SDimitry Andric   DebugLoc DL;
3470b57cec5SDimitry Andric   if (MI != MBB.end()) DL = MI->getDebugLoc();
3480b57cec5SDimitry Andric 
3490b57cec5SDimitry Andric   MachineFunction &MF = *MBB.getParent();
3500b57cec5SDimitry Andric   const TargetInstrInfo &TII = *MF.getSubtarget().getInstrInfo();
3510b57cec5SDimitry Andric 
35206c3fb27SDimitry Andric   for (const CalleeSavedInfo &I : llvm::reverse(CSI))
35306c3fb27SDimitry Andric     BuildMI(MBB, MI, DL, TII.get(MSP430::POP16r), I.getReg())
35406c3fb27SDimitry Andric         .setMIFlag(MachineInstr::FrameDestroy);
3550b57cec5SDimitry Andric 
3560b57cec5SDimitry Andric   return true;
3570b57cec5SDimitry Andric }
3580b57cec5SDimitry Andric 
3590b57cec5SDimitry Andric MachineBasicBlock::iterator MSP430FrameLowering::eliminateCallFramePseudoInstr(
3600b57cec5SDimitry Andric     MachineFunction &MF, MachineBasicBlock &MBB,
3610b57cec5SDimitry Andric     MachineBasicBlock::iterator I) const {
3620b57cec5SDimitry Andric   const MSP430InstrInfo &TII =
3630b57cec5SDimitry Andric       *static_cast<const MSP430InstrInfo *>(MF.getSubtarget().getInstrInfo());
3640b57cec5SDimitry Andric   if (!hasReservedCallFrame(MF)) {
3650b57cec5SDimitry Andric     // If the stack pointer can be changed after prologue, turn the
3660b57cec5SDimitry Andric     // adjcallstackup instruction into a 'sub SP, <amt>' and the
3670b57cec5SDimitry Andric     // adjcallstackdown instruction into 'add SP, <amt>'
3680b57cec5SDimitry Andric     // TODO: consider using push / pop instead of sub + store / add
3690b57cec5SDimitry Andric     MachineInstr &Old = *I;
3700b57cec5SDimitry Andric     uint64_t Amount = TII.getFrameSize(Old);
3710b57cec5SDimitry Andric     if (Amount != 0) {
3720b57cec5SDimitry Andric       // We need to keep the stack aligned properly.  To do this, we round the
3730b57cec5SDimitry Andric       // amount of space needed for the outgoing arguments up to the next
3740b57cec5SDimitry Andric       // alignment boundary.
3755ffd83dbSDimitry Andric       Amount = alignTo(Amount, getStackAlign());
3760b57cec5SDimitry Andric 
3770b57cec5SDimitry Andric       MachineInstr *New = nullptr;
3780b57cec5SDimitry Andric       if (Old.getOpcode() == TII.getCallFrameSetupOpcode()) {
3790b57cec5SDimitry Andric         New =
3800b57cec5SDimitry Andric             BuildMI(MF, Old.getDebugLoc(), TII.get(MSP430::SUB16ri), MSP430::SP)
3810b57cec5SDimitry Andric                 .addReg(MSP430::SP)
3820b57cec5SDimitry Andric                 .addImm(Amount);
3830b57cec5SDimitry Andric       } else {
3840b57cec5SDimitry Andric         assert(Old.getOpcode() == TII.getCallFrameDestroyOpcode());
3850b57cec5SDimitry Andric         // factor out the amount the callee already popped.
3860b57cec5SDimitry Andric         Amount -= TII.getFramePoppedByCallee(Old);
3870b57cec5SDimitry Andric         if (Amount)
3880b57cec5SDimitry Andric           New = BuildMI(MF, Old.getDebugLoc(), TII.get(MSP430::ADD16ri),
3890b57cec5SDimitry Andric                         MSP430::SP)
3900b57cec5SDimitry Andric                     .addReg(MSP430::SP)
3910b57cec5SDimitry Andric                     .addImm(Amount);
3920b57cec5SDimitry Andric       }
3930b57cec5SDimitry Andric 
3940b57cec5SDimitry Andric       if (New) {
3950b57cec5SDimitry Andric         // The SRW implicit def is dead.
3960b57cec5SDimitry Andric         New->getOperand(3).setIsDead();
3970b57cec5SDimitry Andric 
3980b57cec5SDimitry Andric         // Replace the pseudo instruction with a new instruction...
3990b57cec5SDimitry Andric         MBB.insert(I, New);
4000b57cec5SDimitry Andric       }
4010b57cec5SDimitry Andric     }
4020b57cec5SDimitry Andric   } else if (I->getOpcode() == TII.getCallFrameDestroyOpcode()) {
4030b57cec5SDimitry Andric     // If we are performing frame pointer elimination and if the callee pops
4040b57cec5SDimitry Andric     // something off the stack pointer, add it back.
4050b57cec5SDimitry Andric     if (uint64_t CalleeAmt = TII.getFramePoppedByCallee(*I)) {
4060b57cec5SDimitry Andric       MachineInstr &Old = *I;
4070b57cec5SDimitry Andric       MachineInstr *New =
4080b57cec5SDimitry Andric           BuildMI(MF, Old.getDebugLoc(), TII.get(MSP430::SUB16ri), MSP430::SP)
4090b57cec5SDimitry Andric               .addReg(MSP430::SP)
4100b57cec5SDimitry Andric               .addImm(CalleeAmt);
41106c3fb27SDimitry Andric       if (!hasFP(MF)) {
41206c3fb27SDimitry Andric         DebugLoc DL = I->getDebugLoc();
41306c3fb27SDimitry Andric         BuildCFI(MBB, I, DL,
41406c3fb27SDimitry Andric                  MCCFIInstruction::createAdjustCfaOffset(nullptr, CalleeAmt));
41506c3fb27SDimitry Andric       }
4160b57cec5SDimitry Andric       // The SRW implicit def is dead.
4170b57cec5SDimitry Andric       New->getOperand(3).setIsDead();
4180b57cec5SDimitry Andric 
4190b57cec5SDimitry Andric       MBB.insert(I, New);
4200b57cec5SDimitry Andric     }
4210b57cec5SDimitry Andric   }
4220b57cec5SDimitry Andric 
4230b57cec5SDimitry Andric   return MBB.erase(I);
4240b57cec5SDimitry Andric }
4250b57cec5SDimitry Andric 
4260b57cec5SDimitry Andric void
4270b57cec5SDimitry Andric MSP430FrameLowering::processFunctionBeforeFrameFinalized(MachineFunction &MF,
4280b57cec5SDimitry Andric                                                          RegScavenger *) const {
4290b57cec5SDimitry Andric   // Create a frame entry for the FP register that must be saved.
4300b57cec5SDimitry Andric   if (hasFP(MF)) {
4310b57cec5SDimitry Andric     int FrameIdx = MF.getFrameInfo().CreateFixedObject(2, -4, true);
4320b57cec5SDimitry Andric     (void)FrameIdx;
4330b57cec5SDimitry Andric     assert(FrameIdx == MF.getFrameInfo().getObjectIndexBegin() &&
4340b57cec5SDimitry Andric            "Slot for FP register must be last in order to be found!");
4350b57cec5SDimitry Andric   }
4360b57cec5SDimitry Andric }
437