[llvm-commits] [llvm-gcc-4.2] r102148 - /llvm-gcc-4.2/trunk/gcc/llvm-convert.cpp
Bill Wendling
isanbard at gmail.com
Thu Apr 22 17:01:20 PDT 2010
Author: void
Date: Thu Apr 22 19:01:20 2010
New Revision: 102148
URL: http://llvm.org/viewvc/llvm-project?rev=102148&view=rev
Log:
A fix for a nasty bug (<rdar://problem/7885482>). Here's what's happening:
Consider this pseudo-ObjC code:
// locking using some "lock" variable
@try {
// ...
} @catch (...) {
// ...
@throw;
} @finally {
// unlocking using the "lock" variable
}
The "lock" variable has live intervals from the top of the function through the
@try block and in the @finally block. On 32-bit x86, it doesn't have a live
interval in the @catch block. This is because in 32-bit mode Objective-C uses
setjmp/longjmp for exception handling and not the invoke/DWARF method. The
@throw is implemented as an "objc_exception_throw" call marked with
NORETURN. The upshot is that if the "lock" variable is placed into a stack slot,
there won't be an indication that the "lock" can be used after the
"objc_exception_throw" executes. With the invoke/DWARF method, the unwind edge
of the invoke points to the @finally block, so the "lock" variable will have a
live interval leading to there.
The solution is to have the "objc_exception_throw" behave in a similar manner to
the invoke/DWARF method. That is remove the "NORETURN" attribute, allowing it to
have an edge from the call to the @finally block.
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=102148&r1=102147&r2=102148&view=diff
==============================================================================
--- llvm-gcc-4.2/trunk/gcc/llvm-convert.cpp (original)
+++ llvm-gcc-4.2/trunk/gcc/llvm-convert.cpp Thu Apr 22 19:01:20 2010
@@ -2535,8 +2535,43 @@
// from thinking that control flow will fall into the subsequent block.
//
if (fndecl && TREE_THIS_VOLATILE(fndecl)) {
- Builder.CreateUnreachable();
- EmitBlock(BasicBlock::Create(Context, ""));
+ // LLVM LOCAL - begin radar 7885482
+ /*
+ Consider this pseudo-ObjC code:
+
+ // locking using some "lock" variable
+ @try {
+ // ...
+ } @catch (...) {
+ // ...
+ @throw;
+ } @finally {
+ // unlocking using the "lock" variable
+ }
+
+ The "lock" variable has live intervals from the top of the function
+ through the @try block and in the @finally block. On 32-bit x86, it
+ doesn't have a live interval in the @catch block. This is because in
+ 32-bit mode Objective-C uses setjmp/longjmp for exception handling and not
+ the invoke/DWARF method. The @throw is implemented as an
+ "objc_exception_throw" call marked with NORETURN. The upshot is that if
+ the "lock" variable is placed into a stack slot, there won't be an
+ indication that the "lock" can be used after the "objc_exception_throw"
+ executes. With the invoke/DWARF method, the unwind edge of the invoke
+ points to the @finally block, so the "lock" variable will have a live
+ interval leading to there.
+
+ The solution is to have the "objc_exception_throw" behave in a similar
+ manner to the invoke/DWARF method. That is remove the "NORETURN"
+ attribute, allowing it to have an edge from the call to the @finally
+ block. */
+ if (!TARGET_64BIT && Callee->getName() == "objc_exception_throw")
+ cast<Function>(Callee)->removeFnAttr(Attribute::NoReturn);
+ else {
+ Builder.CreateUnreachable();
+ EmitBlock(BasicBlock::Create(Context, ""));
+ }
+ // LLVM LOCAL - end radar 7885482
}
return Result;
}
@@ -2939,6 +2974,40 @@
Call = Builder.CreateCall(Callee, CallOperands.begin(), CallOperands.end());
cast<CallInst>(Call)->setCallingConv(CallingConvention);
cast<CallInst>(Call)->setAttributes(PAL);
+
+ // LLVM LOCAL - begin radar 7885482
+ /*
+ Consider this pseudo-ObjC code:
+
+ // locking using some "lock" variable
+ @try {
+ // ...
+ } @catch (...) {
+ // ...
+ @throw;
+ } @finally {
+ // unlocking using the "lock" variable
+ }
+
+ The "lock" variable has live intervals from the top of the function
+ through the @try block and in the @finally block. On 32-bit x86, it
+ doesn't have a live interval in the @catch block. This is because in
+ 32-bit mode Objective-C uses setjmp/longjmp for exception handling and not
+ the invoke/DWARF method. The @throw is implemented as an
+ "objc_exception_throw" call marked with NORETURN. The upshot is that if
+ the "lock" variable is placed into a stack slot, there won't be an
+ indication that the "lock" can be used after the "objc_exception_throw"
+ executes. With the invoke/DWARF method, the unwind edge of the invoke
+ points to the @finally block, so the "lock" variable will have a live
+ interval leading to there.
+
+ The solution is to have the "objc_exception_throw" behave in a similar
+ manner to the invoke/DWARF method. That is remove the "NORETURN"
+ attribute, allowing it to have an edge from the call to the @finally
+ block. */
+ if (!TARGET_64BIT && Callee->getName() == "objc_exception_throw")
+ cast<CallInst>(Call)->removeAttribute(~0U, Attribute::NoReturn);
+ // LLVM LOCAL - end radar 7885482
} else {
BasicBlock *NextBlock = BasicBlock::Create(Context, "invcont");
Call = Builder.CreateInvoke(Callee, NextBlock, LandingPad,
More information about the llvm-commits
mailing list