[llvm-commits] [llvm] r37875 - in /llvm/trunk: docs/ExceptionHandling.html include/llvm/Intrinsics.td lib/CodeGen/IntrinsicLowering.cpp lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp

Duncan Sands baldrick at free.fr
Wed Jul 4 13:52:51 PDT 2007


Author: baldrick
Date: Wed Jul  4 15:52:51 2007
New Revision: 37875

URL: http://llvm.org/viewvc/llvm-project?rev=37875&view=rev
Log:
Extend eh.selector to support both catches and filters.
Drop the eh.filter intrinsic.

Modified:
    llvm/trunk/docs/ExceptionHandling.html
    llvm/trunk/include/llvm/Intrinsics.td
    llvm/trunk/lib/CodeGen/IntrinsicLowering.cpp
    llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp

Modified: llvm/trunk/docs/ExceptionHandling.html
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/docs/ExceptionHandling.html?rev=37875&r1=37874&r2=37875&view=diff

==============================================================================
--- llvm/trunk/docs/ExceptionHandling.html (original)
+++ llvm/trunk/docs/ExceptionHandling.html Wed Jul  4 15:52:51 2007
@@ -29,7 +29,6 @@
   <ol>
   	<li><a href="#llvm_eh_exception"><tt>llvm.eh.exception</tt></a></li>
   	<li><a href="#llvm_eh_selector"><tt>llvm.eh.selector</tt></a></li>
-  	<li><a href="#llvm_eh_filter"><tt>llvm.eh.filter</tt></a></li>
   	<li><a href="#llvm_eh_typeid_for"><tt>llvm.eh.typeid.for</tt></a></li>
   </ol></li>
   <li><a href="#asm">Asm Table Formats</a>
@@ -212,13 +211,18 @@
 <p><a href="#llvm_eh_selector"><tt>llvm.eh.selector</tt></a> takes a minimum of
 three arguments.  The first argument is the reference to the exception
 structure. The second argument is a reference to the personality function to be
-used for this try catch sequence. The remaining arguments are references to the
-type infos for each of the catch statements in the order they should be tested.
+used for this try catch sequence. Each of the remaining arguments is either a
+reference to the type info for a catch statement, or a non-negative integer
+followed by that many type info references, representing a
+<a href="#throw_filters">filter</a>.
+The exception is tested against the arguments sequentially from first to last.
 The <i>catch all</i> (...) is represented with a <tt>null i8*</tt>.  The result
-of the <a href="#llvm_eh_selector"><tt>llvm.eh.selector</tt></a> is the index of
-the type info in the corresponding exception table. The LLVM C++ front end
-generates code to save this value in an alloca location for further use in the
-landing pad and catch code.</p>
+of the <a href="#llvm_eh_selector"><tt>llvm.eh.selector</tt></a> is a positive
+number if the exception matched a type info, a negative number if it matched a
+filter, and zero if it didn't match anything.  If a type info matched then the
+returned value is the index of the type info in the exception table.
+The LLVM C++ front end generates code to save this value in an alloca location
+for further use in the landing pad and catch code.</p>
 
 <p>Once the landing pad has the type info selector, the code branches to the
 code for the first catch.  The catch then checks the value of the type info
@@ -268,12 +272,12 @@
 <p>C++ allows the specification of which exception types that can be thrown from
 a function.  To represent this a top level landing pad may exist to filter out
 invalid types.  To express this in LLVM code the landing pad will call <a
-href="#llvm_eh_filter"><tt>llvm.eh.filter</tt></a> instead of <a
 href="#llvm_eh_selector"><tt>llvm.eh.selector</tt></a>.  The arguments are the
-same, but what gets created in the exception table is different. <a
-href="#llvm_eh_filter"><tt>llvm.eh.filter</tt></a>  will return a negative value
-if it doesn't find a match. If no match is found then a call to
-<tt>__cxa_call_unexpected</tt> should be made, otherwise
+number of different type infos the function may throw, followed by the type
+infos themselves.
+<a href="#llvm_eh_selector"><tt>llvm.eh.selector</tt></a> will return a negative
+value if the exception does not match any of the type infos.  If no match is
+found then a call to <tt>__cxa_call_unexpected</tt> should be made, otherwise
 <tt>_Unwind_Resume</tt>.  Each of these functions require a reference to the
 exception structure.</p>
 
@@ -326,32 +330,16 @@
 <p><a href="#llvm_eh_selector"><tt>llvm.eh.selector</tt></a> takes a minimum of
 three arguments.  The first argument is the reference to the exception
 structure. The second argument is a reference to the personality function to be
-used for this try catch sequence. The remaining arguments are references to the
-type infos for each of the catch statements in the order they should be tested.
-The <i>catch all</i> (...) is represented with a <tt>null i8*</tt>.</p>
-
-</div>
-
-<!-- ======================================================================= -->
-<div class="doc_subsubsection">
-  <a name="llvm_eh_filter">llvm.eh.filter</a>
-</div>
-
-<div class="doc_text">
-<pre>
-  i32 %<a href="#llvm_eh_filter">llvm.eh.filter</a>(i8*, i8*, i8*, ...)
-</pre>
-
-<p>This intrinsic indicates that the exception selector is available at this
-point in the code.  The backend will replace this intrinsic with code to fetch
-the second argument of a call.  The effect is that the intrinsic result is the
-exception selector.</p>
-
-<p><a href="#llvm_eh_filter"><tt>llvm.eh.filter</tt></a> takes a minimum of
-three arguments.  The first argument is the reference to the exception
-structure. The second argument is a reference to the personality function to be
-used for this function. The remaining arguments are references to the type infos
-for each type that can be thrown by the current function.</p>
+used for this try catch sequence.  Each of the remaining arguments is either a
+reference to the type info for a catch statement, or a non-negative integer
+followed by that many type info references, representing a
+<a href="#throw_filters">filter</a>.
+The exception is tested against the arguments sequentially from first to last.
+The <i>catch all</i> (...) is represented with a <tt>null i8*</tt>.  The result
+of the <a href="#llvm_eh_selector"><tt>llvm.eh.selector</tt></a> is a positive
+number if the exception matched a type info, a negative number if it matched a
+filter, and zero if it didn't match anything.  If a type info matched then the
+returned value is the index of the type info in the exception table.</p>
 
 </div>
 
@@ -427,15 +415,6 @@
 
 <ol>
 
-<li><p>Need to create landing pads for code in between explicit landing pads. 
-The landing pads will have a zero action and a NULL landing pad address and are
-used to inform the runtime that the exception should be rethrown.</li></p>
-
-<li><p>Actions for a given function should be folded to save space.</p></li>
-
-<li><p>Filters for inlined functions need to be handled more extensively.
-Currently it's hardwired for one filter per function.</li></p>
-
 <li><p>Testing/Testing/Testing.</li></p>
 
 </ol>

Modified: llvm/trunk/include/llvm/Intrinsics.td
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Intrinsics.td?rev=37875&r1=37874&r2=37875&view=diff

==============================================================================
--- llvm/trunk/include/llvm/Intrinsics.td (original)
+++ llvm/trunk/include/llvm/Intrinsics.td Wed Jul  4 15:52:51 2007
@@ -231,8 +231,6 @@
 def int_eh_exception  : Intrinsic<[llvm_ptr_ty]>;
 def int_eh_selector   : Intrinsic<[llvm_i32_ty, llvm_ptr_ty, llvm_ptr_ty,
                                                 llvm_vararg_ty]>;
-def int_eh_filter     : Intrinsic<[llvm_i32_ty, llvm_ptr_ty, llvm_ptr_ty,
-                                                llvm_vararg_ty]>;
 def int_eh_typeid_for : Intrinsic<[llvm_i32_ty, llvm_ptr_ty]>;
 
 //===---------------- Generic Variable Attribute Intrinsics----------------===//

Modified: llvm/trunk/lib/CodeGen/IntrinsicLowering.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/IntrinsicLowering.cpp?rev=37875&r1=37874&r2=37875&view=diff

==============================================================================
--- llvm/trunk/lib/CodeGen/IntrinsicLowering.cpp (original)
+++ llvm/trunk/lib/CodeGen/IntrinsicLowering.cpp Wed Jul  4 15:52:51 2007
@@ -708,7 +708,6 @@
   case Intrinsic::dbg_declare:
   case Intrinsic::eh_exception:
   case Intrinsic::eh_selector:
-  case Intrinsic::eh_filter:
     break;    // Simply strip out debugging and eh intrinsics
 
   case Intrinsic::var_annotation:

Modified: llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp?rev=37875&r1=37874&r2=37875&view=diff

==============================================================================
--- llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp (original)
+++ llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp Wed Jul  4 15:52:51 2007
@@ -205,12 +205,11 @@
   };
 }
 
-/// isFilterOrSelector - Return true if this instruction is a call to the
-/// eh.filter or the eh.selector intrinsic.
-static bool isFilterOrSelector(Instruction *I) {
+/// isSelector - Return true if this instruction is a call to the
+/// eh.selector intrinsic.
+static bool isSelector(Instruction *I) {
   if (IntrinsicInst *II = dyn_cast<IntrinsicInst>(I))
-    return II->getIntrinsicID() == Intrinsic::eh_selector
-      || II->getIntrinsicID() == Intrinsic::eh_filter;
+    return II->getIntrinsicID() == Intrinsic::eh_selector;
   return false;
 }
 
@@ -2293,12 +2292,12 @@
   }
 }
 
-/// ExtractGlobalVariable - If C is a global variable, or a bitcast of one
+/// ExtractGlobalVariable - If V is a global variable, or a bitcast of one
 /// (possibly constant folded), return it.  Otherwise return NULL.
-static GlobalVariable *ExtractGlobalVariable (Constant *C) {
-  if (GlobalVariable *GV = dyn_cast<GlobalVariable>(C))
+static GlobalVariable *ExtractGlobalVariable (Value *V) {
+  if (GlobalVariable *GV = dyn_cast<GlobalVariable>(V))
     return GV;
-  else if (ConstantExpr *CE = dyn_cast<ConstantExpr>(C)) {
+  else if (ConstantExpr *CE = dyn_cast<ConstantExpr>(V)) {
     if (CE->getOpcode() == Instruction::BitCast)
       return dyn_cast<GlobalVariable>(CE->getOperand(0));
     else if (CE->getOpcode() == Instruction::GetElementPtr) {
@@ -2311,8 +2310,16 @@
   return NULL;
 }
 
+/// ExtractTypeInfo - Extracts the type info from a value.
+static GlobalVariable *ExtractTypeInfo (Value *V) {
+  GlobalVariable *GV = ExtractGlobalVariable(V);
+  assert (GV || isa<ConstantPointerNull>(V) &&
+          "TypeInfo must be a global variable or NULL");
+  return GV;
+}
+
 /// addCatchInfo - Extract the personality and type infos from an eh.selector
-/// or eh.filter call, and add them to the specified machine basic block.
+/// call, and add them to the specified machine basic block.
 static void addCatchInfo(CallInst &I, MachineModuleInfo *MMI,
                          MachineBasicBlock *MBB) {
   // Inform the MachineModuleInfo of the personality for this landing pad.
@@ -2325,17 +2332,38 @@
   // 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);
+  unsigned N = I.getNumOperands();
+
+  for (unsigned i = N - 1; i > 2; --i) {
+    if (ConstantInt *CI = dyn_cast<ConstantInt>(I.getOperand(i))) {
+      unsigned FilterLength = CI->getZExtValue();
+      unsigned FirstCatch = i + FilterLength + 1;
+      assert (FirstCatch <= N && "Invalid filter length");
+
+      if (FirstCatch < N) {
+        TyInfo.reserve(N - FirstCatch);
+        for (unsigned j = FirstCatch; j < N; ++j)
+          TyInfo.push_back(ExtractTypeInfo(I.getOperand(j)));
+        MMI->addCatchTypeInfo(MBB, TyInfo);
+        TyInfo.clear();
+      }
+
+      TyInfo.reserve(FilterLength);
+      for (unsigned j = i + 1; j < FirstCatch; ++j)
+        TyInfo.push_back(ExtractTypeInfo(I.getOperand(j)));
+      MMI->addFilterTypeInfo(MBB, TyInfo);
+      TyInfo.clear();
+
+      N = i;
+    }
   }
-  if (I.getCalledFunction()->getIntrinsicID() == Intrinsic::eh_filter)
-    MMI->addFilterTypeInfo(MBB, TyInfo);
-  else
+
+  if (N > 3) {
+    TyInfo.reserve(N - 3);
+    for (unsigned j = 3; j < N; ++j)
+      TyInfo.push_back(ExtractTypeInfo(I.getOperand(j)));
     MMI->addCatchTypeInfo(MBB, TyInfo);
+  }
 }
 
 /// propagateEHRegister - The specified EH register is required in a successor
@@ -2483,8 +2511,7 @@
     return 0;
   }
 
-  case Intrinsic::eh_selector:
-  case Intrinsic::eh_filter:{
+  case Intrinsic::eh_selector:{
     MachineModuleInfo *MMI = DAG.getMachineModuleInfo();
 
     if (ExceptionHandling && MMI) {
@@ -2518,10 +2545,7 @@
     
     if (MMI) {
       // Find the type id for the given typeinfo.
-      Constant *C = cast<Constant>(I.getOperand(1));
-      GlobalVariable *GV = ExtractGlobalVariable(C);
-      assert (GV || isa<ConstantPointerNull>(C) &&
-              "TypeInfo must be a global variable or NULL");
+      GlobalVariable *GV = ExtractTypeInfo(I.getOperand(1));
 
       unsigned TypeID = MMI->getTypeIDFor(GV);
       setValue(&I, DAG.getConstant(TypeID, MVT::i32));
@@ -4297,7 +4321,7 @@
   assert(!FLI.MBBMap[SrcBB]->isLandingPad() &&
          "Copying catch info out of a landing pad!");
   for (BasicBlock::iterator I = SrcBB->begin(), E = --SrcBB->end(); I != E; ++I)
-    if (isFilterOrSelector(I)) {
+    if (isSelector(I)) {
       // Apply the catch info to DestBB.
       addCatchInfo(cast<CallInst>(*I), MMI, FLI.MBBMap[DestBB]);
 #ifndef NDEBUG
@@ -4341,19 +4365,19 @@
     // 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.
+    // information is provided by an intrinsic (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()) { // Critical edge?
       BasicBlock::iterator I, E;
       for (I = LLVMBB->begin(), E = --LLVMBB->end(); I != E; ++I)
-        if (isFilterOrSelector(I))
+        if (isSelector(I))
           break;
 
       if (I == E)





More information about the llvm-commits mailing list