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-exception 6// 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/TargetSubtargetInfo.h" 19#include "llvm/IR/Attributes.h" 20#include "llvm/IR/Function.h" 21#include "llvm/IR/InstrTypes.h" 22#include "llvm/MC/MCAsmInfo.h" 23#include "llvm/MC/MCRegisterInfo.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(MachineFunction &MF) const { 40 return MF.needsFrameMoves() && 41 !MF.getTarget().getMCAsmInfo()->usesWindowsCFI(); 42} 43 44/// Returns the displacement from the frame register to the stack 45/// frame of the specified index, along with the frame register used 46/// (in output arg FrameReg). This is the default implementation which 47/// is overridden for some targets. 48StackOffset 49TargetFrameLowering::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 whatever 55 // getFrameRegister() says. The target can override this if it's doing 56 // something different. 57 FrameReg = RI->getFrameRegister(MF); 58 59 return StackOffset::getFixed(MFI.getObjectOffset(FI) + MFI.getStackSize() - 60 getOffsetOfLocalArea() + 61 MFI.getOffsetAdjustment()); 62} 63 64bool TargetFrameLowering::needsFrameIndexResolution( 65 const MachineFunction &MF) const { 66 return MF.getFrameInfo().hasStackObjects(); 67} 68 69void TargetFrameLowering::getCalleeSaves(const MachineFunction &MF, 70 BitVector &CalleeSaves) const { 71 const TargetRegisterInfo &TRI = *MF.getSubtarget().getRegisterInfo(); 72 CalleeSaves.resize(TRI.getNumRegs()); 73 74 const MachineFrameInfo &MFI = MF.getFrameInfo(); 75 if (!MFI.isCalleeSavedInfoValid()) 76 return; 77 78 for (const CalleeSavedInfo &Info : MFI.getCalleeSavedInfo()) 79 CalleeSaves.set(Info.getReg()); 80} 81 82void TargetFrameLowering::determineCalleeSaves(MachineFunction &MF, 83 BitVector &SavedRegs, 84 RegScavenger *RS) const { 85 const TargetRegisterInfo &TRI = *MF.getSubtarget().getRegisterInfo(); 86 87 // Resize before the early returns. Some backends expect that 88 // SavedRegs.size() == TRI.getNumRegs() after this call even if there are no 89 // saved registers. 90 SavedRegs.resize(TRI.getNumRegs()); 91 92 // When interprocedural register allocation is enabled caller saved registers 93 // are preferred over callee saved registers. 94 if (MF.getTarget().Options.EnableIPRA && 95 isSafeForNoCSROpt(MF.getFunction()) && 96 isProfitableForNoCSROpt(MF.getFunction())) 97 return; 98 99 // Get the callee saved register list... 100 const MCPhysReg *CSRegs = MF.getRegInfo().getCalleeSavedRegs(); 101 102 // Early exit if there are no callee saved registers. 103 if (!CSRegs || CSRegs[0] == 0) 104 return; 105 106 // In Naked functions we aren't going to save any registers. 107 if (MF.getFunction().hasFnAttribute(Attribute::Naked)) 108 return; 109 110 // Noreturn+nounwind functions never restore CSR, so no saves are needed. 111 // Purely noreturn functions may still return through throws, so those must 112 // save CSR for caller exception handlers. 113 // 114 // If the function uses longjmp to break out of its current path of 115 // execution we do not need the CSR spills either: setjmp stores all CSRs 116 // it was called with into the jmp_buf, which longjmp then restores. 117 if (MF.getFunction().hasFnAttribute(Attribute::NoReturn) && 118 MF.getFunction().hasFnAttribute(Attribute::NoUnwind) && 119 !MF.getFunction().hasFnAttribute(Attribute::UWTable) && 120 enableCalleeSaveSkip(MF)) 121 return; 122 123 // Functions which call __builtin_unwind_init get all their registers saved. 124 bool CallsUnwindInit = MF.callsUnwindInit(); 125 const MachineRegisterInfo &MRI = MF.getRegInfo(); 126 for (unsigned i = 0; CSRegs[i]; ++i) { 127 unsigned Reg = CSRegs[i]; 128 if (CallsUnwindInit || MRI.isPhysRegModified(Reg)) 129 SavedRegs.set(Reg); 130 } 131} 132 133bool TargetFrameLowering::allocateScavengingFrameIndexesNearIncomingSP( 134 const MachineFunction &MF) const { 135 if (!hasFP(MF)) 136 return false; 137 138 const TargetRegisterInfo *RegInfo = MF.getSubtarget().getRegisterInfo(); 139 return RegInfo->useFPForScavengingIndex(MF) && 140 !RegInfo->hasStackRealignment(MF); 141} 142 143bool TargetFrameLowering::isSafeForNoCSROpt(const Function &F) { 144 if (!F.hasLocalLinkage() || F.hasAddressTaken() || 145 !F.hasFnAttribute(Attribute::NoRecurse)) 146 return false; 147 // Function should not be optimized as tail call. 148 for (const User *U : F.users()) 149 if (auto *CB = dyn_cast<CallBase>(U)) 150 if (CB->isTailCall()) 151 return false; 152 return true; 153} 154 155int TargetFrameLowering::getInitialCFAOffset(const MachineFunction &MF) const { 156 llvm_unreachable("getInitialCFAOffset() not implemented!"); 157} 158 159Register 160TargetFrameLowering::getInitialCFARegister(const MachineFunction &MF) const { 161 llvm_unreachable("getInitialCFARegister() not implemented!"); 162} 163 164TargetFrameLowering::DwarfFrameBase 165TargetFrameLowering::getDwarfFrameBase(const MachineFunction &MF) const { 166 const TargetRegisterInfo *RI = MF.getSubtarget().getRegisterInfo(); 167 return DwarfFrameBase{DwarfFrameBase::Register, {RI->getFrameRegister(MF)}}; 168} 169