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