2017-08-24 23:40:33 +08:00
|
|
|
//===- ARCFrameLowering.cpp - ARC Frame Information -------------*- C++ -*-===//
|
|
|
|
//
|
|
|
|
// 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 ARC implementation of the TargetFrameLowering class.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
#include "ARCFrameLowering.h"
|
|
|
|
#include "ARCMachineFunctionInfo.h"
|
|
|
|
#include "ARCSubtarget.h"
|
|
|
|
#include "llvm/CodeGen/MachineInstrBuilder.h"
|
|
|
|
#include "llvm/CodeGen/MachineModuleInfo.h"
|
|
|
|
#include "llvm/CodeGen/RegisterScavenging.h"
|
2017-11-17 09:07:10 +08:00
|
|
|
#include "llvm/CodeGen/TargetRegisterInfo.h"
|
2017-08-24 23:40:33 +08:00
|
|
|
#include "llvm/IR/Function.h"
|
|
|
|
#include "llvm/Support/Debug.h"
|
|
|
|
|
|
|
|
#define DEBUG_TYPE "arc-frame-lowering"
|
|
|
|
|
|
|
|
using namespace llvm;
|
|
|
|
|
|
|
|
static cl::opt<bool>
|
|
|
|
UseSaveRestoreFunclet("arc-save-restore-funclet", cl::Hidden,
|
|
|
|
cl::desc("Use arc callee save/restore functions"),
|
|
|
|
cl::init(true));
|
|
|
|
|
|
|
|
static const char *store_funclet_name[] = {
|
|
|
|
"__st_r13_to_r15", "__st_r13_to_r16", "__st_r13_to_r17", "__st_r13_to_r18",
|
|
|
|
"__st_r13_to_r19", "__st_r13_to_r20", "__st_r13_to_r21", "__st_r13_to_r22",
|
|
|
|
"__st_r13_to_r23", "__st_r13_to_r24", "__st_r13_to_r25",
|
|
|
|
};
|
|
|
|
|
|
|
|
static const char *load_funclet_name[] = {
|
|
|
|
"__ld_r13_to_r15", "__ld_r13_to_r16", "__ld_r13_to_r17", "__ld_r13_to_r18",
|
|
|
|
"__ld_r13_to_r19", "__ld_r13_to_r20", "__ld_r13_to_r21", "__ld_r13_to_r22",
|
|
|
|
"__ld_r13_to_r23", "__ld_r13_to_r24", "__ld_r13_to_r25",
|
|
|
|
};
|
|
|
|
|
|
|
|
static void generateStackAdjustment(MachineBasicBlock &MBB,
|
|
|
|
MachineBasicBlock::iterator MBBI,
|
|
|
|
const ARCInstrInfo &TII, DebugLoc dl,
|
|
|
|
int Amount, int StackPtr) {
|
|
|
|
unsigned AdjOp;
|
|
|
|
if (!Amount)
|
|
|
|
return;
|
|
|
|
bool Positive;
|
|
|
|
unsigned AbsAmount;
|
|
|
|
if (Amount < 0) {
|
|
|
|
AbsAmount = -Amount;
|
|
|
|
Positive = false;
|
|
|
|
} else {
|
|
|
|
AbsAmount = Amount;
|
|
|
|
Positive = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
DEBUG(dbgs() << "Internal: adjust stack by: " << Amount << "," << AbsAmount
|
|
|
|
<< "\n");
|
|
|
|
|
|
|
|
assert((AbsAmount % 4 == 0) && "Stack adjustments must be 4-byte aligned.");
|
|
|
|
if (isUInt<6>(AbsAmount))
|
|
|
|
AdjOp = Positive ? ARC::ADD_rru6 : ARC::SUB_rru6;
|
|
|
|
else
|
|
|
|
AdjOp = Positive ? ARC::ADD_rrlimm : ARC::SUB_rrlimm;
|
|
|
|
|
|
|
|
BuildMI(MBB, MBBI, dl, TII.get(AdjOp), StackPtr)
|
|
|
|
.addReg(StackPtr)
|
|
|
|
.addImm(AbsAmount);
|
|
|
|
}
|
|
|
|
|
|
|
|
static unsigned
|
|
|
|
determineLastCalleeSave(const std::vector<CalleeSavedInfo> &CSI) {
|
|
|
|
unsigned Last = 0;
|
|
|
|
for (auto Reg : CSI) {
|
|
|
|
assert(Reg.getReg() >= ARC::R13 && Reg.getReg() <= ARC::R25 &&
|
|
|
|
"Unexpected callee saved reg.");
|
|
|
|
if (Reg.getReg() > Last)
|
|
|
|
Last = Reg.getReg();
|
|
|
|
}
|
|
|
|
return Last;
|
|
|
|
}
|
|
|
|
|
|
|
|
void ARCFrameLowering::determineCalleeSaves(MachineFunction &MF,
|
|
|
|
BitVector &SavedRegs,
|
|
|
|
RegScavenger *RS) const {
|
|
|
|
DEBUG(dbgs() << "Determine Callee Saves: " << MF.getFunction()->getName()
|
|
|
|
<< "\n");
|
|
|
|
TargetFrameLowering::determineCalleeSaves(MF, SavedRegs, RS);
|
|
|
|
SavedRegs.set(ARC::BLINK);
|
|
|
|
}
|
|
|
|
|
|
|
|
void ARCFrameLowering::adjustStackToMatchRecords(
|
|
|
|
MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
|
|
|
|
bool Allocate) const {
|
|
|
|
MachineFunction &MF = *MBB.getParent();
|
|
|
|
int ScalarAlloc = MF.getFrameInfo().getStackSize();
|
|
|
|
|
|
|
|
if (Allocate) {
|
|
|
|
// Allocate by adjusting by the negative of what the record holder tracked
|
|
|
|
// it tracked a positive offset in a downward growing stack.
|
|
|
|
ScalarAlloc = -ScalarAlloc;
|
|
|
|
}
|
|
|
|
|
|
|
|
generateStackAdjustment(MBB, MBBI, *ST.getInstrInfo(), DebugLoc(),
|
|
|
|
ScalarAlloc, ARC::SP);
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Insert prolog code into the function.
|
|
|
|
/// For ARC, this inserts a call to a function that puts required callee saved
|
|
|
|
/// registers onto the stack, when enough callee saved registers are required.
|
|
|
|
void ARCFrameLowering::emitPrologue(MachineFunction &MF,
|
|
|
|
MachineBasicBlock &MBB) const {
|
|
|
|
DEBUG(dbgs() << "Emit Prologue: " << MF.getFunction()->getName() << "\n");
|
|
|
|
auto *AFI = MF.getInfo<ARCFunctionInfo>();
|
|
|
|
MachineModuleInfo &MMI = MF.getMMI();
|
|
|
|
MCContext &Context = MMI.getContext();
|
|
|
|
const MCRegisterInfo *MRI = Context.getRegisterInfo();
|
|
|
|
const ARCInstrInfo *TII = MF.getSubtarget<ARCSubtarget>().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;
|
|
|
|
MachineFrameInfo &MFI = MF.getFrameInfo();
|
|
|
|
const std::vector<CalleeSavedInfo> &CSI = MFI.getCalleeSavedInfo();
|
|
|
|
unsigned Last = determineLastCalleeSave(CSI);
|
|
|
|
unsigned StackSlotsUsedByFunclet = 0;
|
|
|
|
bool SavedBlink = false;
|
|
|
|
unsigned AlreadyAdjusted = 0;
|
|
|
|
if (MF.getFunction()->isVarArg()) {
|
|
|
|
// Add in the varargs area here first.
|
|
|
|
DEBUG(dbgs() << "Varargs\n");
|
|
|
|
unsigned VarArgsBytes = MFI.getObjectSize(AFI->getVarArgsFrameIndex());
|
|
|
|
BuildMI(MBB, MBBI, dl, TII->get(ARC::SUB_rru6))
|
|
|
|
.addReg(ARC::SP)
|
|
|
|
.addReg(ARC::SP)
|
|
|
|
.addImm(VarArgsBytes);
|
|
|
|
}
|
|
|
|
if (hasFP(MF)) {
|
|
|
|
DEBUG(dbgs() << "Saving FP\n");
|
|
|
|
BuildMI(MBB, MBBI, dl, TII->get(ARC::ST_AW_rs9))
|
|
|
|
.addReg(ARC::SP, RegState::Define)
|
|
|
|
.addReg(ARC::FP)
|
|
|
|
.addReg(ARC::SP)
|
|
|
|
.addImm(-4);
|
|
|
|
AlreadyAdjusted += 4;
|
|
|
|
}
|
|
|
|
if (UseSaveRestoreFunclet && Last > ARC::R14) {
|
|
|
|
DEBUG(dbgs() << "Creating store funclet.\n");
|
|
|
|
// BL to __save_r13_to_<TRI->getRegAsmName()>
|
|
|
|
StackSlotsUsedByFunclet = Last - ARC::R12;
|
|
|
|
BuildMI(MBB, MBBI, dl, TII->get(ARC::PUSH_S_BLINK));
|
|
|
|
BuildMI(MBB, MBBI, dl, TII->get(ARC::SUB_rru6))
|
|
|
|
.addReg(ARC::SP)
|
|
|
|
.addReg(ARC::SP)
|
|
|
|
.addImm(4 * StackSlotsUsedByFunclet);
|
|
|
|
BuildMI(MBB, MBBI, dl, TII->get(ARC::BL))
|
|
|
|
.addExternalSymbol(store_funclet_name[Last - ARC::R15])
|
|
|
|
.addReg(ARC::BLINK, RegState::Implicit | RegState::Kill);
|
|
|
|
AlreadyAdjusted += 4 * (StackSlotsUsedByFunclet + 1);
|
|
|
|
SavedBlink = true;
|
|
|
|
}
|
|
|
|
// If we haven't saved BLINK, but we need to...do that now.
|
|
|
|
if (MFI.hasCalls() && !SavedBlink) {
|
|
|
|
DEBUG(dbgs() << "Creating save blink.\n");
|
|
|
|
BuildMI(MBB, MBBI, dl, TII->get(ARC::PUSH_S_BLINK));
|
|
|
|
AlreadyAdjusted += 4;
|
|
|
|
}
|
|
|
|
if (AFI->MaxCallStackReq > 0)
|
|
|
|
MFI.setStackSize(MFI.getStackSize() + AFI->MaxCallStackReq);
|
|
|
|
// We have already saved some of the stack...
|
|
|
|
DEBUG(dbgs() << "Adjusting stack by: "
|
|
|
|
<< (MFI.getStackSize() - AlreadyAdjusted) << "\n");
|
|
|
|
generateStackAdjustment(MBB, MBBI, *ST.getInstrInfo(), dl,
|
|
|
|
-(MFI.getStackSize() - AlreadyAdjusted), ARC::SP);
|
|
|
|
|
|
|
|
if (hasFP(MF)) {
|
|
|
|
DEBUG(dbgs() << "Setting FP from SP.\n");
|
|
|
|
BuildMI(MBB, MBBI, dl,
|
|
|
|
TII->get(isUInt<6>(MFI.getStackSize()) ? ARC::ADD_rru6
|
|
|
|
: ARC::ADD_rrlimm),
|
|
|
|
ARC::FP)
|
|
|
|
.addReg(ARC::SP)
|
|
|
|
.addImm(MFI.getStackSize());
|
|
|
|
}
|
|
|
|
|
|
|
|
// Emit CFI records:
|
|
|
|
// .cfi_def_cfa_offset StackSize
|
|
|
|
// .cfi_offset fp, -StackSize
|
|
|
|
// .cfi_offset blink, -StackSize+4
|
|
|
|
unsigned CFIIndex = MF.addFrameInst(
|
|
|
|
MCCFIInstruction::createDefCfaOffset(nullptr, -MFI.getStackSize()));
|
|
|
|
BuildMI(MBB, MBBI, dl, TII->get(TargetOpcode::CFI_INSTRUCTION))
|
|
|
|
.addCFIIndex(CFIIndex)
|
|
|
|
.setMIFlags(MachineInstr::FrameSetup);
|
|
|
|
|
|
|
|
int CurOffset = -4;
|
|
|
|
if (hasFP(MF)) {
|
|
|
|
CFIIndex = MF.addFrameInst(MCCFIInstruction::createOffset(
|
|
|
|
nullptr, MRI->getDwarfRegNum(ARC::FP, true), CurOffset));
|
|
|
|
BuildMI(MBB, MBBI, dl, TII->get(TargetOpcode::CFI_INSTRUCTION))
|
|
|
|
.addCFIIndex(CFIIndex)
|
|
|
|
.setMIFlags(MachineInstr::FrameSetup);
|
|
|
|
CurOffset -= 4;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (MFI.hasCalls()) {
|
|
|
|
CFIIndex = MF.addFrameInst(MCCFIInstruction::createOffset(
|
|
|
|
nullptr, MRI->getDwarfRegNum(ARC::BLINK, true), CurOffset));
|
|
|
|
BuildMI(MBB, MBBI, dl, TII->get(TargetOpcode::CFI_INSTRUCTION))
|
|
|
|
.addCFIIndex(CFIIndex)
|
|
|
|
.setMIFlags(MachineInstr::FrameSetup);
|
|
|
|
}
|
|
|
|
// CFI for the rest of the registers.
|
|
|
|
for (const auto &Entry : CSI) {
|
|
|
|
unsigned Reg = Entry.getReg();
|
|
|
|
int FI = Entry.getFrameIdx();
|
|
|
|
// Skip BLINK and FP.
|
|
|
|
if ((hasFP(MF) && Reg == ARC::FP) || (MFI.hasCalls() && Reg == ARC::BLINK))
|
|
|
|
continue;
|
|
|
|
CFIIndex = MF.addFrameInst(MCCFIInstruction::createOffset(
|
|
|
|
nullptr, MRI->getDwarfRegNum(Reg, true), MFI.getObjectOffset(FI)));
|
|
|
|
BuildMI(MBB, MBBI, dl, TII->get(TargetOpcode::CFI_INSTRUCTION))
|
|
|
|
.addCFIIndex(CFIIndex)
|
|
|
|
.setMIFlags(MachineInstr::FrameSetup);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Insert epilog code into the function.
|
|
|
|
/// For ARC, this inserts a call to a function that restores callee saved
|
|
|
|
/// registers onto the stack, when enough callee saved registers are required.
|
|
|
|
void ARCFrameLowering::emitEpilogue(MachineFunction &MF,
|
|
|
|
MachineBasicBlock &MBB) const {
|
|
|
|
DEBUG(dbgs() << "Emit Epilogue: " << MF.getFunction()->getName() << "\n");
|
|
|
|
auto *AFI = MF.getInfo<ARCFunctionInfo>();
|
|
|
|
const ARCInstrInfo *TII = MF.getSubtarget<ARCSubtarget>().getInstrInfo();
|
|
|
|
MachineBasicBlock::iterator MBBI = MBB.getFirstTerminator();
|
|
|
|
MachineFrameInfo &MFI = MF.getFrameInfo();
|
|
|
|
uint64_t StackSize = MF.getFrameInfo().getStackSize();
|
|
|
|
bool SavedBlink = false;
|
|
|
|
unsigned AmountAboveFunclet = 0;
|
|
|
|
// If we have variable sized frame objects, then we have to move
|
|
|
|
// the stack pointer to a known spot (fp - StackSize).
|
|
|
|
// Then, replace the frame pointer by (new) [sp,StackSize-4].
|
|
|
|
// Then, move the stack pointer the rest of the way (sp = sp + StackSize).
|
|
|
|
if (hasFP(MF)) {
|
|
|
|
BuildMI(MBB, MBBI, DebugLoc(), TII->get(ARC::SUB_rru6), ARC::SP)
|
|
|
|
.addReg(ARC::FP)
|
|
|
|
.addImm(StackSize);
|
|
|
|
AmountAboveFunclet += 4;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Now, move the stack pointer to the bottom of the save area for the funclet.
|
|
|
|
const std::vector<CalleeSavedInfo> &CSI = MFI.getCalleeSavedInfo();
|
|
|
|
unsigned Last = determineLastCalleeSave(CSI);
|
|
|
|
unsigned StackSlotsUsedByFunclet = 0;
|
|
|
|
// Now, restore the callee save registers.
|
|
|
|
if (UseSaveRestoreFunclet && Last > ARC::R14) {
|
|
|
|
// BL to __ld_r13_to_<TRI->getRegAsmName()>
|
|
|
|
StackSlotsUsedByFunclet = Last - ARC::R12;
|
|
|
|
AmountAboveFunclet += 4 * (StackSlotsUsedByFunclet + 1);
|
|
|
|
SavedBlink = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (MFI.hasCalls() && !SavedBlink) {
|
|
|
|
AmountAboveFunclet += 4;
|
|
|
|
SavedBlink = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Move the stack pointer up to the point of the funclet.
|
|
|
|
if (StackSize - AmountAboveFunclet) {
|
|
|
|
BuildMI(MBB, MBBI, MBB.findDebugLoc(MBBI), TII->get(ARC::ADD_rru6))
|
|
|
|
.addReg(ARC::SP)
|
|
|
|
.addReg(ARC::SP)
|
|
|
|
.addImm(StackSize - AmountAboveFunclet);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (StackSlotsUsedByFunclet) {
|
|
|
|
BuildMI(MBB, MBBI, MBB.findDebugLoc(MBBI), TII->get(ARC::BL))
|
|
|
|
.addExternalSymbol(load_funclet_name[Last - ARC::R15])
|
|
|
|
.addReg(ARC::BLINK, RegState::Implicit | RegState::Kill);
|
|
|
|
BuildMI(MBB, MBBI, MBB.findDebugLoc(MBBI), TII->get(ARC::ADD_rru6))
|
|
|
|
.addReg(ARC::SP)
|
|
|
|
.addReg(ARC::SP)
|
|
|
|
.addImm(4 * (StackSlotsUsedByFunclet));
|
|
|
|
}
|
|
|
|
// Now, pop blink if necessary.
|
|
|
|
if (SavedBlink) {
|
|
|
|
BuildMI(MBB, MBBI, MBB.findDebugLoc(MBBI), TII->get(ARC::POP_S_BLINK));
|
|
|
|
}
|
|
|
|
// Now, pop fp if necessary.
|
|
|
|
if (hasFP(MF)) {
|
|
|
|
BuildMI(MBB, MBBI, MBB.findDebugLoc(MBBI), TII->get(ARC::LD_AB_rs9))
|
|
|
|
.addReg(ARC::SP, RegState::Define)
|
|
|
|
.addReg(ARC::FP, RegState::Define)
|
|
|
|
.addReg(ARC::SP)
|
|
|
|
.addImm(4);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Relieve the varargs area if necessary.
|
|
|
|
if (MF.getFunction()->isVarArg()) {
|
|
|
|
// Add in the varargs area here first.
|
|
|
|
DEBUG(dbgs() << "Varargs\n");
|
|
|
|
unsigned VarArgsBytes = MFI.getObjectSize(AFI->getVarArgsFrameIndex());
|
|
|
|
BuildMI(MBB, MBBI, MBB.findDebugLoc(MBBI), TII->get(ARC::ADD_rru6))
|
|
|
|
.addReg(ARC::SP)
|
|
|
|
.addReg(ARC::SP)
|
|
|
|
.addImm(VarArgsBytes);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static std::vector<CalleeSavedInfo>::iterator
|
|
|
|
getSavedReg(std::vector<CalleeSavedInfo> &V, unsigned reg) {
|
|
|
|
for (auto I = V.begin(), E = V.end(); I != E; ++I) {
|
|
|
|
if (reg == I->getReg())
|
|
|
|
return I;
|
|
|
|
}
|
|
|
|
return V.end();
|
|
|
|
}
|
|
|
|
|
|
|
|
bool ARCFrameLowering::assignCalleeSavedSpillSlots(
|
|
|
|
MachineFunction &MF, const TargetRegisterInfo *TRI,
|
|
|
|
std::vector<CalleeSavedInfo> &CSI) const {
|
|
|
|
// Use this opportunity to assign the spill slots for all of the potential
|
|
|
|
// callee save registers (blink, fp, r13->r25) that we care about the
|
|
|
|
// placement for. We can calculate all of that data here.
|
|
|
|
int CurOffset = -4;
|
|
|
|
unsigned Last = determineLastCalleeSave(CSI);
|
|
|
|
MachineFrameInfo &MFI = MF.getFrameInfo();
|
|
|
|
if (hasFP(MF)) {
|
|
|
|
// Create a fixed slot at for FP
|
|
|
|
int StackObj = MFI.CreateFixedSpillStackObject(4, CurOffset, true);
|
|
|
|
DEBUG(dbgs() << "Creating fixed object (" << StackObj << ") for FP at "
|
|
|
|
<< CurOffset << "\n");
|
|
|
|
(void)StackObj;
|
|
|
|
CurOffset -= 4;
|
|
|
|
}
|
|
|
|
if (MFI.hasCalls() || (UseSaveRestoreFunclet && Last > ARC::R14)) {
|
|
|
|
// Create a fixed slot for BLINK.
|
|
|
|
int StackObj = MFI.CreateFixedSpillStackObject(4, CurOffset, true);
|
|
|
|
DEBUG(dbgs() << "Creating fixed object (" << StackObj << ") for BLINK at "
|
|
|
|
<< CurOffset << "\n");
|
|
|
|
(void)StackObj;
|
|
|
|
CurOffset -= 4;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Create slots for last down to r13.
|
|
|
|
for (unsigned Which = Last; Which > ARC::R12; Which--) {
|
|
|
|
auto RegI = getSavedReg(CSI, Which);
|
|
|
|
if (RegI == CSI.end() || RegI->getFrameIdx() == 0) {
|
|
|
|
// Always create the stack slot. If for some reason the register isn't in
|
|
|
|
// the save list, then don't worry about it.
|
|
|
|
int FI = MFI.CreateFixedSpillStackObject(4, CurOffset, true);
|
|
|
|
if (RegI != CSI.end())
|
|
|
|
RegI->setFrameIdx(FI);
|
|
|
|
} else
|
|
|
|
MFI.setObjectOffset(RegI->getFrameIdx(), CurOffset);
|
|
|
|
CurOffset -= 4;
|
|
|
|
}
|
|
|
|
for (auto &I : CSI) {
|
|
|
|
if (I.getReg() > ARC::R12)
|
|
|
|
continue;
|
|
|
|
if (I.getFrameIdx() == 0) {
|
|
|
|
I.setFrameIdx(MFI.CreateFixedSpillStackObject(4, CurOffset, true));
|
|
|
|
DEBUG(dbgs() << "Creating fixed object (" << I.getFrameIdx()
|
|
|
|
<< ") for other register at " << CurOffset << "\n");
|
|
|
|
} else {
|
|
|
|
MFI.setObjectOffset(I.getFrameIdx(), CurOffset);
|
|
|
|
DEBUG(dbgs() << "Updating fixed object (" << I.getFrameIdx()
|
|
|
|
<< ") for other register at " << CurOffset << "\n");
|
|
|
|
}
|
|
|
|
CurOffset -= 4;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool ARCFrameLowering::spillCalleeSavedRegisters(
|
|
|
|
MachineBasicBlock &MBB, MachineBasicBlock::iterator MI,
|
|
|
|
const std::vector<CalleeSavedInfo> &CSI,
|
|
|
|
const TargetRegisterInfo *TRI) const {
|
|
|
|
DEBUG(dbgs() << "Spill callee saved registers: "
|
|
|
|
<< MBB.getParent()->getFunction()->getName() << "\n");
|
|
|
|
// There are routines for saving at least 3 registers (r13 to r15, etc.)
|
|
|
|
unsigned Last = determineLastCalleeSave(CSI);
|
|
|
|
if (UseSaveRestoreFunclet && Last > ARC::R14) {
|
|
|
|
// Use setObjectOffset for these registers.
|
|
|
|
// Needs to be in or before processFunctionBeforeFrameFinalized.
|
|
|
|
// Or, do assignCalleeSaveSpillSlots?
|
|
|
|
// Will be handled in prolog.
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool ARCFrameLowering::restoreCalleeSavedRegisters(
|
|
|
|
MachineBasicBlock &MBB, MachineBasicBlock::iterator MI,
|
|
|
|
std::vector<CalleeSavedInfo> &CSI, const TargetRegisterInfo *TRI) const {
|
|
|
|
DEBUG(dbgs() << "Restore callee saved registers: "
|
|
|
|
<< MBB.getParent()->getFunction()->getName() << "\n");
|
|
|
|
// There are routines for saving at least 3 registers (r13 to r15, etc.)
|
|
|
|
unsigned Last = determineLastCalleeSave(CSI);
|
|
|
|
if (UseSaveRestoreFunclet && Last > ARC::R14) {
|
|
|
|
// Will be handled in epilog.
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Adjust local variables that are 4-bytes or larger to 4-byte boundary
|
|
|
|
void ARCFrameLowering::processFunctionBeforeFrameFinalized(
|
|
|
|
MachineFunction &MF, RegScavenger *RS) const {
|
|
|
|
const TargetRegisterInfo *RegInfo = MF.getSubtarget().getRegisterInfo();
|
|
|
|
DEBUG(dbgs() << "Process function before frame finalized: "
|
|
|
|
<< MF.getFunction()->getName() << "\n");
|
|
|
|
MachineFrameInfo &MFI = MF.getFrameInfo();
|
|
|
|
DEBUG(dbgs() << "Current stack size: " << MFI.getStackSize() << "\n");
|
|
|
|
const TargetRegisterClass *RC = &ARC::GPR32RegClass;
|
|
|
|
if (MFI.hasStackObjects()) {
|
|
|
|
int RegScavFI = MFI.CreateStackObject(
|
|
|
|
RegInfo->getSpillSize(*RC), RegInfo->getSpillAlignment(*RC), false);
|
|
|
|
RS->addScavengingFrameIndex(RegScavFI);
|
|
|
|
DEBUG(dbgs() << "Created scavenging index RegScavFI=" << RegScavFI << "\n");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void emitRegUpdate(MachineBasicBlock &MBB,
|
|
|
|
MachineBasicBlock::iterator &MBBI, DebugLoc dl,
|
|
|
|
unsigned Reg, int NumBytes, bool IsAdd,
|
|
|
|
const ARCInstrInfo *TII) {
|
|
|
|
unsigned Opc = IsAdd ? ARC::ADD_rru6 : ARC::SUB_rru6;
|
|
|
|
BuildMI(MBB, MBBI, dl, TII->get(Opc), Reg)
|
|
|
|
.addReg(Reg, RegState::Kill)
|
|
|
|
.addImm(NumBytes);
|
|
|
|
}
|
|
|
|
|
|
|
|
MachineBasicBlock::iterator ARCFrameLowering::eliminateCallFramePseudoInstr(
|
|
|
|
MachineFunction &MF, MachineBasicBlock &MBB,
|
|
|
|
MachineBasicBlock::iterator I) const {
|
|
|
|
DEBUG(dbgs() << "EmitCallFramePseudo: " << MF.getFunction()->getName()
|
|
|
|
<< "\n");
|
|
|
|
const ARCInstrInfo *TII = MF.getSubtarget<ARCSubtarget>().getInstrInfo();
|
|
|
|
MachineInstr &Old = *I;
|
|
|
|
DebugLoc dl = Old.getDebugLoc();
|
|
|
|
unsigned Amt = Old.getOperand(0).getImm();
|
|
|
|
auto *AFI = MF.getInfo<ARCFunctionInfo>();
|
|
|
|
if (!hasFP(MF)) {
|
|
|
|
if (Amt > AFI->MaxCallStackReq && Old.getOpcode() == ARC::ADJCALLSTACKDOWN)
|
|
|
|
AFI->MaxCallStackReq = Amt;
|
|
|
|
} else {
|
|
|
|
if (Amt != 0) {
|
|
|
|
assert((Old.getOpcode() == ARC::ADJCALLSTACKDOWN ||
|
|
|
|
Old.getOpcode() == ARC::ADJCALLSTACKUP) &&
|
|
|
|
"Unknown Frame Pseudo.");
|
|
|
|
bool IsAdd = (Old.getOpcode() == ARC::ADJCALLSTACKUP);
|
|
|
|
emitRegUpdate(MBB, I, dl, ARC::SP, Amt, IsAdd, TII);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return MBB.erase(I);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool ARCFrameLowering::hasFP(const MachineFunction &MF) const {
|
|
|
|
const TargetRegisterInfo *RegInfo = MF.getSubtarget().getRegisterInfo();
|
|
|
|
bool HasFP = MF.getTarget().Options.DisableFramePointerElim(MF) ||
|
|
|
|
MF.getFrameInfo().hasVarSizedObjects() ||
|
|
|
|
MF.getFrameInfo().isFrameAddressTaken() ||
|
|
|
|
RegInfo->needsStackRealignment(MF);
|
|
|
|
return HasFP;
|
|
|
|
}
|