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