Path: blob/main/contrib/llvm-project/llvm/lib/Target/M68k/M68kFrameLowering.cpp
35269 views
//===-- M68kFrameLowering.cpp - M68k Frame Information ----------*- C++ -*-===//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/// \file9/// This file contains the M68k implementation of TargetFrameLowering class.10///11//===----------------------------------------------------------------------===//1213#include "M68kFrameLowering.h"1415#include "M68kInstrBuilder.h"16#include "M68kInstrInfo.h"17#include "M68kMachineFunction.h"18#include "M68kSubtarget.h"1920#include "llvm/ADT/SmallSet.h"21#include "llvm/CodeGen/MachineFrameInfo.h"22#include "llvm/CodeGen/MachineFunction.h"23#include "llvm/CodeGen/MachineInstrBuilder.h"24#include "llvm/CodeGen/MachineModuleInfo.h"25#include "llvm/CodeGen/MachineRegisterInfo.h"26#include "llvm/IR/DataLayout.h"27#include "llvm/IR/Function.h"28#include "llvm/Support/Alignment.h"29#include "llvm/Support/CommandLine.h"30#include "llvm/Target/TargetMachine.h"31#include "llvm/Target/TargetOptions.h"3233using namespace llvm;3435M68kFrameLowering::M68kFrameLowering(const M68kSubtarget &STI, Align Alignment)36: TargetFrameLowering(StackGrowsDown, Alignment, -4), STI(STI),37TII(*STI.getInstrInfo()), TRI(STI.getRegisterInfo()) {38SlotSize = STI.getSlotSize();39StackPtr = TRI->getStackRegister();40}4142bool M68kFrameLowering::hasFP(const MachineFunction &MF) const {43const MachineFrameInfo &MFI = MF.getFrameInfo();44const TargetRegisterInfo *TRI = STI.getRegisterInfo();4546return MF.getTarget().Options.DisableFramePointerElim(MF) ||47MFI.hasVarSizedObjects() || MFI.isFrameAddressTaken() ||48TRI->hasStackRealignment(MF);49}5051// FIXME Make sure no other factors prevent us from reserving call frame52bool M68kFrameLowering::hasReservedCallFrame(const MachineFunction &MF) const {53return !MF.getFrameInfo().hasVarSizedObjects() &&54!MF.getInfo<M68kMachineFunctionInfo>()->getHasPushSequences();55}5657bool M68kFrameLowering::canSimplifyCallFramePseudos(58const MachineFunction &MF) const {59return hasReservedCallFrame(MF) ||60(hasFP(MF) && !TRI->hasStackRealignment(MF)) ||61TRI->hasBasePointer(MF);62}6364bool M68kFrameLowering::needsFrameIndexResolution(65const MachineFunction &MF) const {66return MF.getFrameInfo().hasStackObjects() ||67MF.getInfo<M68kMachineFunctionInfo>()->getHasPushSequences();68}6970// NOTE: this only has a subset of the full frame index logic. In71// particular, the FI < 0 and AfterFPPop logic is handled in72// M68kRegisterInfo::eliminateFrameIndex, but not here. Possibly73// (probably?) it should be moved into here.74StackOffset75M68kFrameLowering::getFrameIndexReference(const MachineFunction &MF, int FI,76Register &FrameReg) const {77const MachineFrameInfo &MFI = MF.getFrameInfo();7879// We can't calculate offset from frame pointer if the stack is realigned,80// so enforce usage of stack/base pointer. The base pointer is used when we81// have dynamic allocas in addition to dynamic realignment.82if (TRI->hasBasePointer(MF))83FrameReg = TRI->getBaseRegister();84else if (TRI->hasStackRealignment(MF))85FrameReg = TRI->getStackRegister();86else87FrameReg = TRI->getFrameRegister(MF);8889// Offset will hold the offset from the stack pointer at function entry to the90// object.91// We need to factor in additional offsets applied during the prologue to the92// frame, base, and stack pointer depending on which is used.93int Offset = MFI.getObjectOffset(FI) - getOffsetOfLocalArea();94const M68kMachineFunctionInfo *MMFI = MF.getInfo<M68kMachineFunctionInfo>();95uint64_t StackSize = MFI.getStackSize();96bool HasFP = hasFP(MF);9798// TODO: Support tail calls99if (TRI->hasBasePointer(MF)) {100assert(HasFP && "VLAs and dynamic stack realign, but no FP?!");101if (FI < 0) {102// Skip the saved FP.103return StackOffset::getFixed(Offset + SlotSize);104}105106assert((-(Offset + StackSize)) % MFI.getObjectAlign(FI).value() == 0);107return StackOffset::getFixed(Offset + StackSize);108}109if (TRI->hasStackRealignment(MF)) {110if (FI < 0) {111// Skip the saved FP.112return StackOffset::getFixed(Offset + SlotSize);113}114115assert((-(Offset + StackSize)) % MFI.getObjectAlign(FI).value() == 0);116return StackOffset::getFixed(Offset + StackSize);117}118119if (!HasFP)120return StackOffset::getFixed(Offset + StackSize);121122// Skip the saved FP.123Offset += SlotSize;124125// Skip the RETADDR move area126int TailCallReturnAddrDelta = MMFI->getTCReturnAddrDelta();127if (TailCallReturnAddrDelta < 0)128Offset -= TailCallReturnAddrDelta;129130return StackOffset::getFixed(Offset);131}132133/// Return a caller-saved register that isn't live134/// when it reaches the "return" instruction. We can then pop a stack object135/// to this register without worry about clobbering it.136static unsigned findDeadCallerSavedReg(MachineBasicBlock &MBB,137MachineBasicBlock::iterator &MBBI,138const M68kRegisterInfo *TRI) {139const MachineFunction *MF = MBB.getParent();140if (MF->callsEHReturn())141return 0;142143const TargetRegisterClass &AvailableRegs = *TRI->getRegsForTailCall(*MF);144145if (MBBI == MBB.end())146return 0;147148switch (MBBI->getOpcode()) {149default:150return 0;151case TargetOpcode::PATCHABLE_RET:152case M68k::RET: {153SmallSet<uint16_t, 8> Uses;154155for (unsigned i = 0, e = MBBI->getNumOperands(); i != e; ++i) {156MachineOperand &MO = MBBI->getOperand(i);157if (!MO.isReg() || MO.isDef())158continue;159Register Reg = MO.getReg();160if (!Reg)161continue;162for (MCRegAliasIterator AI(Reg, TRI, true); AI.isValid(); ++AI)163Uses.insert(*AI);164}165166for (auto CS : AvailableRegs)167if (!Uses.count(CS))168return CS;169}170}171172return 0;173}174175static bool isRegLiveIn(MachineBasicBlock &MBB, unsigned Reg) {176return llvm::any_of(MBB.liveins(),177[Reg](MachineBasicBlock::RegisterMaskPair RegMask) {178return RegMask.PhysReg == Reg;179});180}181182uint64_t183M68kFrameLowering::calculateMaxStackAlign(const MachineFunction &MF) const {184const MachineFrameInfo &MFI = MF.getFrameInfo();185uint64_t MaxAlign = MFI.getMaxAlign().value(); // Desired stack alignment.186unsigned StackAlign = getStackAlignment(); // ABI alignment187if (MF.getFunction().hasFnAttribute("stackrealign")) {188if (MFI.hasCalls())189MaxAlign = (StackAlign > MaxAlign) ? StackAlign : MaxAlign;190else if (MaxAlign < SlotSize)191MaxAlign = SlotSize;192}193return MaxAlign;194}195196void M68kFrameLowering::BuildStackAlignAND(MachineBasicBlock &MBB,197MachineBasicBlock::iterator MBBI,198const DebugLoc &DL, unsigned Reg,199uint64_t MaxAlign) const {200uint64_t Val = -MaxAlign;201unsigned AndOp = M68k::AND32di;202unsigned MovOp = M68k::MOV32rr;203204// This function is normally used with SP which is Address Register, but AND,205// or any other logical instructions in M68k do not support ARs so we need206// to use a temp Data Register to perform the op.207unsigned Tmp = M68k::D0;208209BuildMI(MBB, MBBI, DL, TII.get(MovOp), Tmp)210.addReg(Reg)211.setMIFlag(MachineInstr::FrameSetup);212213MachineInstr *MI = BuildMI(MBB, MBBI, DL, TII.get(AndOp), Tmp)214.addReg(Tmp)215.addImm(Val)216.setMIFlag(MachineInstr::FrameSetup);217218// The CCR implicit def is dead.219MI->getOperand(3).setIsDead();220221BuildMI(MBB, MBBI, DL, TII.get(MovOp), Reg)222.addReg(Tmp)223.setMIFlag(MachineInstr::FrameSetup);224}225226MachineBasicBlock::iterator M68kFrameLowering::eliminateCallFramePseudoInstr(227MachineFunction &MF, MachineBasicBlock &MBB,228MachineBasicBlock::iterator I) const {229bool ReserveCallFrame = hasReservedCallFrame(MF);230unsigned Opcode = I->getOpcode();231bool IsDestroy = Opcode == TII.getCallFrameDestroyOpcode();232DebugLoc DL = I->getDebugLoc();233uint64_t Amount = !ReserveCallFrame ? I->getOperand(0).getImm() : 0;234uint64_t InternalAmt = (IsDestroy && Amount) ? I->getOperand(1).getImm() : 0;235I = MBB.erase(I);236237if (!ReserveCallFrame) {238// If the stack pointer can be changed after prologue, turn the239// adjcallstackup instruction into a 'sub %SP, <amt>' and the240// adjcallstackdown instruction into 'add %SP, <amt>'241242// We need to keep the stack aligned properly. To do this, we round the243// amount of space needed for the outgoing arguments up to the next244// alignment boundary.245unsigned StackAlign = getStackAlignment();246Amount = alignTo(Amount, StackAlign);247248bool DwarfCFI = MF.needsFrameMoves();249250// If we have any exception handlers in this function, and we adjust251// the SP before calls, we may need to indicate this to the unwinder252// using GNU_ARGS_SIZE. Note that this may be necessary even when253// Amount == 0, because the preceding function may have set a non-0254// GNU_ARGS_SIZE.255// TODO: We don't need to reset this between subsequent functions,256// if it didn't change.257bool HasDwarfEHHandlers = !MF.getLandingPads().empty();258259if (HasDwarfEHHandlers && !IsDestroy &&260MF.getInfo<M68kMachineFunctionInfo>()->getHasPushSequences()) {261BuildCFI(MBB, I, DL,262MCCFIInstruction::createGnuArgsSize(nullptr, Amount));263}264265if (Amount == 0)266return I;267268// Factor out the amount that gets handled inside the sequence269// (Pushes of argument for frame setup, callee pops for frame destroy)270Amount -= InternalAmt;271272// TODO: This is needed only if we require precise CFA.273// If this is a callee-pop calling convention, emit a CFA adjust for274// the amount the callee popped.275if (IsDestroy && InternalAmt && DwarfCFI && !hasFP(MF))276BuildCFI(MBB, I, DL,277MCCFIInstruction::createAdjustCfaOffset(nullptr, -InternalAmt));278279// Add Amount to SP to destroy a frame, or subtract to setup.280int64_t StackAdjustment = IsDestroy ? Amount : -Amount;281int64_t CfaAdjustment = -StackAdjustment;282283if (StackAdjustment) {284// Merge with any previous or following adjustment instruction. Note: the285// instructions merged with here do not have CFI, so their stack286// adjustments do not feed into CfaAdjustment.287StackAdjustment += mergeSPUpdates(MBB, I, true);288StackAdjustment += mergeSPUpdates(MBB, I, false);289290if (StackAdjustment) {291BuildStackAdjustment(MBB, I, DL, StackAdjustment, false);292}293}294295if (DwarfCFI && !hasFP(MF)) {296// If we don't have FP, but need to generate unwind information,297// we need to set the correct CFA offset after the stack adjustment.298// How much we adjust the CFA offset depends on whether we're emitting299// CFI only for EH purposes or for debugging. EH only requires the CFA300// offset to be correct at each call site, while for debugging we want301// it to be more precise.302303// TODO: When not using precise CFA, we also need to adjust for the304// InternalAmt here.305if (CfaAdjustment) {306BuildCFI(307MBB, I, DL,308MCCFIInstruction::createAdjustCfaOffset(nullptr, CfaAdjustment));309}310}311312return I;313}314315if (IsDestroy && InternalAmt) {316// If we are performing frame pointer elimination and if the callee pops317// something off the stack pointer, add it back. We do this until we have318// more advanced stack pointer tracking ability.319// We are not tracking the stack pointer adjustment by the callee, so make320// sure we restore the stack pointer immediately after the call, there may321// be spill code inserted between the CALL and ADJCALLSTACKUP instructions.322MachineBasicBlock::iterator CI = I;323MachineBasicBlock::iterator B = MBB.begin();324while (CI != B && !std::prev(CI)->isCall())325--CI;326BuildStackAdjustment(MBB, CI, DL, -InternalAmt, /*InEpilogue=*/false);327}328329return I;330}331332/// Emit a series of instructions to increment / decrement the stack pointer by333/// a constant value.334void M68kFrameLowering::emitSPUpdate(MachineBasicBlock &MBB,335MachineBasicBlock::iterator &MBBI,336int64_t NumBytes, bool InEpilogue) const {337bool IsSub = NumBytes < 0;338uint64_t Offset = IsSub ? -NumBytes : NumBytes;339340uint64_t Chunk = (1LL << 31) - 1;341DebugLoc DL = MBB.findDebugLoc(MBBI);342343while (Offset) {344if (Offset > Chunk) {345// Rather than emit a long series of instructions for large offsets,346// load the offset into a register and do one sub/add347Register Reg;348349if (IsSub && !isRegLiveIn(MBB, M68k::D0))350Reg = M68k::D0;351else352Reg = findDeadCallerSavedReg(MBB, MBBI, TRI);353354if (Reg) {355unsigned Opc = M68k::MOV32ri;356BuildMI(MBB, MBBI, DL, TII.get(Opc), Reg).addImm(Offset);357Opc = IsSub ? M68k::SUB32ar : M68k::ADD32ar;358MachineInstr *MI = BuildMI(MBB, MBBI, DL, TII.get(Opc), StackPtr)359.addReg(StackPtr)360.addReg(Reg);361// ??? still no CCR362MI->getOperand(3).setIsDead(); // The CCR implicit def is dead.363Offset = 0;364continue;365}366}367368uint64_t ThisVal = std::min(Offset, Chunk);369370MachineInstrBuilder MI = BuildStackAdjustment(371MBB, MBBI, DL, IsSub ? -ThisVal : ThisVal, InEpilogue);372if (IsSub)373MI.setMIFlag(MachineInstr::FrameSetup);374else375MI.setMIFlag(MachineInstr::FrameDestroy);376377Offset -= ThisVal;378}379}380381int M68kFrameLowering::mergeSPUpdates(MachineBasicBlock &MBB,382MachineBasicBlock::iterator &MBBI,383bool MergeWithPrevious) const {384if ((MergeWithPrevious && MBBI == MBB.begin()) ||385(!MergeWithPrevious && MBBI == MBB.end()))386return 0;387388MachineBasicBlock::iterator PI = MergeWithPrevious ? std::prev(MBBI) : MBBI;389MachineBasicBlock::iterator NI =390MergeWithPrevious ? nullptr : std::next(MBBI);391unsigned Opc = PI->getOpcode();392int Offset = 0;393394if (!MergeWithPrevious && NI != MBB.end() &&395NI->getOpcode() == TargetOpcode::CFI_INSTRUCTION) {396// Don't merge with the next instruction if it has CFI.397return Offset;398}399400if (Opc == M68k::ADD32ai && PI->getOperand(0).getReg() == StackPtr) {401assert(PI->getOperand(1).getReg() == StackPtr);402Offset += PI->getOperand(2).getImm();403MBB.erase(PI);404if (!MergeWithPrevious)405MBBI = NI;406} else if (Opc == M68k::SUB32ai && PI->getOperand(0).getReg() == StackPtr) {407assert(PI->getOperand(1).getReg() == StackPtr);408Offset -= PI->getOperand(2).getImm();409MBB.erase(PI);410if (!MergeWithPrevious)411MBBI = NI;412}413414return Offset;415}416417MachineInstrBuilder M68kFrameLowering::BuildStackAdjustment(418MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,419const DebugLoc &DL, int64_t Offset, bool InEpilogue) const {420assert(Offset != 0 && "zero offset stack adjustment requested");421422// TODO can `lea` be used to adjust stack?423424bool IsSub = Offset < 0;425uint64_t AbsOffset = IsSub ? -Offset : Offset;426unsigned Opc = IsSub ? M68k::SUB32ai : M68k::ADD32ai;427428MachineInstrBuilder MI = BuildMI(MBB, MBBI, DL, TII.get(Opc), StackPtr)429.addReg(StackPtr)430.addImm(AbsOffset);431// FIXME Update CCR as well. For now we just432// conservatively say CCR implicit def is dead433MI->getOperand(3).setIsDead();434return MI;435}436437void M68kFrameLowering::BuildCFI(MachineBasicBlock &MBB,438MachineBasicBlock::iterator MBBI,439const DebugLoc &DL,440const MCCFIInstruction &CFIInst) const {441MachineFunction &MF = *MBB.getParent();442unsigned CFIIndex = MF.addFrameInst(CFIInst);443BuildMI(MBB, MBBI, DL, TII.get(TargetOpcode::CFI_INSTRUCTION))444.addCFIIndex(CFIIndex);445}446447void M68kFrameLowering::emitPrologueCalleeSavedFrameMoves(448MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,449const DebugLoc &DL) const {450MachineFunction &MF = *MBB.getParent();451MachineFrameInfo &MFI = MF.getFrameInfo();452const MCRegisterInfo *MRI = MF.getContext().getRegisterInfo();453454// Add callee saved registers to move list.455const auto &CSI = MFI.getCalleeSavedInfo();456if (CSI.empty())457return;458459// Calculate offsets.460for (const auto &I : CSI) {461int64_t Offset = MFI.getObjectOffset(I.getFrameIdx());462Register Reg = I.getReg();463464unsigned DwarfReg = MRI->getDwarfRegNum(Reg, true);465BuildCFI(MBB, MBBI, DL,466MCCFIInstruction::createOffset(nullptr, DwarfReg, Offset));467}468}469470void M68kFrameLowering::emitPrologue(MachineFunction &MF,471MachineBasicBlock &MBB) const {472assert(&STI == &MF.getSubtarget<M68kSubtarget>() &&473"MF used frame lowering for wrong subtarget");474475MachineBasicBlock::iterator MBBI = MBB.begin();476MachineFrameInfo &MFI = MF.getFrameInfo();477const auto &Fn = MF.getFunction();478MachineModuleInfo &MMI = MF.getMMI();479M68kMachineFunctionInfo *MMFI = MF.getInfo<M68kMachineFunctionInfo>();480uint64_t MaxAlign = calculateMaxStackAlign(MF); // Desired stack alignment.481uint64_t StackSize = MFI.getStackSize(); // Number of bytes to allocate.482bool HasFP = hasFP(MF);483bool NeedsDwarfCFI = MMI.hasDebugInfo() || Fn.needsUnwindTableEntry();484Register FramePtr = TRI->getFrameRegister(MF);485const unsigned MachineFramePtr = FramePtr;486unsigned BasePtr = TRI->getBaseRegister();487488// Debug location must be unknown since the first debug location is used489// to determine the end of the prologue.490DebugLoc DL;491492// Add RETADDR move area to callee saved frame size.493int TailCallReturnAddrDelta = MMFI->getTCReturnAddrDelta();494495if (TailCallReturnAddrDelta < 0) {496MMFI->setCalleeSavedFrameSize(MMFI->getCalleeSavedFrameSize() -497TailCallReturnAddrDelta);498}499500// Insert stack pointer adjustment for later moving of return addr. Only501// applies to tail call optimized functions where the callee argument stack502// size is bigger than the callers.503if (TailCallReturnAddrDelta < 0) {504BuildStackAdjustment(MBB, MBBI, DL, TailCallReturnAddrDelta,505/*InEpilogue=*/false)506.setMIFlag(MachineInstr::FrameSetup);507}508509// Mapping for machine moves:510//511// DST: VirtualFP AND512// SRC: VirtualFP => DW_CFA_def_cfa_offset513// ELSE => DW_CFA_def_cfa514//515// SRC: VirtualFP AND516// DST: Register => DW_CFA_def_cfa_register517//518// ELSE519// OFFSET < 0 => DW_CFA_offset_extended_sf520// REG < 64 => DW_CFA_offset + Reg521// ELSE => DW_CFA_offset_extended522523uint64_t NumBytes = 0;524int stackGrowth = -SlotSize;525526if (HasFP) {527// Calculate required stack adjustment.528uint64_t FrameSize = StackSize - SlotSize;529// If required, include space for extra hidden slot for stashing base530// pointer.531if (MMFI->getRestoreBasePointer())532FrameSize += SlotSize;533534NumBytes = FrameSize - MMFI->getCalleeSavedFrameSize();535536// Callee-saved registers are pushed on stack before the stack is realigned.537if (TRI->hasStackRealignment(MF))538NumBytes = alignTo(NumBytes, MaxAlign);539540// Get the offset of the stack slot for the FP register, which is541// guaranteed to be the last slot by processFunctionBeforeFrameFinalized.542// Update the frame offset adjustment.543MFI.setOffsetAdjustment(-NumBytes);544545BuildMI(MBB, MBBI, DL, TII.get(M68k::LINK16))546.addReg(M68k::WA6, RegState::Kill)547.addImm(-NumBytes)548.setMIFlag(MachineInstr::FrameSetup);549550if (NeedsDwarfCFI) {551// Mark the place where FP was saved.552// Define the current CFA rule to use the provided offset.553assert(StackSize);554BuildCFI(MBB, MBBI, DL,555MCCFIInstruction::cfiDefCfaOffset(nullptr, 2 * stackGrowth));556557// Change the rule for the FramePtr to be an "offset" rule.558int DwarfFramePtr = TRI->getDwarfRegNum(MachineFramePtr, true);559assert(DwarfFramePtr > 0);560BuildCFI(MBB, MBBI, DL,561MCCFIInstruction::createOffset(nullptr, DwarfFramePtr,5622 * stackGrowth));563}564565if (NeedsDwarfCFI) {566// Mark effective beginning of when frame pointer becomes valid.567// Define the current CFA to use the FP register.568unsigned DwarfFramePtr = TRI->getDwarfRegNum(MachineFramePtr, true);569BuildCFI(MBB, MBBI, DL,570MCCFIInstruction::createDefCfaRegister(nullptr, DwarfFramePtr));571}572573// Mark the FramePtr as live-in in every block. Don't do this again for574// funclet prologues.575for (MachineBasicBlock &EveryMBB : MF)576EveryMBB.addLiveIn(MachineFramePtr);577} else {578NumBytes = StackSize - MMFI->getCalleeSavedFrameSize();579}580581// Skip the callee-saved push instructions.582bool PushedRegs = false;583int StackOffset = 2 * stackGrowth;584585while (MBBI != MBB.end() && MBBI->getFlag(MachineInstr::FrameSetup) &&586MBBI->getOpcode() == M68k::PUSH32r) {587PushedRegs = true;588++MBBI;589590if (!HasFP && NeedsDwarfCFI) {591// Mark callee-saved push instruction.592// Define the current CFA rule to use the provided offset.593assert(StackSize);594BuildCFI(MBB, MBBI, DL,595MCCFIInstruction::cfiDefCfaOffset(nullptr, StackOffset));596StackOffset += stackGrowth;597}598}599600// Realign stack after we pushed callee-saved registers (so that we'll be601// able to calculate their offsets from the frame pointer).602if (TRI->hasStackRealignment(MF)) {603assert(HasFP && "There should be a frame pointer if stack is realigned.");604BuildStackAlignAND(MBB, MBBI, DL, StackPtr, MaxAlign);605}606607// If there is an SUB32ri of SP immediately before this instruction, merge608// the two. This can be the case when tail call elimination is enabled and609// the callee has more arguments then the caller.610NumBytes -= mergeSPUpdates(MBB, MBBI, true);611612// Adjust stack pointer: ESP -= numbytes.613if (!HasFP)614emitSPUpdate(MBB, MBBI, -(int64_t)NumBytes, /*InEpilogue=*/false);615616unsigned SPOrEstablisher = StackPtr;617618// If we need a base pointer, set it up here. It's whatever the value619// of the stack pointer is at this point. Any variable size objects620// will be allocated after this, so we can still use the base pointer621// to reference locals.622if (TRI->hasBasePointer(MF)) {623// Update the base pointer with the current stack pointer.624BuildMI(MBB, MBBI, DL, TII.get(M68k::MOV32aa), BasePtr)625.addReg(SPOrEstablisher)626.setMIFlag(MachineInstr::FrameSetup);627if (MMFI->getRestoreBasePointer()) {628// Stash value of base pointer. Saving SP instead of FP shortens629// dependence chain. Used by SjLj EH.630unsigned Opm = M68k::MOV32ja;631M68k::addRegIndirectWithDisp(BuildMI(MBB, MBBI, DL, TII.get(Opm)),632FramePtr, true,633MMFI->getRestoreBasePointerOffset())634.addReg(SPOrEstablisher)635.setMIFlag(MachineInstr::FrameSetup);636}637}638639if (((!HasFP && NumBytes) || PushedRegs) && NeedsDwarfCFI) {640// Mark end of stack pointer adjustment.641if (!HasFP && NumBytes) {642// Define the current CFA rule to use the provided offset.643assert(StackSize);644BuildCFI(645MBB, MBBI, DL,646MCCFIInstruction::cfiDefCfaOffset(nullptr, -StackSize + stackGrowth));647}648649// Emit DWARF info specifying the offsets of the callee-saved registers.650if (PushedRegs)651emitPrologueCalleeSavedFrameMoves(MBB, MBBI, DL);652}653654// TODO Interrupt handlers655// M68k Interrupt handling function cannot assume anything about the656// direction flag (DF in CCR register). Clear this flag by creating "cld"657// instruction in each prologue of interrupt handler function. The "cld"658// instruction should only in these cases:659// 1. The interrupt handling function uses any of the "rep" instructions.660// 2. Interrupt handling function calls another function.661}662663static bool isTailCallOpcode(unsigned Opc) {664return Opc == M68k::TCRETURNj || Opc == M68k::TCRETURNq;665}666667void M68kFrameLowering::emitEpilogue(MachineFunction &MF,668MachineBasicBlock &MBB) const {669const MachineFrameInfo &MFI = MF.getFrameInfo();670M68kMachineFunctionInfo *MMFI = MF.getInfo<M68kMachineFunctionInfo>();671MachineBasicBlock::iterator MBBI = MBB.getFirstTerminator();672std::optional<unsigned> RetOpcode;673if (MBBI != MBB.end())674RetOpcode = MBBI->getOpcode();675DebugLoc DL;676if (MBBI != MBB.end())677DL = MBBI->getDebugLoc();678Register FramePtr = TRI->getFrameRegister(MF);679unsigned MachineFramePtr = FramePtr;680681// Get the number of bytes to allocate from the FrameInfo.682uint64_t StackSize = MFI.getStackSize();683uint64_t MaxAlign = calculateMaxStackAlign(MF);684unsigned CSSize = MMFI->getCalleeSavedFrameSize();685uint64_t NumBytes = 0;686687if (hasFP(MF)) {688// Calculate required stack adjustment.689uint64_t FrameSize = StackSize - SlotSize;690NumBytes = FrameSize - CSSize;691692// Callee-saved registers were pushed on stack before the stack was693// realigned.694if (TRI->hasStackRealignment(MF))695NumBytes = alignTo(FrameSize, MaxAlign);696697} else {698NumBytes = StackSize - CSSize;699}700701// Skip the callee-saved pop instructions.702while (MBBI != MBB.begin()) {703MachineBasicBlock::iterator PI = std::prev(MBBI);704unsigned Opc = PI->getOpcode();705706if ((Opc != M68k::POP32r || !PI->getFlag(MachineInstr::FrameDestroy)) &&707Opc != M68k::DBG_VALUE && !PI->isTerminator())708break;709710--MBBI;711}712MachineBasicBlock::iterator FirstCSPop = MBBI;713714if (MBBI != MBB.end())715DL = MBBI->getDebugLoc();716717// If there is an ADD32ri or SUB32ri of SP immediately before this718// instruction, merge the two instructions.719if (NumBytes || MFI.hasVarSizedObjects())720NumBytes += mergeSPUpdates(MBB, MBBI, true);721722// If dynamic alloca is used, then reset SP to point to the last callee-saved723// slot before popping them off! Same applies for the case, when stack was724// realigned. Don't do this if this was a funclet epilogue, since the funclets725// will not do realignment or dynamic stack allocation.726if ((TRI->hasStackRealignment(MF) || MFI.hasVarSizedObjects())) {727if (TRI->hasStackRealignment(MF))728MBBI = FirstCSPop;729uint64_t LEAAmount = -CSSize;730731// 'move %FramePtr, SP' will not be recognized as an epilogue sequence.732// However, we may use this sequence if we have a frame pointer because the733// effects of the prologue can safely be undone.734if (LEAAmount != 0) {735unsigned Opc = M68k::LEA32p;736M68k::addRegIndirectWithDisp(737BuildMI(MBB, MBBI, DL, TII.get(Opc), StackPtr), FramePtr, false,738LEAAmount);739--MBBI;740} else {741BuildMI(MBB, MBBI, DL, TII.get(M68k::UNLK))742.addReg(MachineFramePtr, RegState::Kill)743.setMIFlag(MachineInstr::FrameDestroy);744--MBBI;745}746} else if (hasFP(MF)) {747BuildMI(MBB, MBBI, DL, TII.get(M68k::UNLK))748.addReg(MachineFramePtr, RegState::Kill)749.setMIFlag(MachineInstr::FrameDestroy);750} else if (NumBytes) {751// Adjust stack pointer back: SP += numbytes.752emitSPUpdate(MBB, MBBI, NumBytes, /*InEpilogue=*/true);753--MBBI;754}755756if (!RetOpcode || !isTailCallOpcode(*RetOpcode)) {757// Add the return addr area delta back since we are not tail calling.758int Offset = -1 * MMFI->getTCReturnAddrDelta();759assert(Offset >= 0 && "TCDelta should never be positive");760if (Offset) {761MBBI = MBB.getFirstTerminator();762763// Check for possible merge with preceding ADD instruction.764Offset += mergeSPUpdates(MBB, MBBI, true);765emitSPUpdate(MBB, MBBI, Offset, /*InEpilogue=*/true);766}767}768}769770void M68kFrameLowering::determineCalleeSaves(MachineFunction &MF,771BitVector &SavedRegs,772RegScavenger *RS) const {773TargetFrameLowering::determineCalleeSaves(MF, SavedRegs, RS);774775MachineFrameInfo &MFI = MF.getFrameInfo();776777M68kMachineFunctionInfo *M68kFI = MF.getInfo<M68kMachineFunctionInfo>();778int64_t TailCallReturnAddrDelta = M68kFI->getTCReturnAddrDelta();779780if (TailCallReturnAddrDelta < 0) {781// create RETURNADDR area782// arg783// arg784// RETADDR785// { ...786// RETADDR area787// ...788// }789// [FP]790MFI.CreateFixedObject(-TailCallReturnAddrDelta,791TailCallReturnAddrDelta - SlotSize, true);792}793794// Spill the BasePtr if it's used.795if (TRI->hasBasePointer(MF)) {796SavedRegs.set(TRI->getBaseRegister());797}798}799800bool M68kFrameLowering::assignCalleeSavedSpillSlots(801MachineFunction &MF, const TargetRegisterInfo *TRI,802std::vector<CalleeSavedInfo> &CSI) const {803MachineFrameInfo &MFI = MF.getFrameInfo();804M68kMachineFunctionInfo *M68kFI = MF.getInfo<M68kMachineFunctionInfo>();805806int SpillSlotOffset = getOffsetOfLocalArea() + M68kFI->getTCReturnAddrDelta();807808if (hasFP(MF)) {809// emitPrologue always spills frame register the first thing.810SpillSlotOffset -= SlotSize;811MFI.CreateFixedSpillStackObject(SlotSize, SpillSlotOffset);812813// Since emitPrologue and emitEpilogue will handle spilling and restoring of814// the frame register, we can delete it from CSI list and not have to worry815// about avoiding it later.816Register FPReg = TRI->getFrameRegister(MF);817for (unsigned i = 0, e = CSI.size(); i < e; ++i) {818if (TRI->regsOverlap(CSI[i].getReg(), FPReg)) {819CSI.erase(CSI.begin() + i);820break;821}822}823}824825// The rest is fine826return false;827}828829bool M68kFrameLowering::spillCalleeSavedRegisters(830MachineBasicBlock &MBB, MachineBasicBlock::iterator MI,831ArrayRef<CalleeSavedInfo> CSI, const TargetRegisterInfo *TRI) const {832auto &MRI = *static_cast<const M68kRegisterInfo *>(TRI);833auto DL = MBB.findDebugLoc(MI);834835int FI = 0;836unsigned Mask = 0;837for (const auto &Info : CSI) {838FI = std::max(FI, Info.getFrameIdx());839Register Reg = Info.getReg();840unsigned Shift = MRI.getSpillRegisterOrder(Reg);841Mask |= 1 << Shift;842}843844auto I =845M68k::addFrameReference(BuildMI(MBB, MI, DL, TII.get(M68k::MOVM32pm)), FI)846.addImm(Mask)847.setMIFlag(MachineInstr::FrameSetup);848849// Append implicit registers and mem locations850const MachineFunction &MF = *MBB.getParent();851const MachineRegisterInfo &RI = MF.getRegInfo();852for (const auto &Info : CSI) {853Register Reg = Info.getReg();854bool IsLiveIn = RI.isLiveIn(Reg);855if (!IsLiveIn)856MBB.addLiveIn(Reg);857I.addReg(Reg, IsLiveIn ? RegState::Implicit : RegState::ImplicitKill);858M68k::addMemOperand(I, Info.getFrameIdx(), 0);859}860861return true;862}863864bool M68kFrameLowering::restoreCalleeSavedRegisters(865MachineBasicBlock &MBB, MachineBasicBlock::iterator MI,866MutableArrayRef<CalleeSavedInfo> CSI, const TargetRegisterInfo *TRI) const {867auto &MRI = *static_cast<const M68kRegisterInfo *>(TRI);868auto DL = MBB.findDebugLoc(MI);869870int FI = 0;871unsigned Mask = 0;872for (const auto &Info : CSI) {873FI = std::max(FI, Info.getFrameIdx());874Register Reg = Info.getReg();875unsigned Shift = MRI.getSpillRegisterOrder(Reg);876Mask |= 1 << Shift;877}878879auto I = M68k::addFrameReference(880BuildMI(MBB, MI, DL, TII.get(M68k::MOVM32mp)).addImm(Mask), FI)881.setMIFlag(MachineInstr::FrameDestroy);882883// Append implicit registers and mem locations884for (const auto &Info : CSI) {885I.addReg(Info.getReg(), RegState::ImplicitDefine);886M68k::addMemOperand(I, Info.getFrameIdx(), 0);887}888889return true;890}891892893