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

source code of llvm/lib/Target/MSP430/MSP430FrameLowering.cpp