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