diff options
Diffstat (limited to 'llvm/lib/Target/RISCV/RISCVFrameLowering.cpp')
-rw-r--r-- | llvm/lib/Target/RISCV/RISCVFrameLowering.cpp | 147 |
1 files changed, 145 insertions, 2 deletions
diff --git a/llvm/lib/Target/RISCV/RISCVFrameLowering.cpp b/llvm/lib/Target/RISCV/RISCVFrameLowering.cpp index cd18a104631..e9e003e63d5 100644 --- a/llvm/lib/Target/RISCV/RISCVFrameLowering.cpp +++ b/llvm/lib/Target/RISCV/RISCVFrameLowering.cpp @@ -22,11 +22,144 @@ using namespace llvm; bool RISCVFrameLowering::hasFP(const MachineFunction &MF) const { return true; } +// Determines the size of the frame and maximum call frame size. +void RISCVFrameLowering::determineFrameLayout(MachineFunction &MF) const { + MachineFrameInfo &MFI = MF.getFrameInfo(); + const RISCVRegisterInfo *RI = STI.getRegisterInfo(); + + // Get the number of bytes to allocate from the FrameInfo. + uint64_t FrameSize = MFI.getStackSize(); + + // Get the alignment. + uint64_t StackAlign = RI->needsStackRealignment(MF) ? MFI.getMaxAlignment() + : getStackAlignment(); + + // Get the maximum call frame size of all the calls. + uint64_t MaxCallFrameSize = MFI.getMaxCallFrameSize(); + + // If we have dynamic alloca then MaxCallFrameSize needs to be aligned so + // that allocations will be aligned. + if (MFI.hasVarSizedObjects()) + MaxCallFrameSize = alignTo(MaxCallFrameSize, StackAlign); + + // Update maximum call frame size. + MFI.setMaxCallFrameSize(MaxCallFrameSize); + + // Include call frame size in total. + if (!(hasReservedCallFrame(MF) && MFI.adjustsStack())) + FrameSize += MaxCallFrameSize; + + // Make sure the frame is aligned. + FrameSize = alignTo(FrameSize, StackAlign); + + // Update frame info. + MFI.setStackSize(FrameSize); +} + +void RISCVFrameLowering::adjustReg(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MBBI, + const DebugLoc &DL, unsigned DestReg, + unsigned SrcReg, int64_t Val, + MachineInstr::MIFlag Flag) const { + const RISCVInstrInfo *TII = STI.getInstrInfo(); + + if (DestReg == SrcReg && Val == 0) + return; + + if (!isInt<12>(Val)) + report_fatal_error("adjustReg cannot yet handle adjustments >12 bits"); + + BuildMI(MBB, MBBI, DL, TII->get(RISCV::ADDI), DestReg) + .addReg(SrcReg) + .addImm(Val) + .setMIFlag(Flag); +} + +// Returns the register used to hold the frame pointer. +static unsigned getFPReg(const RISCVSubtarget &STI) { return RISCV::X8; } + +// Returns the register used to hold the stack pointer. +static unsigned getSPReg(const RISCVSubtarget &STI) { return RISCV::X2; } + void RISCVFrameLowering::emitPrologue(MachineFunction &MF, - MachineBasicBlock &MBB) const {} + MachineBasicBlock &MBB) const { + assert(&MF.front() == &MBB && "Shrink-wrapping not yet supported"); + + if (!hasFP(MF)) { + report_fatal_error( + "emitPrologue doesn't support framepointer-less functions"); + } + + MachineFrameInfo &MFI = MF.getFrameInfo(); + MachineBasicBlock::iterator MBBI = MBB.begin(); + + unsigned FPReg = getFPReg(STI); + unsigned SPReg = getSPReg(STI); + + // Debug location must be unknown since the first debug location is used + // to determine the end of the prologue. + DebugLoc DL; + + // Determine the correct frame layout + determineFrameLayout(MF); + + // FIXME (note copied from Lanai): This appears to be overallocating. Needs + // investigation. Get the number of bytes to allocate from the FrameInfo. + uint64_t StackSize = MFI.getStackSize(); + + // Early exit if there is no need to allocate on the stack + if (StackSize == 0 && !MFI.adjustsStack()) + return; + + // Allocate space on the stack if necessary. + adjustReg(MBB, MBBI, DL, SPReg, SPReg, -StackSize, MachineInstr::FrameSetup); + + // The frame pointer is callee-saved, and code has been generated for us to + // save it to the stack. We need to skip over the storing of callee-saved + // registers as the frame pointer must be modified after it has been saved + // to the stack, not before. + // FIXME: assumes exactly one instruction is used to save each callee-saved + // register. + const std::vector<CalleeSavedInfo> &CSI = MFI.getCalleeSavedInfo(); + std::advance(MBBI, CSI.size()); + + // Generate new FP. + adjustReg(MBB, MBBI, DL, FPReg, SPReg, StackSize, MachineInstr::FrameSetup); +} void RISCVFrameLowering::emitEpilogue(MachineFunction &MF, - MachineBasicBlock &MBB) const {} + MachineBasicBlock &MBB) const { + if (!hasFP(MF)) { + report_fatal_error( + "emitEpilogue doesn't support framepointer-less functions"); + } + + MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr(); + const RISCVRegisterInfo *RI = STI.getRegisterInfo(); + MachineFrameInfo &MFI = MF.getFrameInfo(); + DebugLoc DL = MBBI->getDebugLoc(); + unsigned FPReg = getFPReg(STI); + unsigned SPReg = getSPReg(STI); + + // Skip to before the restores of callee-saved registers + // FIXME: assumes exactly one instruction is used to restore each + // callee-saved register. + MachineBasicBlock::iterator LastFrameDestroy = MBBI; + std::advance(LastFrameDestroy, -MFI.getCalleeSavedInfo().size()); + + uint64_t StackSize = MFI.getStackSize(); + + // Restore the stack pointer using the value of the frame pointer. Only + // necessary if the stack pointer was modified, meaning the stack size is + // unknown. + if (RI->needsStackRealignment(MF) || MFI.hasVarSizedObjects()) { + adjustReg(MBB, LastFrameDestroy, DL, SPReg, FPReg, -StackSize, + MachineInstr::FrameDestroy); + } + + // Deallocate stack + adjustReg(MBB, MBBI, DL, SPReg, SPReg, StackSize, MachineInstr::FrameDestroy); +} int RISCVFrameLowering::getFrameIndexReference(const MachineFunction &MF, int FI, @@ -56,3 +189,13 @@ int RISCVFrameLowering::getFrameIndexReference(const MachineFunction &MF, } return Offset; } + +void RISCVFrameLowering::determineCalleeSaves(MachineFunction &MF, + BitVector &SavedRegs, + RegScavenger *RS) const { + TargetFrameLowering::determineCalleeSaves(MF, SavedRegs, RS); + // TODO: Once frame pointer elimination is implemented, don't + // unconditionally spill the frame pointer and return address. + SavedRegs.set(RISCV::X1); + SavedRegs.set(RISCV::X8); +} |