-
-
Notifications
You must be signed in to change notification settings - Fork 0
/
0008-Xtensa-Implement-emitPrologue-emitEpilogue.patch
284 lines (275 loc) · 11.2 KB
/
0008-Xtensa-Implement-emitPrologue-emitEpilogue.patch
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
From 7d2d847a8a3888a9b176e52a18e31655fe5a0151 Mon Sep 17 00:00:00 2001
From: Andrei Safronov <safronov@espressif.com>
Date: Wed, 5 Apr 2023 00:58:39 +0300
Subject: [PATCH 008/158] [Xtensa] Implement emitPrologue/emitEpilogue
---
.../lib/Target/Xtensa/XtensaFrameLowering.cpp | 223 +++++++++++++++++-
llvm/lib/Target/Xtensa/XtensaFrameLowering.h | 13 +
2 files changed, 234 insertions(+), 2 deletions(-)
diff --git a/llvm/lib/Target/Xtensa/XtensaFrameLowering.cpp b/llvm/lib/Target/Xtensa/XtensaFrameLowering.cpp
index 71941e767193..e87f2809a51e 100644
--- a/llvm/lib/Target/Xtensa/XtensaFrameLowering.cpp
+++ b/llvm/lib/Target/Xtensa/XtensaFrameLowering.cpp
@@ -28,6 +28,48 @@ XtensaFrameLowering::XtensaFrameLowering()
: TargetFrameLowering(TargetFrameLowering::StackGrowsDown, Align(4), 0,
Align(4)) {}
+/* Xtensa stack frames look like:
+
+ +-------------------------------+
+ | incoming stack arguments |
+ +-------------------------------+
+ A | caller-allocated save area |
+ | for register arguments |
+ +-------------------------------+ <-- incoming stack pointer
+ B | CALL0 ABI: |
+ | callee-allocated save area |
+ | for arguments that are |
+ | split between registers and |
+ | the stack (Register-Spill |
+ | Area) |
+ | |
+ | Win ABI: |
+ | Register-Spill Overflow |
+ | 8 words for CALL8/CALLX8 |
+ +-------------------------------+ <-- arg_pointer_rtx
+ C | callee-allocated save area |
+ | for register varargs |
+ +-------------------------------+ <-- hard_frame_pointer_rtx;
+ | | stack_pointer_rtx + gp_sp_offset
+ | GPR save area | + UNITS_PER_WORD
+ +-------------------------------+ <-- stack_pointer_rtx + fp_sp_offset
+ | | + UNITS_PER_HWVALUE
+ | FPR save area |
+ +-------------------------------+ <-- frame_pointer_rtx (virtual)
+ | local variables |
+ P +-------------------------------+
+ | outgoing stack arguments |
+ +-------------------------------+
+ | caller-allocated save area |
+ | for register arguments |
+ +-------------------------------+ <-- stack_pointer_rtx
+
+ At least two of A, B and C will be empty.
+
+ Dynamic stack allocations such as alloca insert data at point P.
+ They decrease stack_pointer_rtx but leave frame_pointer_rtx and
+ hard_frame_pointer_rtx unchanged. */
+
// hasFP - Return true if the specified function should have a dedicated frame
// pointer register. This is true if the function has variable sized allocas or
// if frame pointer elimination is disabled.
@@ -38,10 +80,159 @@ bool XtensaFrameLowering::hasFP(const MachineFunction &MF) const {
}
void XtensaFrameLowering::emitPrologue(MachineFunction &MF,
- MachineBasicBlock &MBB) const {}
+ MachineBasicBlock &MBB) const {
+ assert(&MBB == &MF.front() && "Shrink-wrapping not yet implemented");
+ MachineFrameInfo &MFI = MF.getFrameInfo();
+ const XtensaRegisterInfo *RegInfo = static_cast<const XtensaRegisterInfo *>(
+ MF.getSubtarget().getRegisterInfo());
+ const XtensaInstrInfo &TII =
+ *static_cast<const XtensaInstrInfo *>(MF.getSubtarget().getInstrInfo());
+ MachineBasicBlock::iterator MBBI = MBB.begin();
+ DebugLoc dl = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc();
+ unsigned SP = Xtensa::SP;
+ unsigned FP = RegInfo->getFrameRegister(MF);
+ MachineModuleInfo &MMI = MF.getMMI();
+ const MCRegisterInfo *MRI = MMI.getContext().getRegisterInfo();
+
+ // First, compute final stack size.
+ uint64_t StackSize = MFI.getStackSize();
+ uint64_t PrevStackSize = StackSize;
+
+ // Round up StackSize to 16*N
+ StackSize += (16 - StackSize) & 0xf;
+
+ // No need to allocate space on the stack.
+ if (StackSize == 0 && !MFI.adjustsStack())
+ return;
+
+ // Adjust stack.
+ TII.adjustStackPtr(SP, -StackSize, MBB, MBBI);
+
+ // emit ".cfi_def_cfa_offset StackSize"
+ unsigned CFIIndex = MF.addFrameInst(
+ MCCFIInstruction::cfiDefCfaOffset(nullptr, StackSize));
+ BuildMI(MBB, MBBI, dl, TII.get(TargetOpcode::CFI_INSTRUCTION))
+ .addCFIIndex(CFIIndex);
+
+ const std::vector<CalleeSavedInfo> &CSI = MFI.getCalleeSavedInfo();
+
+ if (CSI.size()) {
+ // Find the instruction past the last instruction that saves a
+ // callee-saved register to the stack.
+ for (unsigned i = 0; i < CSI.size(); ++i)
+ ++MBBI;
+
+ // Iterate over list of callee-saved registers and emit .cfi_offset
+ // directives.
+ for (const auto &I : CSI) {
+ int64_t Offset = MFI.getObjectOffset(I.getFrameIdx());
+ unsigned Reg = I.getReg();
+
+ unsigned CFIIndex = MF.addFrameInst(MCCFIInstruction::createOffset(
+ nullptr, MRI->getDwarfRegNum(Reg, 1), Offset));
+ BuildMI(MBB, MBBI, dl, TII.get(TargetOpcode::CFI_INSTRUCTION))
+ .addCFIIndex(CFIIndex);
+ }
+ }
+
+ // if framepointer enabled, set it to point to the stack pointer.
+ if (hasFP(MF)) {
+ // Insert instruction "move $fp, $sp" at this location.
+ BuildMI(MBB, MBBI, dl, TII.get(Xtensa::OR), FP)
+ .addReg(SP)
+ .addReg(SP)
+ .setMIFlag(MachineInstr::FrameSetup);
+
+ // emit ".cfi_def_cfa_register $fp"
+ unsigned CFIIndex = MF.addFrameInst(MCCFIInstruction::createDefCfaRegister(
+ nullptr, MRI->getDwarfRegNum(FP, true)));
+ BuildMI(MBB, MBBI, dl, TII.get(TargetOpcode::CFI_INSTRUCTION))
+ .addCFIIndex(CFIIndex);
+ }
+
+ if (StackSize != PrevStackSize) {
+ MFI.setStackSize(StackSize);
+
+ for (int i = MFI.getObjectIndexBegin(); i < MFI.getObjectIndexEnd(); i++) {
+ if (!MFI.isDeadObjectIndex(i)) {
+ int64_t SPOffset = MFI.getObjectOffset(i);
+
+ if (SPOffset < 0)
+ MFI.setObjectOffset(i, SPOffset - StackSize + PrevStackSize);
+ }
+ }
+ }
+}
void XtensaFrameLowering::emitEpilogue(MachineFunction &MF,
- MachineBasicBlock &MBB) const {}
+ MachineBasicBlock &MBB) const {
+ MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr();
+ MachineFrameInfo &MFI = MF.getFrameInfo();
+ const XtensaRegisterInfo *RegInfo = static_cast<const XtensaRegisterInfo *>(
+ MF.getSubtarget().getRegisterInfo());
+ const XtensaInstrInfo &TII =
+ *static_cast<const XtensaInstrInfo *>(MF.getSubtarget().getInstrInfo());
+ DebugLoc dl = MBBI->getDebugLoc();
+ unsigned SP = Xtensa::SP;
+ unsigned FP = RegInfo->getFrameRegister(MF);
+
+ // if framepointer enabled, restore the stack pointer.
+ if (hasFP(MF)) {
+ // Find the first instruction that restores a callee-saved register.
+ MachineBasicBlock::iterator I = MBBI;
+
+ for (unsigned i = 0; i < MFI.getCalleeSavedInfo().size(); ++i)
+ --I;
+
+ BuildMI(MBB, I, dl, TII.get(Xtensa::OR), SP).addReg(FP).addReg(FP);
+ }
+
+ // Get the number of bytes from FrameInfo
+ uint64_t StackSize = MFI.getStackSize();
+
+ if (!StackSize)
+ return;
+
+ // Adjust stack.
+ TII.adjustStackPtr(SP, StackSize, MBB, MBBI);
+}
+
+bool XtensaFrameLowering::spillCalleeSavedRegisters(
+ MachineBasicBlock &MBB, MachineBasicBlock::iterator MI,
+ ArrayRef<CalleeSavedInfo> CSI, const TargetRegisterInfo *TRI) const {
+ MachineFunction *MF = MBB.getParent();
+
+ MachineBasicBlock &EntryBlock = *(MF->begin());
+ const TargetInstrInfo &TII = *MF->getSubtarget().getInstrInfo();
+
+ for (unsigned i = 0, e = CSI.size(); i != e; ++i) {
+ // Add the callee-saved register as live-in. Do not add if the register is
+ // A0 and return address is taken, because it will be implemented in
+ // method XtensaTargetLowering::LowerRETURNADDR.
+ // It's killed at the spill, unless the register is RA and return address
+ // is taken.
+ unsigned Reg = CSI[i].getReg();
+ bool IsA0AndRetAddrIsTaken =
+ (Reg == Xtensa::A0) && MF->getFrameInfo().isReturnAddressTaken();
+ if (!IsA0AndRetAddrIsTaken)
+ EntryBlock.addLiveIn(Reg);
+
+ // Insert the spill to the stack frame.
+ bool IsKill = !IsA0AndRetAddrIsTaken;
+ const TargetRegisterClass *RC = TRI->getMinimalPhysRegClass(Reg);
+ TII.storeRegToStackSlot(EntryBlock, MI, Reg, IsKill, CSI[i].getFrameIdx(),
+ RC, TRI, Register());
+ }
+
+ return true;
+}
+
+bool XtensaFrameLowering::restoreCalleeSavedRegisters(
+ MachineBasicBlock &MBB, MachineBasicBlock::iterator MI,
+ MutableArrayRef<CalleeSavedInfo> CSI,
+ const TargetRegisterInfo *TRI) const {
+ return TargetFrameLowering::restoreCalleeSavedRegisters(MBB, MI, CSI, TRI);
+}
// Eliminate ADJCALLSTACKDOWN, ADJCALLSTACKUP pseudo instructions
MachineBasicBlock::iterator XtensaFrameLowering::eliminateCallFramePseudoInstr(
@@ -62,3 +253,31 @@ MachineBasicBlock::iterator XtensaFrameLowering::eliminateCallFramePseudoInstr(
return MBB.erase(I);
}
+
+void XtensaFrameLowering::determineCalleeSaves(MachineFunction &MF,
+ BitVector &SavedRegs,
+ RegScavenger *RS) const {
+ MachineFrameInfo &MFI = MF.getFrameInfo();
+ const XtensaRegisterInfo *RegInfo = static_cast<const XtensaRegisterInfo *>(
+ MF.getSubtarget().getRegisterInfo());
+ unsigned FP = RegInfo->getFrameRegister(MF);
+
+ TargetFrameLowering::determineCalleeSaves(MF, SavedRegs, RS);
+
+ // Mark $fp as used if function has dedicated frame pointer.
+ if (hasFP(MF))
+ SavedRegs.set(FP);
+
+ // Set scavenging frame index if necessary.
+ uint64_t MaxSPOffset = MFI.estimateStackSize(MF);
+
+ if (isInt<12>(MaxSPOffset))
+ return;
+
+ const TargetRegisterClass &RC = Xtensa::ARRegClass;
+ const TargetRegisterInfo *TRI = MF.getSubtarget().getRegisterInfo();
+ unsigned Size = TRI->getSpillSize(RC);
+ Align Alignment = TRI->getSpillAlign(RC);
+ int FI = MF.getFrameInfo().CreateStackObject(Size, Alignment, false);
+ RS->addScavengingFrameIndex(FI);
+}
diff --git a/llvm/lib/Target/Xtensa/XtensaFrameLowering.h b/llvm/lib/Target/Xtensa/XtensaFrameLowering.h
index 584438d179bb..b112f069cd61 100644
--- a/llvm/lib/Target/Xtensa/XtensaFrameLowering.h
+++ b/llvm/lib/Target/Xtensa/XtensaFrameLowering.h
@@ -31,6 +31,19 @@ public:
MachineBasicBlock::iterator
eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB,
MachineBasicBlock::iterator I) const override;
+
+ bool spillCalleeSavedRegisters(MachineBasicBlock &MBB,
+ MachineBasicBlock::iterator MI,
+ ArrayRef<CalleeSavedInfo> CSI,
+ const TargetRegisterInfo *TRI) const override;
+ bool
+ restoreCalleeSavedRegisters(MachineBasicBlock &MBB,
+ MachineBasicBlock::iterator MI,
+ MutableArrayRef<CalleeSavedInfo> CSI,
+ const TargetRegisterInfo *TRI) const override;
+
+ void determineCalleeSaves(MachineFunction &MF, BitVector &SavedRegs,
+ RegScavenger *RS) const override;
};
} // namespace llvm
--
2.40.1