ARM EABI Exceptions

classic Classic list List threaded Threaded
20 messages Options
Reply | Threaded
Open this post in threaded view
|

ARM EABI Exceptions

Renato Golin-3
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


_______________________________________________
cfe-dev mailing list
[hidden email]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-dev

exception-clang-example.tar.gz (12K) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: [LLVMdev] ARM EABI Exceptions

Anton Korobeynikov
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
_______________________________________________
cfe-dev mailing list
[hidden email]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-dev
Reply | Threaded
Open this post in threaded view
|

Re: [LLVMdev] ARM EABI Exceptions

Bill Wendling
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

_______________________________________________
cfe-dev mailing list
[hidden email]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-dev
Reply | Threaded
Open this post in threaded view
|

Re: [LLVMdev] ARM EABI Exceptions

Renato Golin-3
In reply to this post by Anton Korobeynikov
> -----Original Message-----
> From: Anton Korobeynikov [mailto:[hidden email]]
>
> 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.

_______________________________________________
cfe-dev mailing list
[hidden email]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-dev
Reply | Threaded
Open this post in threaded view
|

Re: [LLVMdev] ARM EABI Exceptions

Anton Korobeynikov
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
_______________________________________________
cfe-dev mailing list
[hidden email]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-dev
Reply | Threaded
Open this post in threaded view
|

Re: [LLVMdev] ARM EABI Exceptions

Renato Golin-3
> -----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



_______________________________________________
cfe-dev mailing list
[hidden email]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-dev
Reply | Threaded
Open this post in threaded view
|

Re: [LLVMdev] ARM EABI Exceptions

Jim Grosbach
In reply to this post by Anton Korobeynikov

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
_______________________________________________
cfe-dev mailing list
[hidden email]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-dev
Reply | Threaded
Open this post in threaded view
|

Re: [LLVMdev] ARM EABI Exceptions

Renato Golin-3
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



_______________________________________________
cfe-dev mailing list
[hidden email]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-dev
Reply | Threaded
Open this post in threaded view
|

Re: [LLVMdev] ARM EABI Exceptions

Anton Korobeynikov
In reply to this post by Jim Grosbach
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
_______________________________________________
cfe-dev mailing list
[hidden email]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-dev
Reply | Threaded
Open this post in threaded view
|

Re: [LLVMdev] ARM EABI Exceptions

Renato Golin-3
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



_______________________________________________
cfe-dev mailing list
[hidden email]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-dev
Reply | Threaded
Open this post in threaded view
|

Re: [LLVMdev] ARM EABI Exceptions

Duncan Sands
Hi Renato,

> 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.

if you compile with -fverbose-asm you should get some helpful comments in the
action table.  You could also send the tables to the mailing list.

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

These aren't intrinsics, they are C++ standard library functions.

Ciao,

Duncan.
_______________________________________________
cfe-dev mailing list
[hidden email]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-dev
Reply | Threaded
Open this post in threaded view
|

Re: [LLVMdev] ARM EABI Exceptions

Renato Golin-3
Hi Duncan,

> if you compile with -fverbose-asm you should get some helpful comments
> in the
> action table.

I can't compile directly with clang, I need first to generate IR than use
LLC to generate the assembly. LLC doesn't accept that option. :(

I don't know why, but my changes only took effect on LLC, maybe I'm doing
something wrong when compiling clang...


> You could also send the tables to the mailing list.

I did, my first post. Attached again, just in case.


> These aren't intrinsics, they are C++ standard library functions.

Sorry, you're right.

Cheers,
--renato

_______________________________________________
cfe-dev mailing list
[hidden email]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-dev

ehabi.zip (10K) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: [LLVMdev] ARM EABI Exceptions

Duncan Sands
Hi Renato,

>> if you compile with -fverbose-asm you should get some helpful comments
>> in the
>> action table.
>
> I can't compile directly with clang, I need first to generate IR than use
> LLC to generate the assembly. LLC doesn't accept that option. :(

in llc it's called -asm-verbose

> I did, my first post. Attached again, just in case.

OK, I may have time to take a look later.

Best wishes,

Duncan.
_______________________________________________
cfe-dev mailing list
[hidden email]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-dev
Reply | Threaded
Open this post in threaded view
|

Re: [LLVMdev] ARM EABI Exceptions

Renato Golin-3
> -----Original Message-----
> in llc it's called -asm-verbose

Hi Duncan,

Didn't make any difference, I think the asm was already quite verbose... ;)


> OK, I may have time to take a look later.

Thanks, I'll be digging it a bit more these days.

Cheers,
--renato


_______________________________________________
cfe-dev mailing list
[hidden email]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-dev
Reply | Threaded
Open this post in threaded view
|

Re: [LLVMdev] ARM EABI Exceptions

Bill Wendling
In reply to this post by Duncan Sands
On May 20, 2010, at 2:34 AM, Renato Golin wrote:

> Hi Duncan,
>
>> if you compile with -fverbose-asm you should get some helpful comments
>> in the
>> action table.
>
> I can't compile directly with clang, I need first to generate IR than use
> LLC to generate the assembly. LLC doesn't accept that option. :(
>
> I don't know why, but my changes only took effect on LLC, maybe I'm doing
> something wrong when compiling clang...
>
>
>> You could also send the tables to the mailing list.
>
> I did, my first post. Attached again, just in case.
>
>
>> These aren't intrinsics, they are C++ standard library functions.
>
> Sorry, you're right.
>
Hi Renato,

I looked at the .s file you sent. We end up at the throw here:

.Ltmp9:
        ldr     r1, .LCPI1_2
        bl      __cxa_throw
.Ltmp10:


This has an action table of:

        .long   .Ltmp9-.Leh_func_begin1 @ Region start
        .long   .Ltmp10-.Ltmp9          @ Region length
        .long   .Ltmp11-.Leh_func_begin1 @ Landing pad
        .uleb128        3               @ Action

The action record is this:

        .sleb128        1               @   TypeInfo index
        .sleb128        0               @   Next action

(Here are the type infos

        .long   _ZTIc                   @ TypeInfo
        .long   _ZTIi                   @ TypeInfo
        .long   0                       @ TypeInfo
)

So the landing pad is a "catch-all", which is how LLVM does things (*mutter*guh*mutter*). That falls into here:

.Ltmp14:
        bl      _Unwind_Resume_or_Rethrow
.Ltmp15:

Which has an action table of:

        .long   .Ltmp14-.Leh_func_begin1 @ Region start
        .long   .Ltmp15-.Ltmp14         @ Region length
        .long   .Ltmp21-.Leh_func_begin1 @ Landing pad
        .uleb128        7               @ Action

And action record:

        .sleb128        3               @   TypeInfo index
        .sleb128        -3              @   Next action

So it'll try to catch a character type. If it can't, then it tries this action record:

        .sleb128        2               @   TypeInfo index
        .sleb128        -3              @   Next action

Which is an integer type. It should catch this, so it should go to the landing pad .Ltmp21. It should make its way to this lump of code:

.LBB1_20:                               @ %catch.next
        cmp     r1, #2
        bne     .LBB1_27
@ BB#21:                                @ %match27
        mov     r0, r4
        bl      __cxa_begin_catch
        ldr     r1, [r0]
        str     r1, [sp, #8]

And eventually the __cxa_end_catch here:

.LBB1_25:                               @ %match.end38
.Ltmp30:
        bl      __cxa_end_catch
.Ltmp31:

Is this the behavior you're seeing?

-bw


_______________________________________________
cfe-dev mailing list
[hidden email]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-dev
Reply | Threaded
Open this post in threaded view
|

Re: [LLVMdev] ARM EABI Exceptions

Duncan Sands
Hi Bill,

> So the landing pad is a "catch-all", which is how LLVM does things (*mutter*guh*mutter*). That falls into here:
>
> .Ltmp14:
>          bl      _Unwind_Resume_or_Rethrow

gcc uses __cxa_end_cleanup rather than _Unwind_Resume when using the ARM EABI.
I think Anton is quite right to advise Renato to use llvm-gcc rather than clang,
since it should output the correct thing here.

Ciao,

Duncan.
_______________________________________________
cfe-dev mailing list
[hidden email]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-dev
Reply | Threaded
Open this post in threaded view
|

Re: [LLVMdev] ARM EABI Exceptions

Bill Wendling
On May 20, 2010, at 12:09 PM, Duncan Sands wrote:

> Hi Bill,
>
>> So the landing pad is a "catch-all", which is how LLVM does things (*mutter*guh*mutter*). That falls into here:
>>
>> .Ltmp14:
>>         bl      _Unwind_Resume_or_Rethrow
>
> gcc uses __cxa_end_cleanup rather than _Unwind_Resume when using the ARM EABI.
> I think Anton is quite right to advise Renato to use llvm-gcc rather than clang,
> since it should output the correct thing here.
>
Sounds like a good plan. You should file a PR against clang about this.

-bw



_______________________________________________
cfe-dev mailing list
[hidden email]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-dev
Reply | Threaded
Open this post in threaded view
|

Re: [LLVMdev] ARM EABI Exceptions

Duncan Sands
>> gcc uses __cxa_end_cleanup rather than _Unwind_Resume when using the ARM EABI.
>> I think Anton is quite right to advise Renato to use llvm-gcc rather than clang,
>> since it should output the correct thing here.
>>
> Sounds like a good plan. You should file a PR against clang about this.

You can also file a PR against dragonegg - I was too lazy to handle the ARM case
there :)  OK, it doesn't support ARM yet, but still!

Ciao,

Duncan.
_______________________________________________
cfe-dev mailing list
[hidden email]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-dev
Reply | Threaded
Open this post in threaded view
|

Re: [LLVMdev] ARM EABI Exceptions

Renato Golin-3
In reply to this post by Bill Wendling
> Is this the behavior you're seeing?

Hi Bill,

The ASM file is perfectly correct. I have compiled both asm files with
eabi-gcc and got very similar tables, including using the EHABI compact mode
for personality routines (generated by eabi-gcc).

But there was one difference in the handler's list (one less entry, the
first one), which agrees with the fact that the code is failing in the
_Unwind_RaiseException while searching for the throw action
(search_EIT_table in gcc).

I think it's something in Clang's code that should take into account that
the table will be converted into an ARM EHABI format, that doesn't affect
x86 codegen. My intent if to fix it.

Thanks!
--renato


_______________________________________________
cfe-dev mailing list
[hidden email]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-dev
Reply | Threaded
Open this post in threaded view
|

Re: [LLVMdev] ARM EABI Exceptions

Renato Golin-3
In reply to this post by Bill Wendling
> Sounds like a good plan. You should file a PR against clang about this.

I've created a bug against clang:

http://llvm.org/bugs/show_bug.cgi?id=7187

And linked this conversation. Any new information/progress I'll ad to the
bug, so if you're interested, please follow the bug.

Cheers,
--renato


_______________________________________________
cfe-dev mailing list
[hidden email]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-dev