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) _______________________________________________ llvm-commits mailing list llvm-commits@cs.uiuc.edu http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits