mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-23 11:13:28 +01:00
XCore target: Lower EH_RETURN
llvm-svn: 198615
This commit is contained in:
parent
2c10e542b0
commit
69e4de31bf
@ -252,6 +252,15 @@ void XCoreFrameLowering::emitEpilogue(MachineFunction &MF,
|
||||
DebugLoc dl = MBBI->getDebugLoc();
|
||||
unsigned RetOpcode = MBBI->getOpcode();
|
||||
|
||||
if (RetOpcode == XCore::EH_RETURN) {
|
||||
unsigned EhStackReg = MBBI->getOperand(0).getReg();
|
||||
unsigned EhHandlerReg = MBBI->getOperand(1).getReg();
|
||||
BuildMI(MBB, MBBI, dl, TII.get(XCore::SETSP_1r)).addReg(EhStackReg);
|
||||
BuildMI(MBB, MBBI, dl, TII.get(XCore::BAU_1r)).addReg(EhHandlerReg);
|
||||
MBB.erase(MBBI); // Erase the previous return instruction.
|
||||
return;
|
||||
}
|
||||
|
||||
// Work out frame sizes.
|
||||
// We will adjust the SP in stages towards the final FrameSize.
|
||||
int RemainingAdj = MFI->getStackSize();
|
||||
|
@ -61,6 +61,7 @@ getTargetNodeName(unsigned Opcode) const
|
||||
case XCoreISD::BR_JT : return "XCoreISD::BR_JT";
|
||||
case XCoreISD::BR_JT32 : return "XCoreISD::BR_JT32";
|
||||
case XCoreISD::FRAME_TO_ARGS_OFFSET : return "XCoreISD::FRAME_TO_ARGS_OFFSET";
|
||||
case XCoreISD::EH_RETURN : return "XCoreISD::EH_RETURN";
|
||||
case XCoreISD::MEMBARRIER : return "XCoreISD::MEMBARRIER";
|
||||
default : return NULL;
|
||||
}
|
||||
@ -152,6 +153,7 @@ XCoreTargetLowering::XCoreTargetLowering(XCoreTargetMachine &XTM)
|
||||
setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i32, Expand);
|
||||
|
||||
// Exception handling
|
||||
setOperationAction(ISD::EH_RETURN, MVT::Other, Custom);
|
||||
setExceptionPointerRegister(XCore::R0);
|
||||
setExceptionSelectorRegister(XCore::R1);
|
||||
setOperationAction(ISD::FRAME_TO_ARGS_OFFSET, MVT::i32, Custom);
|
||||
@ -199,6 +201,7 @@ SDValue XCoreTargetLowering::
|
||||
LowerOperation(SDValue Op, SelectionDAG &DAG) const {
|
||||
switch (Op.getOpcode())
|
||||
{
|
||||
case ISD::EH_RETURN: return LowerEH_RETURN(Op, DAG);
|
||||
case ISD::GlobalAddress: return LowerGlobalAddress(Op, DAG);
|
||||
case ISD::BlockAddress: return LowerBlockAddress(Op, DAG);
|
||||
case ISD::ConstantPool: return LowerConstantPool(Op, DAG);
|
||||
@ -838,6 +841,45 @@ LowerFRAME_TO_ARGS_OFFSET(SDValue Op, SelectionDAG &DAG) const {
|
||||
return DAG.getNode(XCoreISD::FRAME_TO_ARGS_OFFSET, SDLoc(Op), MVT::i32);
|
||||
}
|
||||
|
||||
SDValue XCoreTargetLowering::
|
||||
LowerEH_RETURN(SDValue Op, SelectionDAG &DAG) const {
|
||||
// OUTCHAIN = EH_RETURN(INCHAIN, OFFSET, HANDLER)
|
||||
// This node represents 'eh_return' gcc dwarf builtin, which is used to
|
||||
// return from exception. The general meaning is: adjust stack by OFFSET and
|
||||
// pass execution to HANDLER.
|
||||
MachineFunction &MF = DAG.getMachineFunction();
|
||||
SDValue Chain = Op.getOperand(0);
|
||||
SDValue Offset = Op.getOperand(1);
|
||||
SDValue Handler = Op.getOperand(2);
|
||||
SDLoc dl(Op);
|
||||
|
||||
// Absolute SP = (FP + FrameToArgs) + Offset
|
||||
const TargetRegisterInfo *RegInfo = getTargetMachine().getRegisterInfo();
|
||||
SDValue Stack = DAG.getCopyFromReg(DAG.getEntryNode(), dl,
|
||||
RegInfo->getFrameRegister(MF), MVT::i32);
|
||||
SDValue FrameToArgs = DAG.getNode(XCoreISD::FRAME_TO_ARGS_OFFSET, dl,
|
||||
MVT::i32);
|
||||
Stack = DAG.getNode(ISD::ADD, dl, MVT::i32, Stack, FrameToArgs);
|
||||
Stack = DAG.getNode(ISD::ADD, dl, MVT::i32, Stack, Offset);
|
||||
|
||||
// R0=ExceptionPointerRegister R1=ExceptionSelectorRegister
|
||||
// which leaves 2 caller saved registers, R2 & R3 for us to use.
|
||||
unsigned StackReg = XCore::R2;
|
||||
unsigned HandlerReg = XCore::R3;
|
||||
|
||||
SDValue OutChains[] = {
|
||||
DAG.getCopyToReg(Chain, dl, StackReg, Stack),
|
||||
DAG.getCopyToReg(Chain, dl, HandlerReg, Handler)
|
||||
};
|
||||
|
||||
Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, OutChains, 2);
|
||||
|
||||
return DAG.getNode(XCoreISD::EH_RETURN, dl, MVT::Other, Chain,
|
||||
DAG.getRegister(StackReg, MVT::i32),
|
||||
DAG.getRegister(HandlerReg, MVT::i32));
|
||||
|
||||
}
|
||||
|
||||
SDValue XCoreTargetLowering::
|
||||
LowerADJUST_TRAMPOLINE(SDValue Op, SelectionDAG &DAG) const {
|
||||
return Op.getOperand(0);
|
||||
|
@ -75,6 +75,10 @@ namespace llvm {
|
||||
// Offset from frame pointer to the first (possible) on-stack argument
|
||||
FRAME_TO_ARGS_OFFSET,
|
||||
|
||||
// Exception handler return. The stack is restored to the first
|
||||
// followed by a jump to the second argument.
|
||||
EH_RETURN,
|
||||
|
||||
// Memory barrier.
|
||||
MEMBARRIER
|
||||
};
|
||||
@ -150,6 +154,7 @@ namespace llvm {
|
||||
// Lower Operand specifics
|
||||
SDValue LowerLOAD(SDValue Op, SelectionDAG &DAG) const;
|
||||
SDValue LowerSTORE(SDValue Op, SelectionDAG &DAG) const;
|
||||
SDValue LowerEH_RETURN(SDValue Op, SelectionDAG &DAG) const;
|
||||
SDValue LowerGlobalAddress(SDValue Op, SelectionDAG &DAG) const;
|
||||
SDValue LowerGlobalTLSAddress(SDValue Op, SelectionDAG &DAG) const;
|
||||
SDValue LowerBlockAddress(SDValue Op, SelectionDAG &DAG) const;
|
||||
|
@ -35,6 +35,11 @@ def XCoreBranchLink : SDNode<"XCoreISD::BL",SDT_XCoreBranchLink,
|
||||
def XCoreRetsp : SDNode<"XCoreISD::RETSP", SDTBrind,
|
||||
[SDNPHasChain, SDNPOptInGlue, SDNPMayLoad, SDNPVariadic]>;
|
||||
|
||||
def SDT_XCoreEhRet : SDTypeProfile<0, 2,
|
||||
[SDTCisSameAs<0, 1>, SDTCisPtrTy<0>]>;
|
||||
def XCoreEhRet : SDNode<"XCoreISD::EH_RETURN", SDT_XCoreEhRet,
|
||||
[SDNPHasChain, SDNPOptInGlue]>;
|
||||
|
||||
def SDT_XCoreBR_JT : SDTypeProfile<0, 2,
|
||||
[SDTCisVT<0, i32>, SDTCisVT<1, i32>]>;
|
||||
|
||||
@ -334,6 +339,11 @@ def FRAME_TO_ARGS_OFFSET : PseudoInstXCore<(outs GRRegs:$dst), (ins),
|
||||
"# FRAME_TO_ARGS_OFFSET $dst",
|
||||
[(set GRRegs:$dst, (frametoargsoffset))]>;
|
||||
|
||||
let isReturn = 1, isTerminator = 1, isBarrier = 1 in
|
||||
def EH_RETURN : PseudoInstXCore<(outs), (ins GRRegs:$s, GRRegs:$handler),
|
||||
"# EH_RETURN $s, $handler",
|
||||
[(XCoreEhRet GRRegs:$s, GRRegs:$handler)]>;
|
||||
|
||||
def LDWFI : PseudoInstXCore<(outs GRRegs:$dst), (ins MEMii:$addr),
|
||||
"# LDWFI $dst, $addr",
|
||||
[(set GRRegs:$dst, (load ADDRspii:$addr))]>;
|
||||
|
@ -21,7 +21,6 @@ entry:
|
||||
ret i8* %1
|
||||
}
|
||||
|
||||
|
||||
declare i8* @llvm.returnaddress(i32) nounwind readnone
|
||||
define i8* @RA0() nounwind {
|
||||
entry:
|
||||
@ -70,3 +69,64 @@ entry:
|
||||
%1 = call i8* @llvm.eh.dwarf.cfa(i32 0)
|
||||
ret i8* %1
|
||||
}
|
||||
|
||||
declare void @llvm.eh.return.i32(i32, i8*)
|
||||
define i8* @EH0(i32 %offset, i8* %handler) {
|
||||
entry:
|
||||
; CHECK-LABEL: EH0
|
||||
; CHECK: ldc r2, 0
|
||||
; CHECK-NEXT: ldaw r3, sp[0]
|
||||
; CHECK-NEXT: add r2, r3, r2
|
||||
; CHECK-NEXT: add r2, r2, r0
|
||||
; CHECK-NEXT: mov r3, r1
|
||||
; CHECK-NEXT: set sp, r2
|
||||
; CHECK-NEXT: bau r3
|
||||
call void @llvm.eh.return.i32(i32 %offset, i8* %handler)
|
||||
unreachable
|
||||
}
|
||||
|
||||
declare void @foo(...)
|
||||
define i8* @EH1(i32 %offset, i8* %handler) {
|
||||
entry:
|
||||
; CHECK-LABEL: EH1
|
||||
; CHECK: entsp 3
|
||||
; CHECK: stw r4, sp[2]
|
||||
; CHECK: stw r5, sp[1]
|
||||
; CHECK: mov r4, r1
|
||||
; CHECK-NEXT: mov r5, r0
|
||||
; CHECK-NEXT: bl foo
|
||||
; CHECK-NEXT: ldc r0, 12
|
||||
; CHECK-NEXT: ldaw r1, sp[0]
|
||||
; CHECK-NEXT: add r0, r1, r0
|
||||
; CHECK-NEXT: add r2, r0, r5
|
||||
; CHECK-NEXT: mov r3, r4
|
||||
; CHECK-NEXT: ldw r5, sp[1]
|
||||
; CHECK-NEXT: ldw r4, sp[2]
|
||||
; CHECK-NEXT: set sp, r2
|
||||
; CHECK-NEXT: bau r3
|
||||
call void (...)* @foo()
|
||||
call void @llvm.eh.return.i32(i32 %offset, i8* %handler)
|
||||
unreachable
|
||||
}
|
||||
|
||||
@offset = external constant i32
|
||||
@handler = external constant i8
|
||||
define i8* @EH2(i32 %r0, i32 %r1, i32 %r2, i32 %r3) {
|
||||
entry:
|
||||
; CHECK-LABEL: EH2
|
||||
; CHECK: entsp 1
|
||||
; CHECK: bl foo
|
||||
; CHECK-NEXT: ldw r0, cp[offset]
|
||||
; CHECK-NEXT: ldc r1, 4
|
||||
; CHECK-NEXT: ldaw r2, sp[0]
|
||||
; CHECK-NEXT: add r1, r2, r1
|
||||
; CHECK-NEXT: add r2, r1, r0
|
||||
; CHECK-NEXT: ldaw r11, cp[handler]
|
||||
; CHECK-NEXT: mov r3, r11
|
||||
; CHECK-NEXT: set sp, r2
|
||||
; CHECK-NEXT: bau r3
|
||||
call void (...)* @foo()
|
||||
%0 = load i32* @offset
|
||||
call void @llvm.eh.return.i32(i32 %0, i8* @handler)
|
||||
unreachable
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user