219 lines · cpp
1//===- TargetFrameLoweringImpl.cpp - Implement target frame interface ------==//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8//9// Implements the layout of a stack frame on the target machine.10//11//===----------------------------------------------------------------------===//12 13#include "llvm/ADT/BitVector.h"14#include "llvm/CodeGen/MachineFrameInfo.h"15#include "llvm/CodeGen/MachineFunction.h"16#include "llvm/CodeGen/MachineRegisterInfo.h"17#include "llvm/CodeGen/TargetFrameLowering.h"18#include "llvm/CodeGen/TargetInstrInfo.h"19#include "llvm/CodeGen/TargetSubtargetInfo.h"20#include "llvm/IR/Attributes.h"21#include "llvm/IR/Function.h"22#include "llvm/IR/InstrTypes.h"23#include "llvm/MC/MCAsmInfo.h"24#include "llvm/Support/Compiler.h"25#include "llvm/Target/TargetMachine.h"26#include "llvm/Target/TargetOptions.h"27 28using namespace llvm;29 30TargetFrameLowering::~TargetFrameLowering() = default;31 32bool TargetFrameLowering::enableCalleeSaveSkip(const MachineFunction &MF) const {33 assert(MF.getFunction().hasFnAttribute(Attribute::NoReturn) &&34 MF.getFunction().hasFnAttribute(Attribute::NoUnwind) &&35 !MF.getFunction().hasFnAttribute(Attribute::UWTable));36 return false;37}38 39bool TargetFrameLowering::enableCFIFixup(const MachineFunction &MF) const {40 return MF.needsFrameMoves() &&41 !MF.getTarget().getMCAsmInfo()->usesWindowsCFI();42}43 44/// Returns the displacement from the frame register to the stack45/// frame of the specified index, along with the frame register used46/// (in output arg FrameReg). This is the default implementation which47/// is overridden for some targets.48StackOffset49TargetFrameLowering::getFrameIndexReference(const MachineFunction &MF, int FI,50 Register &FrameReg) const {51 const MachineFrameInfo &MFI = MF.getFrameInfo();52 const TargetRegisterInfo *RI = MF.getSubtarget().getRegisterInfo();53 54 // By default, assume all frame indices are referenced via whatever55 // getFrameRegister() says. The target can override this if it's doing56 // something different.57 FrameReg = RI->getFrameRegister(MF);58 59 return StackOffset::getFixed(MFI.getObjectOffset(FI) + MFI.getStackSize() -60 getOffsetOfLocalArea() +61 MFI.getOffsetAdjustment());62}63 64/// Returns the offset from the stack pointer to the slot of the specified65/// index. This function serves to provide a comparable offset from a single66/// reference point (the value of the stack-pointer at function entry) that can67/// be used for analysis. This is the default implementation using68/// MachineFrameInfo offsets.69StackOffset70TargetFrameLowering::getFrameIndexReferenceFromSP(const MachineFunction &MF,71 int FI) const {72 // To display the true offset from SP, we need to subtract the offset to the73 // local area from MFI's ObjectOffset.74 return StackOffset::getFixed(MF.getFrameInfo().getObjectOffset(FI) -75 getOffsetOfLocalArea());76}77 78bool TargetFrameLowering::needsFrameIndexResolution(79 const MachineFunction &MF) const {80 return MF.getFrameInfo().hasStackObjects();81}82 83void TargetFrameLowering::getCalleeSaves(const MachineFunction &MF,84 BitVector &CalleeSaves) const {85 const TargetRegisterInfo &TRI = *MF.getSubtarget().getRegisterInfo();86 CalleeSaves.resize(TRI.getNumRegs());87 88 const MachineFrameInfo &MFI = MF.getFrameInfo();89 if (!MFI.isCalleeSavedInfoValid())90 return;91 92 for (const CalleeSavedInfo &Info : MFI.getCalleeSavedInfo())93 CalleeSaves.set(Info.getReg());94}95 96void TargetFrameLowering::determineCalleeSaves(MachineFunction &MF,97 BitVector &SavedRegs,98 RegScavenger *RS) const {99 const TargetRegisterInfo &TRI = *MF.getSubtarget().getRegisterInfo();100 101 // Resize before the early returns. Some backends expect that102 // SavedRegs.size() == TRI.getNumRegs() after this call even if there are no103 // saved registers.104 SavedRegs.resize(TRI.getNumRegs());105 106 // Get the callee saved register list...107 const MCPhysReg *CSRegs = nullptr;108 109 // When interprocedural register allocation is enabled, callee saved register110 // list should be empty, since caller saved registers are preferred over111 // callee saved registers. Unless it has some risked CSR to be optimized out.112 if (MF.getTarget().Options.EnableIPRA &&113 isSafeForNoCSROpt(MF.getFunction()) &&114 isProfitableForNoCSROpt(MF.getFunction()))115 CSRegs = TRI.getIPRACSRegs(&MF);116 else117 CSRegs = MF.getRegInfo().getCalleeSavedRegs();118 119 // Early exit if there are no callee saved registers.120 if (!CSRegs || CSRegs[0] == 0)121 return;122 123 // In Naked functions we aren't going to save any registers.124 if (MF.getFunction().hasFnAttribute(Attribute::Naked))125 return;126 127 // Noreturn+nounwind functions never restore CSR, so no saves are needed.128 // Purely noreturn functions may still return through throws, so those must129 // save CSR for caller exception handlers.130 //131 // If the function uses longjmp to break out of its current path of132 // execution we do not need the CSR spills either: setjmp stores all CSRs133 // it was called with into the jmp_buf, which longjmp then restores.134 if (MF.getFunction().hasFnAttribute(Attribute::NoReturn) &&135 MF.getFunction().hasFnAttribute(Attribute::NoUnwind) &&136 !MF.getFunction().hasFnAttribute(Attribute::UWTable) &&137 enableCalleeSaveSkip(MF))138 return;139 140 // Functions which call __builtin_unwind_init get all their registers saved.141 bool CallsUnwindInit = MF.callsUnwindInit();142 const MachineRegisterInfo &MRI = MF.getRegInfo();143 for (unsigned i = 0; CSRegs[i]; ++i) {144 unsigned Reg = CSRegs[i];145 if (CallsUnwindInit || MRI.isPhysRegModified(Reg))146 SavedRegs.set(Reg);147 }148}149 150bool TargetFrameLowering::allocateScavengingFrameIndexesNearIncomingSP(151 const MachineFunction &MF) const {152 if (!hasFP(MF))153 return false;154 155 const TargetRegisterInfo *RegInfo = MF.getSubtarget().getRegisterInfo();156 return RegInfo->useFPForScavengingIndex(MF) &&157 !RegInfo->hasStackRealignment(MF);158}159 160bool TargetFrameLowering::isSafeForNoCSROpt(const Function &F) {161 if (!F.hasLocalLinkage() || F.hasAddressTaken() ||162 !F.hasFnAttribute(Attribute::NoRecurse))163 return false;164 // Function should not be optimized as tail call.165 for (const User *U : F.users())166 if (auto *CB = dyn_cast<CallBase>(U))167 if (CB->isTailCall())168 return false;169 return true;170}171 172int TargetFrameLowering::getInitialCFAOffset(const MachineFunction &MF) const {173 llvm_unreachable("getInitialCFAOffset() not implemented!");174}175 176Register177TargetFrameLowering::getInitialCFARegister(const MachineFunction &MF) const {178 llvm_unreachable("getInitialCFARegister() not implemented!");179}180 181TargetFrameLowering::DwarfFrameBase182TargetFrameLowering::getDwarfFrameBase(const MachineFunction &MF) const {183 const TargetRegisterInfo *RI = MF.getSubtarget().getRegisterInfo();184 return DwarfFrameBase{DwarfFrameBase::Register, {RI->getFrameRegister(MF).id()}};185}186 187void TargetFrameLowering::spillCalleeSavedRegister(188 MachineBasicBlock &SaveBlock, MachineBasicBlock::iterator MI,189 const CalleeSavedInfo &CS, const TargetInstrInfo *TII,190 const TargetRegisterInfo *TRI) const {191 // Insert the spill to the stack frame.192 MCRegister Reg = CS.getReg();193 194 if (CS.isSpilledToReg()) {195 BuildMI(SaveBlock, MI, DebugLoc(), TII->get(TargetOpcode::COPY),196 CS.getDstReg())197 .addReg(Reg, getKillRegState(true));198 } else {199 const TargetRegisterClass *RC = TRI->getMinimalPhysRegClass(Reg);200 TII->storeRegToStackSlot(SaveBlock, MI, Reg, true, CS.getFrameIdx(), RC,201 Register());202 }203}204 205void TargetFrameLowering::restoreCalleeSavedRegister(206 MachineBasicBlock &MBB, MachineBasicBlock::iterator MI,207 const CalleeSavedInfo &CS, const TargetInstrInfo *TII,208 const TargetRegisterInfo *TRI) const {209 MCRegister Reg = CS.getReg();210 if (CS.isSpilledToReg()) {211 BuildMI(MBB, MI, DebugLoc(), TII->get(TargetOpcode::COPY), Reg)212 .addReg(CS.getDstReg(), getKillRegState(true));213 } else {214 const TargetRegisterClass *RC = TRI->getMinimalPhysRegClass(Reg);215 TII->loadRegFromStackSlot(MBB, MI, Reg, CS.getFrameIdx(), RC, Register());216 assert(MI != MBB.begin() && "loadRegFromStackSlot didn't insert any code!");217 }218}219