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
26using namespace llvm;
27
28MSP430FrameLowering::MSP430FrameLowering(const MSP430Subtarget &STI)
29 : TargetFrameLowering(TargetFrameLowering::StackGrowsDown, Align(2), -2,
30 Align(2)),
31 STI(STI), TII(*STI.getInstrInfo()), TRI(STI.getRegisterInfo()) {}
32
33bool 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
41bool MSP430FrameLowering::hasReservedCallFrame(const MachineFunction &MF) const {
42 return !MF.getFrameInfo().hasVarSizedObjects();
43}
44
45void 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(Inst: CFIInst);
52 BuildMI(BB&: MBB, I: MBBI, MIMD: DL, MCID: TII.get(Opcode: TargetOpcode::CFI_INSTRUCTION))
53 .addCFIIndex(CFIIndex)
54 .setMIFlag(Flag);
55}
56
57void 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(ObjectIdx: I.getFrameIdx());
70 Register Reg = I.getReg();
71 unsigned DwarfReg = MRI->getDwarfRegNum(RegNum: Reg, isEH: true);
72
73 if (IsPrologue) {
74 BuildCFI(MBB, MBBI, DL,
75 CFIInst: MCCFIInstruction::createOffset(L: nullptr, Register: DwarfReg, Offset));
76 } else {
77 BuildCFI(MBB, MBBI, DL,
78 CFIInst: MCCFIInstruction::createRestore(L: nullptr, Register: DwarfReg));
79 }
80 }
81}
82
83void 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(BB&: MBB, I: MBBI, MIMD: DL, MCID: TII.get(Opcode: MSP430::PUSH16r))
111 .addReg(RegNo: MSP430::R4, flags: 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 CFIInst: MCCFIInstruction::cfiDefCfaOffset(L: nullptr, Offset: -2 * stackGrowth),
118 Flag: MachineInstr::FrameSetup);
119
120 // Change the rule for the FramePtr to be an "offset" rule.
121 unsigned DwarfFramePtr = TRI->getDwarfRegNum(RegNum: MSP430::R4, isEH: true);
122 BuildCFI(
123 MBB, MBBI, DL,
124 CFIInst: MCCFIInstruction::createOffset(L: nullptr, Register: DwarfFramePtr, Offset: 2 * stackGrowth),
125 Flag: MachineInstr::FrameSetup);
126
127 // Update FP with the new base value...
128 BuildMI(BB&: MBB, I: MBBI, MIMD: DL, MCID: TII.get(Opcode: MSP430::MOV16rr), DestReg: MSP430::R4)
129 .addReg(RegNo: 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 CFIInst: MCCFIInstruction::createDefCfaRegister(L: nullptr, Register: DwarfFramePtr),
136 Flag: MachineInstr::FrameSetup);
137
138 // Mark the FramePtr as live-in in every block except the entry.
139 for (MachineBasicBlock &MBBJ : llvm::drop_begin(RangeOrContainer&: MF))
140 MBBJ.addLiveIn(PhysReg: 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(Flag: 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 CFIInst: MCCFIInstruction::cfiDefCfaOffset(L: nullptr, Offset: -StackOffset),
156 Flag: 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(BB&: MBB, I: MBBI, MIMD: DL, MCID: TII.get(Opcode: MSP430::SUB16ri), DestReg: MSP430::SP)
175 .addReg(RegNo: MSP430::SP)
176 .addImm(Val: NumBytes)
177 .setMIFlag(MachineInstr::FrameSetup);
178 // The SRW implicit def is dead.
179 MI->getOperand(i: 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 CFIInst: MCCFIInstruction::cfiDefCfaOffset(L: nullptr, Offset: StackSize - stackGrowth),
186 Flag: MachineInstr::FrameSetup);
187 }
188 }
189
190 emitCalleeSavedFrameMoves(MBB, MBBI, DL, IsPrologue: true);
191}
192
193void 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(BB&: MBB, I: MBBI, MIMD: DL, MCID: TII.get(Opcode: MSP430::POP16r), DestReg: MSP430::R4)
224 .setMIFlag(MachineInstr::FrameDestroy);
225 unsigned DwarfStackPtr = TRI->getDwarfRegNum(RegNum: MSP430::SP, isEH: true);
226 BuildCFI(MBB, MBBI, DL,
227 CFIInst: MCCFIInstruction::cfiDefCfa(L: nullptr, Register: DwarfStackPtr, Offset: 2),
228 Flag: MachineInstr::FrameDestroy);
229 --MBBI;
230 if (!MBB.succ_empty() && !MBB.isReturnBlock()) {
231 unsigned DwarfFramePtr = TRI->getDwarfRegNum(RegNum: MSP430::R4, isEH: true);
232 BuildCFI(MBB, MBBI: AfterPop, DL,
233 CFIInst: MCCFIInstruction::createRestore(L: nullptr, Register: DwarfFramePtr),
234 Flag: 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(x: MBBI);
245 unsigned Opc = PI->getOpcode();
246 if ((Opc != MSP430::POP16r || !PI->getFlag(Flag: 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(BB&: MBB, I: MBBI, MIMD: DL, MCID: TII.get(Opcode: MSP430::MOV16rr), DestReg: MSP430::SP)
263 .addReg(RegNo: MSP430::R4)
264 .setMIFlag(MachineInstr::FrameDestroy);
265 if (CSSize) {
266 MachineInstr *MI =
267 BuildMI(BB&: MBB, I: MBBI, MIMD: DL, MCID: TII.get(Opcode: MSP430::SUB16ri), DestReg: MSP430::SP)
268 .addReg(RegNo: MSP430::SP)
269 .addImm(Val: CSSize)
270 .setMIFlag(MachineInstr::FrameDestroy);
271 // The SRW implicit def is dead.
272 MI->getOperand(i: 3).setIsDead();
273 }
274 } else {
275 // adjust stack pointer back: SP += numbytes
276 if (NumBytes) {
277 MachineInstr *MI =
278 BuildMI(BB&: MBB, I: MBBI, MIMD: DL, MCID: TII.get(Opcode: MSP430::ADD16ri), DestReg: MSP430::SP)
279 .addReg(RegNo: MSP430::SP)
280 .addImm(Val: NumBytes)
281 .setMIFlag(MachineInstr::FrameDestroy);
282 // The SRW implicit def is dead.
283 MI->getOperand(i: 3).setIsDead();
284
285 if (!hasFP(MF)) {
286 // Adjust CFA value if it was defined by SP
287 BuildCFI(MBB, MBBI, DL,
288 CFIInst: MCCFIInstruction::cfiDefCfaOffset(L: nullptr, Offset: CSSize + 2),
289 Flag: 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 CFIInst: MCCFIInstruction::cfiDefCfaOffset(L: nullptr, Offset: -Offset),
307 Flag: MachineInstr::FrameDestroy);
308 }
309 }
310 }
311 emitCalleeSavedFrameMoves(MBB, MBBI: AfterPop, DL, IsPrologue: false);
312}
313
314// FIXME: Can we eleminate these in favour of generic code?
315bool 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(PhysReg: Reg);
333 BuildMI(BB&: MBB, I: MI, MIMD: DL, MCID: TII.get(Opcode: MSP430::PUSH16r))
334 .addReg(RegNo: Reg, flags: RegState::Kill)
335 .setMIFlag(MachineInstr::FrameSetup);
336 }
337 return true;
338}
339
340bool 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(C&: CSI))
353 BuildMI(BB&: MBB, I: MI, MIMD: DL, MCID: TII.get(Opcode: MSP430::POP16r), DestReg: I.getReg())
354 .setMIFlag(MachineInstr::FrameDestroy);
355
356 return true;
357}
358
359MachineBasicBlock::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(I: 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(Size: Amount, A: getStackAlign());
376
377 MachineInstr *New = nullptr;
378 if (Old.getOpcode() == TII.getCallFrameSetupOpcode()) {
379 New =
380 BuildMI(MF, MIMD: Old.getDebugLoc(), MCID: TII.get(Opcode: MSP430::SUB16ri), DestReg: MSP430::SP)
381 .addReg(RegNo: MSP430::SP)
382 .addImm(Val: Amount);
383 } else {
384 assert(Old.getOpcode() == TII.getCallFrameDestroyOpcode());
385 // factor out the amount the callee already popped.
386 Amount -= TII.getFramePoppedByCallee(I: Old);
387 if (Amount)
388 New = BuildMI(MF, MIMD: Old.getDebugLoc(), MCID: TII.get(Opcode: MSP430::ADD16ri),
389 DestReg: MSP430::SP)
390 .addReg(RegNo: MSP430::SP)
391 .addImm(Val: Amount);
392 }
393
394 if (New) {
395 // The SRW implicit def is dead.
396 New->getOperand(i: 3).setIsDead();
397
398 // Replace the pseudo instruction with a new instruction...
399 MBB.insert(I, MI: 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: *I)) {
406 MachineInstr &Old = *I;
407 MachineInstr *New =
408 BuildMI(MF, MIMD: Old.getDebugLoc(), MCID: TII.get(Opcode: MSP430::SUB16ri), DestReg: MSP430::SP)
409 .addReg(RegNo: MSP430::SP)
410 .addImm(Val: CalleeAmt);
411 if (!hasFP(MF)) {
412 DebugLoc DL = I->getDebugLoc();
413 BuildCFI(MBB, MBBI: I, DL,
414 CFIInst: MCCFIInstruction::createAdjustCfaOffset(L: nullptr, Adjustment: CalleeAmt));
415 }
416 // The SRW implicit def is dead.
417 New->getOperand(i: 3).setIsDead();
418
419 MBB.insert(I, MI: New);
420 }
421 }
422
423 return MBB.erase(I);
424}
425
426void
427MSP430FrameLowering::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(Size: 2, SPOffset: -4, IsImmutable: 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