xref: /freebsd/contrib/llvm-project/llvm/lib/CodeGen/TargetFrameLoweringImpl.cpp (revision e6bfd18d21b225af6a0ed67ceeaf1293b7b9eba5)
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 
33 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 
40 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
50 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 
65 bool TargetFrameLowering::needsFrameIndexResolution(
66     const MachineFunction &MF) const {
67   return MF.getFrameInfo().hasStackObjects();
68 }
69 
70 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 
83 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 
134 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 
144 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 
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 
166 int TargetFrameLowering::getInitialCFAOffset(const MachineFunction &MF) const {
167   llvm_unreachable("getInitialCFAOffset() not implemented!");
168 }
169 
170 Register
171 TargetFrameLowering::getInitialCFARegister(const MachineFunction &MF) const {
172   llvm_unreachable("getInitialCFARegister() not implemented!");
173 }
174 
175 TargetFrameLowering::DwarfFrameBase
176 TargetFrameLowering::getDwarfFrameBase(const MachineFunction &MF) const {
177   const TargetRegisterInfo *RI = MF.getSubtarget().getRegisterInfo();
178   return DwarfFrameBase{DwarfFrameBase::Register, {RI->getFrameRegister(MF)}};
179 }
180