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
MSP430FrameLowering(const MSP430Subtarget & STI)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
hasFP(const MachineFunction & MF) const330b57cec5SDimitry 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
hasReservedCallFrame(const MachineFunction & MF) const410b57cec5SDimitry Andric bool MSP430FrameLowering::hasReservedCallFrame(const MachineFunction &MF) const {
420b57cec5SDimitry Andric return !MF.getFrameInfo().hasVarSizedObjects();
430b57cec5SDimitry Andric }
440b57cec5SDimitry Andric
BuildCFI(MachineBasicBlock & MBB,MachineBasicBlock::iterator MBBI,const DebugLoc & DL,const MCCFIInstruction & CFIInst,MachineInstr::MIFlag Flag) const4506c3fb27SDimitry 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
emitCalleeSavedFrameMoves(MachineBasicBlock & MBB,MachineBasicBlock::iterator MBBI,const DebugLoc & DL,bool IsPrologue) const5706c3fb27SDimitry 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
emitPrologue(MachineFunction & MF,MachineBasicBlock & MBB) const830b57cec5SDimitry 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
emitEpilogue(MachineFunction & MF,MachineBasicBlock & MBB) const1930b57cec5SDimitry 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?
spillCalleeSavedRegisters(MachineBasicBlock & MBB,MachineBasicBlock::iterator MI,ArrayRef<CalleeSavedInfo> CSI,const TargetRegisterInfo * TRI) const3155ffd83dbSDimitry 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
restoreCalleeSavedRegisters(MachineBasicBlock & MBB,MachineBasicBlock::iterator MI,MutableArrayRef<CalleeSavedInfo> CSI,const TargetRegisterInfo * TRI) const3405ffd83dbSDimitry 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
eliminateCallFramePseudoInstr(MachineFunction & MF,MachineBasicBlock & MBB,MachineBasicBlock::iterator I) const3590b57cec5SDimitry 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
processFunctionBeforeFrameFinalized(MachineFunction & MF,RegScavenger *) const4270b57cec5SDimitry 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