From: Jim Laskey Date: Wed, 21 Feb 2007 22:53:45 +0000 (+0000) Subject: Selection and lowering for exception handling. X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=b180aa17539e14a5430d020bbc7de83c79b7fc4b;p=oota-llvm.git Selection and lowering for exception handling. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@34481 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/CodeGen/IntrinsicLowering.cpp b/lib/CodeGen/IntrinsicLowering.cpp index 35e20e3c694..03ca7afb506 100644 --- a/lib/CodeGen/IntrinsicLowering.cpp +++ b/lib/CodeGen/IntrinsicLowering.cpp @@ -357,6 +357,11 @@ void IntrinsicLowering::LowerIntrinsicCall(CallInst *CI) { case Intrinsic::dbg_func_start: case Intrinsic::dbg_declare: break; // Simply strip out debugging intrinsics + + case Intrinsic::eh_exception: + case Intrinsic::eh_handlers: + assert(0 && "Should not have leaked through"); + break; case Intrinsic::memcpy_i32: case Intrinsic::memcpy_i64: { diff --git a/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp b/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp index eb44250cc05..0992e421b1b 100644 --- a/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp +++ b/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp @@ -668,6 +668,8 @@ SDOperand SelectionDAGLegalize::LegalizeOp(SDOperand Op) { break; case ISD::FRAMEADDR: case ISD::RETURNADDR: + case ISD::EXCEPTIONADDR: + case ISD::EHSELECTION: // 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); diff --git a/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/lib/CodeGen/SelectionDAG/SelectionDAG.cpp index 92c84d85e84..23a66f55629 100644 --- a/lib/CodeGen/SelectionDAG/SelectionDAG.cpp +++ b/lib/CodeGen/SelectionDAG/SelectionDAG.cpp @@ -2679,6 +2679,8 @@ const char *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::EXCEPTIONADDR: return "EXCEPTIONADDR"; + case ISD::EHSELECTION: return "EHSELECTION"; 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 38d2300d709..10053acaab9 100644 --- a/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp +++ b/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp @@ -496,8 +496,8 @@ public: void visitJumpTable(SelectionDAGISel::JumpTable &JT); // These all get lowered before this pass. - void visitInvoke(InvokeInst &I) { assert(0 && "TODO"); } - void visitUnwind(UnwindInst &I) { assert(0 && "TODO"); } + void visitInvoke(InvokeInst &I); + void visitUnwind(UnwindInst &I); void visitScalarBinary(User &I, unsigned OpCode); void visitVectorBinary(User &I, unsigned OpCode); @@ -1101,6 +1101,56 @@ void SelectionDAGLowering::visitJumpTable(SelectionDAGISel::JumpTable &JT) { return; } +void SelectionDAGLowering::visitInvoke(InvokeInst &I) { + // Retrieve successors. + MachineBasicBlock *Return = FuncInfo.MBBMap[I.getSuccessor(0)]; + MachineBasicBlock *LandingPad = FuncInfo.MBBMap[I.getSuccessor(1)]; + + // Mark landing pad so that it doesn't get deleted in branch folding. + LandingPad->setIsLandingPad(); + + // Insert a label before the invoke call to mark the try range. + // This can be used to detect deletion of the invoke via the + // MachineModuleInfo. + MachineModuleInfo *MMI = DAG.getMachineModuleInfo(); + unsigned BeginLabel = MMI->NextLabelID(); + DAG.setRoot(DAG.getNode(ISD::LABEL, MVT::Other, getRoot(), + DAG.getConstant(BeginLabel, MVT::i32))); + + // Insert a normal call instruction. + std::vector Args; + for (InvokeInst::op_iterator OI = I.op_begin() + 3, E = I.op_end(); + OI != E; ++OI) { + Args.push_back(*OI); + } + CallInst *NewCall = new CallInst(I.getCalledValue(), &Args[0], Args.size(), + I.getName(), &I); + NewCall->setCallingConv(I.getCallingConv()); + I.replaceAllUsesWith(NewCall); + visitCall(*NewCall); + + // Insert a label before the invoke call to mark the try range. + // This can be used to detect deletion of the invoke via the + // MachineModuleInfo. + unsigned EndLabel = MMI->NextLabelID(); + DAG.setRoot(DAG.getNode(ISD::LABEL, MVT::Other, getRoot(), + DAG.getConstant(EndLabel, MVT::i32))); + + // Inform MachineModuleInfo of range. + MMI->addInvoke(LandingPad, BeginLabel, EndLabel); + + // Drop into normal successor. + DAG.setRoot(DAG.getNode(ISD::BR, MVT::Other, getRoot(), + DAG.getBasicBlock(Return))); + + // Update successor info + CurMBB->addSuccessor(Return); + CurMBB->addSuccessor(LandingPad); +} + +void SelectionDAGLowering::visitUnwind(UnwindInst &I) { +} + void SelectionDAGLowering::visitSwitch(SwitchInst &I) { // Figure out which block is immediately after the current one. MachineBasicBlock *NextBlock = 0; @@ -2033,6 +2083,91 @@ SelectionDAGLowering::visitIntrinsicCall(CallInst &I, unsigned Intrinsic) { return 0; } + case Intrinsic::eh_exception: { + MachineModuleInfo *MMI = DAG.getMachineModuleInfo(); + + // Add a label to mark the beginning of the landing pad. Deletion of the + // landing pad can thus be detected via the MachineModuleInfo. + unsigned LabelID = MMI->addLandingPad(CurMBB); + DAG.setRoot(DAG.getNode(ISD::LABEL, MVT::Other, DAG.getEntryNode(), + DAG.getConstant(LabelID, MVT::i32))); + + // Mark exception register as live in. + const MRegisterInfo *MRI = DAG.getTarget().getRegisterInfo(); + unsigned Reg = MRI->getEHExceptionRegister(); + if (Reg) CurMBB->addLiveIn(Reg); + + // Insert the EXCEPTIONADDR instruction. + SDVTList VTs = DAG.getVTList(TLI.getPointerTy(), MVT::Other); + SDOperand Ops[1]; + Ops[0] = DAG.getRoot(); + SDOperand Op = DAG.getNode(ISD::EXCEPTIONADDR, VTs, Ops, 1); + setValue(&I, Op); + DAG.setRoot(Op.getValue(1)); + + return 0; + } + + case Intrinsic::eh_handlers: { + MachineModuleInfo *MMI = DAG.getMachineModuleInfo(); + + // Inform the MachineModuleInfo of the personality for this landing pad. + if (ConstantExpr *CE = dyn_cast(I.getOperand(2))) { + if (CE->getOpcode() == Instruction::BitCast) { + MMI->addPersonality(CurMBB, + cast(CE->getOperand(0))); + } + } + + // Gather all the type infos for this landing pad and pass them along to + // MachineModuleInfo. + std::vector TyInfo; + for (unsigned i = 3, N = I.getNumOperands(); i < N; ++i) { + if (ConstantExpr *CE = dyn_cast(I.getOperand(i))) { + if (CE->getOpcode() == Instruction::BitCast) { + TyInfo.push_back(cast(CE->getOperand(0))); + continue; + } + } + + TyInfo.push_back(NULL); + } + MMI->addCatchTypeInfo(CurMBB, TyInfo); + + // Mark exception selector register as live in. + const MRegisterInfo *MRI = DAG.getTarget().getRegisterInfo(); + unsigned Reg = MRI->getEHHandlerRegister(); + if (Reg) CurMBB->addLiveIn(Reg); + + // Insert the EHSELECTION instruction. + SDVTList VTs = DAG.getVTList(TLI.getPointerTy(), MVT::Other); + SDOperand Ops[2]; + Ops[0] = getValue(I.getOperand(1)); + Ops[1] = getRoot(); + SDOperand Op = DAG.getNode(ISD::EHSELECTION, VTs, Ops, 2); + setValue(&I, Op); + DAG.setRoot(Op.getValue(1)); + + return 0; + } + + case Intrinsic::eh_typeid_for: { + GlobalVariable *GV = NULL; + + // Find the type id for the given typeinfo. + MachineModuleInfo *MMI = DAG.getMachineModuleInfo(); + if (ConstantExpr *CE = dyn_cast(I.getOperand(1))) { + if (CE->getOpcode() == Instruction::BitCast) { + GV = cast(CE->getOperand(0)); + } + } + + unsigned TypeID = MMI->getTypeIDFor(GV); + setValue(&I, DAG.getConstant(TypeID, MVT::i32)); + + return 0; + } + case Intrinsic::sqrt_f32: case Intrinsic::sqrt_f64: setValue(&I, DAG.getNode(ISD::FSQRT,