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

Reply via email to