mirror of
https://github.com/RPCSX/llvm.git
synced 2024-11-29 14:40:25 +00:00
Lower the MBlaze target specific calling conventions for "interrupt_handler"
and "save_volatiles" correctly. This completes the custom calling convention functionality changes for the MBlaze backend that were started in 121888. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@121891 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
d364acd3d7
commit
dc9d87a9bb
@ -132,6 +132,92 @@ static void analyzeFrameIndexes(MachineFunction &MF) {
|
||||
MBlazeFI->setStackAdjust(StackAdjust);
|
||||
}
|
||||
|
||||
static void interruptFrameLayout(MachineFunction &MF) {
|
||||
const Function *F = MF.getFunction();
|
||||
llvm::CallingConv::ID CallConv = F->getCallingConv();
|
||||
|
||||
// If this function is not using either the interrupt_handler
|
||||
// calling convention or the save_volatiles calling convention
|
||||
// then we don't need to do any additional frame layout.
|
||||
if (CallConv != llvm::CallingConv::MBLAZE_INTR &&
|
||||
CallConv != llvm::CallingConv::MBLAZE_SVOL)
|
||||
return;
|
||||
|
||||
MachineFrameInfo *MFI = MF.getFrameInfo();
|
||||
const MachineRegisterInfo &MRI = MF.getRegInfo();
|
||||
const MBlazeInstrInfo &TII =
|
||||
*static_cast<const MBlazeInstrInfo*>(MF.getTarget().getInstrInfo());
|
||||
|
||||
// Determine if the calling convention is the interrupt_handler
|
||||
// calling convention. Some pieces of the prologue and epilogue
|
||||
// only need to be emitted if we are lowering and interrupt handler.
|
||||
bool isIntr = CallConv == llvm::CallingConv::MBLAZE_INTR;
|
||||
|
||||
// Determine where to put prologue and epilogue additions
|
||||
MachineBasicBlock &MENT = MF.front();
|
||||
MachineBasicBlock &MEXT = MF.back();
|
||||
|
||||
MachineBasicBlock::iterator MENTI = MENT.begin();
|
||||
MachineBasicBlock::iterator MEXTI = prior(MEXT.end());
|
||||
|
||||
DebugLoc ENTDL = MENTI != MENT.end() ? MENTI->getDebugLoc() : DebugLoc();
|
||||
DebugLoc EXTDL = MEXTI != MEXT.end() ? MEXTI->getDebugLoc() : DebugLoc();
|
||||
|
||||
// Store the frame indexes generated during prologue additions for use
|
||||
// when we are generating the epilogue additions.
|
||||
SmallVector<int, 10> VFI;
|
||||
|
||||
// Build the prologue SWI for R3 - R12 if needed. Note that R11 must
|
||||
// always have a SWI because it is used when processing RMSR.
|
||||
for (unsigned r = MBlaze::R3; r <= MBlaze::R12; ++r) {
|
||||
if (!MRI.isPhysRegUsed(r) && !(isIntr && r == MBlaze::R11)) continue;
|
||||
|
||||
int FI = MFI->CreateStackObject(4,4,false,false);
|
||||
VFI.push_back(FI);
|
||||
|
||||
BuildMI(MENT, MENTI, ENTDL, TII.get(MBlaze::SWI), r)
|
||||
.addFrameIndex(FI).addImm(0);
|
||||
}
|
||||
|
||||
// Build the prologue SWI for R17, R18
|
||||
int R17FI = MFI->CreateStackObject(4,4,false,false);
|
||||
int R18FI = MFI->CreateStackObject(4,4,false,false);
|
||||
|
||||
BuildMI(MENT, MENTI, ENTDL, TII.get(MBlaze::SWI), MBlaze::R17)
|
||||
.addFrameIndex(R17FI).addImm(0);
|
||||
|
||||
BuildMI(MENT, MENTI, ENTDL, TII.get(MBlaze::SWI), MBlaze::R18)
|
||||
.addFrameIndex(R18FI).addImm(0);
|
||||
|
||||
// Buid the prologue SWI and the epilogue LWI for RMSR if needed
|
||||
if (isIntr) {
|
||||
int MSRFI = MFI->CreateStackObject(4,4,false,false);
|
||||
BuildMI(MENT, MENTI, ENTDL, TII.get(MBlaze::MFS), MBlaze::R11)
|
||||
.addReg(MBlaze::RMSR);
|
||||
BuildMI(MENT, MENTI, ENTDL, TII.get(MBlaze::SWI), MBlaze::R11)
|
||||
.addFrameIndex(MSRFI).addImm(0);
|
||||
|
||||
BuildMI(MEXT, MEXTI, EXTDL, TII.get(MBlaze::LWI), MBlaze::R11)
|
||||
.addFrameIndex(MSRFI).addImm(0);
|
||||
BuildMI(MEXT, MEXTI, EXTDL, TII.get(MBlaze::MTS), MBlaze::RMSR)
|
||||
.addReg(MBlaze::R11);
|
||||
}
|
||||
|
||||
// Build the epilogue LWI for R17, R18
|
||||
BuildMI(MEXT, MEXTI, EXTDL, TII.get(MBlaze::LWI), MBlaze::R18)
|
||||
.addFrameIndex(R18FI).addImm(0);
|
||||
|
||||
BuildMI(MEXT, MEXTI, EXTDL, TII.get(MBlaze::LWI), MBlaze::R17)
|
||||
.addFrameIndex(R17FI).addImm(0);
|
||||
|
||||
// Build the epilogue LWI for R3 - R12 if needed
|
||||
for (unsigned r = MBlaze::R12, i = VFI.size(); r >= MBlaze::R3; --r) {
|
||||
if (!MRI.isPhysRegUsed(r)) continue;
|
||||
BuildMI(MEXT, MEXTI, EXTDL, TII.get(MBlaze::LWI), r)
|
||||
.addFrameIndex(VFI[--i]).addImm(0);
|
||||
}
|
||||
}
|
||||
|
||||
static void determineFrameLayout(MachineFunction &MF) {
|
||||
MachineFrameInfo *MFI = MF.getFrameInfo();
|
||||
MBlazeFunctionInfo *MBlazeFI = MF.getInfo<MBlazeFunctionInfo>();
|
||||
@ -174,6 +260,9 @@ void MBlazeFrameInfo::emitPrologue(MachineFunction &MF) const {
|
||||
MachineBasicBlock::iterator MBBI = MBB.begin();
|
||||
DebugLoc DL = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc();
|
||||
|
||||
llvm::CallingConv::ID CallConv = MF.getFunction()->getCallingConv();
|
||||
bool requiresRA = CallConv == llvm::CallingConv::MBLAZE_INTR;
|
||||
|
||||
// Determine the correct frame layout
|
||||
determineFrameLayout(MF);
|
||||
|
||||
@ -181,7 +270,7 @@ void MBlazeFrameInfo::emitPrologue(MachineFunction &MF) const {
|
||||
unsigned StackSize = MFI->getStackSize();
|
||||
|
||||
// No need to allocate space on the stack.
|
||||
if (StackSize == 0 && !MFI->adjustsStack()) return;
|
||||
if (StackSize == 0 && !MFI->adjustsStack() && !requiresRA) return;
|
||||
|
||||
int FPOffset = MBlazeFI->getFPStackOffset();
|
||||
int RAOffset = MBlazeFI->getRAStackOffset();
|
||||
@ -191,7 +280,7 @@ void MBlazeFrameInfo::emitPrologue(MachineFunction &MF) const {
|
||||
.addReg(MBlaze::R1).addImm(-StackSize);
|
||||
|
||||
// swi R15, R1, stack_loc
|
||||
if (MFI->adjustsStack()) {
|
||||
if (MFI->adjustsStack() || requiresRA) {
|
||||
BuildMI(MBB, MBBI, DL, TII.get(MBlaze::SWI))
|
||||
.addReg(MBlaze::R15).addReg(MBlaze::R1).addImm(RAOffset);
|
||||
}
|
||||
@ -217,6 +306,9 @@ void MBlazeFrameInfo::emitEpilogue(MachineFunction &MF,
|
||||
|
||||
DebugLoc dl = MBBI->getDebugLoc();
|
||||
|
||||
llvm::CallingConv::ID CallConv = MF.getFunction()->getCallingConv();
|
||||
bool requiresRA = CallConv == llvm::CallingConv::MBLAZE_INTR;
|
||||
|
||||
// Get the FI's where RA and FP are saved.
|
||||
int FPOffset = MBlazeFI->getFPStackOffset();
|
||||
int RAOffset = MBlazeFI->getRAStackOffset();
|
||||
@ -232,7 +324,7 @@ void MBlazeFrameInfo::emitEpilogue(MachineFunction &MF,
|
||||
}
|
||||
|
||||
// lwi R15, R1, stack_loc
|
||||
if (MFI->adjustsStack()) {
|
||||
if (MFI->adjustsStack() || requiresRA) {
|
||||
BuildMI(MBB, MBBI, dl, TII.get(MBlaze::LWI), MBlaze::R15)
|
||||
.addReg(MBlaze::R1).addImm(RAOffset);
|
||||
}
|
||||
@ -251,8 +343,10 @@ void MBlazeFrameInfo::processFunctionBeforeCalleeSavedScan(MachineFunction &MF,
|
||||
const {
|
||||
MachineFrameInfo *MFI = MF.getFrameInfo();
|
||||
MBlazeFunctionInfo *MBlazeFI = MF.getInfo<MBlazeFunctionInfo>();
|
||||
llvm::CallingConv::ID CallConv = MF.getFunction()->getCallingConv();
|
||||
bool requiresRA = CallConv == llvm::CallingConv::MBLAZE_INTR;
|
||||
|
||||
if (MFI->adjustsStack()) {
|
||||
if (MFI->adjustsStack() || requiresRA) {
|
||||
MBlazeFI->setRAStackOffset(0);
|
||||
MFI->CreateFixedObject(4,0,true);
|
||||
}
|
||||
@ -262,5 +356,6 @@ void MBlazeFrameInfo::processFunctionBeforeCalleeSavedScan(MachineFunction &MF,
|
||||
MFI->CreateFixedObject(4,4,true);
|
||||
}
|
||||
|
||||
interruptFrameLayout(MF);
|
||||
analyzeFrameIndexes(MF);
|
||||
}
|
||||
|
@ -864,13 +864,18 @@ LowerReturn(SDValue Chain, CallingConv::ID CallConv, bool isVarArg,
|
||||
Flag = Chain.getValue(1);
|
||||
}
|
||||
|
||||
// Return on MBlaze is always a "rtsd R15, 8"
|
||||
// If this function is using the interrupt_handler calling convention
|
||||
// then use "rtid r14, 0" otherwise use "rtsd r15, 8"
|
||||
unsigned Ret = (CallConv == llvm::CallingConv::MBLAZE_INTR) ? MBlazeISD::IRet
|
||||
: MBlazeISD::Ret;
|
||||
unsigned Reg = (CallConv == llvm::CallingConv::MBLAZE_INTR) ? MBlaze::R14
|
||||
: MBlaze::R15;
|
||||
SDValue DReg = DAG.getRegister(Reg, MVT::i32);
|
||||
|
||||
if (Flag.getNode())
|
||||
return DAG.getNode(MBlazeISD::Ret, dl, MVT::Other,
|
||||
Chain, DAG.getRegister(MBlaze::R15, MVT::i32), Flag);
|
||||
else // Return Void
|
||||
return DAG.getNode(MBlazeISD::Ret, dl, MVT::Other,
|
||||
Chain, DAG.getRegister(MBlaze::R15, MVT::i32));
|
||||
return DAG.getNode(Ret, dl, MVT::Other, Chain, DReg, Flag);
|
||||
|
||||
return DAG.getNode(Ret, dl, MVT::Other, Chain, DReg);
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
@ -78,8 +78,11 @@ namespace llvm {
|
||||
// Integer Compare
|
||||
ICmp,
|
||||
|
||||
// Return
|
||||
Ret
|
||||
// Return from subroutine
|
||||
Ret,
|
||||
|
||||
// Return from interrupt
|
||||
IRet
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -18,6 +18,7 @@ include "MBlazeInstrFormats.td"
|
||||
|
||||
// def SDTMBlazeSelectCC : SDTypeProfile<1, 3, [SDTCisSameAs<0, 1>]>;
|
||||
def SDT_MBlazeRet : SDTypeProfile<0, 1, [SDTCisInt<0>]>;
|
||||
def SDT_MBlazeIRet : SDTypeProfile<0, 1, [SDTCisInt<0>]>;
|
||||
def SDT_MBlazeJmpLink : SDTypeProfile<0, 1, [SDTCisVT<0, i32>]>;
|
||||
def SDT_MBCallSeqStart : SDCallSeqStart<[SDTCisVT<0, i32>]>;
|
||||
def SDT_MBCallSeqEnd : SDCallSeqEnd<[SDTCisVT<0, i32>, SDTCisVT<1, i32>]>;
|
||||
@ -28,6 +29,8 @@ def SDT_MBCallSeqEnd : SDCallSeqEnd<[SDTCisVT<0, i32>, SDTCisVT<1, i32>]>;
|
||||
|
||||
def MBlazeRet : SDNode<"MBlazeISD::Ret", SDT_MBlazeRet,
|
||||
[SDNPHasChain, SDNPOptInFlag]>;
|
||||
def MBlazeIRet : SDNode<"MBlazeISD::IRet", SDT_MBlazeIRet,
|
||||
[SDNPHasChain, SDNPOptInFlag]>;
|
||||
|
||||
def MBlazeJmpLink : SDNode<"MBlazeISD::JmpLink",SDT_MBlazeJmpLink,
|
||||
[SDNPHasChain,SDNPOptInFlag,SDNPOutFlag]>;
|
||||
@ -727,6 +730,7 @@ def : Pat<(selectcc (i32 GPR:$L), (i32 GPR:$R),
|
||||
|
||||
// Ret instructions
|
||||
def : Pat<(MBlazeRet GPR:$target), (RTSD GPR:$target, 0x8)>;
|
||||
def : Pat<(MBlazeIRet GPR:$target), (RTID GPR:$target, 0x0)>;
|
||||
|
||||
// BR instructions
|
||||
def : Pat<(br bb:$T), (BRID bb:$T)>;
|
||||
|
48
test/CodeGen/MBlaze/intr.ll
Normal file
48
test/CodeGen/MBlaze/intr.ll
Normal file
@ -0,0 +1,48 @@
|
||||
; Ensure that the MBlaze interrupt_handler calling convention (cc73) is handled
|
||||
; correctly correctly by the MBlaze backend.
|
||||
;
|
||||
; RUN: llc < %s -march=mblaze | FileCheck %s
|
||||
|
||||
@.str = private constant [28 x i8] c"The interrupt has gone off\0A\00"
|
||||
@_interrupt_handler = alias void ()* @myintr
|
||||
|
||||
define cc73 void @myintr() nounwind noinline {
|
||||
; CHECK: myintr:
|
||||
; CHECK: swi r3, r1
|
||||
; CHECK: swi r4, r1
|
||||
; CHECK: swi r5, r1
|
||||
; CHECK: swi r6, r1
|
||||
; CHECK: swi r7, r1
|
||||
; CHECK: swi r8, r1
|
||||
; CHECK: swi r9, r1
|
||||
; CHECK: swi r10, r1
|
||||
; CHECK: swi r11, r1
|
||||
; CHECK: swi r12, r1
|
||||
; CHECK: swi r17, r1
|
||||
; CHECK: swi r18, r1
|
||||
; CHECK: mfs r11, rmsr
|
||||
; CHECK: swi r11, r1
|
||||
entry:
|
||||
%call = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([28 x i8]* @.str, i32 0, i32 0))
|
||||
ret void
|
||||
|
||||
; CHECK: lwi r11, r1
|
||||
; CHECK: mts rmsr, r11
|
||||
; CHECK: lwi r18, r1
|
||||
; CHECK: lwi r17, r1
|
||||
; CHECK: lwi r12, r1
|
||||
; CHECK: lwi r11, r1
|
||||
; CHECK: lwi r10, r1
|
||||
; CHECK: lwi r9, r1
|
||||
; CHECK: lwi r8, r1
|
||||
; CHECK: lwi r7, r1
|
||||
; CHECK: lwi r6, r1
|
||||
; CHECK: lwi r5, r1
|
||||
; CHECK: lwi r4, r1
|
||||
; CHECK: lwi r3, r1
|
||||
; CHECK: rtid r14, 0
|
||||
}
|
||||
|
||||
; CHECK: .globl _interrupt_handler
|
||||
; CHECK: _interrupt_handler = myintr
|
||||
declare i32 @printf(i8*, ...)
|
80
test/CodeGen/MBlaze/svol.ll
Normal file
80
test/CodeGen/MBlaze/svol.ll
Normal file
@ -0,0 +1,80 @@
|
||||
; Ensure that the MBlaze save_volatiles calling convention (cc74) is handled
|
||||
; correctly correctly by the MBlaze backend.
|
||||
;
|
||||
; RUN: llc < %s -march=mblaze | FileCheck %s
|
||||
|
||||
@.str = private constant [28 x i8] c"The interrupt has gone off\0A\00"
|
||||
|
||||
define cc74 void @mysvol() nounwind noinline {
|
||||
; CHECK: mysvol:
|
||||
; CHECK: swi r3, r1
|
||||
; CHECK: swi r4, r1
|
||||
; CHECK: swi r5, r1
|
||||
; CHECK: swi r6, r1
|
||||
; CHECK: swi r7, r1
|
||||
; CHECK: swi r8, r1
|
||||
; CHECK: swi r9, r1
|
||||
; CHECK: swi r10, r1
|
||||
; CHECK: swi r11, r1
|
||||
; CHECK: swi r12, r1
|
||||
; CHECK: swi r17, r1
|
||||
; CHECK: swi r18, r1
|
||||
; CHECK-NOT: mfs r11, rmsr
|
||||
entry:
|
||||
%call = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([28 x i8]* @.str, i32 0, i32 0))
|
||||
ret void
|
||||
|
||||
; CHECK-NOT: mts rmsr, r11
|
||||
; CHECK: lwi r18, r1
|
||||
; CHECK: lwi r17, r1
|
||||
; CHECK: lwi r12, r1
|
||||
; CHECK: lwi r11, r1
|
||||
; CHECK: lwi r10, r1
|
||||
; CHECK: lwi r9, r1
|
||||
; CHECK: lwi r8, r1
|
||||
; CHECK: lwi r7, r1
|
||||
; CHECK: lwi r6, r1
|
||||
; CHECK: lwi r5, r1
|
||||
; CHECK: lwi r4, r1
|
||||
; CHECK: lwi r3, r1
|
||||
; CHECK: rtsd r15, 8
|
||||
}
|
||||
|
||||
define cc74 void @mysvol2() nounwind noinline {
|
||||
; CHECK: mysvol2:
|
||||
; CHECK-NOT: swi r3, r1
|
||||
; CHECK-NOT: swi r4, r1
|
||||
; CHECK-NOT: swi r5, r1
|
||||
; CHECK-NOT: swi r6, r1
|
||||
; CHECK-NOT: swi r7, r1
|
||||
; CHECK-NOT: swi r8, r1
|
||||
; CHECK-NOT: swi r9, r1
|
||||
; CHECK-NOT: swi r10, r1
|
||||
; CHECK-NOT: swi r11, r1
|
||||
; CHECK-NOT: swi r12, r1
|
||||
; CHECK: swi r17, r1
|
||||
; CHECK: swi r18, r1
|
||||
; CHECK-NOT: mfs r11, rmsr
|
||||
entry:
|
||||
|
||||
; CHECK-NOT: mts rmsr, r11
|
||||
; CHECK: lwi r18, r1
|
||||
; CHECK: lwi r17, r1
|
||||
; CHECK-NOT: lwi r12, r1
|
||||
; CHECK-NOT: lwi r11, r1
|
||||
; CHECK-NOT: lwi r10, r1
|
||||
; CHECK-NOT: lwi r9, r1
|
||||
; CHECK-NOT: lwi r8, r1
|
||||
; CHECK-NOT: lwi r7, r1
|
||||
; CHECK-NOT: lwi r6, r1
|
||||
; CHECK-NOT: lwi r5, r1
|
||||
; CHECK-NOT: lwi r4, r1
|
||||
; CHECK-NOT: lwi r3, r1
|
||||
; CHECK: rtsd r15, 8
|
||||
ret void
|
||||
}
|
||||
|
||||
; CHECK-NOT: .globl _interrupt_handler
|
||||
; CHECK-NOT: _interrupt_handler = mysvol
|
||||
; CHECK-NOT: _interrupt_handler = mysvol2
|
||||
declare i32 @printf(i8*, ...)
|
Loading…
Reference in New Issue
Block a user