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
22using namespace llvm;
23
24// Determines the size of the frame and maximum call frame size.
25void 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.
61void 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)
86void 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
136MachineBasicBlock::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.
173void 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
192void 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