Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/llvm/lib/Target/Xtensa/XtensaFrameLowering.cpp
35271 views
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
25
XtensaFrameLowering::XtensaFrameLowering(const XtensaSubtarget &STI)
26
: TargetFrameLowering(TargetFrameLowering::StackGrowsDown, Align(4), 0,
27
Align(4)),
28
TII(*STI.getInstrInfo()), TRI(STI.getRegisterInfo()) {}
29
30
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
36
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
138
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
193
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
221
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
228
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
246
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
258
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
275