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->needsStackRealignment(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(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 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) 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