Difference between revisions of "NaplesPUFrameLowering.cpp"

From NaplesPU Documentation
Jump to: navigation, search
(Created page with "Category:C++ Classes The NuPlusFrameLowering class must handle all the operations concerning the stack frame. It implements the '''TargetFrameLowering''' interface. In nu...")
 
 
(One intermediate revision by the same user not shown)
Line 2: Line 2:
 
The NuPlusFrameLowering class must handle all the operations concerning the stack frame. It implements the '''TargetFrameLowering''' interface.  
 
The NuPlusFrameLowering class must handle all the operations concerning the stack frame. It implements the '''TargetFrameLowering''' interface.  
 
In nu+ the stack grows incrementing the address (i.e. the stack grows down) and it is 64-byte aligned.  
 
In nu+ the stack grows incrementing the address (i.e. the stack grows down) and it is 64-byte aligned.  
The NuPlusFrameLowering implements the following functions:
+
 
*'''emitPrologue''' and '''emitEpilogue''', which insert prolog and epilog code into the function.
+
<syntaxhighlight>
*'''eliminateCallFramePseudoInstr''', responsible for eliminating call frame setup and destroy pseudo instructions, replacing them with concrete instructions.
+
//===-- NuPlusFrameLowering.cpp - NuPlus Frame Information -----------------===//
*'''hasReservedCallFrame''', returns true if the prologue inserter should reserve space for outgoing arguments.
+
//
*'''hasFP''', returns true if the specified function should have a dedicated frame pointer register. This is true if the function has variable sized allocas or if frame pointer elimination is disabled.
+
//                    The LLVM Compiler Infrastructure
*'''determineCalleeSaves''', determines which of the registers reported by TargetRegisterInfo::getCalleeSavedRegs() should actually get saved.
+
//
 +
// This file is distributed under the University of Illinois Open Source
 +
// License. See LICENSE.TXT for details.
 +
//
 +
//===----------------------------------------------------------------------===//
 +
//
 +
// This file contains the NuPlus implementation of TargetFrameLowering
 +
// class.
 +
//
 +
//===----------------------------------------------------------------------===//
 +
 
 +
#include "NuPlusFrameLowering.h"
 +
#include "MCTargetDesc/NuPlusMCTargetDesc.h"
 +
#include "NuPlusInstrInfo.h"
 +
#include "NuPlusMachineFunctionInfo.h"
 +
#include "llvm/CodeGen/MachineFrameInfo.h"
 +
#include "llvm/CodeGen/MachineFunction.h"
 +
#include "llvm/CodeGen/MachineInstrBuilder.h"
 +
#include "llvm/CodeGen/MachineModuleInfo.h"
 +
#include "llvm/CodeGen/MachineRegisterInfo.h"
 +
#include "llvm/CodeGen/RegisterScavenging.h"
 +
#include "llvm/IR/DataLayout.h"
 +
#include "llvm/IR/Function.h"
 +
#include "llvm/Support/CommandLine.h"
 +
#include "llvm/Support/Debug.h"
 +
#include "llvm/Target/TargetOptions.h"
 +
 
 +
using namespace llvm;
 +
 
 +
void NuPlusFrameLowering::emitPrologue(MachineFunction &MF,
 +
                                      MachineBasicBlock &MBB) const {
 +
  assert(&MF.front() == &MBB);
 +
  MachineFrameInfo &MFI = MF.getFrameInfo();
 +
  const NuPlusInstrInfo &TII =
 +
      *static_cast<const NuPlusInstrInfo *>(MF.getSubtarget().getInstrInfo());
 +
  const MCRegisterInfo *MRI = MF.getMMI().getContext().getRegisterInfo();
 +
  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;
 +
 
 +
  // Compute stack size to allocate, keeping SP 64 byte aligned so we
 +
  // can do block vector load/stores
 +
  int StackSize = alignTo(MFI.getStackSize(), getStackAlignment());
 +
 
 +
  // Bail if there is no stack allocation
 +
  if (StackSize == 0 && !MFI.adjustsStack())
 +
    return;
 +
 
 +
  TII.adjustStackPointer(MBB, MBBI, DL, -StackSize);
 +
 
 +
  // Emit DW_CFA_def_cfa
 +
  unsigned CFIIndex = MF.addFrameInst(
 +
      MCCFIInstruction::createDefCfaOffset(nullptr, -StackSize));
 +
  BuildMI(MBB, MBBI, DL, TII.get(TargetOpcode::CFI_INSTRUCTION))
 +
      .addCFIIndex(CFIIndex);
 +
 
 +
  // Find the instruction past the last instruction that saves a callee-saved
 +
  // register to the stack.  We need to set up FP after its old value has been
 +
  // saved.
 +
  const std::vector<CalleeSavedInfo> &CSI = MFI.getCalleeSavedInfo();
 +
  if (CSI.size()) {
 +
    for (unsigned i = 0; i < CSI.size(); ++i)
 +
      ++MBBI;
 +
 
 +
    // Iterate over list of callee-saved registers and emit .cfi_offset
 +
    // directives (debug information)
 +
    for (const auto &I : CSI) {
 +
      int64_t Offset = MFI.getObjectOffset(I.getFrameIdx());
 +
      unsigned Reg = I.getReg();
 +
      unsigned CFIIndex = MF.addFrameInst(MCCFIInstruction::createOffset(
 +
          nullptr, MRI->getDwarfRegNum(Reg, 1), Offset));
 +
      BuildMI(MBB, MBBI, DL, TII.get(TargetOpcode::CFI_INSTRUCTION))
 +
          .addCFIIndex(CFIIndex);
 +
    }
 +
  }
 +
 
 +
  // fp = sp
 +
  if (hasFP(MF)) {
 +
    BuildMI(MBB, MBBI, DL, TII.get(NuPlus::MOVE_SS_32))
 +
        .addReg(NuPlus::FP_REG)
 +
        .addReg(NuPlus::SP_REG);
 +
 
 +
    // emit ".cfi_def_cfa_register $fp" (debug information)
 +
    unsigned CFIIndex = MF.addFrameInst(MCCFIInstruction::createDefCfaRegister(
 +
        nullptr, MRI->getDwarfRegNum(NuPlus::FP_REG, true)));
 +
    BuildMI(MBB, MBBI, DL, TII.get(TargetOpcode::CFI_INSTRUCTION))
 +
        .addCFIIndex(CFIIndex);
 +
  }
 +
}
 +
 
 +
void NuPlusFrameLowering::emitEpilogue(MachineFunction &MF,
 +
                                      MachineBasicBlock &MBB) const {
 +
  MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr();
 +
  MachineFrameInfo &MFI = MF.getFrameInfo();
 +
  const NuPlusInstrInfo &TII =
 +
      *static_cast<const NuPlusInstrInfo *>(MF.getSubtarget().getInstrInfo());
 +
  DebugLoc DL = MBBI->getDebugLoc();
 +
  assert(MBBI->getOpcode() == NuPlus::JRET &&
 +
        "Can only put epilog before 'retl' instruction!");
 +
 
 +
  // if framepointer enabled, restore the stack pointer.
 +
  if (hasFP(MF)) {
 +
    // Find the first instruction that restores a callee-saved register.
 +
    MachineBasicBlock::iterator I = MBBI;
 +
    for (unsigned i = 0; i < MFI.getCalleeSavedInfo().size(); ++i)
 +
      --I;
 +
 
 +
    BuildMI(MBB, I, DL, TII.get(NuPlus::MOVE_SS_32))
 +
        .addReg(NuPlus::SP_REG)
 +
        .addReg(NuPlus::FP_REG);
 +
  }
 +
 
 +
  uint64_t StackSize = alignTo(MFI.getStackSize(), getStackAlignment());
 +
  if (!StackSize)
 +
    return;
 +
 
 +
  TII.adjustStackPointer(MBB, MBBI, DL, StackSize);
 +
}
 +
 
 +
MachineBasicBlock::iterator NuPlusFrameLowering::eliminateCallFramePseudoInstr(
 +
    MachineFunction &MF, MachineBasicBlock &MBB,
 +
    MachineBasicBlock::iterator MBBI) const {
 +
  MachineInstr &MI = *MBBI;
 +
 
 +
  const NuPlusInstrInfo &TII =
 +
      *static_cast<const NuPlusInstrInfo *>(MF.getSubtarget().getInstrInfo());
 +
 
 +
  // Note the check for hasReservedCallFrame.  If it returns true,
 +
  // PEI::calculateFrameObjectOffsets has already reserved stack locations for
 +
  // these variables and we don't need to adjust the stack here.
 +
  int Amount = TII.getFrameSize(MI);
 +
  if (Amount != 0 && !hasReservedCallFrame(MF)) {
 +
    assert(hasFP(MF) &&
 +
          "Cannot adjust stack mid-function without a frame pointer");
 +
 
 +
    if (MI.getOpcode() == NuPlus::ADJCALLSTACKDOWN)
 +
      Amount = -Amount;
 +
 
 +
    TII.adjustStackPointer(MBB, MBBI, MBBI->getDebugLoc(), Amount);
 +
  }
 +
 
 +
  return MBB.erase(MBBI);
 +
}
 +
 
 +
void NuPlusFrameLowering::determineCalleeSaves(MachineFunction &MF,
 +
                                              BitVector &SavedRegs,
 +
                                              RegScavenger *RS) const {
 +
 
 +
  TargetFrameLowering::determineCalleeSaves(MF, SavedRegs, RS);
 +
  if (hasFP(MF))
 +
    SavedRegs.set(NuPlus::FP_REG);
 +
 
 +
  // The register scavenger allows us to allocate virtual registers during
 +
  // epilogue/prologue insertion, after register allocation has run. We only
 +
  // need to do this if the frame is too large to be addressed by immediate
 +
  // offsets. If it isn't, don't bother creating a stack slot for it.
 +
  // This may create the scavenge slot when it isn't needed.
 +
  // This check must match the size of the one in
 +
  // NuPlusRegisterInfo::eliminateFrameIndex
 +
  if (isInt<9>(getWorstCaseStackSize(MF)))
 +
    return;
 +
 
 +
  const TargetRegisterInfo *TRI = MF.getSubtarget().getRegisterInfo();
 +
  const TargetRegisterClass &RC = NuPlus::GPR32RegClass;
 +
  int FI = MF.getFrameInfo().CreateStackObject(TRI->getSpillSize(RC),
 +
                                              TRI->getSpillAlignment(RC), false);
 +
  RS->addScavengingFrameIndex(FI);
 +
}
 +
 
 +
// We must use an FP in a few situations.  Note that this *must* return true if
 +
// hasReservedCallFrame returns false.  Otherwise an ADJCALLSTACKDOWN could mess
 +
// up frame offsets from the stack pointer.
 +
bool NuPlusFrameLowering::hasFP(const MachineFunction &MF) const {
 +
  const MachineFrameInfo &MFI = MF.getFrameInfo();
 +
  return MF.getTarget().Options.DisableFramePointerElim(MF) ||
 +
        MFI.hasVarSizedObjects() || MFI.isFrameAddressTaken();
 +
}
 +
 
 +
// Returns true if the prologue inserter should reserve space for outgoing
 +
// arguments to called.
 +
bool NuPlusFrameLowering::hasReservedCallFrame(const MachineFunction &MF) const {
 +
  return !MF.getFrameInfo().hasVarSizedObjects();
 +
}
 +
 
 +
uint64_t
 +
NuPlusFrameLowering::getWorstCaseStackSize(const MachineFunction &MF) const {
 +
  const MachineFrameInfo &MFI = MF.getFrameInfo();
 +
  const TargetRegisterInfo &TRI = *MF.getSubtarget().getRegisterInfo();
 +
 
 +
  int64_t Offset = 0;
 +
 
 +
  // Iterate over fixed sized objects.
 +
  for (int I = MFI.getObjectIndexBegin(); I != 0; ++I)
 +
    Offset = std::max(Offset, -MFI.getObjectOffset(I));
 +
 
 +
  // Conservatively assume all callee-saved registers will be saved.
 +
  for (const uint16_t *R = TRI.getCalleeSavedRegs(&MF); *R; ++R) {
 +
    const TargetRegisterClass *RC = TRI.getMinimalPhysRegClass(*R);
 +
    unsigned Size = TRI.getRegSizeInBits(*RC);
 +
    Offset = alignTo(Offset + Size, Size);
 +
  }
 +
 
 +
  unsigned MaxAlign = MFI.getMaxAlignment();
 +
 
 +
  // Check that MaxAlign is not zero if there is a stack object that is not a
 +
  // callee-saved spill.
 +
  assert(!MFI.getObjectIndexEnd() || MaxAlign);
 +
 
 +
  // Iterate over other objects.
 +
  for (unsigned I = 0, E = MFI.getObjectIndexEnd(); I != E; ++I)
 +
    Offset = alignTo(Offset + MFI.getObjectSize(I), MaxAlign);
 +
 
 +
  // Call frame.
 +
  if (MFI.adjustsStack() && hasReservedCallFrame(MF))
 +
    Offset = alignTo(Offset + MFI.getMaxCallFrameSize(),
 +
                    std::max(MaxAlign, getStackAlignment()));
 +
 
 +
  return alignTo(Offset, getStackAlignment());
 +
}
 +
 
 +
</syntaxhighlight>

Latest revision as of 15:48, 21 June 2019

The NuPlusFrameLowering class must handle all the operations concerning the stack frame. It implements the TargetFrameLowering interface. In nu+ the stack grows incrementing the address (i.e. the stack grows down) and it is 64-byte aligned.

//===-- NuPlusFrameLowering.cpp - NuPlus 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 NuPlus implementation of TargetFrameLowering
// class.
//
//===----------------------------------------------------------------------===//

#include "NuPlusFrameLowering.h"
#include "MCTargetDesc/NuPlusMCTargetDesc.h"
#include "NuPlusInstrInfo.h"
#include "NuPlusMachineFunctionInfo.h"
#include "llvm/CodeGen/MachineFrameInfo.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/CodeGen/MachineModuleInfo.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/CodeGen/RegisterScavenging.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/Function.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
#include "llvm/Target/TargetOptions.h"

using namespace llvm;

void NuPlusFrameLowering::emitPrologue(MachineFunction &MF,
                                      MachineBasicBlock &MBB) const {
  assert(&MF.front() == &MBB);
  MachineFrameInfo &MFI = MF.getFrameInfo();
  const NuPlusInstrInfo &TII =
      *static_cast<const NuPlusInstrInfo *>(MF.getSubtarget().getInstrInfo());
  const MCRegisterInfo *MRI = MF.getMMI().getContext().getRegisterInfo();
  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;

  // Compute stack size to allocate, keeping SP 64 byte aligned so we
  // can do block vector load/stores
  int StackSize = alignTo(MFI.getStackSize(), getStackAlignment());

  // Bail if there is no stack allocation
  if (StackSize == 0 && !MFI.adjustsStack())
    return;

  TII.adjustStackPointer(MBB, MBBI, DL, -StackSize);

  // Emit DW_CFA_def_cfa
  unsigned CFIIndex = MF.addFrameInst(
      MCCFIInstruction::createDefCfaOffset(nullptr, -StackSize));
  BuildMI(MBB, MBBI, DL, TII.get(TargetOpcode::CFI_INSTRUCTION))
      .addCFIIndex(CFIIndex);

  // Find the instruction past the last instruction that saves a callee-saved
  // register to the stack.  We need to set up FP after its old value has been
  // saved.
  const std::vector<CalleeSavedInfo> &CSI = MFI.getCalleeSavedInfo();
  if (CSI.size()) {
    for (unsigned i = 0; i < CSI.size(); ++i)
      ++MBBI;

    // Iterate over list of callee-saved registers and emit .cfi_offset
    // directives (debug information)
    for (const auto &I : CSI) {
      int64_t Offset = MFI.getObjectOffset(I.getFrameIdx());
      unsigned Reg = I.getReg();
      unsigned CFIIndex = MF.addFrameInst(MCCFIInstruction::createOffset(
          nullptr, MRI->getDwarfRegNum(Reg, 1), Offset));
      BuildMI(MBB, MBBI, DL, TII.get(TargetOpcode::CFI_INSTRUCTION))
          .addCFIIndex(CFIIndex);
    }
  }

  // fp = sp
  if (hasFP(MF)) {
    BuildMI(MBB, MBBI, DL, TII.get(NuPlus::MOVE_SS_32))
        .addReg(NuPlus::FP_REG)
        .addReg(NuPlus::SP_REG);

    // emit ".cfi_def_cfa_register $fp" (debug information)
    unsigned CFIIndex = MF.addFrameInst(MCCFIInstruction::createDefCfaRegister(
        nullptr, MRI->getDwarfRegNum(NuPlus::FP_REG, true)));
    BuildMI(MBB, MBBI, DL, TII.get(TargetOpcode::CFI_INSTRUCTION))
        .addCFIIndex(CFIIndex);
  }
}

void NuPlusFrameLowering::emitEpilogue(MachineFunction &MF,
                                      MachineBasicBlock &MBB) const {
  MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr();
  MachineFrameInfo &MFI = MF.getFrameInfo();
  const NuPlusInstrInfo &TII =
      *static_cast<const NuPlusInstrInfo *>(MF.getSubtarget().getInstrInfo());
  DebugLoc DL = MBBI->getDebugLoc();
  assert(MBBI->getOpcode() == NuPlus::JRET &&
         "Can only put epilog before 'retl' instruction!");

  // if framepointer enabled, restore the stack pointer.
  if (hasFP(MF)) {
    // Find the first instruction that restores a callee-saved register.
    MachineBasicBlock::iterator I = MBBI;
    for (unsigned i = 0; i < MFI.getCalleeSavedInfo().size(); ++i)
      --I;

    BuildMI(MBB, I, DL, TII.get(NuPlus::MOVE_SS_32))
        .addReg(NuPlus::SP_REG)
        .addReg(NuPlus::FP_REG);
  }

  uint64_t StackSize = alignTo(MFI.getStackSize(), getStackAlignment());
  if (!StackSize)
    return;

  TII.adjustStackPointer(MBB, MBBI, DL, StackSize);
}

MachineBasicBlock::iterator NuPlusFrameLowering::eliminateCallFramePseudoInstr(
    MachineFunction &MF, MachineBasicBlock &MBB,
    MachineBasicBlock::iterator MBBI) const {
  MachineInstr &MI = *MBBI;

  const NuPlusInstrInfo &TII =
      *static_cast<const NuPlusInstrInfo *>(MF.getSubtarget().getInstrInfo());

  // Note the check for hasReservedCallFrame.  If it returns true,
  // PEI::calculateFrameObjectOffsets has already reserved stack locations for
  // these variables and we don't need to adjust the stack here.
  int Amount = TII.getFrameSize(MI);
  if (Amount != 0 && !hasReservedCallFrame(MF)) {
    assert(hasFP(MF) &&
           "Cannot adjust stack mid-function without a frame pointer");

    if (MI.getOpcode() == NuPlus::ADJCALLSTACKDOWN)
      Amount = -Amount;

    TII.adjustStackPointer(MBB, MBBI, MBBI->getDebugLoc(), Amount);
  }

  return MBB.erase(MBBI);
}

void NuPlusFrameLowering::determineCalleeSaves(MachineFunction &MF,
                                              BitVector &SavedRegs,
                                              RegScavenger *RS) const {

  TargetFrameLowering::determineCalleeSaves(MF, SavedRegs, RS);
  if (hasFP(MF))
    SavedRegs.set(NuPlus::FP_REG);

  // The register scavenger allows us to allocate virtual registers during
  // epilogue/prologue insertion, after register allocation has run. We only
  // need to do this if the frame is too large to be addressed by immediate
  // offsets. If it isn't, don't bother creating a stack slot for it.
  // This may create the scavenge slot when it isn't needed.
  // This check must match the size of the one in
  // NuPlusRegisterInfo::eliminateFrameIndex
  if (isInt<9>(getWorstCaseStackSize(MF)))
    return;

  const TargetRegisterInfo *TRI = MF.getSubtarget().getRegisterInfo();
  const TargetRegisterClass &RC = NuPlus::GPR32RegClass;
  int FI = MF.getFrameInfo().CreateStackObject(TRI->getSpillSize(RC),
                                               TRI->getSpillAlignment(RC), false);
  RS->addScavengingFrameIndex(FI);
}

// We must use an FP in a few situations.  Note that this *must* return true if
// hasReservedCallFrame returns false.  Otherwise an ADJCALLSTACKDOWN could mess
// up frame offsets from the stack pointer.
bool NuPlusFrameLowering::hasFP(const MachineFunction &MF) const {
  const MachineFrameInfo &MFI = MF.getFrameInfo();
  return MF.getTarget().Options.DisableFramePointerElim(MF) ||
         MFI.hasVarSizedObjects() || MFI.isFrameAddressTaken();
}

// Returns true if the prologue inserter should reserve space for outgoing
// arguments to called.
bool NuPlusFrameLowering::hasReservedCallFrame(const MachineFunction &MF) const {
  return !MF.getFrameInfo().hasVarSizedObjects();
}

uint64_t
NuPlusFrameLowering::getWorstCaseStackSize(const MachineFunction &MF) const {
  const MachineFrameInfo &MFI = MF.getFrameInfo();
  const TargetRegisterInfo &TRI = *MF.getSubtarget().getRegisterInfo();

  int64_t Offset = 0;

  // Iterate over fixed sized objects.
  for (int I = MFI.getObjectIndexBegin(); I != 0; ++I)
    Offset = std::max(Offset, -MFI.getObjectOffset(I));

  // Conservatively assume all callee-saved registers will be saved.
  for (const uint16_t *R = TRI.getCalleeSavedRegs(&MF); *R; ++R) {
    const TargetRegisterClass *RC = TRI.getMinimalPhysRegClass(*R);
    unsigned Size = TRI.getRegSizeInBits(*RC);
    Offset = alignTo(Offset + Size, Size);
  }

  unsigned MaxAlign = MFI.getMaxAlignment();

  // Check that MaxAlign is not zero if there is a stack object that is not a
  // callee-saved spill.
  assert(!MFI.getObjectIndexEnd() || MaxAlign);

  // Iterate over other objects.
  for (unsigned I = 0, E = MFI.getObjectIndexEnd(); I != E; ++I)
    Offset = alignTo(Offset + MFI.getObjectSize(I), MaxAlign);

  // Call frame.
  if (MFI.adjustsStack() && hasReservedCallFrame(MF))
    Offset = alignTo(Offset + MFI.getMaxCallFrameSize(),
                     std::max(MaxAlign, getStackAlignment()));

  return alignTo(Offset, getStackAlignment());
}