xref: /freebsd/contrib/llvm-project/llvm/lib/Target/MSP430/MSP430FrameLowering.cpp (revision 36b606ae6aa4b24061096ba18582e0a08ccd5dba)
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 
MSP430FrameLowering(const MSP430Subtarget & STI)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 
hasFP(const MachineFunction & MF) const33 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 
hasReservedCallFrame(const MachineFunction & MF) const41 bool MSP430FrameLowering::hasReservedCallFrame(const MachineFunction &MF) const {
42   return !MF.getFrameInfo().hasVarSizedObjects();
43 }
44 
BuildCFI(MachineBasicBlock & MBB,MachineBasicBlock::iterator MBBI,const DebugLoc & DL,const MCCFIInstruction & CFIInst,MachineInstr::MIFlag Flag) const45 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 
emitCalleeSavedFrameMoves(MachineBasicBlock & MBB,MachineBasicBlock::iterator MBBI,const DebugLoc & DL,bool IsPrologue) const57 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   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(I.getFrameIdx());
70     Register Reg = I.getReg();
71     unsigned DwarfReg = MRI->getDwarfRegNum(Reg, true);
72 
73     if (IsPrologue) {
74       BuildCFI(MBB, MBBI, DL,
75                MCCFIInstruction::createOffset(nullptr, DwarfReg, Offset));
76     } else {
77       BuildCFI(MBB, MBBI, DL,
78                MCCFIInstruction::createRestore(nullptr, DwarfReg));
79     }
80   }
81 }
82 
emitPrologue(MachineFunction & MF,MachineBasicBlock & MBB) const83 void 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(MBB, MBBI, DL, TII.get(MSP430::PUSH16r))
111         .addReg(MSP430::R4, 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              MCCFIInstruction::cfiDefCfaOffset(nullptr, -2 * stackGrowth),
118              MachineInstr::FrameSetup);
119 
120     // Change the rule for the FramePtr to be an "offset" rule.
121     unsigned DwarfFramePtr = TRI->getDwarfRegNum(MSP430::R4, true);
122     BuildCFI(
123         MBB, MBBI, DL,
124         MCCFIInstruction::createOffset(nullptr, DwarfFramePtr, 2 * stackGrowth),
125         MachineInstr::FrameSetup);
126 
127     // Update FP with the new base value...
128     BuildMI(MBB, MBBI, DL, TII.get(MSP430::MOV16rr), MSP430::R4)
129         .addReg(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              MCCFIInstruction::createDefCfaRegister(nullptr, DwarfFramePtr),
136              MachineInstr::FrameSetup);
137 
138     // Mark the FramePtr as live-in in every block except the entry.
139     for (MachineBasicBlock &MBBJ : llvm::drop_begin(MF))
140       MBBJ.addLiveIn(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(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                MCCFIInstruction::cfiDefCfaOffset(nullptr, -StackOffset),
156                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(MBB, MBBI, DL, TII.get(MSP430::SUB16ri), MSP430::SP)
175               .addReg(MSP430::SP)
176               .addImm(NumBytes)
177               .setMIFlag(MachineInstr::FrameSetup);
178       // The SRW implicit def is dead.
179       MI->getOperand(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           MCCFIInstruction::cfiDefCfaOffset(nullptr, StackSize - stackGrowth),
186           MachineInstr::FrameSetup);
187     }
188   }
189 
190   emitCalleeSavedFrameMoves(MBB, MBBI, DL, true);
191 }
192 
emitEpilogue(MachineFunction & MF,MachineBasicBlock & MBB) const193 void 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(MBB, MBBI, DL, TII.get(MSP430::POP16r), MSP430::R4)
224         .setMIFlag(MachineInstr::FrameDestroy);
225     unsigned DwarfStackPtr = TRI->getDwarfRegNum(MSP430::SP, true);
226     BuildCFI(MBB, MBBI, DL,
227              MCCFIInstruction::cfiDefCfa(nullptr, DwarfStackPtr, 2),
228              MachineInstr::FrameDestroy);
229     --MBBI;
230     if (!MBB.succ_empty() && !MBB.isReturnBlock()) {
231       unsigned DwarfFramePtr = TRI->getDwarfRegNum(MSP430::R4, true);
232       BuildCFI(MBB, AfterPop, DL,
233                MCCFIInstruction::createRestore(nullptr, DwarfFramePtr),
234                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(MBBI);
245     unsigned Opc = PI->getOpcode();
246     if ((Opc != MSP430::POP16r || !PI->getFlag(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(MBB, MBBI, DL, TII.get(MSP430::MOV16rr), MSP430::SP)
263         .addReg(MSP430::R4)
264         .setMIFlag(MachineInstr::FrameDestroy);
265     if (CSSize) {
266       MachineInstr *MI =
267           BuildMI(MBB, MBBI, DL, TII.get(MSP430::SUB16ri), MSP430::SP)
268               .addReg(MSP430::SP)
269               .addImm(CSSize)
270               .setMIFlag(MachineInstr::FrameDestroy);
271       // The SRW implicit def is dead.
272       MI->getOperand(3).setIsDead();
273     }
274   } else {
275     // adjust stack pointer back: SP += numbytes
276     if (NumBytes) {
277       MachineInstr *MI =
278           BuildMI(MBB, MBBI, DL, TII.get(MSP430::ADD16ri), MSP430::SP)
279               .addReg(MSP430::SP)
280               .addImm(NumBytes)
281               .setMIFlag(MachineInstr::FrameDestroy);
282       // The SRW implicit def is dead.
283       MI->getOperand(3).setIsDead();
284 
285       if (!hasFP(MF)) {
286         // Adjust CFA value if it was defined by SP
287         BuildCFI(MBB, MBBI, DL,
288                  MCCFIInstruction::cfiDefCfaOffset(nullptr, CSSize + 2),
289                  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                  MCCFIInstruction::cfiDefCfaOffset(nullptr, -Offset),
307                  MachineInstr::FrameDestroy);
308       }
309     }
310   }
311   emitCalleeSavedFrameMoves(MBB, AfterPop, DL, false);
312 }
313 
314 // FIXME: Can we eleminate these in favour of generic code?
spillCalleeSavedRegisters(MachineBasicBlock & MBB,MachineBasicBlock::iterator MI,ArrayRef<CalleeSavedInfo> CSI,const TargetRegisterInfo * TRI) const315 bool 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(Reg);
333     BuildMI(MBB, MI, DL, TII.get(MSP430::PUSH16r))
334         .addReg(Reg, RegState::Kill)
335         .setMIFlag(MachineInstr::FrameSetup);
336   }
337   return true;
338 }
339 
restoreCalleeSavedRegisters(MachineBasicBlock & MBB,MachineBasicBlock::iterator MI,MutableArrayRef<CalleeSavedInfo> CSI,const TargetRegisterInfo * TRI) const340 bool 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(CSI))
353     BuildMI(MBB, MI, DL, TII.get(MSP430::POP16r), I.getReg())
354         .setMIFlag(MachineInstr::FrameDestroy);
355 
356   return true;
357 }
358 
eliminateCallFramePseudoInstr(MachineFunction & MF,MachineBasicBlock & MBB,MachineBasicBlock::iterator I) const359 MachineBasicBlock::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(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(Amount, getStackAlign());
376 
377       MachineInstr *New = nullptr;
378       if (Old.getOpcode() == TII.getCallFrameSetupOpcode()) {
379         New =
380             BuildMI(MF, Old.getDebugLoc(), TII.get(MSP430::SUB16ri), MSP430::SP)
381                 .addReg(MSP430::SP)
382                 .addImm(Amount);
383       } else {
384         assert(Old.getOpcode() == TII.getCallFrameDestroyOpcode());
385         // factor out the amount the callee already popped.
386         Amount -= TII.getFramePoppedByCallee(Old);
387         if (Amount)
388           New = BuildMI(MF, Old.getDebugLoc(), TII.get(MSP430::ADD16ri),
389                         MSP430::SP)
390                     .addReg(MSP430::SP)
391                     .addImm(Amount);
392       }
393 
394       if (New) {
395         // The SRW implicit def is dead.
396         New->getOperand(3).setIsDead();
397 
398         // Replace the pseudo instruction with a new instruction...
399         MBB.insert(I, 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)) {
406       MachineInstr &Old = *I;
407       MachineInstr *New =
408           BuildMI(MF, Old.getDebugLoc(), TII.get(MSP430::SUB16ri), MSP430::SP)
409               .addReg(MSP430::SP)
410               .addImm(CalleeAmt);
411       if (!hasFP(MF)) {
412         DebugLoc DL = I->getDebugLoc();
413         BuildCFI(MBB, I, DL,
414                  MCCFIInstruction::createAdjustCfaOffset(nullptr, CalleeAmt));
415       }
416       // The SRW implicit def is dead.
417       New->getOperand(3).setIsDead();
418 
419       MBB.insert(I, New);
420     }
421   }
422 
423   return MBB.erase(I);
424 }
425 
426 void
processFunctionBeforeFrameFinalized(MachineFunction & MF,RegScavenger *) const427 MSP430FrameLowering::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(2, -4, 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