Path: blob/main/contrib/llvm-project/llvm/lib/Target/MSP430/MSP430FrameLowering.cpp
35294 views
//===-- MSP430FrameLowering.cpp - MSP430 Frame Information ----------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8// This file contains the MSP430 implementation of TargetFrameLowering class.9//10//===----------------------------------------------------------------------===//1112#include "MSP430FrameLowering.h"13#include "MSP430InstrInfo.h"14#include "MSP430MachineFunctionInfo.h"15#include "MSP430Subtarget.h"16#include "llvm/CodeGen/MachineFrameInfo.h"17#include "llvm/CodeGen/MachineFunction.h"18#include "llvm/CodeGen/MachineInstrBuilder.h"19#include "llvm/CodeGen/MachineModuleInfo.h"20#include "llvm/CodeGen/MachineRegisterInfo.h"21#include "llvm/IR/DataLayout.h"22#include "llvm/IR/Function.h"23#include "llvm/Target/TargetOptions.h"2425using namespace llvm;2627MSP430FrameLowering::MSP430FrameLowering(const MSP430Subtarget &STI)28: TargetFrameLowering(TargetFrameLowering::StackGrowsDown, Align(2), -2,29Align(2)),30STI(STI), TII(*STI.getInstrInfo()), TRI(STI.getRegisterInfo()) {}3132bool MSP430FrameLowering::hasFP(const MachineFunction &MF) const {33const MachineFrameInfo &MFI = MF.getFrameInfo();3435return (MF.getTarget().Options.DisableFramePointerElim(MF) ||36MF.getFrameInfo().hasVarSizedObjects() ||37MFI.isFrameAddressTaken());38}3940bool MSP430FrameLowering::hasReservedCallFrame(const MachineFunction &MF) const {41return !MF.getFrameInfo().hasVarSizedObjects();42}4344void MSP430FrameLowering::BuildCFI(MachineBasicBlock &MBB,45MachineBasicBlock::iterator MBBI,46const DebugLoc &DL,47const MCCFIInstruction &CFIInst,48MachineInstr::MIFlag Flag) const {49MachineFunction &MF = *MBB.getParent();50unsigned CFIIndex = MF.addFrameInst(CFIInst);51BuildMI(MBB, MBBI, DL, TII.get(TargetOpcode::CFI_INSTRUCTION))52.addCFIIndex(CFIIndex)53.setMIFlag(Flag);54}5556void MSP430FrameLowering::emitCalleeSavedFrameMoves(57MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,58const DebugLoc &DL, bool IsPrologue) const {59MachineFunction &MF = *MBB.getParent();60MachineFrameInfo &MFI = MF.getFrameInfo();61const MCRegisterInfo *MRI = MF.getContext().getRegisterInfo();6263// Add callee saved registers to move list.64const std::vector<CalleeSavedInfo> &CSI = MFI.getCalleeSavedInfo();6566// Calculate offsets.67for (const CalleeSavedInfo &I : CSI) {68int64_t Offset = MFI.getObjectOffset(I.getFrameIdx());69Register Reg = I.getReg();70unsigned DwarfReg = MRI->getDwarfRegNum(Reg, true);7172if (IsPrologue) {73BuildCFI(MBB, MBBI, DL,74MCCFIInstruction::createOffset(nullptr, DwarfReg, Offset));75} else {76BuildCFI(MBB, MBBI, DL,77MCCFIInstruction::createRestore(nullptr, DwarfReg));78}79}80}8182void MSP430FrameLowering::emitPrologue(MachineFunction &MF,83MachineBasicBlock &MBB) const {84assert(&MF.front() == &MBB && "Shrink-wrapping not yet supported");85MachineFrameInfo &MFI = MF.getFrameInfo();86MSP430MachineFunctionInfo *MSP430FI = MF.getInfo<MSP430MachineFunctionInfo>();87const MSP430InstrInfo &TII =88*static_cast<const MSP430InstrInfo *>(MF.getSubtarget().getInstrInfo());8990MachineBasicBlock::iterator MBBI = MBB.begin();91DebugLoc DL = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc();9293// Get the number of bytes to allocate from the FrameInfo.94uint64_t StackSize = MFI.getStackSize();95int stackGrowth = -2;9697uint64_t NumBytes = 0;98if (hasFP(MF)) {99// Calculate required stack adjustment100uint64_t FrameSize = StackSize - 2;101NumBytes = FrameSize - MSP430FI->getCalleeSavedFrameSize();102103// Get the offset of the stack slot for the EBP register... which is104// guaranteed to be the last slot by processFunctionBeforeFrameFinalized.105// Update the frame offset adjustment.106MFI.setOffsetAdjustment(-NumBytes);107108// Save FP into the appropriate stack slot...109BuildMI(MBB, MBBI, DL, TII.get(MSP430::PUSH16r))110.addReg(MSP430::R4, RegState::Kill)111.setMIFlag(MachineInstr::FrameSetup);112113// Mark the place where FP was saved.114// Define the current CFA rule to use the provided offset.115BuildCFI(MBB, MBBI, DL,116MCCFIInstruction::cfiDefCfaOffset(nullptr, -2 * stackGrowth),117MachineInstr::FrameSetup);118119// Change the rule for the FramePtr to be an "offset" rule.120unsigned DwarfFramePtr = TRI->getDwarfRegNum(MSP430::R4, true);121BuildCFI(122MBB, MBBI, DL,123MCCFIInstruction::createOffset(nullptr, DwarfFramePtr, 2 * stackGrowth),124MachineInstr::FrameSetup);125126// Update FP with the new base value...127BuildMI(MBB, MBBI, DL, TII.get(MSP430::MOV16rr), MSP430::R4)128.addReg(MSP430::SP)129.setMIFlag(MachineInstr::FrameSetup);130131// Mark effective beginning of when frame pointer becomes valid.132// Define the current CFA to use the FP register.133BuildCFI(MBB, MBBI, DL,134MCCFIInstruction::createDefCfaRegister(nullptr, DwarfFramePtr),135MachineInstr::FrameSetup);136137// Mark the FramePtr as live-in in every block except the entry.138for (MachineBasicBlock &MBBJ : llvm::drop_begin(MF))139MBBJ.addLiveIn(MSP430::R4);140} else141NumBytes = StackSize - MSP430FI->getCalleeSavedFrameSize();142143// Skip the callee-saved push instructions.144int StackOffset = 2 * stackGrowth;145while (MBBI != MBB.end() && MBBI->getFlag(MachineInstr::FrameSetup) &&146(MBBI->getOpcode() == MSP430::PUSH16r)) {147++MBBI;148149if (!hasFP(MF)) {150// Mark callee-saved push instruction.151// Define the current CFA rule to use the provided offset.152assert(StackSize && "Expected stack frame");153BuildCFI(MBB, MBBI, DL,154MCCFIInstruction::cfiDefCfaOffset(nullptr, -StackOffset),155MachineInstr::FrameSetup);156StackOffset += stackGrowth;157}158}159160if (MBBI != MBB.end())161DL = MBBI->getDebugLoc();162163if (NumBytes) { // adjust stack pointer: SP -= numbytes164// If there is an SUB16ri of SP immediately before this instruction, merge165// the two.166//NumBytes -= mergeSPUpdates(MBB, MBBI, true);167// If there is an ADD16ri or SUB16ri of SP immediately after this168// instruction, merge the two instructions.169// mergeSPUpdatesDown(MBB, MBBI, &NumBytes);170171if (NumBytes) {172MachineInstr *MI =173BuildMI(MBB, MBBI, DL, TII.get(MSP430::SUB16ri), MSP430::SP)174.addReg(MSP430::SP)175.addImm(NumBytes)176.setMIFlag(MachineInstr::FrameSetup);177// The SRW implicit def is dead.178MI->getOperand(3).setIsDead();179}180if (!hasFP(MF)) {181// Adjust the previous CFA value if CFA was not redefined by FP182BuildCFI(183MBB, MBBI, DL,184MCCFIInstruction::cfiDefCfaOffset(nullptr, StackSize - stackGrowth),185MachineInstr::FrameSetup);186}187}188189emitCalleeSavedFrameMoves(MBB, MBBI, DL, true);190}191192void MSP430FrameLowering::emitEpilogue(MachineFunction &MF,193MachineBasicBlock &MBB) const {194const MachineFrameInfo &MFI = MF.getFrameInfo();195MSP430MachineFunctionInfo *MSP430FI = MF.getInfo<MSP430MachineFunctionInfo>();196const MSP430InstrInfo &TII =197*static_cast<const MSP430InstrInfo *>(MF.getSubtarget().getInstrInfo());198199MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr();200unsigned RetOpcode = MBBI->getOpcode();201DebugLoc DL = MBBI->getDebugLoc();202203switch (RetOpcode) {204case MSP430::RET:205case MSP430::RETI: break; // These are ok206default:207llvm_unreachable("Can only insert epilog into returning blocks");208}209210// Get the number of bytes to allocate from the FrameInfo211uint64_t StackSize = MFI.getStackSize();212unsigned CSSize = MSP430FI->getCalleeSavedFrameSize();213uint64_t NumBytes = 0;214215MachineBasicBlock::iterator AfterPop = MBBI;216if (hasFP(MF)) {217// Calculate required stack adjustment218uint64_t FrameSize = StackSize - 2;219NumBytes = FrameSize - CSSize;220221// pop FP.222BuildMI(MBB, MBBI, DL, TII.get(MSP430::POP16r), MSP430::R4)223.setMIFlag(MachineInstr::FrameDestroy);224unsigned DwarfStackPtr = TRI->getDwarfRegNum(MSP430::SP, true);225BuildCFI(MBB, MBBI, DL,226MCCFIInstruction::cfiDefCfa(nullptr, DwarfStackPtr, 2),227MachineInstr::FrameDestroy);228--MBBI;229if (!MBB.succ_empty() && !MBB.isReturnBlock()) {230unsigned DwarfFramePtr = TRI->getDwarfRegNum(MSP430::R4, true);231BuildCFI(MBB, AfterPop, DL,232MCCFIInstruction::createRestore(nullptr, DwarfFramePtr),233MachineInstr::FrameDestroy);234--MBBI;235--AfterPop;236}237} else238NumBytes = StackSize - CSSize;239240// Skip the callee-saved pop instructions.241MachineBasicBlock::iterator FirstCSPop = MBBI;242while (MBBI != MBB.begin()) {243MachineBasicBlock::iterator PI = std::prev(MBBI);244unsigned Opc = PI->getOpcode();245if ((Opc != MSP430::POP16r || !PI->getFlag(MachineInstr::FrameDestroy)) &&246!PI->isTerminator())247break;248FirstCSPop = PI;249--MBBI;250}251MBBI = FirstCSPop;252253DL = MBBI->getDebugLoc();254255// If there is an ADD16ri or SUB16ri of SP immediately before this256// instruction, merge the two instructions.257//if (NumBytes || MFI.hasVarSizedObjects())258// mergeSPUpdatesUp(MBB, MBBI, StackPtr, &NumBytes);259260if (MFI.hasVarSizedObjects()) {261BuildMI(MBB, MBBI, DL, TII.get(MSP430::MOV16rr), MSP430::SP)262.addReg(MSP430::R4)263.setMIFlag(MachineInstr::FrameDestroy);264if (CSSize) {265MachineInstr *MI =266BuildMI(MBB, MBBI, DL, TII.get(MSP430::SUB16ri), MSP430::SP)267.addReg(MSP430::SP)268.addImm(CSSize)269.setMIFlag(MachineInstr::FrameDestroy);270// The SRW implicit def is dead.271MI->getOperand(3).setIsDead();272}273} else {274// adjust stack pointer back: SP += numbytes275if (NumBytes) {276MachineInstr *MI =277BuildMI(MBB, MBBI, DL, TII.get(MSP430::ADD16ri), MSP430::SP)278.addReg(MSP430::SP)279.addImm(NumBytes)280.setMIFlag(MachineInstr::FrameDestroy);281// The SRW implicit def is dead.282MI->getOperand(3).setIsDead();283284if (!hasFP(MF)) {285// Adjust CFA value if it was defined by SP286BuildCFI(MBB, MBBI, DL,287MCCFIInstruction::cfiDefCfaOffset(nullptr, CSSize + 2),288MachineInstr::FrameDestroy);289}290}291}292293if (!hasFP(MF)) {294MBBI = FirstCSPop;295int64_t Offset = -(int64_t)CSSize - 2;296// Mark callee-saved pop instruction.297// Define the current CFA rule to use the provided offset.298while (MBBI != MBB.end()) {299MachineBasicBlock::iterator PI = MBBI;300unsigned Opc = PI->getOpcode();301++MBBI;302if (Opc == MSP430::POP16r) {303Offset += 2;304BuildCFI(MBB, MBBI, DL,305MCCFIInstruction::cfiDefCfaOffset(nullptr, -Offset),306MachineInstr::FrameDestroy);307}308}309}310emitCalleeSavedFrameMoves(MBB, AfterPop, DL, false);311}312313// FIXME: Can we eleminate these in favour of generic code?314bool MSP430FrameLowering::spillCalleeSavedRegisters(315MachineBasicBlock &MBB, MachineBasicBlock::iterator MI,316ArrayRef<CalleeSavedInfo> CSI, const TargetRegisterInfo *TRI) const {317if (CSI.empty())318return false;319320DebugLoc DL;321if (MI != MBB.end()) DL = MI->getDebugLoc();322323MachineFunction &MF = *MBB.getParent();324const TargetInstrInfo &TII = *MF.getSubtarget().getInstrInfo();325MSP430MachineFunctionInfo *MFI = MF.getInfo<MSP430MachineFunctionInfo>();326MFI->setCalleeSavedFrameSize(CSI.size() * 2);327328for (const CalleeSavedInfo &I : CSI) {329Register Reg = I.getReg();330// Add the callee-saved register as live-in. It's killed at the spill.331MBB.addLiveIn(Reg);332BuildMI(MBB, MI, DL, TII.get(MSP430::PUSH16r))333.addReg(Reg, RegState::Kill)334.setMIFlag(MachineInstr::FrameSetup);335}336return true;337}338339bool MSP430FrameLowering::restoreCalleeSavedRegisters(340MachineBasicBlock &MBB, MachineBasicBlock::iterator MI,341MutableArrayRef<CalleeSavedInfo> CSI, const TargetRegisterInfo *TRI) const {342if (CSI.empty())343return false;344345DebugLoc DL;346if (MI != MBB.end()) DL = MI->getDebugLoc();347348MachineFunction &MF = *MBB.getParent();349const TargetInstrInfo &TII = *MF.getSubtarget().getInstrInfo();350351for (const CalleeSavedInfo &I : llvm::reverse(CSI))352BuildMI(MBB, MI, DL, TII.get(MSP430::POP16r), I.getReg())353.setMIFlag(MachineInstr::FrameDestroy);354355return true;356}357358MachineBasicBlock::iterator MSP430FrameLowering::eliminateCallFramePseudoInstr(359MachineFunction &MF, MachineBasicBlock &MBB,360MachineBasicBlock::iterator I) const {361const MSP430InstrInfo &TII =362*static_cast<const MSP430InstrInfo *>(MF.getSubtarget().getInstrInfo());363if (!hasReservedCallFrame(MF)) {364// If the stack pointer can be changed after prologue, turn the365// adjcallstackup instruction into a 'sub SP, <amt>' and the366// adjcallstackdown instruction into 'add SP, <amt>'367// TODO: consider using push / pop instead of sub + store / add368MachineInstr &Old = *I;369uint64_t Amount = TII.getFrameSize(Old);370if (Amount != 0) {371// We need to keep the stack aligned properly. To do this, we round the372// amount of space needed for the outgoing arguments up to the next373// alignment boundary.374Amount = alignTo(Amount, getStackAlign());375376MachineInstr *New = nullptr;377if (Old.getOpcode() == TII.getCallFrameSetupOpcode()) {378New =379BuildMI(MF, Old.getDebugLoc(), TII.get(MSP430::SUB16ri), MSP430::SP)380.addReg(MSP430::SP)381.addImm(Amount);382} else {383assert(Old.getOpcode() == TII.getCallFrameDestroyOpcode());384// factor out the amount the callee already popped.385Amount -= TII.getFramePoppedByCallee(Old);386if (Amount)387New = BuildMI(MF, Old.getDebugLoc(), TII.get(MSP430::ADD16ri),388MSP430::SP)389.addReg(MSP430::SP)390.addImm(Amount);391}392393if (New) {394// The SRW implicit def is dead.395New->getOperand(3).setIsDead();396397// Replace the pseudo instruction with a new instruction...398MBB.insert(I, New);399}400}401} else if (I->getOpcode() == TII.getCallFrameDestroyOpcode()) {402// If we are performing frame pointer elimination and if the callee pops403// something off the stack pointer, add it back.404if (uint64_t CalleeAmt = TII.getFramePoppedByCallee(*I)) {405MachineInstr &Old = *I;406MachineInstr *New =407BuildMI(MF, Old.getDebugLoc(), TII.get(MSP430::SUB16ri), MSP430::SP)408.addReg(MSP430::SP)409.addImm(CalleeAmt);410if (!hasFP(MF)) {411DebugLoc DL = I->getDebugLoc();412BuildCFI(MBB, I, DL,413MCCFIInstruction::createAdjustCfaOffset(nullptr, CalleeAmt));414}415// The SRW implicit def is dead.416New->getOperand(3).setIsDead();417418MBB.insert(I, New);419}420}421422return MBB.erase(I);423}424425void426MSP430FrameLowering::processFunctionBeforeFrameFinalized(MachineFunction &MF,427RegScavenger *) const {428// Create a frame entry for the FP register that must be saved.429if (hasFP(MF)) {430int FrameIdx = MF.getFrameInfo().CreateFixedObject(2, -4, true);431(void)FrameIdx;432assert(FrameIdx == MF.getFrameInfo().getObjectIndexBegin() &&433"Slot for FP register must be last in order to be found!");434}435}436437438