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