diff options
author | Anton Korobeynikov <asl@math.spbu.ru> | 2007-07-14 14:06:15 +0000 |
---|---|---|
committer | Anton Korobeynikov <asl@math.spbu.ru> | 2007-07-14 14:06:15 +0000 |
commit | 2365f51ed03afe6993bae962fdc2e5a956a64cd5 (patch) | |
tree | 8b31c4075bfb21456ae1257eb68b2368220f7840 /lib/CodeGen/SelectionDAG | |
parent | a73d11efd435cfa5ab275400c9881724f9224ca0 (diff) | |
download | external_llvm-2365f51ed03afe6993bae962fdc2e5a956a64cd5.zip external_llvm-2365f51ed03afe6993bae962fdc2e5a956a64cd5.tar.gz external_llvm-2365f51ed03afe6993bae962fdc2e5a956a64cd5.tar.bz2 |
Long live the exception handling!
This patch fills the last necessary bits to enable exceptions
handling in LLVM. Currently only on x86-32/linux.
In fact, this patch adds necessary intrinsics (and their lowering) which
represent really weird target-specific gcc builtins used inside unwinder.
After corresponding llvm-gcc patch will land (easy) exceptions should be
more or less workable. However, exceptions handling support should not be
thought as 'finished': I expect many small and not so small glitches
everywhere.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@39855 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/CodeGen/SelectionDAG')
-rw-r--r-- | lib/CodeGen/SelectionDAG/LegalizeDAG.cpp | 16 | ||||
-rw-r--r-- | lib/CodeGen/SelectionDAG/SelectionDAG.cpp | 2 | ||||
-rw-r--r-- | lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp | 47 |
3 files changed, 65 insertions, 0 deletions
diff --git a/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp b/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp index a5146bd..8b82b62 100644 --- a/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp +++ b/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp @@ -640,6 +640,7 @@ SDOperand SelectionDAGLegalize::LegalizeOp(SDOperand Op) { break; case ISD::FRAMEADDR: case ISD::RETURNADDR: + case ISD::FRAME_TO_ARGS_OFFSET: // The only option for these nodes is to custom lower them. If the target // does not custom lower them, then return zero. Tmp1 = TLI.LowerOperation(Op, DAG); @@ -695,6 +696,21 @@ SDOperand SelectionDAGLegalize::LegalizeOp(SDOperand Op) { } } break; + case ISD::EH_RETURN: + MVT::ValueType VT = Node->getValueType(0); + // The only "good" option for this node is to custom lower it. + switch (TLI.getOperationAction(Node->getOpcode(), VT)) { + default: assert(0 && "This action is not supported at all!"); + case TargetLowering::Custom: + Result = TLI.LowerOperation(Op, DAG); + if (Result.Val) break; + // Fall Thru + case TargetLowering::Legal: + // Target does not know, how to lower this, lower to noop + Result = LegalizeOp(Node->getOperand(0)); + break; + } + break; case ISD::AssertSext: case ISD::AssertZext: Tmp1 = LegalizeOp(Node->getOperand(0)); diff --git a/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/lib/CodeGen/SelectionDAG/SelectionDAG.cpp index dc23151..9803ab8 100644 --- a/lib/CodeGen/SelectionDAG/SelectionDAG.cpp +++ b/lib/CodeGen/SelectionDAG/SelectionDAG.cpp @@ -3369,8 +3369,10 @@ std::string SDNode::getOperationName(const SelectionDAG *G) const { case ISD::GLOBAL_OFFSET_TABLE: return "GLOBAL_OFFSET_TABLE"; case ISD::RETURNADDR: return "RETURNADDR"; case ISD::FRAMEADDR: return "FRAMEADDR"; + case ISD::FRAME_TO_ARGS_OFFSET: return "FRAME_TO_ARGS_OFFSET"; case ISD::EXCEPTIONADDR: return "EXCEPTIONADDR"; case ISD::EHSELECTION: return "EHSELECTION"; + case ISD::EH_RETURN: return "EH_RETURN"; case ISD::ConstantPool: return "ConstantPool"; case ISD::ExternalSymbol: return "ExternalSymbol"; case ISD::INTRINSIC_WO_CHAIN: { diff --git a/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp b/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp index 87bf249..8a2f7b1 100644 --- a/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp +++ b/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp @@ -2721,6 +2721,53 @@ SelectionDAGLowering::visitIntrinsicCall(CallInst &I, unsigned Intrinsic) { return 0; } + case Intrinsic::eh_return: { + MachineModuleInfo *MMI = DAG.getMachineModuleInfo(); + + if (MMI && ExceptionHandling) { + MMI->setCallsEHReturn(true); + DAG.setRoot(DAG.getNode(ISD::EH_RETURN, + MVT::Other, + getRoot(), + getValue(I.getOperand(1)), + getValue(I.getOperand(2)))); + } else { + setValue(&I, DAG.getConstant(0, TLI.getPointerTy())); + } + + return 0; + } + + case Intrinsic::eh_unwind_init: { + if (MachineModuleInfo *MMI = DAG.getMachineModuleInfo()) { + MMI->setCallsUnwindInit(true); + } + + return 0; + } + + case Intrinsic::eh_dwarf_cfa: { + if (ExceptionHandling) { + MVT::ValueType VT = getValue(I.getOperand(1)).getValueType(); + SDOperand Offset = DAG.getNode(ISD::ADD, + TLI.getPointerTy(), + DAG.getNode(ISD::FRAME_TO_ARGS_OFFSET, + VT), + getValue(I.getOperand(1))); + setValue(&I, DAG.getNode(ISD::ADD, + TLI.getPointerTy(), + DAG.getNode(ISD::FRAMEADDR, + TLI.getPointerTy(), + DAG.getConstant(0, + TLI.getPointerTy())), + Offset)); + } else { + setValue(&I, DAG.getConstant(0, TLI.getPointerTy())); + } + + return 0; + } + case Intrinsic::sqrt_f32: case Intrinsic::sqrt_f64: setValue(&I, DAG.getNode(ISD::FSQRT, |