Index: lib/Target/NDS32/CMakeLists.txt =================================================================== --- lib/Target/NDS32/CMakeLists.txt +++ lib/Target/NDS32/CMakeLists.txt @@ -15,6 +15,7 @@ NDS32MachineFunctionInfo.cpp NDS32InstrInfo.cpp NDS32RegisterInfo.cpp + NDS32FrameLowering.cpp NDS32TargetMachine.cpp ) Index: lib/Target/NDS32/NDS32FrameLowering.h =================================================================== --- /dev/null +++ lib/Target/NDS32/NDS32FrameLowering.h @@ -0,0 +1,58 @@ +//==-- NDS32FrameLowering.h - Define frame lowering for NDS32 --*- C++ -*---==// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIB_TARGET_NDS32_NDS32FRAMELOWERING_H +#define LLVM_LIB_TARGET_NDS32_NDS32FRAMELOWERING_H + +#include "NDS32.h" +#include "llvm/Target/TargetFrameLowering.h" + +namespace llvm { +class NDS32FrameLowering : public TargetFrameLowering { +protected: + +public: + // Frame growing down and always 8-byte alignment for NDS32 target. + // Local area offset is 0 for NDS32. + explicit NDS32FrameLowering() + : TargetFrameLowering(TargetFrameLowering::StackGrowsDown, 8, 0, 8) {} + /// emitProlog/emitEpilog - These methods insert prolog and epilog code into + /// the function. + void emitPrologue(MachineFunction &MF, MachineBasicBlock &MBB) const override; + void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const override; + + MachineBasicBlock::iterator + eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB, + MachineBasicBlock::iterator I) const override; + + bool spillCalleeSavedRegisters(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MI, + const std::vector &CSI, + const TargetRegisterInfo *TRI) const override; + bool restoreCalleeSavedRegisters(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MI, + const std::vector &CSI, + const TargetRegisterInfo *TRI) const override; + + int getFrameIndexReference(const MachineFunction &MF, int FI, + unsigned &FrameReg) const override; + + bool hasFP(const MachineFunction &MF) const override; + bool hasReservedCallFrame(const MachineFunction &MF) const override; + void determineCalleeSaves(MachineFunction &MF, BitVector &SavedRegs, + RegScavenger *RS) const override; +}; + +} // End llvm namespace + +#endif Index: lib/Target/NDS32/NDS32FrameLowering.cpp =================================================================== --- /dev/null +++ lib/Target/NDS32/NDS32FrameLowering.cpp @@ -0,0 +1,247 @@ +//===-- NDS32FrameLowering.cpp - NDS32 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 NDS32 implementation of TargetFrameLowering class. +// +//===----------------------------------------------------------------------===// + +#include "NDS32FrameLowering.h" +#include "NDS32InstrInfo.h" +#include "NDS32MachineFunctionInfo.h" +#include "NDS32Subtarget.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/IR/DataLayout.h" +#include "llvm/IR/Function.h" +#include "llvm/Target/TargetOptions.h" + +using namespace llvm; + +bool NDS32FrameLowering::hasFP(const MachineFunction &MF) const { + const MachineFrameInfo &MFI = MF.getFrameInfo(); + + return (MF.getTarget().Options.DisableFramePointerElim(MF) || + MF.getFrameInfo().hasVarSizedObjects() || + MFI.isFrameAddressTaken()); +} + +bool NDS32FrameLowering::hasReservedCallFrame(const MachineFunction &MF) const { + return !MF.getFrameInfo().hasVarSizedObjects(); +} + +void NDS32FrameLowering::emitPrologue(MachineFunction &MF, + MachineBasicBlock &MBB) const { + unsigned SP = NDS32::SP; + unsigned FP = NDS32::FP; + unsigned ADDI = NDS32::ADDI; + + assert(&MF.front() == &MBB && "Shrink-wrapping not yet supported"); + MachineFrameInfo &MFI = MF.getFrameInfo(); + + const NDS32InstrInfo &TII = + *static_cast(MF.getSubtarget().getInstrInfo()); + + MachineBasicBlock::iterator MBBI = MBB.begin(); + DebugLoc dl; + + // First, compute final stack size. + uint64_t StackSize = MFI.getStackSize(); + + // No need to allocate space on the stack. + if (StackSize == 0 && !MFI.adjustsStack()) return; + + MachineModuleInfo &MMI = MF.getMMI(); + const MCRegisterInfo *MRI = MMI.getContext().getRegisterInfo(); + + // Adjust stack. + TII.adjustStackPtr(SP, -StackSize, MBB, MBBI); + + // emit ".cfi_def_cfa_offset StackSize" + unsigned CFIIndex = MF.addFrameInst( + MCCFIInstruction::createDefCfaOffset(nullptr, -StackSize)); + BuildMI(MBB, MBBI, dl, TII.get(TargetOpcode::CFI_INSTRUCTION)) + .addCFIIndex(CFIIndex); + + const std::vector &CSI = MFI.getCalleeSavedInfo(); + + if (CSI.size()) { + // Find the instruction past the last instruction that saves a callee-saved + // register to the stack. + for (unsigned i = 0; i < CSI.size(); ++i) + ++MBBI; + + // Iterate over list of callee-saved registers and emit .cfi_offset + // directives. + for (std::vector::const_iterator I = CSI.begin(), + E = CSI.end(); I != E; ++I) { + 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); + } + } + + // if framepointer enabled, set it to point to the stack pointer. + if (hasFP(MF)) { + + // Insert instruction "move $fp, $sp" at this location. + BuildMI(MBB, MBBI, dl, TII.get(ADDI), FP).addReg(SP).addImm(0) + .setMIFlag(MachineInstr::FrameSetup); + + // emit ".cfi_def_cfa_register $fp" + unsigned CFIIndex = MF.addFrameInst(MCCFIInstruction::createDefCfaRegister( + nullptr, MRI->getDwarfRegNum(FP, true))); + BuildMI(MBB, MBBI, dl, TII.get(TargetOpcode::CFI_INSTRUCTION)) + .addCFIIndex(CFIIndex); + } +} + + +void NDS32FrameLowering::emitEpilogue(MachineFunction &MF, + MachineBasicBlock &MBB) const { + unsigned SP = NDS32::SP; + unsigned FP = NDS32::FP; + unsigned ADDI = NDS32::ADDI; + + MachineFrameInfo &MFI = MF.getFrameInfo(); + const NDS32InstrInfo &TII = + *static_cast(MF.getSubtarget().getInstrInfo()); + + MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr(); + DebugLoc dl = MBBI->getDebugLoc(); + + // Get the number of bytes from FrameInfo + uint64_t StackSize = MFI.getStackSize(); + + // if framepointer enabled, restore the stack pointer. + if (hasFP(MF)) { + // Mark the FramePtr as live-in in every block except the entry. + for (MachineFunction::iterator I = std::next(MF.begin()), E = MF.end(); + I != E; ++I) + I->addLiveIn(FP); + + // Find the first instruction that restores a callee-saved register. + MachineBasicBlock::iterator I = MBBI; + + for (unsigned i = 0; i < MFI.getCalleeSavedInfo().size(); ++i) + --I; + + // Insert instruction "move $sp, $fp" at this location. + BuildMI(MBB, I, dl, TII.get(ADDI), SP).addReg(FP).addImm(0); + } + + if (!StackSize) + return; + else + // Adjust stack. + TII.adjustStackPtr(NDS32::SP, StackSize, MBB, MBBI); +} + +bool NDS32FrameLowering:: +spillCalleeSavedRegisters(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MI, + const std::vector &CSI, + const TargetRegisterInfo *TRI) const { + if (CSI.empty()) + return false; + + MachineFunction &MF = *MBB.getParent(); + MachineBasicBlock *EntryBlock = &(&MF)->front(); + const TargetInstrInfo &TII = *MF.getSubtarget().getInstrInfo(); + + for (unsigned i = 0, e = CSI.size(); i != e; ++i) { + unsigned Reg = CSI[i].getReg(); + + // Add the callee-saved register as live-in. It's killed at the spill. + MBB.addLiveIn(Reg); + + // Insert the spill to the stack frame. + bool IsKill = 1; + const TargetRegisterClass *RC = TRI->getMinimalPhysRegClass(Reg); + TII.storeRegToStackSlot(*EntryBlock, MI, Reg, IsKill, + CSI[i].getFrameIdx(), RC, TRI); + } + + return true; +} + +bool NDS32FrameLowering:: +restoreCalleeSavedRegisters(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MI, + const std::vector &CSI, + const TargetRegisterInfo *TRI) const { + if (CSI.empty()) + return false; + + DebugLoc DL; + if (MI != MBB.end()) DL = MI->getDebugLoc(); + + MachineFunction &MF = *MBB.getParent(); + const TargetInstrInfo &TII = *MF.getSubtarget().getInstrInfo(); + + for (unsigned i = 0, e = CSI.size(); i != e; ++i) { + unsigned Reg = CSI[i].getReg(); + const TargetRegisterClass *RC = TRI->getMinimalPhysRegClass(Reg); + TII.loadRegFromStackSlot(MBB, MI, Reg, CSI[i].getFrameIdx(), RC, TRI); + } + + return true; +} + +int NDS32FrameLowering::getFrameIndexReference(const MachineFunction &MF, + int FI, + unsigned &FrameReg) const { + const MachineFrameInfo &MFI = MF.getFrameInfo(); + + FrameReg = hasFP(MF) ? NDS32::FP : NDS32::SP; + + return MFI.getObjectOffset(FI) + MFI.getStackSize() - + getOffsetOfLocalArea() + MFI.getOffsetAdjustment(); +} + +MachineBasicBlock::iterator NDS32FrameLowering:: +eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB, + MachineBasicBlock::iterator MI) const { + unsigned SP = NDS32::SP; + const NDS32InstrInfo &TII = + *static_cast(MF.getSubtarget().getInstrInfo()); + + if (!hasReservedCallFrame(MF)) { + int64_t Amount = MI->getOperand(0).getImm(); + if (MI->getOpcode() == NDS32::ADJCALLSTACKDOWN) + Amount = -Amount; + + TII.adjustStackPtr(SP, Amount, MBB, MI); + } + + return MBB.erase(MI); +} + +/// Mark \p Reg and all registers aliasing it in the bitset. +static void setAliasRegs(MachineFunction &MF, BitVector &SavedRegs, + unsigned Reg) { + const TargetRegisterInfo *TRI = MF.getSubtarget().getRegisterInfo(); + for (MCRegAliasIterator AI(Reg, TRI, true); AI.isValid(); ++AI) + SavedRegs.set(*AI); +} + +void NDS32FrameLowering::determineCalleeSaves(MachineFunction &MF, + BitVector &SavedRegs, + RegScavenger *RS) const { + TargetFrameLowering::determineCalleeSaves(MF, SavedRegs, RS); + + // Mark $fp as used if function has dedicated frame pointer. + if (hasFP(MF)) + setAliasRegs(MF, SavedRegs, NDS32::FP); +}