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