xref: /freebsd/contrib/llvm-project/llvm/lib/Target/MSP430/MSP430FrameLowering.cpp (revision 5ca8e32633c4ffbbcd6762e5888b6a4ba0708c6c)
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 
26 using namespace llvm;
27 
28 MSP430FrameLowering::MSP430FrameLowering(const MSP430Subtarget &STI)
29     : TargetFrameLowering(TargetFrameLowering::StackGrowsDown, Align(2), -2,
30                           Align(2)),
31       STI(STI), TII(*STI.getInstrInfo()), TRI(STI.getRegisterInfo()) {}
32 
33 bool 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 
41 bool MSP430FrameLowering::hasReservedCallFrame(const MachineFunction &MF) const {
42   return !MF.getFrameInfo().hasVarSizedObjects();
43 }
44 
45 void 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(CFIInst);
52   BuildMI(MBB, MBBI, DL, TII.get(TargetOpcode::CFI_INSTRUCTION))
53       .addCFIIndex(CFIIndex)
54       .setMIFlag(Flag);
55 }
56 
57 void 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(I.getFrameIdx());
71     Register Reg = I.getReg();
72     unsigned DwarfReg = MRI->getDwarfRegNum(Reg, true);
73 
74     if (IsPrologue) {
75       BuildCFI(MBB, MBBI, DL,
76                MCCFIInstruction::createOffset(nullptr, DwarfReg, Offset));
77     } else {
78       BuildCFI(MBB, MBBI, DL,
79                MCCFIInstruction::createRestore(nullptr, DwarfReg));
80     }
81   }
82 }
83 
84 void 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              MCCFIInstruction::cfiDefCfaOffset(nullptr, -2 * stackGrowth),
119              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         MCCFIInstruction::createOffset(nullptr, DwarfFramePtr, 2 * stackGrowth),
126         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              MCCFIInstruction::createDefCfaRegister(nullptr, DwarfFramePtr),
137              MachineInstr::FrameSetup);
138 
139     // Mark the FramePtr as live-in in every block except the entry.
140     for (MachineBasicBlock &MBBJ : llvm::drop_begin(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(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                MCCFIInstruction::cfiDefCfaOffset(nullptr, -StackOffset),
157                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(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           MCCFIInstruction::cfiDefCfaOffset(nullptr, StackSize - stackGrowth),
187           MachineInstr::FrameSetup);
188     }
189   }
190 
191   emitCalleeSavedFrameMoves(MBB, MBBI, DL, true);
192 }
193 
194 void 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              MCCFIInstruction::cfiDefCfa(nullptr, DwarfStackPtr, 2),
229              MachineInstr::FrameDestroy);
230     --MBBI;
231     if (!MBB.succ_empty() && !MBB.isReturnBlock()) {
232       unsigned DwarfFramePtr = TRI->getDwarfRegNum(MSP430::R4, true);
233       BuildCFI(MBB, AfterPop, DL,
234                MCCFIInstruction::createRestore(nullptr, DwarfFramePtr),
235                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(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(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(3).setIsDead();
285 
286       if (!hasFP(MF)) {
287         // Adjust CFA value if it was defined by SP
288         BuildCFI(MBB, MBBI, DL,
289                  MCCFIInstruction::cfiDefCfaOffset(nullptr, CSSize + 2),
290                  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                  MCCFIInstruction::cfiDefCfaOffset(nullptr, -Offset),
308                  MachineInstr::FrameDestroy);
309       }
310     }
311   }
312   emitCalleeSavedFrameMoves(MBB, AfterPop, DL, false);
313 }
314 
315 // FIXME: Can we eleminate these in favour of generic code?
316 bool 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(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 
341 bool 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 
360 MachineBasicBlock::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(Amount, 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(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(3).setIsDead();
398 
399         // Replace the pseudo instruction with a new instruction...
400         MBB.insert(I, 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)) {
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, I, DL,
415                  MCCFIInstruction::createAdjustCfaOffset(nullptr, CalleeAmt));
416       }
417       // The SRW implicit def is dead.
418       New->getOperand(3).setIsDead();
419 
420       MBB.insert(I, New);
421     }
422   }
423 
424   return MBB.erase(I);
425 }
426 
427 void
428 MSP430FrameLowering::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(2, -4, 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