[LLVMdev] RFC: Exception Handling Proposal II

Renato Golin rengolin at systemcall.org
Sun Nov 28 06:23:00 PST 2010


On 28 November 2010 10:20, Bill Wendling <wendling at apple.com> wrote:
> Or am I missing something? :-)

Hi Bill, John,

There still seems to be a confusion between clean-ups and catch areas.
What you both describe are catch areas, on which your arguments
(AFAICS) are perfectly valid. The distinction is between catch and
clean-up areas.

You would never print the value of %x in a clean-up area. The sole
purpose of clean-up areas is to cleanly destroy variables that
wouldn't otherwise because of exception handling. During normal flow,
the destruction code doesn't need to be in a clean-up area, it can
easily be at the end of the scope, and it normally is on both places.

The destruction code itself can print the value of %x (if it has
access to it), and the validity of such value in the destructor code
is up to the language + the user code. For instance, accessing a null
pointer in C++ is allowed by the language (nobody stops you from doing
so in compile time) but it's illegal during execution on most
platforms.

But, under no circumstances, a clean-up area can access a user
variable to print it on the screen. It's like calling an intrinsic and
expecting it to print the value of a random variable inside your code.
It doesn't even make sense.

Catch areas, on the other hand, are user code. Like destructors, the
user can print the value of %x if it has access to, and if the
variable was never initialised, it's the user's problem of relying on
such condition. Catch areas are NOT unwinding basic blocks, they are
the first user code blocks that, in case of a match, it's where
execution returns to normal flow. They can also throw again, and make
the flow go back to unwinding, but per se, they're user code.

As was pointed out, some optimizations in LLVM can move user code to
clean-up areas. The compiler may prove it valid and the execution
might even work, but that's an artefact of how the compiler works and
how other optimizations work around the same issue (such as inlining).

Moving code from try to catch areas (and vice-versa) is fine, as both
are user blocks. But moving user code to clean-up areas can lead to
undefined behaviour. For example, during the unwinding of several
functions without a single match to the exception, local variables in
all intermediate functions have to be cleaned up, and that's done via
the clean-up areas. The personality routine is controlling this flow,
so if you move user code that could have side effects to a clean-up
area (say only on -O3), a perfectly valid unwinding can break
completely and terminate.

That breaking is not inside the destructor, nor inside the catch
areas, but inside a clean-up area, on which the user has no access nor
control. This is a compiler bug.

cheers,
--renato



More information about the llvm-dev mailing list