Difference between revisions of "NaplesPUFrameLowering.cpp"
From NaplesPU Documentation
(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...") |
|||
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 | + | |
− | + | <syntaxhighlight> | |
− | + | //===-- NuPlusFrameLowering.cpp - NuPlus Frame Information -----------------===// | |
− | *'''hasReservedCallFrame | + | // |
− | * | + | // 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()); | ||
+ | } | ||
+ | |||
+ | </syntaxhighlight> |
Revision as of 13:34, 5 April 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());
}