LanaiFrameLowering.cpp revision 360784
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
24using namespace llvm;
25
26// Determines the size of the frame and maximum call frame size.
27void 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.
63void 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        Register Dst = MI.getOperand(0).getReg();
76        Register 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)
91void 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
141MachineBasicBlock::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.
178void 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
197void 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