diff options
author | Robert Lytton <robert@xmos.com> | 2014-01-06 14:21:07 +0000 |
---|---|---|
committer | Robert Lytton <robert@xmos.com> | 2014-01-06 14:21:07 +0000 |
commit | c8c4aa667b0d9de90eb17ab0aa953edf0fa9dc60 (patch) | |
tree | 00d5aaa21f2f2397380f73cf73623357917b1a17 /llvm/lib | |
parent | 5da175214bffc33e394bf7531a8de49a2649b58c (diff) | |
download | bcm5719-llvm-c8c4aa667b0d9de90eb17ab0aa953edf0fa9dc60.tar.gz bcm5719-llvm-c8c4aa667b0d9de90eb17ab0aa953edf0fa9dc60.zip |
XCore target: Lower EH_RETURN
llvm-svn: 198615
Diffstat (limited to 'llvm/lib')
-rw-r--r-- | llvm/lib/Target/XCore/XCoreFrameLowering.cpp | 9 | ||||
-rw-r--r-- | llvm/lib/Target/XCore/XCoreISelLowering.cpp | 42 | ||||
-rw-r--r-- | llvm/lib/Target/XCore/XCoreISelLowering.h | 5 | ||||
-rw-r--r-- | llvm/lib/Target/XCore/XCoreInstrInfo.td | 10 |
4 files changed, 66 insertions, 0 deletions
diff --git a/llvm/lib/Target/XCore/XCoreFrameLowering.cpp b/llvm/lib/Target/XCore/XCoreFrameLowering.cpp index 3d1fb9cafc1..109b74d445c 100644 --- a/llvm/lib/Target/XCore/XCoreFrameLowering.cpp +++ b/llvm/lib/Target/XCore/XCoreFrameLowering.cpp @@ -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(); diff --git a/llvm/lib/Target/XCore/XCoreISelLowering.cpp b/llvm/lib/Target/XCore/XCoreISelLowering.cpp index c0edee55e43..dd268c4cddc 100644 --- a/llvm/lib/Target/XCore/XCoreISelLowering.cpp +++ b/llvm/lib/Target/XCore/XCoreISelLowering.cpp @@ -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); @@ -839,6 +842,45 @@ LowerFRAME_TO_ARGS_OFFSET(SDValue Op, SelectionDAG &DAG) const { } 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); } diff --git a/llvm/lib/Target/XCore/XCoreISelLowering.h b/llvm/lib/Target/XCore/XCoreISelLowering.h index c4de86e22dc..05e2a86a9b5 100644 --- a/llvm/lib/Target/XCore/XCoreISelLowering.h +++ b/llvm/lib/Target/XCore/XCoreISelLowering.h @@ -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; diff --git a/llvm/lib/Target/XCore/XCoreInstrInfo.td b/llvm/lib/Target/XCore/XCoreInstrInfo.td index 144d4fec246..0aecca064f2 100644 --- a/llvm/lib/Target/XCore/XCoreInstrInfo.td +++ b/llvm/lib/Target/XCore/XCoreInstrInfo.td @@ -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))]>; |