[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