Look for eh.filter and eh.selector intrinsics in the
successor to an empty (exception for a branch) landing pad.
The big FIXME comment explains more. Testcase included,
along with an XFAIL for a test which uses eh.selector in a
routine with no landing pads (not possible in llvm-gcc
generated code).
Ciao,
Duncan.
Index: lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
===================================================================
RCS file: /var/cvs/llvm/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp,v
retrieving revision 1.462
diff -u -3 -p -r1.462 SelectionDAGISel.cpp
--- lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp 13 Jun 2007 16:53:21 -0000 1.462
+++ lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp 13 Jun 2007 17:17:29 -0000
@@ -179,6 +179,11 @@ namespace llvm {
/// anywhere in the function.
std::map<const AllocaInst*, int> StaticAllocaMap;
+#ifndef NDEBUG
+ std::set<CallInst *> SelectorsLost;
+ std::set<CallInst *> SelectorsFound;
+#endif
+
unsigned MakeReg(MVT::ValueType VT) {
return RegMap->createVirtualRegister(TLI.getRegClassFor(VT));
}
@@ -2463,6 +2468,33 @@ static GlobalVariable *ExtractGlobalVari
return NULL;
}
+/// addCatchInfo - Extract the personality and type infos from an eh.selector
+/// or eh.filter call, and add them to the specified machine basic block.
+static void addCatchInfo(CallInst &I, MachineModuleInfo *MMI,
+ MachineBasicBlock *MBB, bool isFilter) {
+ // Inform the MachineModuleInfo of the personality for this landing pad.
+ ConstantExpr *CE = dyn_cast<ConstantExpr>(I.getOperand(2));
+ assert(CE && CE->getOpcode() == Instruction::BitCast &&
+ isa<Function>(CE->getOperand(0)) &&
+ "Personality should be a function");
+ MMI->addPersonality(MBB, cast<Function>(CE->getOperand(0)));
+
+ // Gather all the type infos for this landing pad and pass them along to
+ // MachineModuleInfo.
+ std::vector<GlobalVariable *> TyInfo;
+ for (unsigned i = 3, N = I.getNumOperands(); i < N; ++i) {
+ Constant *C = cast<Constant>(I.getOperand(i));
+ GlobalVariable *GV = ExtractGlobalVariable(C);
+ assert (GV || isa<ConstantPointerNull>(C) &&
+ "TypeInfo must be a global variable or NULL");
+ TyInfo.push_back(GV);
+ }
+ if (isFilter)
+ MMI->addFilterTypeInfo(MBB, TyInfo);
+ else
+ MMI->addCatchTypeInfo(MBB, TyInfo);
+}
+
/// visitIntrinsicCall - Lower the call to the specified intrinsic function. If
/// we want to emit this as a call to a named external function, return the name
/// otherwise lower it and return null.
@@ -2595,29 +2627,14 @@ SelectionDAGLowering::visitIntrinsicCall
case Intrinsic::eh_selector:
case Intrinsic::eh_filter:{
MachineModuleInfo *MMI = DAG.getMachineModuleInfo();
-
+
if (ExceptionHandling && MMI) {
- // Inform the MachineModuleInfo of the personality for this landing pad.
- ConstantExpr *CE = dyn_cast<ConstantExpr>(I.getOperand(2));
- assert(CE && CE->getOpcode() == Instruction::BitCast &&
- isa<Function>(CE->getOperand(0)) &&
- "Personality should be a function");
- MMI->addPersonality(CurMBB, cast<Function>(CE->getOperand(0)));
-
- // Gather all the type infos for this landing pad and pass them along to
- // MachineModuleInfo.
- std::vector<GlobalVariable *> TyInfo;
- for (unsigned i = 3, N = I.getNumOperands(); i < N; ++i) {
- Constant *C = cast<Constant>(I.getOperand(i));
- GlobalVariable *GV = ExtractGlobalVariable(C);
- assert (GV || isa<ConstantPointerNull>(C) &&
- "TypeInfo must be a global variable or NULL");
- TyInfo.push_back(GV);
- }
- if (Intrinsic == Intrinsic::eh_filter)
- MMI->addFilterTypeInfo(CurMBB, TyInfo);
+ if (CurMBB->isLandingPad())
+ addCatchInfo(I, MMI, CurMBB, Intrinsic == Intrinsic::eh_filter);
+#ifndef NDEBUG
else
- MMI->addCatchTypeInfo(CurMBB, TyInfo);
+ FuncInfo.SelectorsLost.insert(&I);
+#endif
// Mark exception selector register as live in.
unsigned Reg = TLI.getExceptionSelectorRegister();
@@ -4403,6 +4420,11 @@ bool SelectionDAGISel::runOnFunction(Fun
E = MF.livein_end(); I != E; ++I)
BB->addLiveIn(I->first);
+#ifndef NDEBUG
+ assert(FuncInfo.SelectorsFound.size() == FuncInfo.SelectorsLost.size() &&
+ "Not all catch info was assigned to a landing pad!");
+#endif
+
return true;
}
@@ -4536,6 +4558,39 @@ void SelectionDAGISel::BuildSelectionDAG
unsigned LabelID = MMI->addLandingPad(BB);
DAG.setRoot(DAG.getNode(ISD::LABEL, MVT::Other, DAG.getEntryNode(),
DAG.getConstant(LabelID, MVT::i32)));
+
+ // FIXME: Hack around an exception handling design flaw: the personality
+ // function and list of typeids logically belong to the invoke (or, if you
+ // like, the basic block containing the invoke), and need to be associated
+ // with it in the dwarf exception handling tables. Currently however the
+ // information is provided by intrinsics (eh.filter and eh.selector) that
+ // can be moved to unexpected places by the optimizers: if the unwind edge
+ // is critical, then breaking it can result in the intrinsics being in the
+ // successor of the landing pad, not the landing pad itself. This results
+ // in exceptions not being caught because no typeids are associated with
+ // the invoke. This may not be the only way things can go wrong, but it
+ // is the only way we try to work around for the moment.
+ BranchInst *Br = dyn_cast<BranchInst>(LLVMBB->getTerminator());
+
+ if (Br && Br->isUnconditional() && LLVMBB->size() == 1) {
+ // Smells like a critical edge: look for eh intrinsics in the successor.
+ BasicBlock *S = Br->getSuccessor(0);
+
+ assert(!FuncInfo.MBBMap[S]->isLandingPad() &&
+ "Chained landing pads!");
+ for (BasicBlock::iterator I = S->begin(), E = --S->end(); I != E; ++I)
+ if (CallInst *C = dyn_cast<CallInst>(I))
+ if (Function *F = C->getCalledFunction())
+ if (F->isDeclaration())
+ if (unsigned IID = F->getIntrinsicID())
+ if (IID == Intrinsic::eh_selector ||
+ IID == Intrinsic::eh_filter) {
+ addCatchInfo(*C, MMI, BB, IID == Intrinsic::eh_filter);
+#ifndef NDEBUG
+ FuncInfo.SelectorsFound.insert(C);
+#endif
+ }
+ }
}
}
Index: test/CodeGen/Generic/2007-04-14-EHSelectorCrash.ll
===================================================================
RCS file: /var/cvs/llvm/llvm/test/CodeGen/Generic/2007-04-14-EHSelectorCrash.ll,v
retrieving revision 1.2
diff -u -3 -p -r1.2 2007-04-14-EHSelectorCrash.ll
--- test/CodeGen/Generic/2007-04-14-EHSelectorCrash.ll 27 Apr 2007 17:12:23 -0000 1.2
+++ test/CodeGen/Generic/2007-04-14-EHSelectorCrash.ll 13 Jun 2007 17:17:29 -0000
@@ -1,5 +1,7 @@
; RUN: llvm-as < %s | llc -enable-eh
; RUN: llvm-as < %s | llc -enable-eh -march=x86-64
+; XFAIL: *
+; Un-XFAIL this when PR1508 is fixed.
; PR1326
Index: test/CodeGen/Generic/2007-06-06-CriticalEdgeLandingPad.ll
===================================================================
RCS file: /var/cvs/llvm/llvm/test/CodeGen/Generic/2007-06-06-CriticalEdgeLandingPad.ll,v
retrieving revision 1.1
diff -u -3 -p -r1.1 2007-06-06-CriticalEdgeLandingPad.ll
--- test/CodeGen/Generic/2007-06-06-CriticalEdgeLandingPad.ll 6 Jun 2007 09:59:53 -0000 1.1
+++ test/CodeGen/Generic/2007-06-06-CriticalEdgeLandingPad.ll 13 Jun 2007 17:17:30 -0000
@@ -1,4 +1,5 @@
-; RUN: llvm-as < %s | llc -enable-eh -asm-verbose -o - | grep {Llabel137.*Region start}
+; RUN: llvm-as < %s | llc -enable-eh -asm-verbose -o - | \
+; RUN: grep -A 3 {Llabel137.*Region start} | grep {5.*Action}
; PR1422
target triple = "i686-pc-linux-gnu"
_______________________________________________
llvm-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits