[LLVMdev] One way to support unwind on x86

Bjarke Walling bwp at bwp.dk
Tue Mar 3 05:27:04 PST 2009


Hi Duncan,

On Tue, Mar 3, 2009 at 10:26 AM, Duncan Sands <baldrick at free.fr> wrote:
> why?  The DWARF EH info encodes two things: (1) how to restore
> registers; and (2) matching rules for exception objects, and
> what to do with them.  You will need something along the lines
> of (1) if you unwind out of the middle of functions.  As for (2),
> if you don't do any matching of exceptions against types, this is
> an extremely minimal amount of info.  In any case, it is entirely
> up to the personality function what happens here - you can always
> write your own.  Check out the C personality function (yes, C not
> C++!) in gcc/unwind-c.c to get an idea of what a small personality
> function looks like.

Yes, I need (1) to restore registers. I don't see why the type
checking can't be done in the landing pad. Yes, it is an overhead, but
not more than interpreting DWARF gives me.

I will look at the C personality function, thank you for that.

> You can link statically with libgcc.

Yes, I know, but I think 50KB is a lot. It's not a microkernel I'm
writing anymore.

Also I don't get the benefits of invoke/unwind. LLVM handles function
inlining with invoke/unwind quite nicely. I'm not sure it can do that
to the same degree with calls to libgcc?

>>  *  Unwinding should be a read-only operation regarding the
>>     stack, so I can create a stack dump in the landing pad.
>
> You can get stack dumps with gcc dwarf eh.  The Ada front-end
> does this for example - very convenient.

Very convenient. Does libgcc provide that too? I like the features of
DWARF, just not the time and space overhead.

> Take a look at libunwind (http://www.hpl.hp.com/research/linux/libunwind/).

I will, thank you.

> Another possibility, very close you yours and currently used by the vmkit
> project, is to modify all functions so they return two values, the usual
> return value and an additional boolean value indicating whether an exception
> was thrown during the call or not.  Callers then branch to an appropriate
> place based on this value.  Thus there is no special stack unwinding, it
> is just functions returning.  This adds some distributed overhead, but
> unwinding is fast.  You can always return something more complicated than
> a boolean of course.

Maybe that's an option. I think I know how to do that already by
writing a LLVM pass. I guess it would be translated to something like
this in machine code:

    call  some_function
    test  ebx, ebx      ; Check second return value
    jz    handle_unwind ; If nessescary handle unwinding

That is a fairly small overhead.

>> My idea on handling the DWARF EH actions is to compile it to machine
>> instructions. Fx. given an Instruction Pointer, unwinding a call frame
>> might be described as [...]
>
> This is a lot like what you get using the "function returns an extra
> boolean" method.

Yes, you're right and it's conceptually easier to handle.

>> Other call frames might be more complex to handle. It depends on the
>> moves needed to restore the registers of the previous call frame (the
>> caller) and to remove the current frame.
>
> If you really plan to unwind out of the middle of functions you will
> have to do magic to restore registers.  Do you plan to use the dwarf
> frame moves info for this?

Yes. The information is available. It is stored as a DWARF virtual
machine (CFA instructions). I "just" need to translate this to machine
instructions. I thought that it would be somewhat easy to hook into
LLVM to get the DWARF instructions it would write and then emit
machine instructions instead.

> If you use the "functions return an
> extra boolean" method then you don't have to do anything, since
> functions return and have registers restored in the usual way.

Yes, I see.

>> I want to tag all calls and invokes in a manner that can be easily
>> recognized by a runtime. I can tolerate a small overhead on calls. The
>> idea is to do something like this [...]
>
> This again looks a lot like the "have functions return an extra boolean"
> method.

Except there's a less overhead on a jmp instruction than test+jz
instructions. Maybe it's worth it. It is definitely easier to
implement than my first idea.

> The vmkit experience is that unwinding using their method is a lot faster
> than using the dwarf unwinder.  I don't know if the distributed overhead
> is noticeable or not.

It can be measured. Maybe I should look at the vmkit code as well.

Bjarke Walling



More information about the llvm-dev mailing list