18971842fSAlex Bradbury //===-- RISCVFrameLowering.cpp - RISCV Frame Information ------------------===// 28971842fSAlex Bradbury // 38971842fSAlex Bradbury // The LLVM Compiler Infrastructure 48971842fSAlex Bradbury // 58971842fSAlex Bradbury // This file is distributed under the University of Illinois Open Source 68971842fSAlex Bradbury // License. See LICENSE.TXT for details. 78971842fSAlex Bradbury // 88971842fSAlex Bradbury //===----------------------------------------------------------------------===// 98971842fSAlex Bradbury // 108971842fSAlex Bradbury // This file contains the RISCV implementation of TargetFrameLowering class. 118971842fSAlex Bradbury // 128971842fSAlex Bradbury //===----------------------------------------------------------------------===// 138971842fSAlex Bradbury 148971842fSAlex Bradbury #include "RISCVFrameLowering.h" 158971842fSAlex Bradbury #include "RISCVSubtarget.h" 168971842fSAlex Bradbury #include "llvm/CodeGen/MachineFrameInfo.h" 178971842fSAlex Bradbury #include "llvm/CodeGen/MachineFunction.h" 188971842fSAlex Bradbury #include "llvm/CodeGen/MachineInstrBuilder.h" 198971842fSAlex Bradbury #include "llvm/CodeGen/MachineRegisterInfo.h" 208971842fSAlex Bradbury 218971842fSAlex Bradbury using namespace llvm; 228971842fSAlex Bradbury 238971842fSAlex Bradbury bool RISCVFrameLowering::hasFP(const MachineFunction &MF) const { return true; } 248971842fSAlex Bradbury 25*b014e3deSAlex Bradbury // Determines the size of the frame and maximum call frame size. 26*b014e3deSAlex Bradbury void RISCVFrameLowering::determineFrameLayout(MachineFunction &MF) const { 27*b014e3deSAlex Bradbury MachineFrameInfo &MFI = MF.getFrameInfo(); 28*b014e3deSAlex Bradbury const RISCVRegisterInfo *RI = STI.getRegisterInfo(); 29*b014e3deSAlex Bradbury 30*b014e3deSAlex Bradbury // Get the number of bytes to allocate from the FrameInfo. 31*b014e3deSAlex Bradbury uint64_t FrameSize = MFI.getStackSize(); 32*b014e3deSAlex Bradbury 33*b014e3deSAlex Bradbury // Get the alignment. 34*b014e3deSAlex Bradbury uint64_t StackAlign = RI->needsStackRealignment(MF) ? MFI.getMaxAlignment() 35*b014e3deSAlex Bradbury : getStackAlignment(); 36*b014e3deSAlex Bradbury 37*b014e3deSAlex Bradbury // Get the maximum call frame size of all the calls. 38*b014e3deSAlex Bradbury uint64_t MaxCallFrameSize = MFI.getMaxCallFrameSize(); 39*b014e3deSAlex Bradbury 40*b014e3deSAlex Bradbury // If we have dynamic alloca then MaxCallFrameSize needs to be aligned so 41*b014e3deSAlex Bradbury // that allocations will be aligned. 42*b014e3deSAlex Bradbury if (MFI.hasVarSizedObjects()) 43*b014e3deSAlex Bradbury MaxCallFrameSize = alignTo(MaxCallFrameSize, StackAlign); 44*b014e3deSAlex Bradbury 45*b014e3deSAlex Bradbury // Update maximum call frame size. 46*b014e3deSAlex Bradbury MFI.setMaxCallFrameSize(MaxCallFrameSize); 47*b014e3deSAlex Bradbury 48*b014e3deSAlex Bradbury // Include call frame size in total. 49*b014e3deSAlex Bradbury if (!(hasReservedCallFrame(MF) && MFI.adjustsStack())) 50*b014e3deSAlex Bradbury FrameSize += MaxCallFrameSize; 51*b014e3deSAlex Bradbury 52*b014e3deSAlex Bradbury // Make sure the frame is aligned. 53*b014e3deSAlex Bradbury FrameSize = alignTo(FrameSize, StackAlign); 54*b014e3deSAlex Bradbury 55*b014e3deSAlex Bradbury // Update frame info. 56*b014e3deSAlex Bradbury MFI.setStackSize(FrameSize); 57*b014e3deSAlex Bradbury } 58*b014e3deSAlex Bradbury 59*b014e3deSAlex Bradbury void RISCVFrameLowering::adjustReg(MachineBasicBlock &MBB, 60*b014e3deSAlex Bradbury MachineBasicBlock::iterator MBBI, 61*b014e3deSAlex Bradbury const DebugLoc &DL, unsigned DestReg, 62*b014e3deSAlex Bradbury unsigned SrcReg, int64_t Val, 63*b014e3deSAlex Bradbury MachineInstr::MIFlag Flag) const { 64*b014e3deSAlex Bradbury const RISCVInstrInfo *TII = STI.getInstrInfo(); 65*b014e3deSAlex Bradbury 66*b014e3deSAlex Bradbury if (DestReg == SrcReg && Val == 0) 67*b014e3deSAlex Bradbury return; 68*b014e3deSAlex Bradbury 69*b014e3deSAlex Bradbury if (!isInt<12>(Val)) 70*b014e3deSAlex Bradbury report_fatal_error("adjustReg cannot yet handle adjustments >12 bits"); 71*b014e3deSAlex Bradbury 72*b014e3deSAlex Bradbury BuildMI(MBB, MBBI, DL, TII->get(RISCV::ADDI), DestReg) 73*b014e3deSAlex Bradbury .addReg(SrcReg) 74*b014e3deSAlex Bradbury .addImm(Val) 75*b014e3deSAlex Bradbury .setMIFlag(Flag); 76*b014e3deSAlex Bradbury } 77*b014e3deSAlex Bradbury 78*b014e3deSAlex Bradbury // Returns the register used to hold the frame pointer. 79*b014e3deSAlex Bradbury static unsigned getFPReg(const RISCVSubtarget &STI) { return RISCV::X8; } 80*b014e3deSAlex Bradbury 81*b014e3deSAlex Bradbury // Returns the register used to hold the stack pointer. 82*b014e3deSAlex Bradbury static unsigned getSPReg(const RISCVSubtarget &STI) { return RISCV::X2; } 83*b014e3deSAlex Bradbury 848971842fSAlex Bradbury void RISCVFrameLowering::emitPrologue(MachineFunction &MF, 85*b014e3deSAlex Bradbury MachineBasicBlock &MBB) const { 86*b014e3deSAlex Bradbury assert(&MF.front() == &MBB && "Shrink-wrapping not yet supported"); 87*b014e3deSAlex Bradbury 88*b014e3deSAlex Bradbury if (!hasFP(MF)) { 89*b014e3deSAlex Bradbury report_fatal_error( 90*b014e3deSAlex Bradbury "emitPrologue doesn't support framepointer-less functions"); 91*b014e3deSAlex Bradbury } 92*b014e3deSAlex Bradbury 93*b014e3deSAlex Bradbury MachineFrameInfo &MFI = MF.getFrameInfo(); 94*b014e3deSAlex Bradbury MachineBasicBlock::iterator MBBI = MBB.begin(); 95*b014e3deSAlex Bradbury 96*b014e3deSAlex Bradbury unsigned FPReg = getFPReg(STI); 97*b014e3deSAlex Bradbury unsigned SPReg = getSPReg(STI); 98*b014e3deSAlex Bradbury 99*b014e3deSAlex Bradbury // Debug location must be unknown since the first debug location is used 100*b014e3deSAlex Bradbury // to determine the end of the prologue. 101*b014e3deSAlex Bradbury DebugLoc DL; 102*b014e3deSAlex Bradbury 103*b014e3deSAlex Bradbury // Determine the correct frame layout 104*b014e3deSAlex Bradbury determineFrameLayout(MF); 105*b014e3deSAlex Bradbury 106*b014e3deSAlex Bradbury // FIXME (note copied from Lanai): This appears to be overallocating. Needs 107*b014e3deSAlex Bradbury // investigation. Get the number of bytes to allocate from the FrameInfo. 108*b014e3deSAlex Bradbury uint64_t StackSize = MFI.getStackSize(); 109*b014e3deSAlex Bradbury 110*b014e3deSAlex Bradbury // Early exit if there is no need to allocate on the stack 111*b014e3deSAlex Bradbury if (StackSize == 0 && !MFI.adjustsStack()) 112*b014e3deSAlex Bradbury return; 113*b014e3deSAlex Bradbury 114*b014e3deSAlex Bradbury // Allocate space on the stack if necessary. 115*b014e3deSAlex Bradbury adjustReg(MBB, MBBI, DL, SPReg, SPReg, -StackSize, MachineInstr::FrameSetup); 116*b014e3deSAlex Bradbury 117*b014e3deSAlex Bradbury // The frame pointer is callee-saved, and code has been generated for us to 118*b014e3deSAlex Bradbury // save it to the stack. We need to skip over the storing of callee-saved 119*b014e3deSAlex Bradbury // registers as the frame pointer must be modified after it has been saved 120*b014e3deSAlex Bradbury // to the stack, not before. 121*b014e3deSAlex Bradbury // FIXME: assumes exactly one instruction is used to save each callee-saved 122*b014e3deSAlex Bradbury // register. 123*b014e3deSAlex Bradbury const std::vector<CalleeSavedInfo> &CSI = MFI.getCalleeSavedInfo(); 124*b014e3deSAlex Bradbury std::advance(MBBI, CSI.size()); 125*b014e3deSAlex Bradbury 126*b014e3deSAlex Bradbury // Generate new FP. 127*b014e3deSAlex Bradbury adjustReg(MBB, MBBI, DL, FPReg, SPReg, StackSize, MachineInstr::FrameSetup); 128*b014e3deSAlex Bradbury } 1298971842fSAlex Bradbury 1308971842fSAlex Bradbury void RISCVFrameLowering::emitEpilogue(MachineFunction &MF, 131*b014e3deSAlex Bradbury MachineBasicBlock &MBB) const { 132*b014e3deSAlex Bradbury if (!hasFP(MF)) { 133*b014e3deSAlex Bradbury report_fatal_error( 134*b014e3deSAlex Bradbury "emitEpilogue doesn't support framepointer-less functions"); 135*b014e3deSAlex Bradbury } 136*b014e3deSAlex Bradbury 137*b014e3deSAlex Bradbury MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr(); 138*b014e3deSAlex Bradbury const RISCVRegisterInfo *RI = STI.getRegisterInfo(); 139*b014e3deSAlex Bradbury MachineFrameInfo &MFI = MF.getFrameInfo(); 140*b014e3deSAlex Bradbury DebugLoc DL = MBBI->getDebugLoc(); 141*b014e3deSAlex Bradbury unsigned FPReg = getFPReg(STI); 142*b014e3deSAlex Bradbury unsigned SPReg = getSPReg(STI); 143*b014e3deSAlex Bradbury 144*b014e3deSAlex Bradbury // Skip to before the restores of callee-saved registers 145*b014e3deSAlex Bradbury // FIXME: assumes exactly one instruction is used to restore each 146*b014e3deSAlex Bradbury // callee-saved register. 147*b014e3deSAlex Bradbury MachineBasicBlock::iterator LastFrameDestroy = MBBI; 148*b014e3deSAlex Bradbury std::advance(LastFrameDestroy, -MFI.getCalleeSavedInfo().size()); 149*b014e3deSAlex Bradbury 150*b014e3deSAlex Bradbury uint64_t StackSize = MFI.getStackSize(); 151*b014e3deSAlex Bradbury 152*b014e3deSAlex Bradbury // Restore the stack pointer using the value of the frame pointer. Only 153*b014e3deSAlex Bradbury // necessary if the stack pointer was modified, meaning the stack size is 154*b014e3deSAlex Bradbury // unknown. 155*b014e3deSAlex Bradbury if (RI->needsStackRealignment(MF) || MFI.hasVarSizedObjects()) { 156*b014e3deSAlex Bradbury adjustReg(MBB, LastFrameDestroy, DL, SPReg, FPReg, -StackSize, 157*b014e3deSAlex Bradbury MachineInstr::FrameDestroy); 158*b014e3deSAlex Bradbury } 159*b014e3deSAlex Bradbury 160*b014e3deSAlex Bradbury // Deallocate stack 161*b014e3deSAlex Bradbury adjustReg(MBB, MBBI, DL, SPReg, SPReg, StackSize, MachineInstr::FrameDestroy); 162*b014e3deSAlex Bradbury } 163660bccecSAlex Bradbury 164660bccecSAlex Bradbury int RISCVFrameLowering::getFrameIndexReference(const MachineFunction &MF, 165660bccecSAlex Bradbury int FI, 166660bccecSAlex Bradbury unsigned &FrameReg) const { 167660bccecSAlex Bradbury const MachineFrameInfo &MFI = MF.getFrameInfo(); 168660bccecSAlex Bradbury const TargetRegisterInfo *RI = MF.getSubtarget().getRegisterInfo(); 169660bccecSAlex Bradbury 170660bccecSAlex Bradbury // Callee-saved registers should be referenced relative to the stack 171660bccecSAlex Bradbury // pointer (positive offset), otherwise use the frame pointer (negative 172660bccecSAlex Bradbury // offset). 173660bccecSAlex Bradbury const std::vector<CalleeSavedInfo> &CSI = MFI.getCalleeSavedInfo(); 174660bccecSAlex Bradbury int MinCSFI = 0; 175660bccecSAlex Bradbury int MaxCSFI = -1; 176660bccecSAlex Bradbury 177660bccecSAlex Bradbury int Offset = MFI.getObjectOffset(FI) - getOffsetOfLocalArea() + 178660bccecSAlex Bradbury MFI.getOffsetAdjustment(); 179660bccecSAlex Bradbury 180660bccecSAlex Bradbury if (CSI.size()) { 181660bccecSAlex Bradbury MinCSFI = CSI[0].getFrameIdx(); 182660bccecSAlex Bradbury MaxCSFI = CSI[CSI.size() - 1].getFrameIdx(); 183660bccecSAlex Bradbury } 184660bccecSAlex Bradbury 185660bccecSAlex Bradbury FrameReg = RI->getFrameRegister(MF); 186660bccecSAlex Bradbury if (FI >= MinCSFI && FI <= MaxCSFI) { 187660bccecSAlex Bradbury FrameReg = RISCV::X2; 188660bccecSAlex Bradbury Offset += MF.getFrameInfo().getStackSize(); 189660bccecSAlex Bradbury } 190660bccecSAlex Bradbury return Offset; 191660bccecSAlex Bradbury } 192*b014e3deSAlex Bradbury 193*b014e3deSAlex Bradbury void RISCVFrameLowering::determineCalleeSaves(MachineFunction &MF, 194*b014e3deSAlex Bradbury BitVector &SavedRegs, 195*b014e3deSAlex Bradbury RegScavenger *RS) const { 196*b014e3deSAlex Bradbury TargetFrameLowering::determineCalleeSaves(MF, SavedRegs, RS); 197*b014e3deSAlex Bradbury // TODO: Once frame pointer elimination is implemented, don't 198*b014e3deSAlex Bradbury // unconditionally spill the frame pointer and return address. 199*b014e3deSAlex Bradbury SavedRegs.set(RISCV::X1); 200*b014e3deSAlex Bradbury SavedRegs.set(RISCV::X8); 201*b014e3deSAlex Bradbury } 202