xref: /freebsd/contrib/llvm-project/llvm/lib/Target/MSP430/MSP430FrameLowering.cpp (revision 770cf0a5f02dc8983a89c6568d741fbc25baa999)
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 
24 using namespace llvm;
25 
26 MSP430FrameLowering::MSP430FrameLowering(const MSP430Subtarget &STI)
27     : TargetFrameLowering(TargetFrameLowering::StackGrowsDown, Align(2), -2,
28                           Align(2)),
29       STI(STI), TII(*STI.getInstrInfo()), TRI(STI.getRegisterInfo()) {}
30 
31 bool 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 
39 bool MSP430FrameLowering::hasReservedCallFrame(const MachineFunction &MF) const {
40   return !MF.getFrameInfo().hasVarSizedObjects();
41 }
42 
43 void 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(CFIInst);
50   BuildMI(MBB, MBBI, DL, TII.get(TargetOpcode::CFI_INSTRUCTION))
51       .addCFIIndex(CFIIndex)
52       .setMIFlag(Flag);
53 }
54 
55 void 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(I.getFrameIdx());
68     MCRegister Reg = I.getReg();
69     unsigned DwarfReg = MRI->getDwarfRegNum(Reg, true);
70 
71     if (IsPrologue) {
72       BuildCFI(MBB, MBBI, DL,
73                MCCFIInstruction::createOffset(nullptr, DwarfReg, Offset));
74     } else {
75       BuildCFI(MBB, MBBI, DL,
76                MCCFIInstruction::createRestore(nullptr, DwarfReg));
77     }
78   }
79 }
80 
81 void 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(MBB, MBBI, DL, TII.get(MSP430::PUSH16r))
109         .addReg(MSP430::R4, 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              MCCFIInstruction::cfiDefCfaOffset(nullptr, -2 * stackGrowth),
116              MachineInstr::FrameSetup);
117 
118     // Change the rule for the FramePtr to be an "offset" rule.
119     unsigned DwarfFramePtr = TRI->getDwarfRegNum(MSP430::R4, true);
120     BuildCFI(
121         MBB, MBBI, DL,
122         MCCFIInstruction::createOffset(nullptr, DwarfFramePtr, 2 * stackGrowth),
123         MachineInstr::FrameSetup);
124 
125     // Update FP with the new base value...
126     BuildMI(MBB, MBBI, DL, TII.get(MSP430::MOV16rr), MSP430::R4)
127         .addReg(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              MCCFIInstruction::createDefCfaRegister(nullptr, DwarfFramePtr),
134              MachineInstr::FrameSetup);
135 
136     // Mark the FramePtr as live-in in every block except the entry.
137     for (MachineBasicBlock &MBBJ : llvm::drop_begin(MF))
138       MBBJ.addLiveIn(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(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                MCCFIInstruction::cfiDefCfaOffset(nullptr, -StackOffset),
154                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(MBB, MBBI, DL, TII.get(MSP430::SUB16ri), MSP430::SP)
173               .addReg(MSP430::SP)
174               .addImm(NumBytes)
175               .setMIFlag(MachineInstr::FrameSetup);
176       // The SRW implicit def is dead.
177       MI->getOperand(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           MCCFIInstruction::cfiDefCfaOffset(nullptr, StackSize - stackGrowth),
184           MachineInstr::FrameSetup);
185     }
186   }
187 
188   emitCalleeSavedFrameMoves(MBB, MBBI, DL, true);
189 }
190 
191 void 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(MBB, MBBI, DL, TII.get(MSP430::POP16r), MSP430::R4)
222         .setMIFlag(MachineInstr::FrameDestroy);
223     unsigned DwarfStackPtr = TRI->getDwarfRegNum(MSP430::SP, true);
224     BuildCFI(MBB, MBBI, DL,
225              MCCFIInstruction::cfiDefCfa(nullptr, DwarfStackPtr, 2),
226              MachineInstr::FrameDestroy);
227     --MBBI;
228     if (!MBB.succ_empty() && !MBB.isReturnBlock()) {
229       unsigned DwarfFramePtr = TRI->getDwarfRegNum(MSP430::R4, true);
230       BuildCFI(MBB, AfterPop, DL,
231                MCCFIInstruction::createRestore(nullptr, DwarfFramePtr),
232                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(MBBI);
243     unsigned Opc = PI->getOpcode();
244     if ((Opc != MSP430::POP16r || !PI->getFlag(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(MBB, MBBI, DL, TII.get(MSP430::MOV16rr), MSP430::SP)
261         .addReg(MSP430::R4)
262         .setMIFlag(MachineInstr::FrameDestroy);
263     if (CSSize) {
264       MachineInstr *MI =
265           BuildMI(MBB, MBBI, DL, TII.get(MSP430::SUB16ri), MSP430::SP)
266               .addReg(MSP430::SP)
267               .addImm(CSSize)
268               .setMIFlag(MachineInstr::FrameDestroy);
269       // The SRW implicit def is dead.
270       MI->getOperand(3).setIsDead();
271     }
272   } else {
273     // adjust stack pointer back: SP += numbytes
274     if (NumBytes) {
275       MachineInstr *MI =
276           BuildMI(MBB, MBBI, DL, TII.get(MSP430::ADD16ri), MSP430::SP)
277               .addReg(MSP430::SP)
278               .addImm(NumBytes)
279               .setMIFlag(MachineInstr::FrameDestroy);
280       // The SRW implicit def is dead.
281       MI->getOperand(3).setIsDead();
282 
283       if (!hasFP(MF)) {
284         // Adjust CFA value if it was defined by SP
285         BuildCFI(MBB, MBBI, DL,
286                  MCCFIInstruction::cfiDefCfaOffset(nullptr, CSSize + 2),
287                  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                  MCCFIInstruction::cfiDefCfaOffset(nullptr, -Offset),
305                  MachineInstr::FrameDestroy);
306       }
307     }
308   }
309   emitCalleeSavedFrameMoves(MBB, AfterPop, DL, false);
310 }
311 
312 // FIXME: Can we eleminate these in favour of generic code?
313 bool 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(Reg);
331     BuildMI(MBB, MI, DL, TII.get(MSP430::PUSH16r))
332         .addReg(Reg, RegState::Kill)
333         .setMIFlag(MachineInstr::FrameSetup);
334   }
335   return true;
336 }
337 
338 bool 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(CSI))
351     BuildMI(MBB, MI, DL, TII.get(MSP430::POP16r), I.getReg())
352         .setMIFlag(MachineInstr::FrameDestroy);
353 
354   return true;
355 }
356 
357 MachineBasicBlock::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(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(Amount, getStackAlign());
374 
375       MachineInstr *New = nullptr;
376       if (Old.getOpcode() == TII.getCallFrameSetupOpcode()) {
377         New =
378             BuildMI(MF, Old.getDebugLoc(), TII.get(MSP430::SUB16ri), MSP430::SP)
379                 .addReg(MSP430::SP)
380                 .addImm(Amount);
381       } else {
382         assert(Old.getOpcode() == TII.getCallFrameDestroyOpcode());
383         // factor out the amount the callee already popped.
384         Amount -= TII.getFramePoppedByCallee(Old);
385         if (Amount)
386           New = BuildMI(MF, Old.getDebugLoc(), TII.get(MSP430::ADD16ri),
387                         MSP430::SP)
388                     .addReg(MSP430::SP)
389                     .addImm(Amount);
390       }
391 
392       if (New) {
393         // The SRW implicit def is dead.
394         New->getOperand(3).setIsDead();
395 
396         // Replace the pseudo instruction with a new instruction...
397         MBB.insert(I, 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)) {
404       MachineInstr &Old = *I;
405       MachineInstr *New =
406           BuildMI(MF, Old.getDebugLoc(), TII.get(MSP430::SUB16ri), MSP430::SP)
407               .addReg(MSP430::SP)
408               .addImm(CalleeAmt);
409       if (!hasFP(MF)) {
410         CFIInstBuilder(MBB, I, MachineInstr::NoFlags)
411             .buildAdjustCFAOffset(CalleeAmt);
412       }
413       // The SRW implicit def is dead.
414       New->getOperand(3).setIsDead();
415 
416       MBB.insert(I, New);
417     }
418   }
419 
420   return MBB.erase(I);
421 }
422 
423 void
424 MSP430FrameLowering::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(2, -4, 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