[LLVMdev] ARM EABI Exceptions

73 views
Skip to first unread message

Renato Golin

unread,
May 17, 2010, 1:02:35 PM5/17/10
to LLVM Developers, Clang Developers
Hi,

I was comparing the way LLVM generates the exception table and it looks
a bit different from what GCC (arm-none-eabi-g++) generates.

Maybe that's because clang is not generating ARM IR when I do:

$ clang -c -emit-llvm -march=arm -mcpu=cortex-a8 -mtriple=arm-none-eabi
exception.cpp -o exception.clang.bc
clang: warning: argument unused during compilation: '-mcpu=cortex-a8'
clang: warning: argument unused during compilation:
'-mtriple=arm-none-eabi'

The IR triple is "x86_64-unknown-linux-gnu". Is there a way I can force
the triple?

Then I compiled with llc:

$ llc -march=arm -mcpu=cortex-a8 -mtriple=arm-none-eabi
exception.clang.ll -o exception.clang.s

It doesn't generate the tables because ARMELFMCAsmInfo doesn't set
ExceptionsType. If I set it to Dwarf and fix the missing lowering
operations (EXCEPTIONADDR and EHSELECTION), it does generate a table
which is slightly different than what GCC is doing.

I've compared the assembly generated and it's close, but not perfect.
Some EABI issues (frame pointer, some intrinsics mismatch, EH call
table) were present, but the general execution flow seems very similar.

If I compile the resulting asm with GCC ("-T generic-hosted.ld") and
run, it breaks completely. GCC's run flawlessly.

Anyone has any idea on the status of exception handling in clang/LLVM?
DwarfException cannot be easily overwritten, and adding target specific
code to it seems wrong...

Attached is my example compiled with Codesourcery's GCC (2009q3) and
clang (2.7).

cheers,
--renato

exception-clang-example.tar.gz

Anton Korobeynikov

unread,
May 17, 2010, 1:38:33 PM5/17/10
to Renato Golin, Clang Developers, LLVM Developers
Hello, Renato

> Anyone has any idea on the status of exception handling in clang/LLVM?
> DwarfException cannot be easily overwritten, and adding target specific
> code to it seems wrong...
Neither llvm-gcc nor clang support exceptions on ARM (except, maybe,
sjlj excheptions on arm/darwin). I have some patched uncommitted for
EH on ARM but they are too far from being complete.

--
With best regards, Anton Korobeynikov
Faculty of Mathematics and Mechanics, Saint Petersburg State University
_______________________________________________
LLVM Developers mailing list
LLV...@cs.uiuc.edu http://llvm.cs.uiuc.edu
http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev

Bill Wendling

unread,
May 17, 2010, 4:23:41 PM5/17/10
to Anton Korobeynikov, LLVM Developers, Clang Developers
On May 17, 2010, at 10:38 AM, Anton Korobeynikov wrote:

> Hello, Renato
>
>> Anyone has any idea on the status of exception handling in clang/LLVM?
>> DwarfException cannot be easily overwritten, and adding target specific
>> code to it seems wrong...
> Neither llvm-gcc nor clang support exceptions on ARM (except, maybe,
> sjlj excheptions on arm/darwin). I have some patched uncommitted for
> EH on ARM but they are too far from being complete.
>
We do support SJLJ exceptions on ARM for Darwin at least.

-bw

Renato Golin

unread,
May 18, 2010, 5:39:53 AM5/18/10
to Anton Korobeynikov, Clang Developers, LLVM Developers
> -----Original Message-----
> From: Anton Korobeynikov [mailto:an...@korobeynikov.info]
>
> Neither llvm-gcc nor clang support exceptions on ARM (except, maybe,
> sjlj excheptions on arm/darwin). I have some patched uncommitted for
> EH on ARM but they are too far from being complete.

Hi Anton,

Are you actively working in that area? I did some experiments and managed to understand how LLVM does the exception handling, but my changes are also far from working.

My main concern is that DwarfException is not extensible at all. I can't inherit from it (DwarfWriter creates it directly) and there are no call backs to target-specific code (nor registration of such mechanism). To change that in line with AsmWriter would be a major change and passing a ARMException reference through AsmWriter would pass the object through many places that are not concerned with it.

A simple registration mechanism (DE->registerTargetCode-thingy) would be the least change and more direct approach, but it's damn ugly. ;)

Apart from that, the format of the table and the calls to intrinsic functions are quite close.

About Sj/Lj exceptions, that's not ARM EHABI compliant. EABI GCC won't compile that, I guess. Not to mention it hampers normal execution...

Thanks,
--renato

-- IMPORTANT NOTICE: The contents of this email and any attachments are confidential and may also be privileged. If you are not the intended recipient, please notify the sender immediately and do not disclose the contents to any other person, use it for any purpose, or store or copy the information in any medium. Thank you.

Anton Korobeynikov

unread,
May 19, 2010, 5:06:54 AM5/19/10
to Renato Golin, Clang Developers, LLVM Developers
Hello, Renato

> Are you actively working in that area?
No, I started to experiment with ARM EH ~year ago, but never had
anything complete, unfortunately

> My main concern is that DwarfException is not extensible at all. I can't inherit from it (DwarfWriter creates it directly) and there are no call backs to target-specific code (nor registration of such mechanism).
Why do you need this? My feeling that this will not be required. I
might be mistaken though.

--
With best regards, Anton Korobeynikov
Faculty of Mathematics and Mechanics, Saint Petersburg State University

Renato Golin

unread,
May 19, 2010, 5:37:41 AM5/19/10
to Anton Korobeynikov, Clang Developers, LLVM Developers
> -----Original Message-----
> > My main concern is that DwarfException is not extensible at all. I
> > can't inherit from it (DwarfWriter creates it directly) and there are
> > no call backs to target-specific code (nor registration of such
> > mechanism).
>
> Why do you need this? My feeling that this will not be required. I
> might be mistaken though.

Hi Anton,

Maybe I'm following the wrong path, then.

When trying to make llc print the EH table for clang-compiled IR, I noticed that there was none. If I turn on the Dwarf exception in ARMMCAsmInfo, I could see a table that looks like GCC's. ARM EHABI tables are quite different and the idea is not to produce them now, but to make clang generated asm/objects to be compiled/linked with arm-none-eabi-gcc.

In that area, I was trying to make LLVM DwarfException more like GCC's, and for that I had to make some changes in the order things appear (the table is inside the function instead of in a new section, thus the size has to appear after the table), and add new things (.fnstart, .fnend, .personality, etc), and make sure all Actions are in conformance with GCC's intrinsics. Also, looks like gcc doesn't produce the CIE nor any of the FDEs, so maybe I have to suppress that as well.

For all those changes, the only place I can implement, AFAIK, is DwarfException. Now, as a local hack, I have added a new ExceptionABI { None, ARM }; enum to MCAsmInfo to if/else inside DwarfException, but that's far from ideal.

I'd like to be able to have with DwarfException the same we have with AsmPrinter, calling target-implemented functions (like EmitFunctionBodyStart, etc), so one could customise the particular differences of a target. But this change is a bit wide-spread, since DwarfWriter will also have to be changed to create a target-specific exception writer rather than the generic one.

But again, maybe the whole thing is pointless, and clang already generates exception tables compatible with eabi-gcc and I was not able to make it work.

Cheers,
--renato

Jim Grosbach

unread,
May 19, 2010, 12:03:20 PM5/19/10
to Renato Golin, LLVM Developers, Clang Developers

On May 19, 2010, at 2:37 AM, Renato Golin wrote:

>> -----Original Message-----
>>> My main concern is that DwarfException is not extensible at all. I
>>> can't inherit from it (DwarfWriter creates it directly) and there are
>>> no call backs to target-specific code (nor registration of such
>>> mechanism).
>>
>> Why do you need this? My feeling that this will not be required. I
>> might be mistaken though.
>
> Hi Anton,
>
> Maybe I'm following the wrong path, then.
>
> When trying to make llc print the EH table for clang-compiled IR, I noticed that there was none. If I turn on the Dwarf exception in ARMMCAsmInfo, I could see a table that looks like GCC's. ARM EHABI tables are quite different and the idea is not to produce them now, but to make clang generated asm/objects to be compiled/linked with arm-none-eabi-gcc.
>
> In that area, I was trying to make LLVM DwarfException more like GCC's, and for that I had to make some changes in the order things appear (the table is inside the function instead of in a new section, thus the size has to appear after the table), and add new things (.fnstart, .fnend, .personality, etc), and make sure all Actions are in conformance with GCC's intrinsics. Also, looks like gcc doesn't produce the CIE nor any of the FDEs, so maybe I have to suppress that as well.
>
> For all those changes, the only place I can implement, AFAIK, is DwarfException. Now, as a local hack, I have added a new ExceptionABI { None, ARM }; enum to MCAsmInfo to if/else inside DwarfException, but that's far from ideal.
>
> I'd like to be able to have with DwarfException the same we have with AsmPrinter, calling target-implemented functions (like EmitFunctionBodyStart, etc), so one could customise the particular differences of a target. But this change is a bit wide-spread, since DwarfWriter will also have to be changed to create a target-specific exception writer rather than the generic one.
>
> But again, maybe the whole thing is pointless, and clang already generates exception tables compatible with eabi-gcc and I was not able to make it work.
>

It's likely there will be some work to get DWARF EH working for ARM. That said, keep in mind that the goal is to get the code to conform to the ABI, not to produce code and tables that look the same as what GCC produces. The former is reasonable, the latter is going to feel like tilting at windmills, as the internal EH representations in gcc are very different than what llvm IR represents. GCC uses a side-table of EH "regions" that it references to determine call sites and such, for example. LLVM doesn't have that concept and uses the invoke instruction instead. One result of this is that the tables that come out often look quite different. So long as they adhere to the spec, though, the code will interoperate correctly.

Regards,
Jim

Renato Golin

unread,
May 19, 2010, 12:49:50 PM5/19/10
to Jim Grosbach, LLVM Developers, Clang Developers
Hi Jim,


> -----Original Message-----
> It's likely there will be some work to get DWARF EH working for ARM.

Tell me about it! ;)


> That said, keep in mind that the goal is to get the code to conform to
> the ABI, not to produce code and tables that look the same as what GCC
> produces.

Absolutely. I'm only trying to get exception handling working on ARM. Right
now, I'm linking with eabi-gcc, and because clang's table is similar, I
thought I could adapt it. Unfortunately, the testability is nil and the end
goal is not good, so the task is probably not worth it.


> The former is reasonable, the latter is going to feel like
> tilting at windmills, as the internal EH representations in gcc are
> very different than what llvm IR represents. GCC uses a side-table of
> EH "regions" that it references to determine call sites and such, for
> example. LLVM doesn't have that concept and uses the invoke instruction
> instead. One result of this is that the tables that come out often look
> quite different.

As I gathered, the invoke calls were populating the call site table, similar
to the .LEH regions GCC does, and the call site table of both look quite
similar, to me. I noticed more differences around the call table, for
instance, the headers, the type info actions and the relocation information.

Also, the normal flow (try/catch blocks, with cleanup regions and intrinsic
calls) didn't seem that different.


> So long as they adhere to the spec, though, the code
> will interoperate correctly.

The spec is quite vague when expressing the personality routines, AFAICT.

If the tables are different, when you link code compiled with Clang and GCC,
both using the same personality routine (GCC's or Clang's, but not both),
how do you expect them to work together?

Nevertheless, I digress. I may have started it the wrong way, but my
immediate goal is to compile a simple exception example to ARM. Do you know
a better path?

Cheers,
--renato

Anton Korobeynikov

unread,
May 19, 2010, 1:31:06 PM5/19/10
to renato...@arm.com, Clang Developers, LLVM Developers
Hello, Renato

> If the tables are different, when you link code compiled with Clang and GCC,
> both using the same personality routine (GCC's or Clang's, but not both),
> how do you expect them to work together?
Because both tables are "standard" ?

> Nevertheless, I digress. I may have started it the wrong way, but my
> immediate goal is to compile a simple exception example to ARM. Do you know
> a better path?
Here is how EH was implemented first for x86:
1. LLVM was made to emit tables for some "easy" examples, this
involves some low-level stuff like register moves, encoding, etc. At
this point one can use LLVM-generated .s files with gcc-provided
unwinding library.
2. Necessary EH intrinsics was implemented
3. More refinements (PIC mode, etc.)

--
With best regards, Anton Korobeynikov
Faculty of Mathematics and Mechanics, Saint Petersburg State University

Renato Golin

unread,
May 20, 2010, 4:55:49 AM5/20/10
to Anton Korobeynikov, Clang Developers, LLVM Developers
Hi Anton,

> Because both tables are "standard" ?

Ok, we're in different pages, I think.

I trust that LLVM is binary compatible with GCC, including the exception tables, for x86. What I was referring to is about the LLVM's x86 EH table compatibility with ARM GCC's personality routine.

I'm not an expert in exception handling, so I don't know all the idiosyncrasies of both standards, but I guessed that hoping ARM PRs to understand x86 tables was a bit too far. As far as I read and dug, both standards are very similar, but I can't yet guarantee that all PRs will read all tables, not without spending months reading and testing every combination.


> Here is how EH was implemented first for x86:
> 1. LLVM was made to emit tables for some "easy" examples, this
> involves some low-level stuff like register moves, encoding, etc. At
> this point one can use LLVM-generated .s files with gcc-provided
> unwinding library.

That's my road...

Just by turning on Dwarf debugging and lowering exception address and selection, I could get an ARM assembly with the default exception table. I've investigated the assembly code and it seems that clang is preparing the intrinsics the same way arm-gcc does, which is good.

Up until __cxa_throw, everything is fine. The parameters are the same, in the same registers and the table header is similar. The failures come when getting into __cxa_begin_catch, when the PR recognizes the type thrown ('int') but still calls terminate. I'm guessing the action table is different, but there is no documentation on neither LLVM nor GCC intrinsics I could find.

Does LLVM have implementations of __cxa_* intrinsics? If so, where are they?


> 2. Necessary EH intrinsics was implemented
> 3. More refinements (PIC mode, etc.)

I didn't want to go that far, for now.

Cheers,
--renato
Reply all
Reply to author
Forward
0 new messages