mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-04-02 10:33:53 +00:00
Add definitions of two subclasses of MipsFrameLowering, Mips16FrameLowering and
MipsSEFrameLowering. Implement MipsSEFrameLowering::hasReservedCallFrame. Call frames will not be reserved if there is a call with a large call frame or there are variable sized objects on the stack. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@161090 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
d7122b8d3c
commit
cdb3ba71ce
@ -13,6 +13,7 @@ tablegen(LLVM MipsGenEDInfo.inc -gen-enhanced-disassembly-info)
|
|||||||
add_public_tablegen_target(MipsCommonTableGen)
|
add_public_tablegen_target(MipsCommonTableGen)
|
||||||
|
|
||||||
add_llvm_target(MipsCodeGen
|
add_llvm_target(MipsCodeGen
|
||||||
|
Mips16FrameLowering.cpp
|
||||||
Mips16InstrInfo.cpp
|
Mips16InstrInfo.cpp
|
||||||
MipsAnalyzeImmediate.cpp
|
MipsAnalyzeImmediate.cpp
|
||||||
MipsAsmPrinter.cpp
|
MipsAsmPrinter.cpp
|
||||||
@ -27,6 +28,7 @@ add_llvm_target(MipsCodeGen
|
|||||||
MipsMCInstLower.cpp
|
MipsMCInstLower.cpp
|
||||||
MipsMachineFunction.cpp
|
MipsMachineFunction.cpp
|
||||||
MipsRegisterInfo.cpp
|
MipsRegisterInfo.cpp
|
||||||
|
MipsSEFrameLowering.cpp
|
||||||
MipsSEInstrInfo.cpp
|
MipsSEInstrInfo.cpp
|
||||||
MipsSubtarget.cpp
|
MipsSubtarget.cpp
|
||||||
MipsTargetMachine.cpp
|
MipsTargetMachine.cpp
|
||||||
|
82
lib/Target/Mips/Mips16FrameLowering.cpp
Normal file
82
lib/Target/Mips/Mips16FrameLowering.cpp
Normal file
@ -0,0 +1,82 @@
|
|||||||
|
//===-- Mips16FrameLowering.cpp - Mips16 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 Mips16 implementation of TargetFrameLowering class.
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
#include "Mips16FrameLowering.h"
|
||||||
|
#include "MipsInstrInfo.h"
|
||||||
|
#include "MCTargetDesc/MipsBaseInfo.h"
|
||||||
|
#include "llvm/Function.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/Target/TargetData.h"
|
||||||
|
#include "llvm/Target/TargetOptions.h"
|
||||||
|
#include "llvm/Support/CommandLine.h"
|
||||||
|
|
||||||
|
using namespace llvm;
|
||||||
|
|
||||||
|
void Mips16FrameLowering::emitPrologue(MachineFunction &MF) const {
|
||||||
|
MachineBasicBlock &MBB = MF.front();
|
||||||
|
MachineFrameInfo *MFI = MF.getFrameInfo();
|
||||||
|
const MipsInstrInfo &TII =
|
||||||
|
*static_cast<const MipsInstrInfo*>(MF.getTarget().getInstrInfo());
|
||||||
|
MachineBasicBlock::iterator MBBI = MBB.begin();
|
||||||
|
DebugLoc dl = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc();
|
||||||
|
uint64_t StackSize = MFI->getStackSize();
|
||||||
|
|
||||||
|
// No need to allocate space on the stack.
|
||||||
|
if (StackSize == 0 && !MFI->adjustsStack()) return;
|
||||||
|
|
||||||
|
// Adjust stack.
|
||||||
|
if (isInt<16>(-StackSize))
|
||||||
|
BuildMI(MBB, MBBI, dl, TII.get(Mips::SaveRaF16)).addImm(StackSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Mips16FrameLowering::emitEpilogue(MachineFunction &MF,
|
||||||
|
MachineBasicBlock &MBB) const {
|
||||||
|
MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr();
|
||||||
|
MachineFrameInfo *MFI = MF.getFrameInfo();
|
||||||
|
const MipsInstrInfo &TII =
|
||||||
|
*static_cast<const MipsInstrInfo*>(MF.getTarget().getInstrInfo());
|
||||||
|
DebugLoc dl = MBBI->getDebugLoc();
|
||||||
|
uint64_t StackSize = MFI->getStackSize();
|
||||||
|
|
||||||
|
if (!StackSize)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Adjust stack.
|
||||||
|
if (isInt<16>(StackSize))
|
||||||
|
// assumes stacksize multiple of 8
|
||||||
|
BuildMI(MBB, MBBI, dl, TII.get(Mips::RestoreRaF16)).addImm(StackSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Mips16FrameLowering::
|
||||||
|
spillCalleeSavedRegisters(MachineBasicBlock &MBB,
|
||||||
|
MachineBasicBlock::iterator MI,
|
||||||
|
const std::vector<CalleeSavedInfo> &CSI,
|
||||||
|
const TargetRegisterInfo *TRI) const {
|
||||||
|
// FIXME: implement.
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
Mips16FrameLowering::hasReservedCallFrame(const MachineFunction &MF) const {
|
||||||
|
// FIXME: implement.
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Mips16FrameLowering::
|
||||||
|
processFunctionBeforeCalleeSavedScan(MachineFunction &MF,
|
||||||
|
RegScavenger *RS) const {
|
||||||
|
}
|
43
lib/Target/Mips/Mips16FrameLowering.h
Normal file
43
lib/Target/Mips/Mips16FrameLowering.h
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
//===-- Mips16FrameLowering.h - Mips16 frame lowering ----------*- C++ -*-===//
|
||||||
|
//
|
||||||
|
// The LLVM Compiler Infrastructure
|
||||||
|
//
|
||||||
|
// This file is distributed under the University of Illinois Open Source
|
||||||
|
// License. See LICENSE.TXT for details.
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
#ifndef MIPS16_FRAMEINFO_H
|
||||||
|
#define MIPS16_FRAMEINFO_H
|
||||||
|
|
||||||
|
#include "MipsFrameLowering.h"
|
||||||
|
|
||||||
|
namespace llvm {
|
||||||
|
class Mips16FrameLowering : public MipsFrameLowering {
|
||||||
|
public:
|
||||||
|
explicit Mips16FrameLowering(const MipsSubtarget &STI)
|
||||||
|
: MipsFrameLowering(STI) {}
|
||||||
|
|
||||||
|
/// emitProlog/emitEpilog - These methods insert prolog and epilog code into
|
||||||
|
/// the function.
|
||||||
|
void emitPrologue(MachineFunction &MF) const;
|
||||||
|
void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const;
|
||||||
|
|
||||||
|
bool spillCalleeSavedRegisters(MachineBasicBlock &MBB,
|
||||||
|
MachineBasicBlock::iterator MI,
|
||||||
|
const std::vector<CalleeSavedInfo> &CSI,
|
||||||
|
const TargetRegisterInfo *TRI) const;
|
||||||
|
|
||||||
|
bool hasReservedCallFrame(const MachineFunction &MF) const;
|
||||||
|
|
||||||
|
void processFunctionBeforeCalleeSavedScan(MachineFunction &MF,
|
||||||
|
RegScavenger *RS) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // End llvm namespace
|
||||||
|
|
||||||
|
#endif
|
@ -89,204 +89,3 @@ bool MipsFrameLowering::hasFP(const MachineFunction &MF) const {
|
|||||||
return MF.getTarget().Options.DisableFramePointerElim(MF) ||
|
return MF.getTarget().Options.DisableFramePointerElim(MF) ||
|
||||||
MFI->hasVarSizedObjects() || MFI->isFrameAddressTaken();
|
MFI->hasVarSizedObjects() || MFI->isFrameAddressTaken();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MipsFrameLowering::emitPrologue(MachineFunction &MF) const {
|
|
||||||
MachineBasicBlock &MBB = MF.front();
|
|
||||||
MachineFrameInfo *MFI = MF.getFrameInfo();
|
|
||||||
const MipsRegisterInfo *RegInfo =
|
|
||||||
static_cast<const MipsRegisterInfo*>(MF.getTarget().getRegisterInfo());
|
|
||||||
const MipsInstrInfo &TII =
|
|
||||||
*static_cast<const MipsInstrInfo*>(MF.getTarget().getInstrInfo());
|
|
||||||
MachineBasicBlock::iterator MBBI = MBB.begin();
|
|
||||||
DebugLoc dl = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc();
|
|
||||||
unsigned SP = STI.isABI_N64() ? Mips::SP_64 : Mips::SP;
|
|
||||||
unsigned FP = STI.isABI_N64() ? Mips::FP_64 : Mips::FP;
|
|
||||||
unsigned ZERO = STI.isABI_N64() ? Mips::ZERO_64 : Mips::ZERO;
|
|
||||||
unsigned ADDu = STI.isABI_N64() ? Mips::DADDu : Mips::ADDu;
|
|
||||||
unsigned ADDiu = STI.isABI_N64() ? Mips::DADDiu : Mips::ADDiu;
|
|
||||||
|
|
||||||
// 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();
|
|
||||||
std::vector<MachineMove> &Moves = MMI.getFrameMoves();
|
|
||||||
MachineLocation DstML, SrcML;
|
|
||||||
|
|
||||||
// Adjust stack.
|
|
||||||
if (isInt<16>(-StackSize)) {// addi sp, sp, (-stacksize)
|
|
||||||
if (STI.inMips16Mode())
|
|
||||||
BuildMI(MBB, MBBI, dl,
|
|
||||||
TII.get(Mips::SaveRaF16)).addImm(StackSize); // cleanup
|
|
||||||
else
|
|
||||||
BuildMI(MBB, MBBI, dl, TII.get(ADDiu), SP).addReg(SP).addImm(-StackSize);
|
|
||||||
}
|
|
||||||
else { // Expand immediate that doesn't fit in 16-bit.
|
|
||||||
unsigned ATReg = STI.isABI_N64() ? Mips::AT_64 : Mips::AT;
|
|
||||||
|
|
||||||
MF.getInfo<MipsFunctionInfo>()->setEmitNOAT();
|
|
||||||
Mips::loadImmediate(-StackSize, STI.isABI_N64(), TII, MBB, MBBI, dl, false,
|
|
||||||
0);
|
|
||||||
BuildMI(MBB, MBBI, dl, TII.get(ADDu), SP).addReg(SP).addReg(ATReg);
|
|
||||||
}
|
|
||||||
|
|
||||||
// emit ".cfi_def_cfa_offset StackSize"
|
|
||||||
MCSymbol *AdjustSPLabel = MMI.getContext().CreateTempSymbol();
|
|
||||||
BuildMI(MBB, MBBI, dl,
|
|
||||||
TII.get(TargetOpcode::PROLOG_LABEL)).addSym(AdjustSPLabel);
|
|
||||||
DstML = MachineLocation(MachineLocation::VirtualFP);
|
|
||||||
SrcML = MachineLocation(MachineLocation::VirtualFP, -StackSize);
|
|
||||||
Moves.push_back(MachineMove(AdjustSPLabel, DstML, SrcML));
|
|
||||||
|
|
||||||
const std::vector<CalleeSavedInfo> &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.
|
|
||||||
MCSymbol *CSLabel = MMI.getContext().CreateTempSymbol();
|
|
||||||
BuildMI(MBB, MBBI, dl,
|
|
||||||
TII.get(TargetOpcode::PROLOG_LABEL)).addSym(CSLabel);
|
|
||||||
|
|
||||||
for (std::vector<CalleeSavedInfo>::const_iterator I = CSI.begin(),
|
|
||||||
E = CSI.end(); I != E; ++I) {
|
|
||||||
int64_t Offset = MFI->getObjectOffset(I->getFrameIdx());
|
|
||||||
unsigned Reg = I->getReg();
|
|
||||||
|
|
||||||
// If Reg is a double precision register, emit two cfa_offsets,
|
|
||||||
// one for each of the paired single precision registers.
|
|
||||||
if (Mips::AFGR64RegClass.contains(Reg)) {
|
|
||||||
MachineLocation DstML0(MachineLocation::VirtualFP, Offset);
|
|
||||||
MachineLocation DstML1(MachineLocation::VirtualFP, Offset + 4);
|
|
||||||
MachineLocation SrcML0(RegInfo->getSubReg(Reg, Mips::sub_fpeven));
|
|
||||||
MachineLocation SrcML1(RegInfo->getSubReg(Reg, Mips::sub_fpodd));
|
|
||||||
|
|
||||||
if (!STI.isLittle())
|
|
||||||
std::swap(SrcML0, SrcML1);
|
|
||||||
|
|
||||||
Moves.push_back(MachineMove(CSLabel, DstML0, SrcML0));
|
|
||||||
Moves.push_back(MachineMove(CSLabel, DstML1, SrcML1));
|
|
||||||
} else {
|
|
||||||
// Reg is either in CPURegs or FGR32.
|
|
||||||
DstML = MachineLocation(MachineLocation::VirtualFP, Offset);
|
|
||||||
SrcML = MachineLocation(Reg);
|
|
||||||
Moves.push_back(MachineMove(CSLabel, DstML, SrcML));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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(ADDu), FP).addReg(SP).addReg(ZERO);
|
|
||||||
|
|
||||||
// emit ".cfi_def_cfa_register $fp"
|
|
||||||
MCSymbol *SetFPLabel = MMI.getContext().CreateTempSymbol();
|
|
||||||
BuildMI(MBB, MBBI, dl,
|
|
||||||
TII.get(TargetOpcode::PROLOG_LABEL)).addSym(SetFPLabel);
|
|
||||||
DstML = MachineLocation(FP);
|
|
||||||
SrcML = MachineLocation(MachineLocation::VirtualFP);
|
|
||||||
Moves.push_back(MachineMove(SetFPLabel, DstML, SrcML));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void MipsFrameLowering::emitEpilogue(MachineFunction &MF,
|
|
||||||
MachineBasicBlock &MBB) const {
|
|
||||||
MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr();
|
|
||||||
MachineFrameInfo *MFI = MF.getFrameInfo();
|
|
||||||
const MipsInstrInfo &TII =
|
|
||||||
*static_cast<const MipsInstrInfo*>(MF.getTarget().getInstrInfo());
|
|
||||||
DebugLoc dl = MBBI->getDebugLoc();
|
|
||||||
unsigned SP = STI.isABI_N64() ? Mips::SP_64 : Mips::SP;
|
|
||||||
unsigned FP = STI.isABI_N64() ? Mips::FP_64 : Mips::FP;
|
|
||||||
unsigned ZERO = STI.isABI_N64() ? Mips::ZERO_64 : Mips::ZERO;
|
|
||||||
unsigned ADDu = STI.isABI_N64() ? Mips::DADDu : Mips::ADDu;
|
|
||||||
unsigned ADDiu = STI.isABI_N64() ? Mips::DADDiu : Mips::ADDiu;
|
|
||||||
|
|
||||||
// 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;
|
|
||||||
|
|
||||||
// Insert instruction "move $sp, $fp" at this location.
|
|
||||||
BuildMI(MBB, I, dl, TII.get(ADDu), SP).addReg(FP).addReg(ZERO);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get the number of bytes from FrameInfo
|
|
||||||
uint64_t StackSize = MFI->getStackSize();
|
|
||||||
|
|
||||||
if (!StackSize)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// Adjust stack.
|
|
||||||
if (isInt<16>(StackSize)) { // addi sp, sp, (-stacksize)
|
|
||||||
if (STI.inMips16Mode())
|
|
||||||
// assumes stacksize multiple of 8
|
|
||||||
BuildMI(MBB, MBBI, dl,
|
|
||||||
TII.get(Mips::RestoreRaF16)).addImm(StackSize);
|
|
||||||
else
|
|
||||||
BuildMI(MBB, MBBI, dl, TII.get(ADDiu), SP).addReg(SP).addImm(StackSize);
|
|
||||||
}
|
|
||||||
else { // Expand immediate that doesn't fit in 16-bit.
|
|
||||||
unsigned ATReg = STI.isABI_N64() ? Mips::AT_64 : Mips::AT;
|
|
||||||
|
|
||||||
MF.getInfo<MipsFunctionInfo>()->setEmitNOAT();
|
|
||||||
Mips::loadImmediate(StackSize, STI.isABI_N64(), TII, MBB, MBBI, dl, false,
|
|
||||||
0);
|
|
||||||
BuildMI(MBB, MBBI, dl, TII.get(ADDu), SP).addReg(SP).addReg(ATReg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void MipsFrameLowering::
|
|
||||||
processFunctionBeforeCalleeSavedScan(MachineFunction &MF,
|
|
||||||
RegScavenger *RS) const {
|
|
||||||
MachineRegisterInfo &MRI = MF.getRegInfo();
|
|
||||||
unsigned FP = STI.isABI_N64() ? Mips::FP_64 : Mips::FP;
|
|
||||||
|
|
||||||
// FIXME: remove this code if register allocator can correctly mark
|
|
||||||
// $fp and $ra used or unused.
|
|
||||||
|
|
||||||
// Mark $fp and $ra as used or unused.
|
|
||||||
if (hasFP(MF))
|
|
||||||
MRI.setPhysRegUsed(FP);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool MipsFrameLowering::
|
|
||||||
spillCalleeSavedRegisters(MachineBasicBlock &MBB,
|
|
||||||
MachineBasicBlock::iterator MI,
|
|
||||||
const std::vector<CalleeSavedInfo> &CSI,
|
|
||||||
const TargetRegisterInfo *TRI) const {
|
|
||||||
MachineFunction *MF = MBB.getParent();
|
|
||||||
MachineBasicBlock *EntryBlock = MF->begin();
|
|
||||||
const TargetInstrInfo &TII = *MF->getTarget().getInstrInfo();
|
|
||||||
|
|
||||||
for (unsigned i = 0, e = CSI.size(); i != e; ++i) {
|
|
||||||
// Add the callee-saved register as live-in. Do not add if the register is
|
|
||||||
// RA and return address is taken, because it has already been added in
|
|
||||||
// method MipsTargetLowering::LowerRETURNADDR.
|
|
||||||
// It's killed at the spill, unless the register is RA and return address
|
|
||||||
// is taken.
|
|
||||||
unsigned Reg = CSI[i].getReg();
|
|
||||||
bool IsRAAndRetAddrIsTaken = (Reg == Mips::RA || Reg == Mips::RA_64)
|
|
||||||
&& MF->getFrameInfo()->isReturnAddressTaken();
|
|
||||||
if (!IsRAAndRetAddrIsTaken)
|
|
||||||
EntryBlock->addLiveIn(Reg);
|
|
||||||
|
|
||||||
// Insert the spill to the stack frame.
|
|
||||||
bool IsKill = !IsRAAndRetAddrIsTaken;
|
|
||||||
const TargetRegisterClass *RC = TRI->getMinimalPhysRegClass(Reg);
|
|
||||||
TII.storeRegToStackSlot(*EntryBlock, MI, Reg, IsKill,
|
|
||||||
CSI[i].getFrameIdx(), RC, TRI);
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
@ -31,20 +31,7 @@ public:
|
|||||||
STI(sti) {
|
STI(sti) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// emitProlog/emitEpilog - These methods insert prolog and epilog code into
|
|
||||||
/// the function.
|
|
||||||
void emitPrologue(MachineFunction &MF) const;
|
|
||||||
void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const;
|
|
||||||
|
|
||||||
bool spillCalleeSavedRegisters(MachineBasicBlock &MBB,
|
|
||||||
MachineBasicBlock::iterator MI,
|
|
||||||
const std::vector<CalleeSavedInfo> &CSI,
|
|
||||||
const TargetRegisterInfo *TRI) const;
|
|
||||||
|
|
||||||
bool hasFP(const MachineFunction &MF) const;
|
bool hasFP(const MachineFunction &MF) const;
|
||||||
|
|
||||||
void processFunctionBeforeCalleeSavedScan(MachineFunction &MF,
|
|
||||||
RegScavenger *RS) const;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // End llvm namespace
|
} // End llvm namespace
|
||||||
|
225
lib/Target/Mips/MipsSEFrameLowering.cpp
Normal file
225
lib/Target/Mips/MipsSEFrameLowering.cpp
Normal file
@ -0,0 +1,225 @@
|
|||||||
|
//===-- MipsSEFrameLowering.cpp - Mips32/64 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 Mips32/64 implementation of TargetFrameLowering class.
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
#include "MipsSEFrameLowering.h"
|
||||||
|
#include "MipsAnalyzeImmediate.h"
|
||||||
|
#include "MipsInstrInfo.h"
|
||||||
|
#include "MipsMachineFunction.h"
|
||||||
|
#include "MCTargetDesc/MipsBaseInfo.h"
|
||||||
|
#include "llvm/Function.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/Target/TargetData.h"
|
||||||
|
#include "llvm/Target/TargetOptions.h"
|
||||||
|
#include "llvm/Support/CommandLine.h"
|
||||||
|
|
||||||
|
using namespace llvm;
|
||||||
|
|
||||||
|
void MipsSEFrameLowering::emitPrologue(MachineFunction &MF) const {
|
||||||
|
MachineBasicBlock &MBB = MF.front();
|
||||||
|
MachineFrameInfo *MFI = MF.getFrameInfo();
|
||||||
|
const MipsRegisterInfo *RegInfo =
|
||||||
|
static_cast<const MipsRegisterInfo*>(MF.getTarget().getRegisterInfo());
|
||||||
|
const MipsInstrInfo &TII =
|
||||||
|
*static_cast<const MipsInstrInfo*>(MF.getTarget().getInstrInfo());
|
||||||
|
MachineBasicBlock::iterator MBBI = MBB.begin();
|
||||||
|
DebugLoc dl = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc();
|
||||||
|
unsigned SP = STI.isABI_N64() ? Mips::SP_64 : Mips::SP;
|
||||||
|
unsigned FP = STI.isABI_N64() ? Mips::FP_64 : Mips::FP;
|
||||||
|
unsigned ZERO = STI.isABI_N64() ? Mips::ZERO_64 : Mips::ZERO;
|
||||||
|
unsigned ADDu = STI.isABI_N64() ? Mips::DADDu : Mips::ADDu;
|
||||||
|
unsigned ADDiu = STI.isABI_N64() ? Mips::DADDiu : Mips::ADDiu;
|
||||||
|
|
||||||
|
// 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();
|
||||||
|
std::vector<MachineMove> &Moves = MMI.getFrameMoves();
|
||||||
|
MachineLocation DstML, SrcML;
|
||||||
|
|
||||||
|
// Adjust stack.
|
||||||
|
if (isInt<16>(-StackSize))// addi sp, sp, (-stacksize)
|
||||||
|
BuildMI(MBB, MBBI, dl, TII.get(ADDiu), SP).addReg(SP).addImm(-StackSize);
|
||||||
|
else { // Expand immediate that doesn't fit in 16-bit.
|
||||||
|
unsigned ATReg = STI.isABI_N64() ? Mips::AT_64 : Mips::AT;
|
||||||
|
|
||||||
|
MF.getInfo<MipsFunctionInfo>()->setEmitNOAT();
|
||||||
|
Mips::loadImmediate(-StackSize, STI.isABI_N64(), TII, MBB, MBBI, dl, false,
|
||||||
|
0);
|
||||||
|
BuildMI(MBB, MBBI, dl, TII.get(ADDu), SP).addReg(SP).addReg(ATReg);
|
||||||
|
}
|
||||||
|
|
||||||
|
// emit ".cfi_def_cfa_offset StackSize"
|
||||||
|
MCSymbol *AdjustSPLabel = MMI.getContext().CreateTempSymbol();
|
||||||
|
BuildMI(MBB, MBBI, dl,
|
||||||
|
TII.get(TargetOpcode::PROLOG_LABEL)).addSym(AdjustSPLabel);
|
||||||
|
DstML = MachineLocation(MachineLocation::VirtualFP);
|
||||||
|
SrcML = MachineLocation(MachineLocation::VirtualFP, -StackSize);
|
||||||
|
Moves.push_back(MachineMove(AdjustSPLabel, DstML, SrcML));
|
||||||
|
|
||||||
|
const std::vector<CalleeSavedInfo> &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.
|
||||||
|
MCSymbol *CSLabel = MMI.getContext().CreateTempSymbol();
|
||||||
|
BuildMI(MBB, MBBI, dl,
|
||||||
|
TII.get(TargetOpcode::PROLOG_LABEL)).addSym(CSLabel);
|
||||||
|
|
||||||
|
for (std::vector<CalleeSavedInfo>::const_iterator I = CSI.begin(),
|
||||||
|
E = CSI.end(); I != E; ++I) {
|
||||||
|
int64_t Offset = MFI->getObjectOffset(I->getFrameIdx());
|
||||||
|
unsigned Reg = I->getReg();
|
||||||
|
|
||||||
|
// If Reg is a double precision register, emit two cfa_offsets,
|
||||||
|
// one for each of the paired single precision registers.
|
||||||
|
if (Mips::AFGR64RegClass.contains(Reg)) {
|
||||||
|
MachineLocation DstML0(MachineLocation::VirtualFP, Offset);
|
||||||
|
MachineLocation DstML1(MachineLocation::VirtualFP, Offset + 4);
|
||||||
|
MachineLocation SrcML0(RegInfo->getSubReg(Reg, Mips::sub_fpeven));
|
||||||
|
MachineLocation SrcML1(RegInfo->getSubReg(Reg, Mips::sub_fpodd));
|
||||||
|
|
||||||
|
if (!STI.isLittle())
|
||||||
|
std::swap(SrcML0, SrcML1);
|
||||||
|
|
||||||
|
Moves.push_back(MachineMove(CSLabel, DstML0, SrcML0));
|
||||||
|
Moves.push_back(MachineMove(CSLabel, DstML1, SrcML1));
|
||||||
|
} else {
|
||||||
|
// Reg is either in CPURegs or FGR32.
|
||||||
|
DstML = MachineLocation(MachineLocation::VirtualFP, Offset);
|
||||||
|
SrcML = MachineLocation(Reg);
|
||||||
|
Moves.push_back(MachineMove(CSLabel, DstML, SrcML));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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(ADDu), FP).addReg(SP).addReg(ZERO);
|
||||||
|
|
||||||
|
// emit ".cfi_def_cfa_register $fp"
|
||||||
|
MCSymbol *SetFPLabel = MMI.getContext().CreateTempSymbol();
|
||||||
|
BuildMI(MBB, MBBI, dl,
|
||||||
|
TII.get(TargetOpcode::PROLOG_LABEL)).addSym(SetFPLabel);
|
||||||
|
DstML = MachineLocation(FP);
|
||||||
|
SrcML = MachineLocation(MachineLocation::VirtualFP);
|
||||||
|
Moves.push_back(MachineMove(SetFPLabel, DstML, SrcML));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MipsSEFrameLowering::emitEpilogue(MachineFunction &MF,
|
||||||
|
MachineBasicBlock &MBB) const {
|
||||||
|
MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr();
|
||||||
|
MachineFrameInfo *MFI = MF.getFrameInfo();
|
||||||
|
const MipsInstrInfo &TII =
|
||||||
|
*static_cast<const MipsInstrInfo*>(MF.getTarget().getInstrInfo());
|
||||||
|
DebugLoc dl = MBBI->getDebugLoc();
|
||||||
|
unsigned SP = STI.isABI_N64() ? Mips::SP_64 : Mips::SP;
|
||||||
|
unsigned FP = STI.isABI_N64() ? Mips::FP_64 : Mips::FP;
|
||||||
|
unsigned ZERO = STI.isABI_N64() ? Mips::ZERO_64 : Mips::ZERO;
|
||||||
|
unsigned ADDu = STI.isABI_N64() ? Mips::DADDu : Mips::ADDu;
|
||||||
|
unsigned ADDiu = STI.isABI_N64() ? Mips::DADDiu : Mips::ADDiu;
|
||||||
|
|
||||||
|
// 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;
|
||||||
|
|
||||||
|
// Insert instruction "move $sp, $fp" at this location.
|
||||||
|
BuildMI(MBB, I, dl, TII.get(ADDu), SP).addReg(FP).addReg(ZERO);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the number of bytes from FrameInfo
|
||||||
|
uint64_t StackSize = MFI->getStackSize();
|
||||||
|
|
||||||
|
if (!StackSize)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Adjust stack.
|
||||||
|
if (isInt<16>(StackSize)) // addi sp, sp, (-stacksize)
|
||||||
|
BuildMI(MBB, MBBI, dl, TII.get(ADDiu), SP).addReg(SP).addImm(StackSize);
|
||||||
|
else { // Expand immediate that doesn't fit in 16-bit.
|
||||||
|
unsigned ATReg = STI.isABI_N64() ? Mips::AT_64 : Mips::AT;
|
||||||
|
|
||||||
|
MF.getInfo<MipsFunctionInfo>()->setEmitNOAT();
|
||||||
|
Mips::loadImmediate(StackSize, STI.isABI_N64(), TII, MBB, MBBI, dl, false,
|
||||||
|
0);
|
||||||
|
BuildMI(MBB, MBBI, dl, TII.get(ADDu), SP).addReg(SP).addReg(ATReg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MipsSEFrameLowering::
|
||||||
|
spillCalleeSavedRegisters(MachineBasicBlock &MBB,
|
||||||
|
MachineBasicBlock::iterator MI,
|
||||||
|
const std::vector<CalleeSavedInfo> &CSI,
|
||||||
|
const TargetRegisterInfo *TRI) const {
|
||||||
|
MachineFunction *MF = MBB.getParent();
|
||||||
|
MachineBasicBlock *EntryBlock = MF->begin();
|
||||||
|
const TargetInstrInfo &TII = *MF->getTarget().getInstrInfo();
|
||||||
|
|
||||||
|
for (unsigned i = 0, e = CSI.size(); i != e; ++i) {
|
||||||
|
// Add the callee-saved register as live-in. Do not add if the register is
|
||||||
|
// RA and return address is taken, because it has already been added in
|
||||||
|
// method MipsTargetLowering::LowerRETURNADDR.
|
||||||
|
// It's killed at the spill, unless the register is RA and return address
|
||||||
|
// is taken.
|
||||||
|
unsigned Reg = CSI[i].getReg();
|
||||||
|
bool IsRAAndRetAddrIsTaken = (Reg == Mips::RA || Reg == Mips::RA_64)
|
||||||
|
&& MF->getFrameInfo()->isReturnAddressTaken();
|
||||||
|
if (!IsRAAndRetAddrIsTaken)
|
||||||
|
EntryBlock->addLiveIn(Reg);
|
||||||
|
|
||||||
|
// Insert the spill to the stack frame.
|
||||||
|
bool IsKill = !IsRAAndRetAddrIsTaken;
|
||||||
|
const TargetRegisterClass *RC = TRI->getMinimalPhysRegClass(Reg);
|
||||||
|
TII.storeRegToStackSlot(*EntryBlock, MI, Reg, IsKill,
|
||||||
|
CSI[i].getFrameIdx(), RC, TRI);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
MipsSEFrameLowering::hasReservedCallFrame(const MachineFunction &MF) const {
|
||||||
|
const MachineFrameInfo *MFI = MF.getFrameInfo();
|
||||||
|
|
||||||
|
// Reserve call frame if the size of the maximum call frame fits into 16-bit
|
||||||
|
// immediate field and there are no variable sized objects on the stack.
|
||||||
|
return isInt<16>(MFI->getMaxCallFrameSize()) && !MFI->hasVarSizedObjects();
|
||||||
|
}
|
||||||
|
|
||||||
|
void MipsSEFrameLowering::
|
||||||
|
processFunctionBeforeCalleeSavedScan(MachineFunction &MF,
|
||||||
|
RegScavenger *RS) const {
|
||||||
|
MachineRegisterInfo &MRI = MF.getRegInfo();
|
||||||
|
unsigned FP = STI.isABI_N64() ? Mips::FP_64 : Mips::FP;
|
||||||
|
|
||||||
|
// Mark $fp as used if function has dedicated frame pointer.
|
||||||
|
if (hasFP(MF))
|
||||||
|
MRI.setPhysRegUsed(FP);
|
||||||
|
}
|
44
lib/Target/Mips/MipsSEFrameLowering.h
Normal file
44
lib/Target/Mips/MipsSEFrameLowering.h
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
//===-- MipsSEFrameLowering.h - Mips32/64 frame lowering --------*- C++ -*-===//
|
||||||
|
//
|
||||||
|
// The LLVM Compiler Infrastructure
|
||||||
|
//
|
||||||
|
// This file is distributed under the University of Illinois Open Source
|
||||||
|
// License. See LICENSE.TXT for details.
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
#ifndef MIPSSE_FRAMEINFO_H
|
||||||
|
#define MIPSSE_FRAMEINFO_H
|
||||||
|
|
||||||
|
#include "MipsFrameLowering.h"
|
||||||
|
|
||||||
|
namespace llvm {
|
||||||
|
|
||||||
|
class MipsSEFrameLowering : public MipsFrameLowering {
|
||||||
|
public:
|
||||||
|
explicit MipsSEFrameLowering(const MipsSubtarget &STI)
|
||||||
|
: MipsFrameLowering(STI) {}
|
||||||
|
|
||||||
|
/// emitProlog/emitEpilog - These methods insert prolog and epilog code into
|
||||||
|
/// the function.
|
||||||
|
void emitPrologue(MachineFunction &MF) const;
|
||||||
|
void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const;
|
||||||
|
|
||||||
|
bool spillCalleeSavedRegisters(MachineBasicBlock &MBB,
|
||||||
|
MachineBasicBlock::iterator MI,
|
||||||
|
const std::vector<CalleeSavedInfo> &CSI,
|
||||||
|
const TargetRegisterInfo *TRI) const;
|
||||||
|
|
||||||
|
bool hasReservedCallFrame(const MachineFunction &MF) const;
|
||||||
|
|
||||||
|
void processFunctionBeforeCalleeSavedScan(MachineFunction &MF,
|
||||||
|
RegScavenger *RS) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // End llvm namespace
|
||||||
|
|
||||||
|
#endif
|
@ -12,9 +12,11 @@
|
|||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
#include "MipsTargetMachine.h"
|
#include "MipsTargetMachine.h"
|
||||||
#include "MipsSEInstrInfo.h"
|
|
||||||
#include "Mips16InstrInfo.h"
|
|
||||||
#include "Mips.h"
|
#include "Mips.h"
|
||||||
|
#include "Mips16FrameLowering.h"
|
||||||
|
#include "Mips16InstrInfo.h"
|
||||||
|
#include "MipsSEFrameLowering.h"
|
||||||
|
#include "MipsSEInstrInfo.h"
|
||||||
#include "llvm/PassManager.h"
|
#include "llvm/PassManager.h"
|
||||||
#include "llvm/CodeGen/Passes.h"
|
#include "llvm/CodeGen/Passes.h"
|
||||||
#include "llvm/Support/TargetRegistry.h"
|
#include "llvm/Support/TargetRegistry.h"
|
||||||
@ -39,6 +41,18 @@ static const MipsInstrInfo *genInstrInfo(MipsTargetMachine &TM) {
|
|||||||
return II;
|
return II;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const MipsFrameLowering *genFrameLowering(MipsTargetMachine &TM,
|
||||||
|
const MipsSubtarget &ST) {
|
||||||
|
const MipsFrameLowering *FL;
|
||||||
|
|
||||||
|
if (TM.getSubtargetImpl()->inMips16Mode())
|
||||||
|
FL = new Mips16FrameLowering(ST);
|
||||||
|
else
|
||||||
|
FL = new MipsSEFrameLowering(ST);
|
||||||
|
|
||||||
|
return FL;
|
||||||
|
}
|
||||||
|
|
||||||
// DataLayout --> Big-endian, 32-bit pointer/ABI/alignment
|
// DataLayout --> Big-endian, 32-bit pointer/ABI/alignment
|
||||||
// The stack is always 8 byte aligned
|
// The stack is always 8 byte aligned
|
||||||
// On function prologue, the stack is created by decrementing
|
// On function prologue, the stack is created by decrementing
|
||||||
@ -62,7 +76,7 @@ MipsTargetMachine(const Target &T, StringRef TT,
|
|||||||
"E-p:64:64:64-i8:8:32-i16:16:32-i64:64:64-f128:128:128-n32" :
|
"E-p:64:64:64-i8:8:32-i16:16:32-i64:64:64-f128:128:128-n32" :
|
||||||
"E-p:32:32:32-i8:8:32-i16:16:32-i64:64:64-n32")),
|
"E-p:32:32:32-i8:8:32-i16:16:32-i64:64:64-n32")),
|
||||||
InstrInfo(genInstrInfo(*this)),
|
InstrInfo(genInstrInfo(*this)),
|
||||||
FrameLowering(Subtarget),
|
FrameLowering(genFrameLowering(*this, Subtarget)),
|
||||||
TLInfo(*this), TSInfo(*this), JITInfo() {
|
TLInfo(*this), TSInfo(*this), JITInfo() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -32,7 +32,7 @@ class MipsTargetMachine : public LLVMTargetMachine {
|
|||||||
MipsSubtarget Subtarget;
|
MipsSubtarget Subtarget;
|
||||||
const TargetData DataLayout; // Calculates type size & alignment
|
const TargetData DataLayout; // Calculates type size & alignment
|
||||||
const MipsInstrInfo *InstrInfo;
|
const MipsInstrInfo *InstrInfo;
|
||||||
MipsFrameLowering FrameLowering;
|
const MipsFrameLowering *FrameLowering;
|
||||||
MipsTargetLowering TLInfo;
|
MipsTargetLowering TLInfo;
|
||||||
MipsSelectionDAGInfo TSInfo;
|
MipsSelectionDAGInfo TSInfo;
|
||||||
MipsJITInfo JITInfo;
|
MipsJITInfo JITInfo;
|
||||||
@ -49,7 +49,7 @@ public:
|
|||||||
virtual const MipsInstrInfo *getInstrInfo() const
|
virtual const MipsInstrInfo *getInstrInfo() const
|
||||||
{ return InstrInfo; }
|
{ return InstrInfo; }
|
||||||
virtual const TargetFrameLowering *getFrameLowering() const
|
virtual const TargetFrameLowering *getFrameLowering() const
|
||||||
{ return &FrameLowering; }
|
{ return FrameLowering; }
|
||||||
virtual const MipsSubtarget *getSubtargetImpl() const
|
virtual const MipsSubtarget *getSubtargetImpl() const
|
||||||
{ return &Subtarget; }
|
{ return &Subtarget; }
|
||||||
virtual const TargetData *getTargetData() const
|
virtual const TargetData *getTargetData() const
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
|
|
||||||
define void @f() nounwind {
|
define void @f() nounwind {
|
||||||
entry:
|
entry:
|
||||||
; CHECK: lui $at, 65534
|
; CHECK: lui $at, 65535
|
||||||
; CHECK: addiu $at, $at, -16
|
; CHECK: addiu $at, $at, -16
|
||||||
; CHECK: addu $sp, $sp, $at
|
; CHECK: addu $sp, $sp, $at
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user