Path: blob/main/contrib/llvm-project/llvm/lib/Target/Xtensa/XtensaFrameLowering.cpp
35271 views
//===- XtensaFrameLowering.cpp - Xtensa 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 Xtensa implementation of TargetFrameLowering class.9//10//===----------------------------------------------------------------------===//1112#include "XtensaFrameLowering.h"13#include "XtensaInstrInfo.h"14#include "XtensaSubtarget.h"15#include "llvm/CodeGen/MachineFrameInfo.h"16#include "llvm/CodeGen/MachineInstrBuilder.h"17#include "llvm/CodeGen/MachineModuleInfo.h"18#include "llvm/CodeGen/MachineRegisterInfo.h"19#include "llvm/CodeGen/RegisterScavenging.h"20#include "llvm/IR/Function.h"2122using namespace llvm;2324XtensaFrameLowering::XtensaFrameLowering(const XtensaSubtarget &STI)25: TargetFrameLowering(TargetFrameLowering::StackGrowsDown, Align(4), 0,26Align(4)),27TII(*STI.getInstrInfo()), TRI(STI.getRegisterInfo()) {}2829bool XtensaFrameLowering::hasFP(const MachineFunction &MF) const {30const MachineFrameInfo &MFI = MF.getFrameInfo();31return MF.getTarget().Options.DisableFramePointerElim(MF) ||32MFI.hasVarSizedObjects();33}3435void XtensaFrameLowering::emitPrologue(MachineFunction &MF,36MachineBasicBlock &MBB) const {37assert(&MBB == &MF.front() && "Shrink-wrapping not yet implemented");38MachineFrameInfo &MFI = MF.getFrameInfo();39MachineBasicBlock::iterator MBBI = MBB.begin();40DebugLoc DL = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc();41MCRegister SP = Xtensa::SP;42MCRegister FP = TRI->getFrameRegister(MF);43const MCRegisterInfo *MRI = MF.getContext().getRegisterInfo();4445// First, compute final stack size.46uint64_t StackSize = MFI.getStackSize();47uint64_t PrevStackSize = StackSize;4849// Round up StackSize to 16*N50StackSize += (16 - StackSize) & 0xf;5152// No need to allocate space on the stack.53if (StackSize == 0 && !MFI.adjustsStack())54return;5556// Adjust stack.57TII.adjustStackPtr(SP, -StackSize, MBB, MBBI);5859// emit ".cfi_def_cfa_offset StackSize"60unsigned CFIIndex =61MF.addFrameInst(MCCFIInstruction::cfiDefCfaOffset(nullptr, StackSize));62BuildMI(MBB, MBBI, DL, TII.get(TargetOpcode::CFI_INSTRUCTION))63.addCFIIndex(CFIIndex);6465const std::vector<CalleeSavedInfo> &CSI = MFI.getCalleeSavedInfo();6667if (!CSI.empty()) {68// Find the instruction past the last instruction that saves a69// callee-saved register to the stack. The callee-saved store70// instructions are placed at the begin of basic block, so71// iterate over instruction sequence and check that72// save instructions are placed correctly.73for (unsigned i = 0, e = CSI.size(); i < e; ++i) {74#ifndef NDEBUG75const CalleeSavedInfo &Info = CSI[i];76int FI = Info.getFrameIdx();77int StoreFI = 0;7879// Checking that the instruction is exactly as expected80bool IsStoreInst = false;81if (MBBI->getOpcode() == TargetOpcode::COPY && Info.isSpilledToReg()) {82Register DstReg = MBBI->getOperand(0).getReg();83Register Reg = MBBI->getOperand(1).getReg();84IsStoreInst = (Info.getDstReg() == DstReg) && (Info.getReg() == Reg);85} else {86Register Reg = TII.isStoreToStackSlot(*MBBI, StoreFI);87IsStoreInst = (Reg == Info.getReg()) && (StoreFI == FI);88}89assert(IsStoreInst &&90"Unexpected callee-saved register store instruction");91#endif92++MBBI;93}9495// Iterate over list of callee-saved registers and emit .cfi_offset96// directives.97for (const auto &I : CSI) {98int64_t Offset = MFI.getObjectOffset(I.getFrameIdx());99Register Reg = I.getReg();100101unsigned CFIIndex = MF.addFrameInst(MCCFIInstruction::createOffset(102nullptr, MRI->getDwarfRegNum(Reg, 1), Offset));103BuildMI(MBB, MBBI, DL, TII.get(TargetOpcode::CFI_INSTRUCTION))104.addCFIIndex(CFIIndex);105}106}107108// if framepointer enabled, set it to point to the stack pointer.109if (hasFP(MF)) {110// Insert instruction "move $fp, $sp" at this location.111BuildMI(MBB, MBBI, DL, TII.get(Xtensa::OR), FP)112.addReg(SP)113.addReg(SP)114.setMIFlag(MachineInstr::FrameSetup);115116// emit ".cfi_def_cfa_register $fp"117unsigned CFIIndex = MF.addFrameInst(MCCFIInstruction::createDefCfaRegister(118nullptr, MRI->getDwarfRegNum(FP, true)));119BuildMI(MBB, MBBI, DL, TII.get(TargetOpcode::CFI_INSTRUCTION))120.addCFIIndex(CFIIndex);121}122123if (StackSize != PrevStackSize) {124MFI.setStackSize(StackSize);125126for (int i = MFI.getObjectIndexBegin(); i < MFI.getObjectIndexEnd(); i++) {127if (!MFI.isDeadObjectIndex(i)) {128int64_t SPOffset = MFI.getObjectOffset(i);129130if (SPOffset < 0)131MFI.setObjectOffset(i, SPOffset - StackSize + PrevStackSize);132}133}134}135}136137void XtensaFrameLowering::emitEpilogue(MachineFunction &MF,138MachineBasicBlock &MBB) const {139MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr();140MachineFrameInfo &MFI = MF.getFrameInfo();141DebugLoc DL = MBBI->getDebugLoc();142MCRegister SP = Xtensa::SP;143MCRegister FP = TRI->getFrameRegister(MF);144145// if framepointer enabled, restore the stack pointer.146if (hasFP(MF)) {147// We should place restore stack pointer instruction just before148// sequence of instructions which restores callee-saved registers.149// This sequence is placed at the end of the basic block,150// so we should find first instruction of the sequence.151MachineBasicBlock::iterator I = MBBI;152153const std::vector<CalleeSavedInfo> &CSI = MFI.getCalleeSavedInfo();154155// Find the first instruction at the end that restores a callee-saved156// register.157for (unsigned i = 0, e = CSI.size(); i < e; ++i) {158--I;159#ifndef NDEBUG160const CalleeSavedInfo &Info = CSI[i];161int FI = Info.getFrameIdx();162int LoadFI = 0;163164// Checking that the instruction is exactly as expected165bool IsRestoreInst = false;166if (I->getOpcode() == TargetOpcode::COPY && Info.isSpilledToReg()) {167Register Reg = I->getOperand(0).getReg();168Register DstReg = I->getOperand(1).getReg();169IsRestoreInst = (Info.getDstReg() == DstReg) && (Info.getReg() == Reg);170} else {171Register Reg = TII.isLoadFromStackSlot(*I, LoadFI);172IsRestoreInst = (Info.getReg() == Reg) && (LoadFI == FI);173}174assert(IsRestoreInst &&175"Unexpected callee-saved register restore instruction");176#endif177}178179BuildMI(MBB, I, DL, TII.get(Xtensa::OR), SP).addReg(FP).addReg(FP);180}181182// Get the number of bytes from FrameInfo183uint64_t StackSize = MFI.getStackSize();184185if (!StackSize)186return;187188// Adjust stack.189TII.adjustStackPtr(SP, StackSize, MBB, MBBI);190}191192bool XtensaFrameLowering::spillCalleeSavedRegisters(193MachineBasicBlock &MBB, MachineBasicBlock::iterator MI,194ArrayRef<CalleeSavedInfo> CSI, const TargetRegisterInfo *TRI) const {195MachineFunction *MF = MBB.getParent();196MachineBasicBlock &EntryBlock = *(MF->begin());197198for (unsigned i = 0, e = CSI.size(); i != e; ++i) {199// Add the callee-saved register as live-in. Do not add if the register is200// A0 and return address is taken, because it will be implemented in201// method XtensaTargetLowering::LowerRETURNADDR.202// It's killed at the spill, unless the register is RA and return address203// is taken.204Register Reg = CSI[i].getReg();205bool IsA0AndRetAddrIsTaken =206(Reg == Xtensa::A0) && MF->getFrameInfo().isReturnAddressTaken();207if (!IsA0AndRetAddrIsTaken)208EntryBlock.addLiveIn(Reg);209210// Insert the spill to the stack frame.211bool IsKill = !IsA0AndRetAddrIsTaken;212const TargetRegisterClass *RC = TRI->getMinimalPhysRegClass(Reg);213TII.storeRegToStackSlot(EntryBlock, MI, Reg, IsKill, CSI[i].getFrameIdx(),214RC, TRI, Register());215}216217return true;218}219220bool XtensaFrameLowering::restoreCalleeSavedRegisters(221MachineBasicBlock &MBB, MachineBasicBlock::iterator MI,222MutableArrayRef<CalleeSavedInfo> CSI, const TargetRegisterInfo *TRI) const {223return TargetFrameLowering::restoreCalleeSavedRegisters(MBB, MI, CSI, TRI);224}225226// Eliminate ADJCALLSTACKDOWN, ADJCALLSTACKUP pseudo instructions227MachineBasicBlock::iterator XtensaFrameLowering::eliminateCallFramePseudoInstr(228MachineFunction &MF, MachineBasicBlock &MBB,229MachineBasicBlock::iterator I) const {230const XtensaInstrInfo &TII =231*static_cast<const XtensaInstrInfo *>(MF.getSubtarget().getInstrInfo());232233if (!hasReservedCallFrame(MF)) {234int64_t Amount = I->getOperand(0).getImm();235236if (I->getOpcode() == Xtensa::ADJCALLSTACKDOWN)237Amount = -Amount;238239TII.adjustStackPtr(Xtensa::SP, Amount, MBB, I);240}241242return MBB.erase(I);243}244245void XtensaFrameLowering::determineCalleeSaves(MachineFunction &MF,246BitVector &SavedRegs,247RegScavenger *RS) const {248unsigned FP = TRI->getFrameRegister(MF);249250TargetFrameLowering::determineCalleeSaves(MF, SavedRegs, RS);251252// Mark $fp as used if function has dedicated frame pointer.253if (hasFP(MF))254SavedRegs.set(FP);255}256257void XtensaFrameLowering::processFunctionBeforeFrameFinalized(258MachineFunction &MF, RegScavenger *RS) const {259// Set scavenging frame index if necessary.260MachineFrameInfo &MFI = MF.getFrameInfo();261uint64_t MaxSPOffset = MFI.estimateStackSize(MF);262263if (isInt<12>(MaxSPOffset))264return;265266const TargetRegisterClass &RC = Xtensa::ARRegClass;267unsigned Size = TRI->getSpillSize(RC);268Align Alignment = TRI->getSpillAlign(RC);269int FI = MF.getFrameInfo().CreateStackObject(Size, Alignment, false);270271RS->addScavengingFrameIndex(FI);272}273274275