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