xref: /freebsd/contrib/llvm-project/llvm/lib/Target/Lanai/LanaiFrameLowering.cpp (revision f976241773df2260e6170317080761d1c5814fe5)
1 //===-- LanaiFrameLowering.cpp - Lanai 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 Lanai implementation of TargetFrameLowering class.
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #include "LanaiFrameLowering.h"
14 
15 #include "LanaiAluCode.h"
16 #include "LanaiInstrInfo.h"
17 #include "LanaiSubtarget.h"
18 #include "llvm/CodeGen/MachineFrameInfo.h"
19 #include "llvm/CodeGen/MachineFunction.h"
20 #include "llvm/CodeGen/MachineInstrBuilder.h"
21 #include "llvm/CodeGen/MachineRegisterInfo.h"
22 #include "llvm/IR/Function.h"
23 
24 using namespace llvm;
25 
26 // Determines the size of the frame and maximum call frame size.
27 void LanaiFrameLowering::determineFrameLayout(MachineFunction &MF) const {
28   MachineFrameInfo &MFI = MF.getFrameInfo();
29   const LanaiRegisterInfo *LRI = STI.getRegisterInfo();
30 
31   // Get the number of bytes to allocate from the FrameInfo.
32   unsigned FrameSize = MFI.getStackSize();
33 
34   // Get the alignment.
35   unsigned StackAlign = LRI->needsStackRealignment(MF) ? MFI.getMaxAlignment()
36                                                        : getStackAlignment();
37 
38   // Get the maximum call frame size of all the calls.
39   unsigned MaxCallFrameSize = MFI.getMaxCallFrameSize();
40 
41   // If we have dynamic alloca then MaxCallFrameSize needs to be aligned so
42   // that allocations will be aligned.
43   if (MFI.hasVarSizedObjects())
44     MaxCallFrameSize = alignTo(MaxCallFrameSize, StackAlign);
45 
46   // Update maximum call frame size.
47   MFI.setMaxCallFrameSize(MaxCallFrameSize);
48 
49   // Include call frame size in total.
50   if (!(hasReservedCallFrame(MF) && MFI.adjustsStack()))
51     FrameSize += MaxCallFrameSize;
52 
53   // Make sure the frame is aligned.
54   FrameSize = alignTo(FrameSize, StackAlign);
55 
56   // Update frame info.
57   MFI.setStackSize(FrameSize);
58 }
59 
60 // Iterates through each basic block in a machine function and replaces
61 // ADJDYNALLOC pseudo instructions with a Lanai:ADDI with the
62 // maximum call frame size as the immediate.
63 void LanaiFrameLowering::replaceAdjDynAllocPseudo(MachineFunction &MF) const {
64   const LanaiInstrInfo &LII =
65       *static_cast<const LanaiInstrInfo *>(STI.getInstrInfo());
66   unsigned MaxCallFrameSize = MF.getFrameInfo().getMaxCallFrameSize();
67 
68   for (MachineFunction::iterator MBB = MF.begin(), E = MF.end(); MBB != E;
69        ++MBB) {
70     MachineBasicBlock::iterator MBBI = MBB->begin();
71     while (MBBI != MBB->end()) {
72       MachineInstr &MI = *MBBI++;
73       if (MI.getOpcode() == Lanai::ADJDYNALLOC) {
74         DebugLoc DL = MI.getDebugLoc();
75         unsigned Dst = MI.getOperand(0).getReg();
76         unsigned Src = MI.getOperand(1).getReg();
77 
78         BuildMI(*MBB, MI, DL, LII.get(Lanai::ADD_I_LO), Dst)
79             .addReg(Src)
80             .addImm(MaxCallFrameSize);
81         MI.eraseFromParent();
82       }
83     }
84   }
85 }
86 
87 // Generates the following sequence for function entry:
88 //   st %fp,-4[*%sp]        !push old FP
89 //   add %sp,8,%fp          !generate new FP
90 //   sub %sp,0x4,%sp        !allocate stack space (as needed)
91 void LanaiFrameLowering::emitPrologue(MachineFunction &MF,
92                                       MachineBasicBlock &MBB) const {
93   assert(&MF.front() == &MBB && "Shrink-wrapping not yet supported");
94 
95   MachineFrameInfo &MFI = MF.getFrameInfo();
96   const LanaiInstrInfo &LII =
97       *static_cast<const LanaiInstrInfo *>(STI.getInstrInfo());
98   MachineBasicBlock::iterator MBBI = MBB.begin();
99 
100   // Debug location must be unknown since the first debug location is used
101   // to determine the end of the prologue.
102   DebugLoc DL;
103 
104   // Determine the correct frame layout
105   determineFrameLayout(MF);
106 
107   // FIXME: This appears to be overallocating.  Needs investigation.
108   // Get the number of bytes to allocate from the FrameInfo.
109   unsigned StackSize = MFI.getStackSize();
110 
111   // Push old FP
112   // st %fp,-4[*%sp]
113   BuildMI(MBB, MBBI, DL, LII.get(Lanai::SW_RI))
114       .addReg(Lanai::FP)
115       .addReg(Lanai::SP)
116       .addImm(-4)
117       .addImm(LPAC::makePreOp(LPAC::ADD))
118       .setMIFlag(MachineInstr::FrameSetup);
119 
120   // Generate new FP
121   // add %sp,8,%fp
122   BuildMI(MBB, MBBI, DL, LII.get(Lanai::ADD_I_LO), Lanai::FP)
123       .addReg(Lanai::SP)
124       .addImm(8)
125       .setMIFlag(MachineInstr::FrameSetup);
126 
127   // Allocate space on the stack if needed
128   // sub %sp,StackSize,%sp
129   if (StackSize != 0) {
130     BuildMI(MBB, MBBI, DL, LII.get(Lanai::SUB_I_LO), Lanai::SP)
131         .addReg(Lanai::SP)
132         .addImm(StackSize)
133         .setMIFlag(MachineInstr::FrameSetup);
134   }
135 
136   // Replace ADJDYNANALLOC
137   if (MFI.hasVarSizedObjects())
138     replaceAdjDynAllocPseudo(MF);
139 }
140 
141 MachineBasicBlock::iterator LanaiFrameLowering::eliminateCallFramePseudoInstr(
142     MachineFunction & /*MF*/, MachineBasicBlock &MBB,
143     MachineBasicBlock::iterator I) const {
144   // Discard ADJCALLSTACKDOWN, ADJCALLSTACKUP instructions.
145   return MBB.erase(I);
146 }
147 
148 // The function epilogue should not depend on the current stack pointer!
149 // It should use the frame pointer only.  This is mandatory because
150 // of alloca; we also take advantage of it to omit stack adjustments
151 // before returning.
152 //
153 // Note that when we go to restore the preserved register values we must
154 // not try to address their slots by using offsets from the stack pointer.
155 // That's because the stack pointer may have been moved during the function
156 // execution due to a call to alloca().  Rather, we must restore all
157 // preserved registers via offsets from the frame pointer value.
158 //
159 // Note also that when the current frame is being "popped" (by adjusting
160 // the value of the stack pointer) on function exit, we must (for the
161 // sake of alloca) set the new value of the stack pointer based upon
162 // the current value of the frame pointer.  We can't just add what we
163 // believe to be the (static) frame size to the stack pointer because
164 // if we did that, and alloca() had been called during this function,
165 // we would end up returning *without* having fully deallocated all of
166 // the space grabbed by alloca.  If that happened, and a function
167 // containing one or more alloca() calls was called over and over again,
168 // then the stack would grow without limit!
169 //
170 // RET is lowered to
171 //      ld -4[%fp],%pc  # modify %pc (two delay slots)
172 // as the return address is in the stack frame and mov to pc is allowed.
173 // emitEpilogue emits
174 //      mov %fp,%sp     # restore the stack pointer
175 //      ld -8[%fp],%fp  # restore the caller's frame pointer
176 // before RET and the delay slot filler will move RET such that these
177 // instructions execute in the delay slots of the load to PC.
178 void LanaiFrameLowering::emitEpilogue(MachineFunction & /*MF*/,
179                                       MachineBasicBlock &MBB) const {
180   MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr();
181   const LanaiInstrInfo &LII =
182       *static_cast<const LanaiInstrInfo *>(STI.getInstrInfo());
183   DebugLoc DL = MBBI->getDebugLoc();
184 
185   // Restore the stack pointer using the callee's frame pointer value.
186   BuildMI(MBB, MBBI, DL, LII.get(Lanai::ADD_I_LO), Lanai::SP)
187       .addReg(Lanai::FP)
188       .addImm(0);
189 
190   // Restore the frame pointer from the stack.
191   BuildMI(MBB, MBBI, DL, LII.get(Lanai::LDW_RI), Lanai::FP)
192       .addReg(Lanai::FP)
193       .addImm(-8)
194       .addImm(LPAC::ADD);
195 }
196 
197 void LanaiFrameLowering::determineCalleeSaves(MachineFunction &MF,
198                                               BitVector &SavedRegs,
199                                               RegScavenger *RS) const {
200   TargetFrameLowering::determineCalleeSaves(MF, SavedRegs, RS);
201 
202   MachineFrameInfo &MFI = MF.getFrameInfo();
203   const LanaiRegisterInfo *LRI =
204       static_cast<const LanaiRegisterInfo *>(STI.getRegisterInfo());
205   int Offset = -4;
206 
207   // Reserve 4 bytes for the saved RCA
208   MFI.CreateFixedObject(4, Offset, true);
209   Offset -= 4;
210 
211   // Reserve 4 bytes for the saved FP
212   MFI.CreateFixedObject(4, Offset, true);
213   Offset -= 4;
214 
215   if (LRI->hasBasePointer(MF)) {
216     MFI.CreateFixedObject(4, Offset, true);
217     SavedRegs.reset(LRI->getBaseRegister());
218   }
219 }
220