221 lines
		
	
	
		
			8.0 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			221 lines
		
	
	
		
			8.0 KiB
		
	
	
	
		
			C++
		
	
	
	
| //===-- LanaiFrameLowering.cpp - Lanai Frame Information ------------------===//
 | |
| //
 | |
| //                     The LLVM Compiler Infrastructure
 | |
| //
 | |
| // This file is distributed under the University of Illinois Open Source
 | |
| // License. See LICENSE.TXT for details.
 | |
| //
 | |
| //===----------------------------------------------------------------------===//
 | |
| //
 | |
| // This file contains the Lanai implementation of TargetFrameLowering class.
 | |
| //
 | |
| //===----------------------------------------------------------------------===//
 | |
| 
 | |
| #include "LanaiFrameLowering.h"
 | |
| 
 | |
| #include "LanaiInstrInfo.h"
 | |
| #include "LanaiMachineFunctionInfo.h"
 | |
| #include "LanaiSubtarget.h"
 | |
| #include "llvm/CodeGen/MachineFrameInfo.h"
 | |
| #include "llvm/CodeGen/MachineFunction.h"
 | |
| #include "llvm/CodeGen/MachineInstrBuilder.h"
 | |
| #include "llvm/CodeGen/MachineRegisterInfo.h"
 | |
| #include "llvm/IR/Function.h"
 | |
| 
 | |
| using namespace llvm;
 | |
| 
 | |
| // Determines the size of the frame and maximum call frame size.
 | |
| void LanaiFrameLowering::determineFrameLayout(MachineFunction &MF) const {
 | |
|   MachineFrameInfo &MFI = MF.getFrameInfo();
 | |
|   const LanaiRegisterInfo *LRI = STI.getRegisterInfo();
 | |
| 
 | |
|   // Get the number of bytes to allocate from the FrameInfo.
 | |
|   unsigned FrameSize = MFI.getStackSize();
 | |
| 
 | |
|   // Get the alignment.
 | |
|   unsigned StackAlign = LRI->needsStackRealignment(MF) ? MFI.getMaxAlignment()
 | |
|                                                        : getStackAlignment();
 | |
| 
 | |
|   // Get the maximum call frame size of all the calls.
 | |
|   unsigned 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);
 | |
| }
 | |
| 
 | |
| // Iterates through each basic block in a machine function and replaces
 | |
| // ADJDYNALLOC pseudo instructions with a Lanai:ADDI with the
 | |
| // maximum call frame size as the immediate.
 | |
| void LanaiFrameLowering::replaceAdjDynAllocPseudo(MachineFunction &MF) const {
 | |
|   const LanaiInstrInfo &LII =
 | |
|       *static_cast<const LanaiInstrInfo *>(STI.getInstrInfo());
 | |
|   unsigned MaxCallFrameSize = MF.getFrameInfo().getMaxCallFrameSize();
 | |
| 
 | |
|   for (MachineFunction::iterator MBB = MF.begin(), E = MF.end(); MBB != E;
 | |
|        ++MBB) {
 | |
|     MachineBasicBlock::iterator MBBI = MBB->begin();
 | |
|     while (MBBI != MBB->end()) {
 | |
|       MachineInstr &MI = *MBBI++;
 | |
|       if (MI.getOpcode() == Lanai::ADJDYNALLOC) {
 | |
|         DebugLoc DL = MI.getDebugLoc();
 | |
|         unsigned Dst = MI.getOperand(0).getReg();
 | |
|         unsigned Src = MI.getOperand(1).getReg();
 | |
| 
 | |
|         BuildMI(*MBB, MI, DL, LII.get(Lanai::ADD_I_LO), Dst)
 | |
|             .addReg(Src)
 | |
|             .addImm(MaxCallFrameSize);
 | |
|         MI.eraseFromParent();
 | |
|       }
 | |
|     }
 | |
|   }
 | |
| }
 | |
| 
 | |
| // Generates the following sequence for function entry:
 | |
| //   st %fp,-4[*%sp]        !push old FP
 | |
| //   add %sp,8,%fp          !generate new FP
 | |
| //   sub %sp,0x4,%sp        !allocate stack space (as needed)
 | |
| void LanaiFrameLowering::emitPrologue(MachineFunction &MF,
 | |
|                                       MachineBasicBlock &MBB) const {
 | |
|   assert(&MF.front() == &MBB && "Shrink-wrapping not yet supported");
 | |
| 
 | |
|   MachineFrameInfo &MFI = MF.getFrameInfo();
 | |
|   const LanaiInstrInfo &LII =
 | |
|       *static_cast<const LanaiInstrInfo *>(STI.getInstrInfo());
 | |
|   MachineBasicBlock::iterator MBBI = MBB.begin();
 | |
| 
 | |
|   // 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: This appears to be overallocating.  Needs investigation.
 | |
|   // Get the number of bytes to allocate from the FrameInfo.
 | |
|   unsigned StackSize = MFI.getStackSize();
 | |
| 
 | |
|   // Push old FP
 | |
|   // st %fp,-4[*%sp]
 | |
|   BuildMI(MBB, MBBI, DL, LII.get(Lanai::SW_RI))
 | |
|       .addReg(Lanai::FP)
 | |
|       .addReg(Lanai::SP)
 | |
|       .addImm(-4)
 | |
|       .addImm(LPAC::makePreOp(LPAC::ADD))
 | |
|       .setMIFlag(MachineInstr::FrameSetup);
 | |
| 
 | |
|   // Generate new FP
 | |
|   // add %sp,8,%fp
 | |
|   BuildMI(MBB, MBBI, DL, LII.get(Lanai::ADD_I_LO), Lanai::FP)
 | |
|       .addReg(Lanai::SP)
 | |
|       .addImm(8)
 | |
|       .setMIFlag(MachineInstr::FrameSetup);
 | |
| 
 | |
|   // Allocate space on the stack if needed
 | |
|   // sub %sp,StackSize,%sp
 | |
|   if (StackSize != 0) {
 | |
|     BuildMI(MBB, MBBI, DL, LII.get(Lanai::SUB_I_LO), Lanai::SP)
 | |
|         .addReg(Lanai::SP)
 | |
|         .addImm(StackSize)
 | |
|         .setMIFlag(MachineInstr::FrameSetup);
 | |
|   }
 | |
| 
 | |
|   // Replace ADJDYNANALLOC
 | |
|   if (MFI.hasVarSizedObjects())
 | |
|     replaceAdjDynAllocPseudo(MF);
 | |
| }
 | |
| 
 | |
| MachineBasicBlock::iterator LanaiFrameLowering::eliminateCallFramePseudoInstr(
 | |
|     MachineFunction & /*MF*/, MachineBasicBlock &MBB,
 | |
|     MachineBasicBlock::iterator I) const {
 | |
|   // Discard ADJCALLSTACKDOWN, ADJCALLSTACKUP instructions.
 | |
|   return MBB.erase(I);
 | |
| }
 | |
| 
 | |
| // The function epilogue should not depend on the current stack pointer!
 | |
| // It should use the frame pointer only.  This is mandatory because
 | |
| // of alloca; we also take advantage of it to omit stack adjustments
 | |
| // before returning.
 | |
| //
 | |
| // Note that when we go to restore the preserved register values we must
 | |
| // not try to address their slots by using offsets from the stack pointer.
 | |
| // That's because the stack pointer may have been moved during the function
 | |
| // execution due to a call to alloca().  Rather, we must restore all
 | |
| // preserved registers via offsets from the frame pointer value.
 | |
| //
 | |
| // Note also that when the current frame is being "popped" (by adjusting
 | |
| // the value of the stack pointer) on function exit, we must (for the
 | |
| // sake of alloca) set the new value of the stack pointer based upon
 | |
| // the current value of the frame pointer.  We can't just add what we
 | |
| // believe to be the (static) frame size to the stack pointer because
 | |
| // if we did that, and alloca() had been called during this function,
 | |
| // we would end up returning *without* having fully deallocated all of
 | |
| // the space grabbed by alloca.  If that happened, and a function
 | |
| // containing one or more alloca() calls was called over and over again,
 | |
| // then the stack would grow without limit!
 | |
| //
 | |
| // RET is lowered to
 | |
| //      ld -4[%fp],%pc  # modify %pc (two delay slots)
 | |
| // as the return address is in the stack frame and mov to pc is allowed.
 | |
| // emitEpilogue emits
 | |
| //      mov %fp,%sp     # restore the stack pointer
 | |
| //      ld -8[%fp],%fp  # restore the caller's frame pointer
 | |
| // before RET and the delay slot filler will move RET such that these
 | |
| // instructions execute in the delay slots of the load to PC.
 | |
| void LanaiFrameLowering::emitEpilogue(MachineFunction & /*MF*/,
 | |
|                                       MachineBasicBlock &MBB) const {
 | |
|   MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr();
 | |
|   const LanaiInstrInfo &LII =
 | |
|       *static_cast<const LanaiInstrInfo *>(STI.getInstrInfo());
 | |
|   DebugLoc DL = MBBI->getDebugLoc();
 | |
| 
 | |
|   // Restore the stack pointer using the callee's frame pointer value.
 | |
|   BuildMI(MBB, MBBI, DL, LII.get(Lanai::ADD_I_LO), Lanai::SP)
 | |
|       .addReg(Lanai::FP)
 | |
|       .addImm(0);
 | |
| 
 | |
|   // Restore the frame pointer from the stack.
 | |
|   BuildMI(MBB, MBBI, DL, LII.get(Lanai::LDW_RI), Lanai::FP)
 | |
|       .addReg(Lanai::FP)
 | |
|       .addImm(-8)
 | |
|       .addImm(LPAC::ADD);
 | |
| }
 | |
| 
 | |
| void LanaiFrameLowering::determineCalleeSaves(MachineFunction &MF,
 | |
|                                               BitVector &SavedRegs,
 | |
|                                               RegScavenger *RS) const {
 | |
|   TargetFrameLowering::determineCalleeSaves(MF, SavedRegs, RS);
 | |
| 
 | |
|   MachineFrameInfo &MFI = MF.getFrameInfo();
 | |
|   const LanaiRegisterInfo *LRI =
 | |
|       static_cast<const LanaiRegisterInfo *>(STI.getRegisterInfo());
 | |
|   int Offset = -4;
 | |
| 
 | |
|   // Reserve 4 bytes for the saved RCA
 | |
|   MFI.CreateFixedObject(4, Offset, true);
 | |
|   Offset -= 4;
 | |
| 
 | |
|   // Reserve 4 bytes for the saved FP
 | |
|   MFI.CreateFixedObject(4, Offset, true);
 | |
|   Offset -= 4;
 | |
| 
 | |
|   if (LRI->hasBasePointer(MF)) {
 | |
|     MFI.CreateFixedObject(4, Offset, true);
 | |
|     SavedRegs.reset(LRI->getBaseRegister());
 | |
|   }
 | |
| }
 |