Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/llvm/lib/Target/MSP430/MSP430FrameLowering.cpp
35294 views
1
//===-- MSP430FrameLowering.cpp - MSP430 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 MSP430 implementation of TargetFrameLowering class.
10
//
11
//===----------------------------------------------------------------------===//
12
13
#include "MSP430FrameLowering.h"
14
#include "MSP430InstrInfo.h"
15
#include "MSP430MachineFunctionInfo.h"
16
#include "MSP430Subtarget.h"
17
#include "llvm/CodeGen/MachineFrameInfo.h"
18
#include "llvm/CodeGen/MachineFunction.h"
19
#include "llvm/CodeGen/MachineInstrBuilder.h"
20
#include "llvm/CodeGen/MachineModuleInfo.h"
21
#include "llvm/CodeGen/MachineRegisterInfo.h"
22
#include "llvm/IR/DataLayout.h"
23
#include "llvm/IR/Function.h"
24
#include "llvm/Target/TargetOptions.h"
25
26
using namespace llvm;
27
28
MSP430FrameLowering::MSP430FrameLowering(const MSP430Subtarget &STI)
29
: TargetFrameLowering(TargetFrameLowering::StackGrowsDown, Align(2), -2,
30
Align(2)),
31
STI(STI), TII(*STI.getInstrInfo()), TRI(STI.getRegisterInfo()) {}
32
33
bool MSP430FrameLowering::hasFP(const MachineFunction &MF) const {
34
const MachineFrameInfo &MFI = MF.getFrameInfo();
35
36
return (MF.getTarget().Options.DisableFramePointerElim(MF) ||
37
MF.getFrameInfo().hasVarSizedObjects() ||
38
MFI.isFrameAddressTaken());
39
}
40
41
bool MSP430FrameLowering::hasReservedCallFrame(const MachineFunction &MF) const {
42
return !MF.getFrameInfo().hasVarSizedObjects();
43
}
44
45
void MSP430FrameLowering::BuildCFI(MachineBasicBlock &MBB,
46
MachineBasicBlock::iterator MBBI,
47
const DebugLoc &DL,
48
const MCCFIInstruction &CFIInst,
49
MachineInstr::MIFlag Flag) const {
50
MachineFunction &MF = *MBB.getParent();
51
unsigned CFIIndex = MF.addFrameInst(CFIInst);
52
BuildMI(MBB, MBBI, DL, TII.get(TargetOpcode::CFI_INSTRUCTION))
53
.addCFIIndex(CFIIndex)
54
.setMIFlag(Flag);
55
}
56
57
void MSP430FrameLowering::emitCalleeSavedFrameMoves(
58
MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
59
const DebugLoc &DL, bool IsPrologue) const {
60
MachineFunction &MF = *MBB.getParent();
61
MachineFrameInfo &MFI = MF.getFrameInfo();
62
const MCRegisterInfo *MRI = MF.getContext().getRegisterInfo();
63
64
// Add callee saved registers to move list.
65
const std::vector<CalleeSavedInfo> &CSI = MFI.getCalleeSavedInfo();
66
67
// Calculate offsets.
68
for (const CalleeSavedInfo &I : CSI) {
69
int64_t Offset = MFI.getObjectOffset(I.getFrameIdx());
70
Register Reg = I.getReg();
71
unsigned DwarfReg = MRI->getDwarfRegNum(Reg, true);
72
73
if (IsPrologue) {
74
BuildCFI(MBB, MBBI, DL,
75
MCCFIInstruction::createOffset(nullptr, DwarfReg, Offset));
76
} else {
77
BuildCFI(MBB, MBBI, DL,
78
MCCFIInstruction::createRestore(nullptr, DwarfReg));
79
}
80
}
81
}
82
83
void MSP430FrameLowering::emitPrologue(MachineFunction &MF,
84
MachineBasicBlock &MBB) const {
85
assert(&MF.front() == &MBB && "Shrink-wrapping not yet supported");
86
MachineFrameInfo &MFI = MF.getFrameInfo();
87
MSP430MachineFunctionInfo *MSP430FI = MF.getInfo<MSP430MachineFunctionInfo>();
88
const MSP430InstrInfo &TII =
89
*static_cast<const MSP430InstrInfo *>(MF.getSubtarget().getInstrInfo());
90
91
MachineBasicBlock::iterator MBBI = MBB.begin();
92
DebugLoc DL = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc();
93
94
// Get the number of bytes to allocate from the FrameInfo.
95
uint64_t StackSize = MFI.getStackSize();
96
int stackGrowth = -2;
97
98
uint64_t NumBytes = 0;
99
if (hasFP(MF)) {
100
// Calculate required stack adjustment
101
uint64_t FrameSize = StackSize - 2;
102
NumBytes = FrameSize - MSP430FI->getCalleeSavedFrameSize();
103
104
// Get the offset of the stack slot for the EBP register... which is
105
// guaranteed to be the last slot by processFunctionBeforeFrameFinalized.
106
// Update the frame offset adjustment.
107
MFI.setOffsetAdjustment(-NumBytes);
108
109
// Save FP into the appropriate stack slot...
110
BuildMI(MBB, MBBI, DL, TII.get(MSP430::PUSH16r))
111
.addReg(MSP430::R4, RegState::Kill)
112
.setMIFlag(MachineInstr::FrameSetup);
113
114
// Mark the place where FP was saved.
115
// Define the current CFA rule to use the provided offset.
116
BuildCFI(MBB, MBBI, DL,
117
MCCFIInstruction::cfiDefCfaOffset(nullptr, -2 * stackGrowth),
118
MachineInstr::FrameSetup);
119
120
// Change the rule for the FramePtr to be an "offset" rule.
121
unsigned DwarfFramePtr = TRI->getDwarfRegNum(MSP430::R4, true);
122
BuildCFI(
123
MBB, MBBI, DL,
124
MCCFIInstruction::createOffset(nullptr, DwarfFramePtr, 2 * stackGrowth),
125
MachineInstr::FrameSetup);
126
127
// Update FP with the new base value...
128
BuildMI(MBB, MBBI, DL, TII.get(MSP430::MOV16rr), MSP430::R4)
129
.addReg(MSP430::SP)
130
.setMIFlag(MachineInstr::FrameSetup);
131
132
// Mark effective beginning of when frame pointer becomes valid.
133
// Define the current CFA to use the FP register.
134
BuildCFI(MBB, MBBI, DL,
135
MCCFIInstruction::createDefCfaRegister(nullptr, DwarfFramePtr),
136
MachineInstr::FrameSetup);
137
138
// Mark the FramePtr as live-in in every block except the entry.
139
for (MachineBasicBlock &MBBJ : llvm::drop_begin(MF))
140
MBBJ.addLiveIn(MSP430::R4);
141
} else
142
NumBytes = StackSize - MSP430FI->getCalleeSavedFrameSize();
143
144
// Skip the callee-saved push instructions.
145
int StackOffset = 2 * stackGrowth;
146
while (MBBI != MBB.end() && MBBI->getFlag(MachineInstr::FrameSetup) &&
147
(MBBI->getOpcode() == MSP430::PUSH16r)) {
148
++MBBI;
149
150
if (!hasFP(MF)) {
151
// Mark callee-saved push instruction.
152
// Define the current CFA rule to use the provided offset.
153
assert(StackSize && "Expected stack frame");
154
BuildCFI(MBB, MBBI, DL,
155
MCCFIInstruction::cfiDefCfaOffset(nullptr, -StackOffset),
156
MachineInstr::FrameSetup);
157
StackOffset += stackGrowth;
158
}
159
}
160
161
if (MBBI != MBB.end())
162
DL = MBBI->getDebugLoc();
163
164
if (NumBytes) { // adjust stack pointer: SP -= numbytes
165
// If there is an SUB16ri of SP immediately before this instruction, merge
166
// the two.
167
//NumBytes -= mergeSPUpdates(MBB, MBBI, true);
168
// If there is an ADD16ri or SUB16ri of SP immediately after this
169
// instruction, merge the two instructions.
170
// mergeSPUpdatesDown(MBB, MBBI, &NumBytes);
171
172
if (NumBytes) {
173
MachineInstr *MI =
174
BuildMI(MBB, MBBI, DL, TII.get(MSP430::SUB16ri), MSP430::SP)
175
.addReg(MSP430::SP)
176
.addImm(NumBytes)
177
.setMIFlag(MachineInstr::FrameSetup);
178
// The SRW implicit def is dead.
179
MI->getOperand(3).setIsDead();
180
}
181
if (!hasFP(MF)) {
182
// Adjust the previous CFA value if CFA was not redefined by FP
183
BuildCFI(
184
MBB, MBBI, DL,
185
MCCFIInstruction::cfiDefCfaOffset(nullptr, StackSize - stackGrowth),
186
MachineInstr::FrameSetup);
187
}
188
}
189
190
emitCalleeSavedFrameMoves(MBB, MBBI, DL, true);
191
}
192
193
void MSP430FrameLowering::emitEpilogue(MachineFunction &MF,
194
MachineBasicBlock &MBB) const {
195
const MachineFrameInfo &MFI = MF.getFrameInfo();
196
MSP430MachineFunctionInfo *MSP430FI = MF.getInfo<MSP430MachineFunctionInfo>();
197
const MSP430InstrInfo &TII =
198
*static_cast<const MSP430InstrInfo *>(MF.getSubtarget().getInstrInfo());
199
200
MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr();
201
unsigned RetOpcode = MBBI->getOpcode();
202
DebugLoc DL = MBBI->getDebugLoc();
203
204
switch (RetOpcode) {
205
case MSP430::RET:
206
case MSP430::RETI: break; // These are ok
207
default:
208
llvm_unreachable("Can only insert epilog into returning blocks");
209
}
210
211
// Get the number of bytes to allocate from the FrameInfo
212
uint64_t StackSize = MFI.getStackSize();
213
unsigned CSSize = MSP430FI->getCalleeSavedFrameSize();
214
uint64_t NumBytes = 0;
215
216
MachineBasicBlock::iterator AfterPop = MBBI;
217
if (hasFP(MF)) {
218
// Calculate required stack adjustment
219
uint64_t FrameSize = StackSize - 2;
220
NumBytes = FrameSize - CSSize;
221
222
// pop FP.
223
BuildMI(MBB, MBBI, DL, TII.get(MSP430::POP16r), MSP430::R4)
224
.setMIFlag(MachineInstr::FrameDestroy);
225
unsigned DwarfStackPtr = TRI->getDwarfRegNum(MSP430::SP, true);
226
BuildCFI(MBB, MBBI, DL,
227
MCCFIInstruction::cfiDefCfa(nullptr, DwarfStackPtr, 2),
228
MachineInstr::FrameDestroy);
229
--MBBI;
230
if (!MBB.succ_empty() && !MBB.isReturnBlock()) {
231
unsigned DwarfFramePtr = TRI->getDwarfRegNum(MSP430::R4, true);
232
BuildCFI(MBB, AfterPop, DL,
233
MCCFIInstruction::createRestore(nullptr, DwarfFramePtr),
234
MachineInstr::FrameDestroy);
235
--MBBI;
236
--AfterPop;
237
}
238
} else
239
NumBytes = StackSize - CSSize;
240
241
// Skip the callee-saved pop instructions.
242
MachineBasicBlock::iterator FirstCSPop = MBBI;
243
while (MBBI != MBB.begin()) {
244
MachineBasicBlock::iterator PI = std::prev(MBBI);
245
unsigned Opc = PI->getOpcode();
246
if ((Opc != MSP430::POP16r || !PI->getFlag(MachineInstr::FrameDestroy)) &&
247
!PI->isTerminator())
248
break;
249
FirstCSPop = PI;
250
--MBBI;
251
}
252
MBBI = FirstCSPop;
253
254
DL = MBBI->getDebugLoc();
255
256
// If there is an ADD16ri or SUB16ri of SP immediately before this
257
// instruction, merge the two instructions.
258
//if (NumBytes || MFI.hasVarSizedObjects())
259
// mergeSPUpdatesUp(MBB, MBBI, StackPtr, &NumBytes);
260
261
if (MFI.hasVarSizedObjects()) {
262
BuildMI(MBB, MBBI, DL, TII.get(MSP430::MOV16rr), MSP430::SP)
263
.addReg(MSP430::R4)
264
.setMIFlag(MachineInstr::FrameDestroy);
265
if (CSSize) {
266
MachineInstr *MI =
267
BuildMI(MBB, MBBI, DL, TII.get(MSP430::SUB16ri), MSP430::SP)
268
.addReg(MSP430::SP)
269
.addImm(CSSize)
270
.setMIFlag(MachineInstr::FrameDestroy);
271
// The SRW implicit def is dead.
272
MI->getOperand(3).setIsDead();
273
}
274
} else {
275
// adjust stack pointer back: SP += numbytes
276
if (NumBytes) {
277
MachineInstr *MI =
278
BuildMI(MBB, MBBI, DL, TII.get(MSP430::ADD16ri), MSP430::SP)
279
.addReg(MSP430::SP)
280
.addImm(NumBytes)
281
.setMIFlag(MachineInstr::FrameDestroy);
282
// The SRW implicit def is dead.
283
MI->getOperand(3).setIsDead();
284
285
if (!hasFP(MF)) {
286
// Adjust CFA value if it was defined by SP
287
BuildCFI(MBB, MBBI, DL,
288
MCCFIInstruction::cfiDefCfaOffset(nullptr, CSSize + 2),
289
MachineInstr::FrameDestroy);
290
}
291
}
292
}
293
294
if (!hasFP(MF)) {
295
MBBI = FirstCSPop;
296
int64_t Offset = -(int64_t)CSSize - 2;
297
// Mark callee-saved pop instruction.
298
// Define the current CFA rule to use the provided offset.
299
while (MBBI != MBB.end()) {
300
MachineBasicBlock::iterator PI = MBBI;
301
unsigned Opc = PI->getOpcode();
302
++MBBI;
303
if (Opc == MSP430::POP16r) {
304
Offset += 2;
305
BuildCFI(MBB, MBBI, DL,
306
MCCFIInstruction::cfiDefCfaOffset(nullptr, -Offset),
307
MachineInstr::FrameDestroy);
308
}
309
}
310
}
311
emitCalleeSavedFrameMoves(MBB, AfterPop, DL, false);
312
}
313
314
// FIXME: Can we eleminate these in favour of generic code?
315
bool MSP430FrameLowering::spillCalleeSavedRegisters(
316
MachineBasicBlock &MBB, MachineBasicBlock::iterator MI,
317
ArrayRef<CalleeSavedInfo> CSI, const TargetRegisterInfo *TRI) const {
318
if (CSI.empty())
319
return false;
320
321
DebugLoc DL;
322
if (MI != MBB.end()) DL = MI->getDebugLoc();
323
324
MachineFunction &MF = *MBB.getParent();
325
const TargetInstrInfo &TII = *MF.getSubtarget().getInstrInfo();
326
MSP430MachineFunctionInfo *MFI = MF.getInfo<MSP430MachineFunctionInfo>();
327
MFI->setCalleeSavedFrameSize(CSI.size() * 2);
328
329
for (const CalleeSavedInfo &I : CSI) {
330
Register Reg = I.getReg();
331
// Add the callee-saved register as live-in. It's killed at the spill.
332
MBB.addLiveIn(Reg);
333
BuildMI(MBB, MI, DL, TII.get(MSP430::PUSH16r))
334
.addReg(Reg, RegState::Kill)
335
.setMIFlag(MachineInstr::FrameSetup);
336
}
337
return true;
338
}
339
340
bool MSP430FrameLowering::restoreCalleeSavedRegisters(
341
MachineBasicBlock &MBB, MachineBasicBlock::iterator MI,
342
MutableArrayRef<CalleeSavedInfo> CSI, const TargetRegisterInfo *TRI) const {
343
if (CSI.empty())
344
return false;
345
346
DebugLoc DL;
347
if (MI != MBB.end()) DL = MI->getDebugLoc();
348
349
MachineFunction &MF = *MBB.getParent();
350
const TargetInstrInfo &TII = *MF.getSubtarget().getInstrInfo();
351
352
for (const CalleeSavedInfo &I : llvm::reverse(CSI))
353
BuildMI(MBB, MI, DL, TII.get(MSP430::POP16r), I.getReg())
354
.setMIFlag(MachineInstr::FrameDestroy);
355
356
return true;
357
}
358
359
MachineBasicBlock::iterator MSP430FrameLowering::eliminateCallFramePseudoInstr(
360
MachineFunction &MF, MachineBasicBlock &MBB,
361
MachineBasicBlock::iterator I) const {
362
const MSP430InstrInfo &TII =
363
*static_cast<const MSP430InstrInfo *>(MF.getSubtarget().getInstrInfo());
364
if (!hasReservedCallFrame(MF)) {
365
// If the stack pointer can be changed after prologue, turn the
366
// adjcallstackup instruction into a 'sub SP, <amt>' and the
367
// adjcallstackdown instruction into 'add SP, <amt>'
368
// TODO: consider using push / pop instead of sub + store / add
369
MachineInstr &Old = *I;
370
uint64_t Amount = TII.getFrameSize(Old);
371
if (Amount != 0) {
372
// We need to keep the stack aligned properly. To do this, we round the
373
// amount of space needed for the outgoing arguments up to the next
374
// alignment boundary.
375
Amount = alignTo(Amount, getStackAlign());
376
377
MachineInstr *New = nullptr;
378
if (Old.getOpcode() == TII.getCallFrameSetupOpcode()) {
379
New =
380
BuildMI(MF, Old.getDebugLoc(), TII.get(MSP430::SUB16ri), MSP430::SP)
381
.addReg(MSP430::SP)
382
.addImm(Amount);
383
} else {
384
assert(Old.getOpcode() == TII.getCallFrameDestroyOpcode());
385
// factor out the amount the callee already popped.
386
Amount -= TII.getFramePoppedByCallee(Old);
387
if (Amount)
388
New = BuildMI(MF, Old.getDebugLoc(), TII.get(MSP430::ADD16ri),
389
MSP430::SP)
390
.addReg(MSP430::SP)
391
.addImm(Amount);
392
}
393
394
if (New) {
395
// The SRW implicit def is dead.
396
New->getOperand(3).setIsDead();
397
398
// Replace the pseudo instruction with a new instruction...
399
MBB.insert(I, New);
400
}
401
}
402
} else if (I->getOpcode() == TII.getCallFrameDestroyOpcode()) {
403
// If we are performing frame pointer elimination and if the callee pops
404
// something off the stack pointer, add it back.
405
if (uint64_t CalleeAmt = TII.getFramePoppedByCallee(*I)) {
406
MachineInstr &Old = *I;
407
MachineInstr *New =
408
BuildMI(MF, Old.getDebugLoc(), TII.get(MSP430::SUB16ri), MSP430::SP)
409
.addReg(MSP430::SP)
410
.addImm(CalleeAmt);
411
if (!hasFP(MF)) {
412
DebugLoc DL = I->getDebugLoc();
413
BuildCFI(MBB, I, DL,
414
MCCFIInstruction::createAdjustCfaOffset(nullptr, CalleeAmt));
415
}
416
// The SRW implicit def is dead.
417
New->getOperand(3).setIsDead();
418
419
MBB.insert(I, New);
420
}
421
}
422
423
return MBB.erase(I);
424
}
425
426
void
427
MSP430FrameLowering::processFunctionBeforeFrameFinalized(MachineFunction &MF,
428
RegScavenger *) const {
429
// Create a frame entry for the FP register that must be saved.
430
if (hasFP(MF)) {
431
int FrameIdx = MF.getFrameInfo().CreateFixedObject(2, -4, true);
432
(void)FrameIdx;
433
assert(FrameIdx == MF.getFrameInfo().getObjectIndexBegin() &&
434
"Slot for FP register must be last in order to be found!");
435
}
436
}
437
438