1 //===- XtensaFrameLowering.cpp - Xtensa Frame Information -----------------===//
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 // This file contains the Xtensa implementation of TargetFrameLowering class.
10 //
11 //===----------------------------------------------------------------------===//
12
13 #include "XtensaFrameLowering.h"
14 #include "XtensaInstrInfo.h"
15 #include "XtensaSubtarget.h"
16 #include "llvm/CodeGen/MachineFrameInfo.h"
17 #include "llvm/CodeGen/MachineInstrBuilder.h"
18 #include "llvm/CodeGen/MachineModuleInfo.h"
19 #include "llvm/CodeGen/MachineRegisterInfo.h"
20 #include "llvm/CodeGen/RegisterScavenging.h"
21 #include "llvm/IR/Function.h"
22
23 using namespace llvm;
24
XtensaFrameLowering(const XtensaSubtarget & STI)25 XtensaFrameLowering::XtensaFrameLowering(const XtensaSubtarget &STI)
26 : TargetFrameLowering(TargetFrameLowering::StackGrowsDown, Align(4), 0,
27 Align(4)),
28 TII(*STI.getInstrInfo()), TRI(STI.getRegisterInfo()) {}
29
hasFP(const MachineFunction & MF) const30 bool XtensaFrameLowering::hasFP(const MachineFunction &MF) const {
31 const MachineFrameInfo &MFI = MF.getFrameInfo();
32 return MF.getTarget().Options.DisableFramePointerElim(MF) ||
33 MFI.hasVarSizedObjects();
34 }
35
emitPrologue(MachineFunction & MF,MachineBasicBlock & MBB) const36 void XtensaFrameLowering::emitPrologue(MachineFunction &MF,
37 MachineBasicBlock &MBB) const {
38 assert(&MBB == &MF.front() && "Shrink-wrapping not yet implemented");
39 MachineFrameInfo &MFI = MF.getFrameInfo();
40 MachineBasicBlock::iterator MBBI = MBB.begin();
41 DebugLoc DL = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc();
42 MCRegister SP = Xtensa::SP;
43 MCRegister FP = TRI->getFrameRegister(MF);
44 const MCRegisterInfo *MRI = MF.getContext().getRegisterInfo();
45
46 // First, compute final stack size.
47 uint64_t StackSize = MFI.getStackSize();
48 uint64_t PrevStackSize = StackSize;
49
50 // Round up StackSize to 16*N
51 StackSize += (16 - StackSize) & 0xf;
52
53 // No need to allocate space on the stack.
54 if (StackSize == 0 && !MFI.adjustsStack())
55 return;
56
57 // Adjust stack.
58 TII.adjustStackPtr(SP, -StackSize, MBB, MBBI);
59
60 // emit ".cfi_def_cfa_offset StackSize"
61 unsigned CFIIndex =
62 MF.addFrameInst(MCCFIInstruction::cfiDefCfaOffset(nullptr, StackSize));
63 BuildMI(MBB, MBBI, DL, TII.get(TargetOpcode::CFI_INSTRUCTION))
64 .addCFIIndex(CFIIndex);
65
66 const std::vector<CalleeSavedInfo> &CSI = MFI.getCalleeSavedInfo();
67
68 if (!CSI.empty()) {
69 // Find the instruction past the last instruction that saves a
70 // callee-saved register to the stack. The callee-saved store
71 // instructions are placed at the begin of basic block, so
72 // iterate over instruction sequence and check that
73 // save instructions are placed correctly.
74 for (unsigned i = 0, e = CSI.size(); i < e; ++i) {
75 #ifndef NDEBUG
76 const CalleeSavedInfo &Info = CSI[i];
77 int FI = Info.getFrameIdx();
78 int StoreFI = 0;
79
80 // Checking that the instruction is exactly as expected
81 bool IsStoreInst = false;
82 if (MBBI->getOpcode() == TargetOpcode::COPY && Info.isSpilledToReg()) {
83 Register DstReg = MBBI->getOperand(0).getReg();
84 Register Reg = MBBI->getOperand(1).getReg();
85 IsStoreInst = (Info.getDstReg() == DstReg) && (Info.getReg() == Reg);
86 } else {
87 Register Reg = TII.isStoreToStackSlot(*MBBI, StoreFI);
88 IsStoreInst = (Reg == Info.getReg()) && (StoreFI == FI);
89 }
90 assert(IsStoreInst &&
91 "Unexpected callee-saved register store instruction");
92 #endif
93 ++MBBI;
94 }
95
96 // Iterate over list of callee-saved registers and emit .cfi_offset
97 // directives.
98 for (const auto &I : CSI) {
99 int64_t Offset = MFI.getObjectOffset(I.getFrameIdx());
100 Register Reg = I.getReg();
101
102 unsigned CFIIndex = MF.addFrameInst(MCCFIInstruction::createOffset(
103 nullptr, MRI->getDwarfRegNum(Reg, 1), Offset));
104 BuildMI(MBB, MBBI, DL, TII.get(TargetOpcode::CFI_INSTRUCTION))
105 .addCFIIndex(CFIIndex);
106 }
107 }
108
109 // if framepointer enabled, set it to point to the stack pointer.
110 if (hasFP(MF)) {
111 // Insert instruction "move $fp, $sp" at this location.
112 BuildMI(MBB, MBBI, DL, TII.get(Xtensa::OR), FP)
113 .addReg(SP)
114 .addReg(SP)
115 .setMIFlag(MachineInstr::FrameSetup);
116
117 // emit ".cfi_def_cfa_register $fp"
118 unsigned CFIIndex = MF.addFrameInst(MCCFIInstruction::createDefCfaRegister(
119 nullptr, MRI->getDwarfRegNum(FP, true)));
120 BuildMI(MBB, MBBI, DL, TII.get(TargetOpcode::CFI_INSTRUCTION))
121 .addCFIIndex(CFIIndex);
122 }
123
124 if (StackSize != PrevStackSize) {
125 MFI.setStackSize(StackSize);
126
127 for (int i = MFI.getObjectIndexBegin(); i < MFI.getObjectIndexEnd(); i++) {
128 if (!MFI.isDeadObjectIndex(i)) {
129 int64_t SPOffset = MFI.getObjectOffset(i);
130
131 if (SPOffset < 0)
132 MFI.setObjectOffset(i, SPOffset - StackSize + PrevStackSize);
133 }
134 }
135 }
136 }
137
emitEpilogue(MachineFunction & MF,MachineBasicBlock & MBB) const138 void XtensaFrameLowering::emitEpilogue(MachineFunction &MF,
139 MachineBasicBlock &MBB) const {
140 MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr();
141 MachineFrameInfo &MFI = MF.getFrameInfo();
142 DebugLoc DL = MBBI->getDebugLoc();
143 MCRegister SP = Xtensa::SP;
144 MCRegister FP = TRI->getFrameRegister(MF);
145
146 // if framepointer enabled, restore the stack pointer.
147 if (hasFP(MF)) {
148 // We should place restore stack pointer instruction just before
149 // sequence of instructions which restores callee-saved registers.
150 // This sequence is placed at the end of the basic block,
151 // so we should find first instruction of the sequence.
152 MachineBasicBlock::iterator I = MBBI;
153
154 const std::vector<CalleeSavedInfo> &CSI = MFI.getCalleeSavedInfo();
155
156 // Find the first instruction at the end that restores a callee-saved
157 // register.
158 for (unsigned i = 0, e = CSI.size(); i < e; ++i) {
159 --I;
160 #ifndef NDEBUG
161 const CalleeSavedInfo &Info = CSI[i];
162 int FI = Info.getFrameIdx();
163 int LoadFI = 0;
164
165 // Checking that the instruction is exactly as expected
166 bool IsRestoreInst = false;
167 if (I->getOpcode() == TargetOpcode::COPY && Info.isSpilledToReg()) {
168 Register Reg = I->getOperand(0).getReg();
169 Register DstReg = I->getOperand(1).getReg();
170 IsRestoreInst = (Info.getDstReg() == DstReg) && (Info.getReg() == Reg);
171 } else {
172 Register Reg = TII.isLoadFromStackSlot(*I, LoadFI);
173 IsRestoreInst = (Info.getReg() == Reg) && (LoadFI == FI);
174 }
175 assert(IsRestoreInst &&
176 "Unexpected callee-saved register restore instruction");
177 #endif
178 }
179
180 BuildMI(MBB, I, DL, TII.get(Xtensa::OR), SP).addReg(FP).addReg(FP);
181 }
182
183 // Get the number of bytes from FrameInfo
184 uint64_t StackSize = MFI.getStackSize();
185
186 if (!StackSize)
187 return;
188
189 // Adjust stack.
190 TII.adjustStackPtr(SP, StackSize, MBB, MBBI);
191 }
192
spillCalleeSavedRegisters(MachineBasicBlock & MBB,MachineBasicBlock::iterator MI,ArrayRef<CalleeSavedInfo> CSI,const TargetRegisterInfo * TRI) const193 bool XtensaFrameLowering::spillCalleeSavedRegisters(
194 MachineBasicBlock &MBB, MachineBasicBlock::iterator MI,
195 ArrayRef<CalleeSavedInfo> CSI, const TargetRegisterInfo *TRI) const {
196 MachineFunction *MF = MBB.getParent();
197 MachineBasicBlock &EntryBlock = *(MF->begin());
198
199 for (unsigned i = 0, e = CSI.size(); i != e; ++i) {
200 // Add the callee-saved register as live-in. Do not add if the register is
201 // A0 and return address is taken, because it will be implemented in
202 // method XtensaTargetLowering::LowerRETURNADDR.
203 // It's killed at the spill, unless the register is RA and return address
204 // is taken.
205 Register Reg = CSI[i].getReg();
206 bool IsA0AndRetAddrIsTaken =
207 (Reg == Xtensa::A0) && MF->getFrameInfo().isReturnAddressTaken();
208 if (!IsA0AndRetAddrIsTaken)
209 EntryBlock.addLiveIn(Reg);
210
211 // Insert the spill to the stack frame.
212 bool IsKill = !IsA0AndRetAddrIsTaken;
213 const TargetRegisterClass *RC = TRI->getMinimalPhysRegClass(Reg);
214 TII.storeRegToStackSlot(EntryBlock, MI, Reg, IsKill, CSI[i].getFrameIdx(),
215 RC, TRI, Register());
216 }
217
218 return true;
219 }
220
restoreCalleeSavedRegisters(MachineBasicBlock & MBB,MachineBasicBlock::iterator MI,MutableArrayRef<CalleeSavedInfo> CSI,const TargetRegisterInfo * TRI) const221 bool XtensaFrameLowering::restoreCalleeSavedRegisters(
222 MachineBasicBlock &MBB, MachineBasicBlock::iterator MI,
223 MutableArrayRef<CalleeSavedInfo> CSI, const TargetRegisterInfo *TRI) const {
224 return TargetFrameLowering::restoreCalleeSavedRegisters(MBB, MI, CSI, TRI);
225 }
226
227 // Eliminate ADJCALLSTACKDOWN, ADJCALLSTACKUP pseudo instructions
eliminateCallFramePseudoInstr(MachineFunction & MF,MachineBasicBlock & MBB,MachineBasicBlock::iterator I) const228 MachineBasicBlock::iterator XtensaFrameLowering::eliminateCallFramePseudoInstr(
229 MachineFunction &MF, MachineBasicBlock &MBB,
230 MachineBasicBlock::iterator I) const {
231 const XtensaInstrInfo &TII =
232 *static_cast<const XtensaInstrInfo *>(MF.getSubtarget().getInstrInfo());
233
234 if (!hasReservedCallFrame(MF)) {
235 int64_t Amount = I->getOperand(0).getImm();
236
237 if (I->getOpcode() == Xtensa::ADJCALLSTACKDOWN)
238 Amount = -Amount;
239
240 TII.adjustStackPtr(Xtensa::SP, Amount, MBB, I);
241 }
242
243 return MBB.erase(I);
244 }
245
determineCalleeSaves(MachineFunction & MF,BitVector & SavedRegs,RegScavenger * RS) const246 void XtensaFrameLowering::determineCalleeSaves(MachineFunction &MF,
247 BitVector &SavedRegs,
248 RegScavenger *RS) const {
249 unsigned FP = TRI->getFrameRegister(MF);
250
251 TargetFrameLowering::determineCalleeSaves(MF, SavedRegs, RS);
252
253 // Mark $fp as used if function has dedicated frame pointer.
254 if (hasFP(MF))
255 SavedRegs.set(FP);
256 }
257
processFunctionBeforeFrameFinalized(MachineFunction & MF,RegScavenger * RS) const258 void XtensaFrameLowering::processFunctionBeforeFrameFinalized(
259 MachineFunction &MF, RegScavenger *RS) const {
260 // Set scavenging frame index if necessary.
261 MachineFrameInfo &MFI = MF.getFrameInfo();
262 uint64_t MaxSPOffset = MFI.estimateStackSize(MF);
263
264 if (isInt<12>(MaxSPOffset))
265 return;
266
267 const TargetRegisterClass &RC = Xtensa::ARRegClass;
268 unsigned Size = TRI->getSpillSize(RC);
269 Align Alignment = TRI->getSpillAlign(RC);
270 int FI = MF.getFrameInfo().CreateStackObject(Size, Alignment, false);
271
272 RS->addScavengingFrameIndex(FI);
273 }
274