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/Support/Compiler.h" 24 #include "llvm/Target/TargetMachine.h" 25 #include "llvm/Target/TargetOptions.h" 26 27 using namespace llvm; 28 29 TargetFrameLowering::~TargetFrameLowering() = default; 30 31 bool TargetFrameLowering::enableCalleeSaveSkip(const MachineFunction &MF) const { 32 assert(MF.getFunction().hasFnAttribute(Attribute::NoReturn) && 33 MF.getFunction().hasFnAttribute(Attribute::NoUnwind) && 34 !MF.getFunction().hasFnAttribute(Attribute::UWTable)); 35 return false; 36 } 37 38 bool TargetFrameLowering::enableCFIFixup(MachineFunction &MF) const { 39 return MF.needsFrameMoves() && 40 !MF.getTarget().getMCAsmInfo()->usesWindowsCFI(); 41 } 42 43 /// Returns the displacement from the frame register to the stack 44 /// frame of the specified index, along with the frame register used 45 /// (in output arg FrameReg). This is the default implementation which 46 /// is overridden for some targets. 47 StackOffset 48 TargetFrameLowering::getFrameIndexReference(const MachineFunction &MF, int FI, 49 Register &FrameReg) const { 50 const MachineFrameInfo &MFI = MF.getFrameInfo(); 51 const TargetRegisterInfo *RI = MF.getSubtarget().getRegisterInfo(); 52 53 // By default, assume all frame indices are referenced via whatever 54 // getFrameRegister() says. The target can override this if it's doing 55 // something different. 56 FrameReg = RI->getFrameRegister(MF); 57 58 return StackOffset::getFixed(MFI.getObjectOffset(FI) + MFI.getStackSize() - 59 getOffsetOfLocalArea() + 60 MFI.getOffsetAdjustment()); 61 } 62 63 /// Returns the offset from the stack pointer to the slot of the specified 64 /// index. This function serves to provide a comparable offset from a single 65 /// reference point (the value of the stack-pointer at function entry) that can 66 /// be used for analysis. This is the default implementation using 67 /// MachineFrameInfo offsets. 68 StackOffset 69 TargetFrameLowering::getFrameIndexReferenceFromSP(const MachineFunction &MF, 70 int FI) const { 71 // To display the true offset from SP, we need to subtract the offset to the 72 // local area from MFI's ObjectOffset. 73 return StackOffset::getFixed(MF.getFrameInfo().getObjectOffset(FI) - 74 getOffsetOfLocalArea()); 75 } 76 77 bool TargetFrameLowering::needsFrameIndexResolution( 78 const MachineFunction &MF) const { 79 return MF.getFrameInfo().hasStackObjects(); 80 } 81 82 void TargetFrameLowering::getCalleeSaves(const MachineFunction &MF, 83 BitVector &CalleeSaves) const { 84 const TargetRegisterInfo &TRI = *MF.getSubtarget().getRegisterInfo(); 85 CalleeSaves.resize(TRI.getNumRegs()); 86 87 const MachineFrameInfo &MFI = MF.getFrameInfo(); 88 if (!MFI.isCalleeSavedInfoValid()) 89 return; 90 91 for (const CalleeSavedInfo &Info : MFI.getCalleeSavedInfo()) 92 CalleeSaves.set(Info.getReg()); 93 } 94 95 void TargetFrameLowering::determineCalleeSaves(MachineFunction &MF, 96 BitVector &SavedRegs, 97 RegScavenger *RS) const { 98 const TargetRegisterInfo &TRI = *MF.getSubtarget().getRegisterInfo(); 99 100 // Resize before the early returns. Some backends expect that 101 // SavedRegs.size() == TRI.getNumRegs() after this call even if there are no 102 // saved registers. 103 SavedRegs.resize(TRI.getNumRegs()); 104 105 // Get the callee saved register list... 106 const MCPhysReg *CSRegs = nullptr; 107 108 // When interprocedural register allocation is enabled, callee saved register 109 // list should be empty, since caller saved registers are preferred over 110 // callee saved registers. Unless it has some risked CSR to be optimized out. 111 if (MF.getTarget().Options.EnableIPRA && 112 isSafeForNoCSROpt(MF.getFunction()) && 113 isProfitableForNoCSROpt(MF.getFunction())) 114 CSRegs = TRI.getIPRACSRegs(&MF); 115 else 116 CSRegs = MF.getRegInfo().getCalleeSavedRegs(); 117 118 // Early exit if there are no callee saved registers. 119 if (!CSRegs || CSRegs[0] == 0) 120 return; 121 122 // In Naked functions we aren't going to save any registers. 123 if (MF.getFunction().hasFnAttribute(Attribute::Naked)) 124 return; 125 126 // Noreturn+nounwind functions never restore CSR, so no saves are needed. 127 // Purely noreturn functions may still return through throws, so those must 128 // save CSR for caller exception handlers. 129 // 130 // If the function uses longjmp to break out of its current path of 131 // execution we do not need the CSR spills either: setjmp stores all CSRs 132 // it was called with into the jmp_buf, which longjmp then restores. 133 if (MF.getFunction().hasFnAttribute(Attribute::NoReturn) && 134 MF.getFunction().hasFnAttribute(Attribute::NoUnwind) && 135 !MF.getFunction().hasFnAttribute(Attribute::UWTable) && 136 enableCalleeSaveSkip(MF)) 137 return; 138 139 // Functions which call __builtin_unwind_init get all their registers saved. 140 bool CallsUnwindInit = MF.callsUnwindInit(); 141 const MachineRegisterInfo &MRI = MF.getRegInfo(); 142 for (unsigned i = 0; CSRegs[i]; ++i) { 143 unsigned Reg = CSRegs[i]; 144 if (CallsUnwindInit || MRI.isPhysRegModified(Reg)) 145 SavedRegs.set(Reg); 146 } 147 } 148 149 bool TargetFrameLowering::allocateScavengingFrameIndexesNearIncomingSP( 150 const MachineFunction &MF) const { 151 if (!hasFP(MF)) 152 return false; 153 154 const TargetRegisterInfo *RegInfo = MF.getSubtarget().getRegisterInfo(); 155 return RegInfo->useFPForScavengingIndex(MF) && 156 !RegInfo->hasStackRealignment(MF); 157 } 158 159 bool TargetFrameLowering::isSafeForNoCSROpt(const Function &F) { 160 if (!F.hasLocalLinkage() || F.hasAddressTaken() || 161 !F.hasFnAttribute(Attribute::NoRecurse)) 162 return false; 163 // Function should not be optimized as tail call. 164 for (const User *U : F.users()) 165 if (auto *CB = dyn_cast<CallBase>(U)) 166 if (CB->isTailCall()) 167 return false; 168 return true; 169 } 170 171 int TargetFrameLowering::getInitialCFAOffset(const MachineFunction &MF) const { 172 llvm_unreachable("getInitialCFAOffset() not implemented!"); 173 } 174 175 Register 176 TargetFrameLowering::getInitialCFARegister(const MachineFunction &MF) const { 177 llvm_unreachable("getInitialCFARegister() not implemented!"); 178 } 179 180 TargetFrameLowering::DwarfFrameBase 181 TargetFrameLowering::getDwarfFrameBase(const MachineFunction &MF) const { 182 const TargetRegisterInfo *RI = MF.getSubtarget().getRegisterInfo(); 183 return DwarfFrameBase{DwarfFrameBase::Register, {RI->getFrameRegister(MF)}}; 184 } 185