[LLVMdev] One way to support unwind on x86

Bjarke Walling bwp at bwp.dk
Tue Mar 3 05:26:16 PST 2009


Hello Anton,

On Tue, Mar 3, 2009 at 10:23 AM, Anton Korobeynikov
<anton at korobeynikov.info> wrote:
> Are you familiar with C++ EH? How would you handle catches? Cleanups?

I guess I'm not familiar with C++ EH in details. Maybe I'm begin
naive, but I think exceptions doesn't have to be that complex.

When compiling C++ the front-end inserts a llvm.eh.selector intrinsic
in the landing pad. It references the types you want to catch and a
personality routine. If you use this intrinsic the type information is
added to the DWARF .eh_frame section. The unwind runtime knows how to
handle the actions described in this section. It is sort of a virtual
machine, if I understand it correctly. The instructions and their
semantics are described in the DWARF specification. The unwind runtime
execute these instructions, unwinding frames and call the personality
routine when it reaches a catch block to ask whether the catch block
can handle this exception.

I read the LLVM documentation on exceptions and regarding C++ cleanups
it sounds a bit more complicated. I would have to find out how exactly
libgcc, the DWARF actions and the personality routine plays together.

I know DWARF was made to provide a platform-independant way to add
debugging information. That is why they made a virtual machine for
stack unwinding. If you have a compiled C++ program you have DWARF
actions and a personality routine that is not going to change. If you
don't care about being ABI compliant, then you could compile this
virtual machine and all its actions to native machine code.

> The idea looks sane. But only for 'basic' unwind. Otherwise you'll end
> with rewriting libgcc unwind runtime.
> Also, how

Maybe so. What is 'basic' unwind? Maybe I shouldn't focus on C++ for
now, but just about supporting invoke/unwind. If I don't use the
llvm.eh.exception and llvm.eh.selector intrinsics, then the landing
pad of an invoke becomes a catch-all. The landing pad code can check
whether it accepts the exception stored as a pointer in a thread-local
store. If it doesn't support the exception it unwind's again. I still
need to handle stack unwinding, but the information is already there.
It is written in .eh_frame and .gcc_except_table. What I want to do is
translating this information, the actions, to native machine code for
great efficiency.

> EH is complex. For C++ EH you will need to have a frontend support.
> Actually, calls to libgcc unwinding runtime is inserted by frontend.
> Backend is only responsible for emission of codegen-time information.
> So, if you're planning to hack on C++ EH somehow, you will need to
> hack on frontend as well.

I think you're right I shouldn't focus on C++. It has quite
complicated and featureful exception handling. I guess the real pain
is multiple inheritance.

> Have you looked into libunwind? Maybe it will be easy to hook it into
> llvm somehow?

I will look at that, thank you.

I haven't timed the unwinding proces yet, but I want to do: How many
clock cycles does it take to handle various types of try/catch +
throw. I don't think libgcc is very efficient, but I can't be sure
before I measure it. Also adding 50KB to your executable is a lot in
my opinion. It is about 13000 machine instructions (I measured that).

Bjarke Walling



More information about the llvm-dev mailing list