Unwinds gone missing

After much delay, I have finally reached the point in my work where I need to implement some kind of exception handling. I understand that "unwind" is currently unimplemented and will remain so for the forseeable future.

In the mean time, are there any examples available for implementing Java or Python-style exceptions using __cxa_throw or something similar? I've read and re-read the various docs on exception handling and I'm not attaining understanding.

I'm mainly interested in knowing how to generate code that is as efficient as possible while still allowing exception objects to live on the garbage-collected heap.

-- Talin

Hi Talin,

Talin wrote:

After much delay, I have finally reached the point in my work where I need to implement some kind of exception handling. I understand that "unwind" is currently unimplemented and will remain so for the forseeable future.

In the mean time, are there any examples available for implementing Java or Python-style exceptions using __cxa_throw or something similar? I've read and re-read the various docs on exception handling and I'm not attaining understanding.

VMKit's your friend! Unfortunately, there's no documentation. Note that the unwinding part is done by libgcc, like llvm-gcc.
Also, VMKit uses the same scheme than llvm-gcc for exceptions, so I'm not sure what more info you need apart from the docs and what llvm-gcc provides. The dwarf output makes it all work magically :slight_smile:

Nicolas

Can you point out to me where in the VMKit code I should be looking?

I spent some additional time reading the docs, and I have some specific questions:

  1. I’m trying to figure out the relationship between the __cxa_throw function, and the _Unwind_RaiseException function mentioned in the ABI doc. My guess is that _Unwind_RaiseException is the language-neutral implementation of stack unwinding, and __cxa_throw is the C++ exception semantics that are implemented on top of it. If that is the case, should I be calling _Unwind_RaiseException since my exceptions are more like Java than C++ exceptions?

  2. How portable is _Unwind_RaiseException and similar functions? In particular, if I call those functions, will I be limiting myself to a subset of the platforms that LLVM supports? (The same question can be asked of __cxa_throw).

Although _Unwind_RaiseException is mentioned as part of the Itanium ABI, it is apparently used on many more platform types than just that one processor. A code search shows that it is in fact part of the standard gcc-provided runtime libs (see http://www.google.com/codesearch/p?hl=en#47R7EH5FbNk/trunk/gcc/gcc/unwind-generic.h&q=_Unwind_RaiseException%20lang:c). There is also a mention of “libunwind”. Is libunwind a portable implementation of the Itanium unwinding ABI?

  1. I really like the “invoke/unwind” abstraction that LLVM provides, as it divorces the mechanism of unwinding from the creation of an exception object. However, looking at the Itanium unwinding API, I don’t see how you can implement LLVM invoke/unwind on top of it, since the API functions take an exception object as a parameter. (I suppose you could use a dummy exception to satisfy the ABI, and then implement your own, separate exception object, but this destroys some of the efficiency of the unwinding implementation.)

Also, the Itanium ABI appears to offer some interesting features that aren’t exposed by the invoke/unwind mechanism which would be useful. For example, the fact that the stack frames are traversed in two passes seems like it might make it possible to implement human-readable stack dumps, which would be difficult with invoke/unwind.

All this suggests to me that, as nice as the invoke/unwind abstraction is, it might not be a good fit for the capabilities that are actually available. Of course, I’m talking out of total ignorance here…

Thanks in advance, and expect more questions after this :slight_smile:

– Talin

I understand that "unwind" is currently unimplemented...

Is it? I was just reading the documentation about LLVM's exception handling
and it sounded ideal for my needs. How much of it does not work as the docs
imply?

and will remain so for the forseeable future...

Surely C++-style exception handling is a priority? What might I want from LLVM
in terms of exception handling once it supports C++?

Jon Harrop wrote:

Is it? I was just reading the documentation about LLVM's exception
handling
and it sounded ideal for my needs. How much of it does not work as the
docs
imply?

Jon, I ran into this issue in September and re-ignited this discussion in
another thread, here:
http://www.nabble.com/Unwinds-Gone-Wild-td18747589.html
http://www.nabble.com/Unwinds-Gone-Wild-td18747589.html

I too had been quite excited by reading the documentation. Unfortunately, it
seems "unwind" does nothing at all - it compiles into a no-op. So you have
to use the lower-level functions in libgcc. I've never figured out how to
get it working, sorry. But there may be helpful information in that thread.

Matt

From what I understand, the unwind instruction is implemented only for the interpreter: there is a -lowerunwind pass for compiling to other systems which will either lower unwind and invoke to setjmp/longjmp (slow) or turn invokes into calls and unwinds into abort()s.

Alastair Lynn wrote:

From what I understand, the unwind instruction is implemented only
for the interpreter: there is a -lowerunwind pass for compiling to
other systems which will either lower unwind and invoke to setjmp/
longjmp (slow) or turn invokes into calls and unwinds into abort()s.

Ah cheers, Alastair. That could be very useful (at least for me personally,
I don't mind the slow so much as long as it behaves correctly!)

I did a bit of research. Looks like it's -lowerinvoke, not -lowerunwind.

http://llvm.org/docs/Passes.html#lowerinvoke

That provides the two options you describe.

Now this question is perhaps getting a bit off-topic, but I can't find a
tool which accepts the -lower* arguments. Is there a tool for running such
passes? Or can it only be accessed from the C++ API side of LLVM?

Thanks
Matt

Matt Giuca wrote:

Alastair Lynn wrote:
  

From what I understand, the unwind instruction is implemented only for the interpreter: there is a -lowerunwind pass for compiling to other systems which will either lower unwind and invoke to setjmp/ longjmp (slow) or turn invokes into calls and unwinds into abort()s.

Ah cheers, Alastair. That could be very useful (at least for me personally,
I don't mind the slow so much as long as it behaves correctly!)

I did a bit of research. Looks like it's -lowerinvoke, not -lowerunwind.

http://llvm.org/docs/Passes.html#lowerinvoke

That provides the two options you describe.

Now this question is perhaps getting a bit off-topic, but I can't find a
tool which accepts the -lower* arguments. Is there a tool for running such
passes? Or can it only be accessed from the C++ API side of LLVM?
  

opt. You can use it like:

  $ opt -lowerinvoke in.bc -o out.bc
or
  $ llvm-as < foo.ll | opt -lowerinvoke | llvm-dis
or
  $ llvm-gcc -O2 foo.c -c -o - -emit-llvm | opt -lowerinvoke | llc -o foo.s

depending on what you're doing.

Nick

Hi Talin,

Talin wrote:

Can you point out to me where in the VMKit code I should be looking?

The compilation of an exception table in Java is in lib/JnJVM/VMCore/JavaJIT.cpp, function "readExceptionTable".
The interaction with the libgcc runtime is in lib/JnJVM/VMCore/JavaThread.cpp.

I spent some additional time reading the docs, and I have some specific questions:

1) I'm trying to figure out the relationship between the __cxa_throw function, and the _Unwind_RaiseException function mentioned in the ABI doc. My guess is that _Unwind_RaiseException is the language-neutral implementation of stack unwinding, and __cxa_throw is the C++ exception semantics that are implemented on top of it. If that is the case, should I be calling _Unwind_RaiseException since my exceptions are more like Java than C++ exceptions?

I don't know... Last time I use __cxa_throw, because it's allocating an exception object and setting the correct values in the header of this exception. _Unwind_RaiseException just takes an exception object as parameter and if it's not filled correctly, some other functions may not work.

2) How portable is _Unwind_RaiseException and similar functions? In particular, if I call those functions, will I be limiting myself to a subset of the platforms that LLVM supports? (The same question can be asked of __cxa_throw).

I think __cxa_throw is fairly portable. That's what g++ uses to assembly generate exception throwing. So it depends on libgcc being implemented on multiple platforms. I have no idea though for _Unwind_RaiseException.

Although _Unwind_RaiseException is mentioned as part of the Itanium ABI, it is apparently used on many more platform types than just that one processor. A code search shows that it is in fact part of the standard gcc-provided runtime libs (see http://www.google.com/codesearch/p?hl=en#47R7EH5FbNk/trunk/gcc/gcc/unwind-generic.h&q=_Unwind_RaiseException%20lang:c). There is also a mention of "libunwind". Is libunwind a portable implementation of the Itanium unwinding ABI?

You'd have to ask the libunwind developers: http://www.nongnu.org/libunwind/people.html. Apparently, i runs on ia64, x86, x86-64, ppc64. I have no idea of how well libunwind fits with libgcc.

3) I really like the "invoke/unwind" abstraction that LLVM provides, as it divorces the mechanism of unwinding from the creation of an exception object. However, looking at the Itanium unwinding API, I don't see how you can implement LLVM invoke/unwind on top of it, since the API functions take an exception object as a parameter. (I suppose you could use a dummy exception to satisfy the ABI, and then implement your own, separate exception object, but this destroys some of the efficiency of the unwinding implementation.)

Yeah, I don't think both match very well. VMKit uses a dummy exception.

Also, the Itanium ABI appears to offer some interesting features that aren't exposed by the invoke/unwind mechanism which would be useful. For example, the fact that the stack frames are traversed in two passes seems like it might make it possible to implement human-readable stack dumps, which would be difficult with invoke/unwind.

What's a human-readable stack dump? :wink: I don't see how invoke/unwind would limit this.

Hi Talin,

1) I'm trying to figure out the relationship between the __cxa_throw
function, and the _Unwind_RaiseException function mentioned in the ABI doc.
My guess is that _Unwind_RaiseException is the language-neutral
implementation of stack unwinding, and __cxa_throw is the C++ exception
semantics that are implemented on top of it. If that is the case, should I
be calling _Unwind_RaiseException since my exceptions are more like Java
than C++ exceptions?

try reading this: http://www.codesourcery.com/public/cxx-abi/abi-eh.html

2) How portable is _Unwind_RaiseException and similar functions? In
particular, if I call those functions, will I be limiting myself to a subset
of the platforms that LLVM supports? (The same question can be asked of
__cxa_throw).

Although _Unwind_RaiseException is mentioned as part of the Itanium ABI, it
is apparently used on many more platform types than just that one processor.
A code search shows that it is in fact part of the standard gcc-provided
runtime libs (see
http://www.google.com/codesearch/p?hl=en#47R7EH5FbNk/trunk/gcc/gcc/unwind-generic.h&q=_Unwind_RaiseException%20lang:c).

Exactly, this is part of libgcc and as such you can assume it is available.

There is also a mention of "libunwind". Is libunwind a portable
implementation of the Itanium unwinding ABI?

I think it's an attempt to have a non-gcc related platform independent
unwinding library.

3) I really like the "invoke/unwind" abstraction that LLVM provides, as it
divorces the mechanism of unwinding from the creation of an exception
object. However, looking at the Itanium unwinding API, I don't see how you
can implement LLVM invoke/unwind on top of it, since the API functions take
an exception object as a parameter. (I suppose you could use a dummy
exception to satisfy the ABI, and then implement your own, separate
exception object, but this destroys some of the efficiency of the unwinding
implementation.)

Right, this is indeed one of the main problems in implementing unwind.
On the other hand invoke can be done fairly easily (in spite of appearances,
invoke is not supported by the code generators, only invoke + an eh.selector
call [provides a personality function] is supported; I have a plan to fix
this).

Also, the Itanium ABI appears to offer some interesting features that aren't
exposed by the invoke/unwind mechanism which would be useful. For example,
the fact that the stack frames are traversed in two passes seems like it
might make it possible to implement human-readable stack dumps, which would
be difficult with invoke/unwind.

Check out http://llvm.org/docs/LangRef.html#int_frameaddress

Ciao,

Duncan.

Hi Talin,

  1. I’m trying to figure out the relationship between the __cxa_throw
    function, and the _Unwind_RaiseException function mentioned in the ABI doc.
    My guess is that _Unwind_RaiseException is the language-neutral
    implementation of stack unwinding, and __cxa_throw is the C++ exception
    semantics that are implemented on top of it. If that is the case, should I
    be calling _Unwind_RaiseException since my exceptions are more like Java
    than C++ exceptions?

try reading this: http://www.codesourcery.com/public/cxx-abi/abi-eh.html

I did :slight_smile:

I was also looking at this article, which purports to use __Unwind_RaiseException directly: http://www.incasoftware.de/~kamm/projects/index.php/2008/08/19/exception-handling-in-llvmdc-using-llvm/

  1. How portable is _Unwind_RaiseException and similar functions? In
    particular, if I call those functions, will I be limiting myself to a subset
    of the platforms that LLVM supports? (The same question can be asked of
    __cxa_throw).

Although _Unwind_RaiseException is mentioned as part of the Itanium ABI, it
is apparently used on many more platform types than just that one processor.
A code search shows that it is in fact part of the standard gcc-provided
runtime libs (see
http://www.google.com/codesearch/p?hl=en#47R7EH5FbNk/trunk/gcc/gcc/unwind-generic.h&q=_Unwind_RaiseException%20lang:c).

Exactly, this is part of libgcc and as such you can assume it is available.

There is also a mention of “libunwind”. Is libunwind a portable
implementation of the Itanium unwinding ABI?

I think it’s an attempt to have a non-gcc related platform independent
unwinding library.

  1. I really like the “invoke/unwind” abstraction that LLVM provides, as it
    divorces the mechanism of unwinding from the creation of an exception
    object. However, looking at the Itanium unwinding API, I don’t see how you
    can implement LLVM invoke/unwind on top of it, since the API functions take
    an exception object as a parameter. (I suppose you could use a dummy
    exception to satisfy the ABI, and then implement your own, separate
    exception object, but this destroys some of the efficiency of the unwinding
    implementation.)

Right, this is indeed one of the main problems in implementing unwind.
On the other hand invoke can be done fairly easily (in spite of appearances,
invoke is not supported by the code generators, only invoke + an eh.selector
call [provides a personality function] is supported; I have a plan to fix
this).

Also, the Itanium ABI appears to offer some interesting features that aren’t
exposed by the invoke/unwind mechanism which would be useful. For example,
the fact that the stack frames are traversed in two passes seems like it
might make it possible to implement human-readable stack dumps, which would
be difficult with invoke/unwind.

Check out http://llvm.org/docs/LangRef.html#int_frameaddress

I knew about that function - the issue isn’t so much getting the stack frames, as it is knowing whether or not you’ll need them. For most exceptions, we would want to simply have the exception be caught and resume execution, in which case saving the state of the stack is a waste of time. However, in some cases you are going to print out the stack trace, which means you need to record the stack frames before you enter the catch handler (because then it’s too late).

The Itanium exception document describes a process where the stack frames between the throw and catch statements can be traversed multiple times. Assuming the compiler knows whether a given catch handler makes reference to the stack trace property of the exception, we can use this information to decide whether or not to allocate space for the stack trace. That is, do a pre-traversal to determine which catch handler will be called and whether stack trace information is needed. If so, then do another traversal to capture the stack trace, and then a final traversal to do the actual unwinding.

Doing something similar using only the LLVM invoke/unwind primitives would be very difficult I think.