Unwinds Gone Wild

Can anyone tell me if invoke/unwind is stable in 2.3? I’m seeing some really weird stuff – unwinds are ending up in seemingly arbitrary places… definitely not inside the caller’s unwind block My target is x86.

As a simple test, I tried to compile the following code and I got a segmentation fault. It looks good to me. Can someone help me out or is this a bug?

define i32 @foo() {
entry:
unwind
}

define i32 @main() nounwind {
entry:
%bar = invoke i32 @foo( ) to label %yes unwind label %no
yes:
ret i32 %bar
no:
ret i32 -1
}

Marc

Hi,

Can anyone tell me if invoke/unwind is stable in 2.3? I'm seeing some
really weird stuff -- unwinds are ending up in seemingly arbitrary places...
definitely not inside the caller's unwind block My target is x86.

codegen doesn't know how to handle "unwind" on any target. You need
to call the libgcc unwinding routines directly (or indirectly by
pretending to be C++ or some other language, and calling eg cxa_throw).

As a simple test, I tried to compile the following code and I got a
segmentation fault. It looks good to me. Can someone help me out or is
this a bug?

It's a bug that it's not supported. Supporting it is not so easy
to do, which is why it's still unsupported...

Ciao,

Duncan.

Hi,

Can anyone tell me if invoke/unwind is stable in 2.3? I’m seeing some
really weird stuff – unwinds are ending up in seemingly arbitrary places…
definitely not inside the caller’s unwind block My target is x86.

codegen doesn’t know how to handle “unwind” on any target. You need
to call the libgcc unwinding routines directly (or indirectly by
pretending to be C++ or some other language, and calling eg cxa_throw).

I’m not familiar with the libgcc unwinding routines. What do these look like and where might I read more about them? Or maybe someone can provide an example? For instance, how could I do it for my little dummy program?

As a simple test, I tried to compile the following code and I got a
segmentation fault. It looks good to me. Can someone help me out or is
this a bug?

It’s a bug that it’s not supported. Supporting it is not so easy
to do, which is why it’s still unsupported…

It would be nice if this was documented somewhere, although I understand the difficulties in keeping documentation up-to-date.

Is setjmp/longjmp what you have in mind?
Is there a timeline for implementing unwind in codegen? I guess I don’t strictly need it, but it would be really handy.

These links might be helpful:

Exception Handling in LLVM:
http://www.llvm.org/docs/ExceptionHandling.html

LSB Core specs from:
http://refspecs.linux-foundation.org/lsb.shtml

libunwind from HP:
http://www.nongnu.org/libunwind/

Intel Stack Unwind Library (for Itanium):
http://www.intel.com/cd/software/products/asmo-na/eng/219984.htm

Regards,
-Mahadevan.

Marc de Kruijf wrote:

Can anyone tell me if invoke/unwind is stable in 2.3? I'm seeing some
really weird stuff -- unwinds are ending up in seemingly arbitrary
places...
definitely not inside the caller's unwind block My target is x86.

As a simple test, I tried to compile the following code and I got a
segmentation fault. It looks good to me. Can someone help me out or is
this a bug?

Marc, I tried the exact same example as you did, and got the same issue.

If you look at the generated x86 machine code, it looks like unwind is
compiled into nothing at all:

foo:
.Leh_func_begin1:
  
.Llabel1:
  .size foo, .-foo
.Leh_func_end1:

(Note that there isn't even a return instruction). This means your execution
just falls through into the following function without unwinding its own
stack frame. In the above example, this causes it to fall into main and push
another stack frame for main, over and over again until it runs out of stack
space and segfaults.

I can't find any information about cxa_throw at all, not even a type
signature. If I could, could I just call it as if it were unwind, and it
would be caught by invoke?

The function cxa_throw appears to be in libstdc++ in GCC - I can find it in
the object file, but not the source code documentation. Calling it instead
of the LLVM "unwind" instruction seems like an epically nasty hack; totally
undocumented and platform-specific.

Maybe I'm misunderstanding the unwind instruction. The
http://llvm.org/pubs/2004-01-30-CGO-LLVM.pdf 2004 paper describes
exceptions in some detail. They use some front-end specific code for
allocating the exception (eg. __llvm_cxxeh_throw), but then call unwind to
actually unwind the stack.

Are you saying that you need to do something (like call cxa_throw) in*stead*
of calling unwind, or as well as calling unwind? In other words, if LLVM
didn't have this "bug", should Marc's code work fine, or is there still
something else needed?

This discovery is pretty disappointing ... I've been reading the LLVM
documentation for a few days, and everything I've read led me to believe it
had built-in exception handling. If unwind is supposed to work the way Marc
and I are assuming, but in fact just compiles into nothing, then this really
ought to be documented, and the assembler should give a warning or something
if you use it. As it stands, there's no warning that the unwind instruction
is totally being ignored (which is made particularly nasty because it's
recognised as a block terminator, and therefore it allows successful
compilation even when not followed by a ret instruction, where an empty
statement would not).

In the mean time, can anyone suggest a fix for Marc's dummy example which
works in the current version of LLVM (even if it's platform specific)?

If you look at the generated x86 machine code, it looks like unwind is
compiled into nothing at all:

Yes, unwind is currently not supported by the code generators. This is
bad, but not that easy to fix (hopefully one day...).

I can't find any information about cxa_throw at all, not even a type
signature. If I could, could I just call it as if it were unwind, and it
would be caught by invoke?

cxa_throw comes from the gcc C++ runtime. In order to see how to throw
and catch things correctly using it, compile some C++ examples down to
bitcode using llvm-g++.

This discovery is pretty disappointing ... I've been reading the LLVM
documentation for a few days, and everything I've read led me to believe it
had built-in exception handling. If unwind is supposed to work the way Marc
and I are assuming, but in fact just compiles into nothing, then this really
ought to be documented, and the assembler should give a warning or something
if you use it. As it stands, there's no warning that the unwind instruction
is totally being ignored (which is made particularly nasty because it's
recognised as a block terminator, and therefore it allows successful
compilation even when not followed by a ret instruction, where an empty
statement would not).

The exception handling stuff needed by llvm-gcc is fully supported. Once that
was done I guess everyone took a breather and kind of forgot about unwind :slight_smile:
I agree that it would be better to have the code generators abort if they see an
unwind.

In the mean time, can anyone suggest a fix for Marc's dummy example which
works in the current version of LLVM (even if it's platform specific)?

You currently have to use a gcc library routine. At some point cxa_throw
and the analogous routines for other languages end up calling _Unwind_RaiseException.
You may want to use that along with the C personality __gcc_personality_v0.

Ciao,

Duncan.

Duncan Sands wrote:

I can't find any information about cxa_throw at all, not even a type
signature. If I could, could I just call it as if it were unwind, and it
would be caught by invoke?
    
cxa_throw comes from the gcc C++ runtime. In order to see how to throw
and catch things correctly using it, compile some C++ examples down to
bitcode using llvm-g++.
  

So what about those of us who are implementing frontends that have no connection with gcc or the c++ runtime at all? Are we out of luck as far as unwind is concerned?

-- Talin

Talin wrote:

  
Yes you are :slight_smile: Currently, if you want exceptions using the JIT or static compilation, you need the libgcc runtime (or an equivalent implementation of an unwinding runtime).

Or you can use the interpreter, which works with invoke/unwind.

Cheers,
Nicolas

So what about those of us who are implementing frontends that have no
connection with gcc or the c++ runtime at all? Are we out of luck as far
as unwind is concerned?

For the moment, yes. If unwind gets implemented one day (I have a plan,
but no time right now), the implementation is sure to call routines in
the gcc runtime.

Ciao,

Duncan.

Just for another voice in here. 'unwind' and its kin would also be
useful for me, especially since this is on platforms without GCC (nor
is GCC used in any way in any step anywhere).

Why does it generate GCC only constructs anyway, that does not sound
very much like the multi-platform that LLVM is targeting.

Hi,

Why does it generate GCC only constructs anyway, that does not sound
very much like the multi-platform that LLVM is targeting.

since libgcc is available everywhere llvm is, it's as multi-platform
as llvm! If we didn't use libgcc then we'd have to introduce an llvm
runtime library. Since it would just duplicate the functionality of
libgcc, it would introduce an additional maintenance burden without
bringing any real advantage AFAICS.

Ciao,

Duncan.

As a transient solution that makes sense, but it seems desirable to have
a generalized unwind scheme that is not tied to libgcc.

shap

I guess Duncan's answer in this thread is the best answer to give:

<<Once that [The exception handling stuff needed by llvm-gcc] was done I guess everyone took a breather and kind of forgot about unwind>>

So yes, ultimately, unwind will be supported and clang/llvm should provide its own unwinding runtime.

Patches welcome :slight_smile:

Cheers,
Nicolas

OvermindDL1 wrote:

Duncan Sands wrote:

since libgcc is available everywhere llvm is, it's as multi-platform
as llvm! If we didn't use libgcc then we'd have to introduce an llvm
runtime library. Since it would just duplicate the functionality of
libgcc, it would introduce an additional maintenance burden without
bringing any real advantage AFAICS.

So if there's to be a dependency on libgcc anyway, why not (at least for the
time being) have the unwind instruction simply compile into a call to
__cxa_throw or whatever libgcc-based mechanism you're thinking of. (Surely
there's some boilerplate code to make this work, assuming libgcc is
available?) It would be better than compiling to nothing, as it does now.

(Though maybe I'm not understanding the complexity of what's involved; it
sounds to me like you're just calling a library function).

Thanks for all the helpful responses, devs.

So if there's to be a dependency on libgcc anyway, why not (at least for the
time being) have the unwind instruction simply compile into a call to
__cxa_throw or whatever libgcc-based mechanism you're thinking of. (Surely
there's some boilerplate code to make this work, assuming libgcc is
available?) It would be better than compiling to nothing, as it does now.

Sure, but someone has to sit down and do it.

(Though maybe I'm not understanding the complexity of what's involved; it
sounds to me like you're just calling a library function).

The devil is in the details :slight_smile: For example, the gcc throw routine expects
you to pass it a suitably initialized object. That object has to be
allocated somewhere, which basically means the heap or in a per-cpu global
(can't be on the stack, because the stack is being unwound!). Getting more
complicated already! When unwinding stops you have to free that memory.
However if the landing pad already contains a dwarf exception handler (eg:
you unwound to a C++ handler) that code will already deal with freeing the
memory (the C++ personality does do some handling of "foreign" exceptions
IIRC), so you have to identify "naked" landing pads and insert appropriate
code there. Anyway, it's not the end of the world, just pointing out that
it requires some thinking and work to get a solution that works right and
interacts nicely with the Ada/C++/XYZ exception handling code.

Ciao,

Duncan.

I have tentative plans to bring over a libunwind-based solution to the clang version of "libgcc" when C++ is farther along in clang.

-Chris

Whoops, did not send to list:

Don't know about perf, but I think the standard libgcc should just
work. AFAIK, mingw-gcc uses it.

-Eli

Ok, but, realize that in order to be platform abi compatible with gcc/g++, one _must_ do certain things. If you had a totally different scheme that didn't interoperate with gcc/g++, then, you break the platform abi. If one can throw out such compatibility, then, well, it just doesn't matter.