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 28 using namespace llvm; 29 30 TargetFrameLowering::~TargetFrameLowering() = default; 31 32 bool 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 39 bool 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. 48 StackOffset 49 TargetFrameLowering::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 64 /// Returns the offset from the stack pointer to the slot of the specified 65 /// index. This function serves to provide a comparable offset from a single 66 /// reference point (the value of the stack-pointer at function entry) that can 67 /// be used for analysis. This is the default implementation using 68 /// MachineFrameInfo offsets. 69 StackOffset 70 TargetFrameLowering::getFrameIndexReferenceFromSP(const MachineFunction &MF, 71 int FI) const { 72 // To display the true offset from SP, we need to subtract the offset to the 73 // local area from MFI's ObjectOffset. 74 return StackOffset::getFixed(MF.getFrameInfo().getObjectOffset(FI) - 75 getOffsetOfLocalArea()); 76 } 77 78 bool TargetFrameLowering::needsFrameIndexResolution( 79 const MachineFunction &MF) const { 80 return MF.getFrameInfo().hasStackObjects(); 81 } 82 83 void 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 96 void 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 that 102 // SavedRegs.size() == TRI.getNumRegs() after this call even if there are no 103 // saved registers. 104 SavedRegs.resize(TRI.getNumRegs()); 105 106 // When interprocedural register allocation is enabled caller saved registers 107 // are preferred over callee saved registers. 108 if (MF.getTarget().Options.EnableIPRA && 109 isSafeForNoCSROpt(MF.getFunction()) && 110 isProfitableForNoCSROpt(MF.getFunction())) 111 return; 112 113 // Get the callee saved register list... 114 const MCPhysReg *CSRegs = MF.getRegInfo().getCalleeSavedRegs(); 115 116 // Early exit if there are no callee saved registers. 117 if (!CSRegs || CSRegs[0] == 0) 118 return; 119 120 // In Naked functions we aren't going to save any registers. 121 if (MF.getFunction().hasFnAttribute(Attribute::Naked)) 122 return; 123 124 // Noreturn+nounwind functions never restore CSR, so no saves are needed. 125 // Purely noreturn functions may still return through throws, so those must 126 // save CSR for caller exception handlers. 127 // 128 // If the function uses longjmp to break out of its current path of 129 // execution we do not need the CSR spills either: setjmp stores all CSRs 130 // it was called with into the jmp_buf, which longjmp then restores. 131 if (MF.getFunction().hasFnAttribute(Attribute::NoReturn) && 132 MF.getFunction().hasFnAttribute(Attribute::NoUnwind) && 133 !MF.getFunction().hasFnAttribute(Attribute::UWTable) && 134 enableCalleeSaveSkip(MF)) 135 return; 136 137 // Functions which call __builtin_unwind_init get all their registers saved. 138 bool CallsUnwindInit = MF.callsUnwindInit(); 139 const MachineRegisterInfo &MRI = MF.getRegInfo(); 140 for (unsigned i = 0; CSRegs[i]; ++i) { 141 unsigned Reg = CSRegs[i]; 142 if (CallsUnwindInit || MRI.isPhysRegModified(Reg)) 143 SavedRegs.set(Reg); 144 } 145 } 146 147 bool TargetFrameLowering::allocateScavengingFrameIndexesNearIncomingSP( 148 const MachineFunction &MF) const { 149 if (!hasFP(MF)) 150 return false; 151 152 const TargetRegisterInfo *RegInfo = MF.getSubtarget().getRegisterInfo(); 153 return RegInfo->useFPForScavengingIndex(MF) && 154 !RegInfo->hasStackRealignment(MF); 155 } 156 157 bool TargetFrameLowering::isSafeForNoCSROpt(const Function &F) { 158 if (!F.hasLocalLinkage() || F.hasAddressTaken() || 159 !F.hasFnAttribute(Attribute::NoRecurse)) 160 return false; 161 // Function should not be optimized as tail call. 162 for (const User *U : F.users()) 163 if (auto *CB = dyn_cast<CallBase>(U)) 164 if (CB->isTailCall()) 165 return false; 166 return true; 167 } 168 169 int TargetFrameLowering::getInitialCFAOffset(const MachineFunction &MF) const { 170 llvm_unreachable("getInitialCFAOffset() not implemented!"); 171 } 172 173 Register 174 TargetFrameLowering::getInitialCFARegister(const MachineFunction &MF) const { 175 llvm_unreachable("getInitialCFARegister() not implemented!"); 176 } 177 178 TargetFrameLowering::DwarfFrameBase 179 TargetFrameLowering::getDwarfFrameBase(const MachineFunction &MF) const { 180 const TargetRegisterInfo *RI = MF.getSubtarget().getRegisterInfo(); 181 return DwarfFrameBase{DwarfFrameBase::Register, {RI->getFrameRegister(MF)}}; 182 } 183