[llvm-commits] [llvm-gcc-4.2] r99670 - /llvm-gcc-4.2/trunk/gcc/llvm-convert.cpp
Bill Wendling
isanbard at gmail.com
Fri Mar 26 16:40:55 PDT 2010
Author: void
Date: Fri Mar 26 18:40:55 2010
New Revision: 99670
URL: http://llvm.org/viewvc/llvm-project?rev=99670&view=rev
Log:
A clean-up needs to be marked as a clean-up. It could cause problems in the
libunwind library otherwise. Take this program for an example:
int main() {
try {
throw new std::exception();
} catch (std::exception *e) {
throw e;
}
}
At the re-throw, the libunwind expects the state to be in a clean-up
state. However, because we generate catch-alls in our code, the personality
returns the wrong state the libunwind, which then barfs.
Marking that re-throw as a clean-up puts libunwind into the correct state.
There is other code here, though. If we mark clean-ups as clean-ups, then it
could break when inlining through an 'invoke' instruction. You will get a
situation like this:
bb:
%ehptr = eh.exception()
%sel = eh.selector(%ehptr, @per, 0);
...
bb2:
invoke _Unwind_Resume_or_Rethrow(%ehptr) %normal unwind to %lpad
lpad:
...
The unwinder will see the %sel call as a clean-up and, if it doesn't have a
catch further up the call stack, it will skip running it. But there *is* another
catch up the stack -- the catch for the %lpad. However, we can't see that. This
is fixed in code-gen, where we detect this situation, and convert the "clean-up"
selector call into a "catch-all" selector call. This gives us the correct
semantics.
Modified:
llvm-gcc-4.2/trunk/gcc/llvm-convert.cpp
Modified: llvm-gcc-4.2/trunk/gcc/llvm-convert.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/gcc/llvm-convert.cpp?rev=99670&r1=99669&r2=99670&view=diff
==============================================================================
--- llvm-gcc-4.2/trunk/gcc/llvm-convert.cpp (original)
+++ llvm-gcc-4.2/trunk/gcc/llvm-convert.cpp Fri Mar 26 18:40:55 2010
@@ -2089,6 +2089,9 @@
// Add selections for each handler.
foreach_reachable_handler(i, false, AddHandler, &Handlers);
+ bool HasCleanup = false;
+ static Value *CatchAll = 0;
+
for (std::vector<struct eh_region *>::iterator I = Handlers.begin(),
E = Handlers.end(); I != E; ++I) {
struct eh_region *region = *I;
@@ -2115,9 +2118,16 @@
if (!TypeList) {
// Catch-all - push a null pointer.
- Args.push_back(
- Constant::getNullValue(Type::getInt8PtrTy(Context))
- );
+ if (!CatchAll) {
+ Constant *Init =
+ Constant::getNullValue(Type::getInt8PtrTy(Context));
+
+ CatchAll = new GlobalVariable(*TheModule, Init->getType(), true,
+ GlobalVariable::LinkOnceAnyLinkage,
+ Init, ".llvm.eh.catch.all.value");
+ }
+
+ Args.push_back(CatchAll);
} else {
// Add the type infos.
for (; TypeList; TypeList = TREE_CHAIN(TypeList)) {
@@ -2125,30 +2135,43 @@
Args.push_back(Emit(TType, 0));
}
}
+ } else {
+ // Cleanup.
+ HasCleanup = true;
}
}
if (can_throw_external_1(i, false)) {
- // Some exceptions from this region may not be caught by any handler.
- // Since invokes are required to branch to the unwind label no matter
- // what exception is being unwound, append a catch-all.
-
- // The representation of a catch-all is language specific.
- Value *CatchAll;
- if (USING_SJLJ_EXCEPTIONS || !lang_eh_catch_all) {
- // Use a "cleanup" - this should be good enough for most languages.
- CatchAll = ConstantInt::get(Type::getInt32Ty(Context), 0);
+ if (HasCleanup && Args.size() == 2) {
+ Args.push_back(ConstantInt::get(Type::getInt32Ty(Context), 0));
} else {
- tree catch_all_type = lang_eh_catch_all();
- if (catch_all_type == NULL_TREE)
- // Use a C++ style null catch-all object.
- CatchAll = Constant::getNullValue(
- Type::getInt8PtrTy(Context));
- else
- // This language has a type that catches all others.
- CatchAll = Emit(catch_all_type, 0);
+ // Some exceptions from this region may not be caught by any handler.
+ // Since invokes are required to branch to the unwind label no matter
+ // what exception is being unwound, append a catch-all.
+
+ // The representation of a catch-all is language specific.
+ if (USING_SJLJ_EXCEPTIONS || !lang_eh_catch_all) {
+ // Use a "cleanup" - this should be good enough for most languages.
+ Args.push_back(ConstantInt::get(Type::getInt32Ty(Context), 0));
+ } else {
+ if (!CatchAll) {
+ Constant *Init = 0;
+ tree catch_all_type = lang_eh_catch_all();
+ if (catch_all_type == NULL_TREE)
+ // Use a C++ style null catch-all object.
+ Init = Constant::getNullValue(Type::getInt8PtrTy(Context));
+ else
+ // This language has a type that catches all others.
+ Init = cast<Constant>(Emit(catch_all_type, 0));
+
+ CatchAll = new GlobalVariable(*TheModule, Init->getType(), true,
+ GlobalVariable::PrivateLinkage,
+ Init, ".llvm.eh.catch.all.value");
+ }
+
+ Args.push_back(CatchAll);
+ }
}
- Args.push_back(CatchAll);
}
// Emit the selector call.
More information about the llvm-commits
mailing list