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