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