Unwind behaviour in Clang/LLVM

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
38 messages Options
12
Reply | Threaded
Open this post in threaded view
|

Unwind behaviour in Clang/LLVM

Renato Golin-2
Folks,

We're having some discussions about the behaviour of exception handling and Dwarf sharing unwind logic, tables, etc. and it seems that the code around it wasn't designed with any particular goal in mind, but evolved (like the EHABI) and now we're seeing the results from it. 

The problems below are assuming C vs. C++, but it actually apply to any possibly-exceptional vs. never-exceptional cases.


1. C vs. C++

We have two unwind flags: nounwind, which flags functions that can't unwind (leaf, nothrow, etc) and uwtable, which forces generation of the table regardless of nounwind. It seems sensible that C++ code with exceptions enabled should generate the tables for all functions, in case they're called by (or call) external functions. In C we don't want any of that.

GCC seems to never emit tables, and G++ always do, even on C code (.c files, no exception or anything), which is very sensible and in line with my reasoning above. Clang, on the other hand, always generates them. I guess it'll have to figure out what to do based on its impressions on what language is being used to produce similar results.

I believe that emitting the tables on anything that could potentially interact with exceptional code makes sense, but that's clearly a front-end decision. To LLVM, nounwind and uwtables should be absolute:

IF (uwtables)
  IF (nownwind)
    CantUnwind
  ELSE
    Unwind Table
ELSE
  do nothing
ENDIF


2. .fnstart/.fnend+friends

Another problem is that the emission of unwinding tables (based on .fnstart/.fnend symbols and others) is conditional *only* to the existence (or not) of an exception handling class being loaded (EHABI, Dwarf). Which means that, we can't disable the EH on a per-function basis.

We'll have to change the way these symbols are emitted, at least when using ARMException, so that we can emit the tables and honour the uwtable on a per-function basis.

Again, this is a requirement for problem 1, but it'd need to be fixed after 3.


3. Unwinding code

Currently, even when no exception handling are needed, the exception code is used to generate Dwarf unwinding directives (CFI) for the debugger.

Both DwarfCFIException and ARMException inherit from DwarfException, and they are called to do the debug info about the stack unwinding, which is (at least) misplaced. The consensus is that this code should be factored out.

The part that is relevant to this thread is that, today, if -arm-disable-ehabi is requested, ARMException will not be used and we won't have a way of generating debug stack directives, which is wrong.

Factoring out this code is a requirement for the unwinding problem (1), since if we disable EH today, we'll disable Dwarf stack unwinding altogether. But we also need a final solution for problem 4 below before we start.


4. Clang EH control

There are a number of Clang/LLVM options to control exception handling:
 * -fno-excetpion (enable/disable EH on C++ mode, off in C mode)
 * -fcxx-exception (no idea, is it objC++ specific? does it control tables in any way?)
 * -funwind-tables (forces uwtable attribute?)
 * -arm-disable-ehabi (ARM specific bogus flag)

Those options are not always completely exclusive, and they damage different parts of the compilation process (as seen recently on the list), so we need a clear consensus on what each option mean (or should mean), and translate it to the back-end (via function attributes). This would considerably simplify the back-end and help us tackle this refactoring.

My main target for this problem is to have the one true option on the front-ends, and rely only on function attributes on the back-end (including tools like llc). For that, I'd love to be left with -fexception only and infer all the rest from the language / conditions of the code.

Ex:

IF (C++ mode)
  IF (-fno-exception)
    no uwtable
    no nounwind
  ELSE
    uwtable
    IF (leaf / nothrow)
      nounwind
    ENDIF
  ENDIF
ELSE
  no uwtable
  no nounwind
ENDIF

My main goal is to get rid of (at least) -arm-disable-ehabi.



Finally,

If you got this far, you're *really* interested in making the exception handling more user/dev friendly in LLVM, so I welcome any critics about the "proposal" above, as well as any explanations of the doubts expressed. I may be wrong about many things, feel free to enlighten me! We may have a lot less work to do, and I'll be happy. ;)

I believe the dependency graph of the solutions are:

4 -> 3 -> 2 -> 1

So, we first should solve the flags problem, than refactor the unwinding code out of EH, make the debug generation use them as well, and then we can start with the EH specific changes. The problem is that 4 will change things considerably, so we might need some scaffolding during the whole process.

Makes sense?

cheers,
--renato


_______________________________________________
LLVM Developers mailing list
[hidden email]         http://llvm.cs.uiuc.edu
http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev
Reply | Threaded
Open this post in threaded view
|

Re: [cfe-dev] Unwind behaviour in Clang/LLVM

Joerg Sonnenberger
On Thu, Feb 06, 2014 at 01:29:43PM +0000, Renato Golin wrote:
> We have two unwind flags: nounwind, which flags functions that can't unwind
> (leaf, nothrow, etc) and uwtable, which forces generation of the table
> regardless of nounwind. It seems sensible that C++ code with exceptions
> enabled should generate the tables for all functions, in case they're
> called by (or call) external functions. In C we don't want any of that.

This is not true. Even for nounwind, you want to get basic tables so
that backtrace(3) works.

Joerg
_______________________________________________
LLVM Developers mailing list
[hidden email]         http://llvm.cs.uiuc.edu
http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev
Reply | Threaded
Open this post in threaded view
|

Re: [cfe-dev] Unwind behaviour in Clang/LLVM

Renato Golin-2
On 6 February 2014 13:59, Joerg Sonnenberger <[hidden email]> wrote:
This is not true. Even for nounwind, you want to get basic tables so
that backtrace(3) works.

Hi Joerg,

It's a matter of consensus, I believe. Is it the general consensus that we will *always* want unwind tables to exist? Code size is a clear reason to not want unwind tables at all, but there might not be many more. If the general consensus is that unwind tables are a must, and should only be turned off in special cases, then we just keep emitting them and create (or reuse) a flag to stop it. If not, language / flags decision (-fexception, -g, profiling, etc) should turn them on. However, if every one agrees that, no matter what, we *will* emit unwind tables, than the whole argument is moot, and there is absolutely nothing to "fix" besides removing -arm-disable-ehabi.

cheers,
--renato

_______________________________________________
LLVM Developers mailing list
[hidden email]         http://llvm.cs.uiuc.edu
http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev
Reply | Threaded
Open this post in threaded view
|

Re: [cfe-dev] Unwind behaviour in Clang/LLVM

Joerg Sonnenberger
On Thu, Feb 06, 2014 at 02:30:11PM +0000, Renato Golin wrote:

> On 6 February 2014 13:59, Joerg Sonnenberger <[hidden email]>wrote:
>
> > This is not true. Even for nounwind, you want to get basic tables so
> > that backtrace(3) works.
> >
>
> Hi Joerg,
>
> It's a matter of consensus, I believe. Is it the general consensus that we
> will *always* want unwind tables to exist? Code size is a clear reason to
> not want unwind tables at all, but there might not be many more. If the
> general consensus is that unwind tables are a must, and should only be
> turned off in special cases, then we just keep emitting them and create (or
> reuse) a flag to stop it. If not, language / flags decision (-fexception,
> -g, profiling, etc) should turn them on. However, if every one agrees that,
> no matter what, we *will* emit unwind tables, than the whole argument is
> moot, and there is absolutely nothing to "fix" besides removing
> -arm-disable-ehabi.

My point is that there are two different questions here:

(1) Should enough unwind data be provided for a basic, read-only stack
walk?

(2) Should landing pads etc. be provided for exception handling.

The second implies the first, but not the other way around. Some
platforms require (1), e.g. AMD64. Debugging in any form is certainly a
lot more difficult without. Binary size (not so much code size itself)
increases a bit, but typically in the 1-2 per cent range. For NetBSD we
are moving to always creating .eh_frame on all platforms as default,
because the troubleshooting help justifies the price.

That said, the option already exists for changing the default:
-funwind-tables. There shouldn't be another ARM specific flag. I can't
say what the best default is.

Joerg
_______________________________________________
LLVM Developers mailing list
[hidden email]         http://llvm.cs.uiuc.edu
http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev
Reply | Threaded
Open this post in threaded view
|

Re: [cfe-dev] Unwind behaviour in Clang/LLVM

Renato Golin-2
Hi Joerg,

You are right, there are three separate issues here: unwinding, debug info and exception handling.

Debug and EH require unwinding, but one doesn't require the other and unwinding is not exclusive to either.


On 6 February 2014 14:51, Joerg Sonnenberger <[hidden email]> wrote:
(1) Should enough unwind data be provided for a basic, read-only stack
walk?

As you said, platforms and systems should define their own defaults, and that's mainly driven by the front-end via flags and triples.

The behaviour of flags should be precise, and different flags should be on/off by default depending on the triple, so build systems can enforce flags if they need to make sure the behaviour will be the same across different platforms.

I can't decide that, but those decisions should stay in the front-end. To the back-end, function attributes should be able to control table emission (or maybe we need flags, I don't know).

 
That said, the option already exists for changing the default:
-funwind-tables. There shouldn't be another ARM specific flag.

So, can I assume that -f{no-}unwind-tables's syntax is to completely enable/disable the unwind tables and add/remove the ELF sections from the objects? If that's so, I can easily remove -arm-disable-ehabi and check on that flag.

thanks,
--renato



_______________________________________________
LLVM Developers mailing list
[hidden email]         http://llvm.cs.uiuc.edu
http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev
Reply | Threaded
Open this post in threaded view
|

Re: [cfe-dev] Unwind behaviour in Clang/LLVM

Joerg Sonnenberger
On Thu, Feb 06, 2014 at 03:18:02PM +0000, Renato Golin wrote:
> Debug and EH require unwinding, but one doesn't require the other and
> unwinding is not exclusive to either.

Correct.

> I can't decide that, but those decisions should stay in the front-end. To
> the back-end, function attributes should be able to control table emission
> (or maybe we need flags, I don't know).

I disagree on this. Table emission by itself doesn't involve code
generation and I don't think it makes sense as a per function attribute
either. You either want it for all functions or only when needed (e.g.
exceptions are possible). As such, it makes perfect sense to me as a
global flag.

> > That said, the option already exists for changing the default:
> > -funwind-tables. There shouldn't be another ARM specific flag.
> >
>
> So, can I assume that -f{no-}unwind-tables's syntax is to completely
> enable/disable the unwind tables and add/remove the ELF sections from the
> objects? If that's so, I can easily remove -arm-disable-ehabi and check on
> that flag.

-funwind-tables says that the tables should always be emitted. If there
are no other reasons like exception handling, they will only destructive
stack unwind.

-fno-unwind-tables says that tables should only be emitted, if another
(language specific) reason requires them. So for C++, it would normally
be ignored as exception support is the default. For C code, it would
ensure that no .eh_frame* sections are emitted, even on platforms that
require them for the ABI like AMD64.

Joerg
_______________________________________________
LLVM Developers mailing list
[hidden email]         http://llvm.cs.uiuc.edu
http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev
Reply | Threaded
Open this post in threaded view
|

Re: Unwind behaviour in Clang/LLVM

Keith Walker
In reply to this post by Renato Golin-2
> From: Renato Golin [mailto:[hidden email]]
>
> We're having some discussions about the behaviour of exception handling and Dwarf
> sharing unwind logic, tables, etc. and it seems that the code around it wasn't
> designed with any particular goal in mind, but evolved (like the EHABI) and now
> we're seeing the results from it.
>
> The problems below are assuming C vs. C++, but it actually apply to any possibly-exceptional
> vs. never-exceptional cases.
>
>
> 1. C vs. C++
>
> We have two unwind flags: nounwind, which flags functions that can't unwind (leaf,
> nothrow, etc) and uwtable, which forces generation of the table regardless of
> nounwind. It seems sensible that C++ code with exceptions enabled should generate
> the tables for all functions, in case they're called by (or call) external functions.
> In C we don't want any of that.
>
> GCC seems to never emit tables, and G++ always do, even on C code (.c files,
> no exception or anything), which is very sensible and in line with my reasoning above.
> Clang, on the other hand, always generates them. I guess it'll have to figure out what
> to do based on its impressions on what language is being used to produce similar results.

You can make GCC emit unwind tables for C if you use the command line option -funwind-tables.

This could be useful if you are compiling C code which is called by C++ code and which itself calls C++ code and you wish the C++ exception to propagate through the C code.

> I believe that emitting the tables on anything that could potentially interact
> with exceptional code makes sense, but that's clearly a front-end decision.
> To LLVM, nounwind and uwtables should be absolute:

> IF (uwtables)
>  IF (nownwind)
>    CantUnwind
>  ELSE
>    Unwind Table
> ELSE
>   do nothing
> ENDIF

This certainly appears to me a sensible sequence of decision.

> 2. .fnstart/.fnend+friends
>
> Another problem is that the emission of unwinding tables (based on
> .fnstart/.fnend symbols and others) is conditional *only* to the existence
> (or not) of an exception handling class being loaded (EHABI, Dwarf). Which
> means that, we can't disable the EH on a per-function basis.
>
> We'll have to change the way these symbols are emitted, at least when using
> ARMException, so that we can emit the tables and honour the uwtable on a per-function basis.
>
> Again, this is a requirement for problem 1, but it'd need to be fixed after 3.
>
>
> 3. Unwinding code
>
> Currently, even when no exception handling are needed, the exception code is
> used to generate Dwarf unwinding directives (CFI) for the debugger.

This is because the 2 are so similar.

> Both DwarfCFIException and ARMException inherit from DwarfException, and they
> are called to do the debug info about the stack unwinding, which is (at least)
> misplaced. The consensus is that this code should be factored out.

There is some interaction in that if you are generating a .eh_frame section for exception handling then there is little sense is generating a DWARF .debug_frame section as well;  I would hope most debuggers could use the .eh_frame section if present as its format is so similar to a .debug_frame section.

> The part that is relevant to this thread is that, today, if -arm-disable-ehabi
> is requested, ARMException will not be used and we won't have a way of
> generating debug stack directives, which is wrong.

What does -arm-disable-ehabi actually mean?

Currently it is effectively "don't generate exception tables".

Maybe is should it rather be "don't generate EHABI exception tables but generate .eh_frame tables instead"?   Obviously this requires the necessary DWARF like support to generate the information for the .eh_frame tables.

> Factoring out this code is a requirement for the unwinding problem (1), since
> if we disable EH today, we'll disable Dwarf stack unwinding altogether. But we
> also need a final solution for problem 4 below before we start.

I think the solution depends on what we mean when we specify -arm-disable-ehabi ... is it

 IF(arm_disable_ehabi)
   USE ARMException
 ELSE
   USE DwarfCFiNoException   <---- Just generates DWARF debugging information
 ENDIF

Or is it

 IF(arm_disable_ehabi)
   USE ARMException
 ELSE
   USE DwarfCFIException
 ENDIF

> 4. Clang EH control
>
> There are a number of Clang/LLVM options to control exception handling:
>  * -fno-excetpion (enable/disable EH on C++ mode, off in C mode)
>  * -fcxx-exception (no idea, is it objC++ specific? does it control tables in any way?)
>  * -funwind-tables (forces uwtable attribute?)
>  * -arm-disable-ehabi (ARM specific bogus flag)
>
> Those options are not always completely exclusive, and they damage different
> parts of the compilation process (as seen recently on the list), so we need
> a clear consensus on what each option mean (or should mean), and translate it
> to the back-end (via function attributes). This would considerably simplify
> the back-end and help us tackle this refactoring.
>
> My main target for this problem is to have the one true option on the front-ends,
> and rely only on function attributes on the back-end (including tools like llc).
> For that, I'd love to be left with -fexception only and infer all the rest from
> the language / conditions of the code.
>
> Ex:
>
> IF (C++ mode)
>   IF (-fno-exception)
>     no uwtable
>     no nounwind
>   ELSE
>     uwtable
>     IF (leaf / nothrow)
>       nounwind
>     ENDIF
>   ENDIF
> ELSE
>   no uwtable
>   no nounwind
> ENDIF
>
> My main goal is to get rid of (at least) -arm-disable-ehabi.

Hmmm!   I'm very nervous about the backend making decisions based on the language.

As I mentioned above I also wonder if you do still need to support -funwind-tables for compiling C code through which you wish to allow exceptions to propogate.

In which case the logic is more like ....

  IF (-funwind-tables || -fexceptions)
    uwtable
    IF (leaf / nothrow)
      nounwind
    ENDIF
  ELSE
    no uwtable
    no nounwind
  ENDIF

The main difference I see between -fexceptions and -funwind-tables is:

-fexceptions allows compiling exception handling constructs in the source language and enables the generation of unwind tables.
-funwind-tables only enables the generation of unwind tables.

Keith



Keith


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

ARM Limited, Registered office 110 Fulbourn Road, Cambridge CB1 9NJ, Registered in England & Wales, Company No:  2557590
ARM Holdings plc, Registered office 110 Fulbourn Road, Cambridge CB1 9NJ, Registered in England & Wales, Company No:  2548782


_______________________________________________
LLVM Developers mailing list
[hidden email]         http://llvm.cs.uiuc.edu
http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev
Reply | Threaded
Open this post in threaded view
|

Re: Unwind behaviour in Clang/LLVM

Renato Golin-2
On 6 February 2014 18:02, Keith Walker <[hidden email]> wrote:
You can make GCC emit unwind tables for C if you use the command line option -funwind-tables.

This could be useful if you are compiling C code which is called by C++ code and which itself calls C++ code and you wish the C++ exception to propagate through the C code.

Yes, we still need the possibility to force unwind tables in C code, and that's what -funwind-tables is there for.

Since -fexception only triggers landing pads and cleanup blocks, we don't need to worry about it, but the -funwind-tables should communicate with the back-end via some clear and unambiguous means.

Maybe function attributes aren't enough, but we need to make sure that they don't clash with the flags, if we do use them.


There is some interaction in that if you are generating a .eh_frame section for exception handling then there is little sense is generating a DWARF .debug_frame section as well;  I would hope most debuggers could use the .eh_frame section if present as its format is so similar to a .debug_frame section.

Right, makes sense.

It seems, then, that we basically need two types of unwinding, and they could live in different places. 

Before your patch, the debugger wasn't able to use the EHABI stack unwinding code. Is that because it was using .push/.save instead of .cfi directives? Or is that because the table generated is not readable by normal debuggers?


What does -arm-disable-ehabi actually mean?

Currently it is effectively "don't generate exception tables".

Yes. It has no effect on the front-end. It should actually be replaced by whatever mechanism -f{no-}unwind-tables is using.

I created a bug (PR18758) and copied you.


Maybe is should it rather be "don't generate EHABI exception tables but generate .eh_frame tables instead"?   Obviously this requires the necessary DWARF like support to generate the information for the .eh_frame tables.

This is where things start getting a little interesting. If we all agree that generating unwind tables is good *in any case*, even on embedded devices like Coretx-M0, than I think we should hard-code .eh_frame generation under any circumstance, and use -funwind-tables to generate EHABI tables.

Clang would then enable it by default depending on the language contract, which is of little importance to the back-end.

But the question I don't have an answer yet is: if we use that flag, what do we do when -fno-unwind-tables clashes with the uwtables function attribute?


 IF(arm_disable_ehabi)
   USE ARMException
 ELSE
   USE DwarfCFIException
 ENDIF

Today, it means:

IF(arm_disable_ehabi)
  nothing at all
ELSE
  USE ARMException
ENDIF

I'm sensing that the consensus is driving towards *always* emitting unwind tables, but I can't just use DwarfCFIException on ARM, it won't work. This is why we need to carefully extract the common interface, not just for the debug x EH problem, but also the Dwarf x EHABI problem.


Hmmm!   I'm very nervous about the backend making decisions based on the language.

No, sorry! That was a front-end decision! I'd die before enquiring the language in the back-end! :D


  IF (-funwind-tables || -fexceptions)
    uwtable
    IF (leaf / nothrow)
      nounwind
    ENDIF
  ELSE
    no uwtable
    no nounwind
  ENDIF

I'd only like to completely remove the unwind tables if the user forcefully selected -fno-unwind-tables, so I wouldn't like Clang to automatically select that, even in C code.


-fexceptions allows compiling exception handling constructs in the source language and enables the generation of unwind tables.
-funwind-tables only enables the generation of unwind tables.

That makes total sense. Right now, I can't see a difference between -fno-unwind-tables and -arm-disable-ehabi.

As far as I could see, -fcxx-exceptions has no relevance to this discussion, so I'll drop it right here.

My questions about the flags were answered, and it's going to be a lot easier than I thought. I'll change the ehabi flag to connect via unwind-tables and will send a patch review. 

Once that's done, we can get some work done on refactoring ARMException, but only after your patch lands upstream.

Thanks!
--renato

_______________________________________________
LLVM Developers mailing list
[hidden email]         http://llvm.cs.uiuc.edu
http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev
Reply | Threaded
Open this post in threaded view
|

Re: Unwind behaviour in Clang/LLVM

Richard Smith-33
In reply to this post by Renato Golin-2
On Thu, Feb 6, 2014 at 5:29 AM, Renato Golin <[hidden email]> wrote:
Folks,

We're having some discussions about the behaviour of exception handling and Dwarf sharing unwind logic, tables, etc. and it seems that the code around it wasn't designed with any particular goal in mind, but evolved (like the EHABI) and now we're seeing the results from it. 

The problems below are assuming C vs. C++, but it actually apply to any possibly-exceptional vs. never-exceptional cases.


1. C vs. C++

We have two unwind flags: nounwind, which flags functions that can't unwind (leaf, nothrow, etc) and uwtable, which forces generation of the table regardless of nounwind. It seems sensible that C++ code with exceptions enabled should generate the tables for all functions, in case they're called by (or call) external functions. In C we don't want any of that.

GCC seems to never emit tables, and G++ always do, even on C code (.c files, no exception or anything), which is very sensible and in line with my reasoning above. Clang, on the other hand, always generates them. I guess it'll have to figure out what to do based on its impressions on what language is being used to produce similar results.

I believe that emitting the tables on anything that could potentially interact with exceptional code makes sense, but that's clearly a front-end decision. To LLVM, nounwind and uwtables should be absolute:

IF (uwtables)
  IF (nownwind)
    CantUnwind
  ELSE
    Unwind Table
ELSE
  do nothing
ENDIF

This looks wrong, based on the LangRef:

"uwtable
  This attribute indicates that the ABI being targeted requires that an unwind table entry be produce for this function even if we can show that no exceptions passes by it."

I think it's probably:

if (nounwind)
  can't unwind

if (uwtable || (!nounwind && need uwtable to unwind))
  unwind table

2. .fnstart/.fnend+friends

Another problem is that the emission of unwinding tables (based on .fnstart/.fnend symbols and others) is conditional *only* to the existence (or not) of an exception handling class being loaded (EHABI, Dwarf). Which means that, we can't disable the EH on a per-function basis.

We'll have to change the way these symbols are emitted, at least when using ARMException, so that we can emit the tables and honour the uwtable on a per-function basis.

Again, this is a requirement for problem 1, but it'd need to be fixed after 3.


3. Unwinding code

Currently, even when no exception handling are needed, the exception code is used to generate Dwarf unwinding directives (CFI) for the debugger.

Both DwarfCFIException and ARMException inherit from DwarfException, and they are called to do the debug info about the stack unwinding, which is (at least) misplaced. The consensus is that this code should be factored out.

The part that is relevant to this thread is that, today, if -arm-disable-ehabi is requested, ARMException will not be used and we won't have a way of generating debug stack directives, which is wrong.

Factoring out this code is a requirement for the unwinding problem (1), since if we disable EH today, we'll disable Dwarf stack unwinding altogether. But we also need a final solution for problem 4 below before we start.


4. Clang EH control

There are a number of Clang/LLVM options to control exception handling:
 * -fno-excetpion (enable/disable EH on C++ mode, off in C mode)
 * -fcxx-exception (no idea, is it objC++ specific? does it control tables in any way?)
 * -funwind-tables (forces uwtable attribute?)
 * -arm-disable-ehabi (ARM specific bogus flag)

Those options are not always completely exclusive, and they damage different parts of the compilation process (as seen recently on the list), so we need a clear consensus on what each option mean (or should mean), and translate it to the back-end (via function attributes). This would considerably simplify the back-end and help us tackle this refactoring.

I believe the intent is:
  -fexceptions/-fno-exceptions controls whether we generate code that copes with exceptions passing through it.
  -fcxx-exceptions/-fno-cxx-exceptions controls whether we allow exception constructs in C++ code (throw, catch, try) and whether we validate exception specifications (both during compilation and at runtime).
  -fobjc-exceptions/-fno-objc-exceptions controls whether we allow exception constructs in ObjC code (@throw, @try, @catch).

So:

  -fno-exceptions implies -fno-cxx-exceptions and -fno-objc-exceptions
  -fcxx-exceptions and -fobjc-exceptions require -fexceptions

The (-cc1) frontend defaults to -fno-exceptions -fno-cxx-exceptions -fno-objc-exceptions (I'm not sure why).
The driver defaults to:
  * in ObjC++: -fcxx-exceptions -fobjc-exceptions -fexceptions
  * in ObjC: -fobjc-exceptions -fexceptions
  * in C++: -fcxx-exceptions -fexceptions
  * in C: <nothing>

(Users might want to specify -fexceptions in C, when building code like qsort that might have exceptions thrown across it.)


-funwind-tables appears to be an entirely orthogonal flag, which is by default determined based on the target (with some -f flags to override the default), entirely ignoring the -fexceptions flags and language mode. This does not appear to be a flag that an end-user should touch, under most circumstances, but it's far from clear to me that we're getting the default right here (maybe it should depend on -fexceptions?).


The 'nounwind' attribute is set if -fexceptions is specified, or if we have some other way of knowing the function does not throw. Exception: in -fobjc-exceptions mode, we ask the ObjC runtime whether to set the flag. This looks like a bug to me.

The 'uwtable' attribute is set based on the value we determined for -funwind-tables (either through an explicit flag or from the target).

My main target for this problem is to have the one true option on the front-ends, and rely only on function attributes on the back-end (including tools like llc). For that, I'd love to be left with -fexception only and infer all the rest from the language / conditions of the code.

Ex:

IF (C++ mode)
  IF (-fno-exception)
    no uwtable
    no nounwind
  ELSE
    uwtable
    IF (leaf / nothrow)
      nounwind
    ENDIF
  ENDIF
ELSE
  no uwtable
  no nounwind

This seems wrong -- in C with -fexceptions we do not want nounwind, and sometimes want uwtable (depending on ABI).
 
ENDIF

My main goal is to get rid of (at least) -arm-disable-ehabi.



Finally,

If you got this far, you're *really* interested in making the exception handling more user/dev friendly in LLVM, so I welcome any critics about the "proposal" above, as well as any explanations of the doubts expressed. I may be wrong about many things, feel free to enlighten me! We may have a lot less work to do, and I'll be happy. ;)

I believe the dependency graph of the solutions are:

4 -> 3 -> 2 -> 1

So, we first should solve the flags problem, than refactor the unwinding code out of EH, make the debug generation use them as well, and then we can start with the EH specific changes. The problem is that 4 will change things considerably, so we might need some scaffolding during the whole process.

Makes sense?

cheers,
--renato


_______________________________________________
LLVM Developers mailing list
[hidden email]         http://llvm.cs.uiuc.edu
http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev



_______________________________________________
LLVM Developers mailing list
[hidden email]         http://llvm.cs.uiuc.edu
http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev
Reply | Threaded
Open this post in threaded view
|

Re: [cfe-dev] Unwind behaviour in Clang/LLVM

Stephen Checkoway
In reply to this post by Joerg Sonnenberger

On Feb 6, 2014, at 10:47 AM, Joerg Sonnenberger <[hidden email]> wrote:

> On Thu, Feb 06, 2014 at 03:18:02PM +0000, Renato Golin wrote:
>> I can't decide that, but those decisions should stay in the front-end. To
>> the back-end, function attributes should be able to control table emission
>> (or maybe we need flags, I don't know).
>
> I disagree on this. Table emission by itself doesn't involve code
> generation and I don't think it makes sense as a per function attribute
> either. You either want it for all functions or only when needed (e.g.
> exceptions are possible). As such, it makes perfect sense to me as a
> global flag.

Does LTO change this analysis?

--
Stephen Checkoway






_______________________________________________
LLVM Developers mailing list
[hidden email]         http://llvm.cs.uiuc.edu
http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev
Reply | Threaded
Open this post in threaded view
|

Re: [cfe-dev] Unwind behaviour in Clang/LLVM

Joerg Sonnenberger
On Thu, Feb 06, 2014 at 03:01:04PM -0500, Stephen Checkoway wrote:

>
> On Feb 6, 2014, at 10:47 AM, Joerg Sonnenberger <[hidden email]> wrote:
>
> > On Thu, Feb 06, 2014 at 03:18:02PM +0000, Renato Golin wrote:
> >> I can't decide that, but those decisions should stay in the front-end. To
> >> the back-end, function attributes should be able to control table emission
> >> (or maybe we need flags, I don't know).
> >
> > I disagree on this. Table emission by itself doesn't involve code
> > generation and I don't think it makes sense as a per function attribute
> > either. You either want it for all functions or only when needed (e.g.
> > exceptions are possible). As such, it makes perfect sense to me as a
> > global flag.
>
> Does LTO change this analysis?

I don't think so.

Joerg
_______________________________________________
LLVM Developers mailing list
[hidden email]         http://llvm.cs.uiuc.edu
http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev
Reply | Threaded
Open this post in threaded view
|

Re: Unwind behaviour in Clang/LLVM

Renato Golin-2
In reply to this post by Richard Smith-33
On 6 February 2014 19:21, Richard Smith <[hidden email]> wrote:
if (nounwind)
  can't unwind

can't unwind == unwind table + no EH directives + no EH table


if (uwtable || (!nounwind && need uwtable to unwind))
  unwind table

"need unwind table to unwind" is probably true in almost all cases. At least in all where ARMException and DwarfCFIException are concerned, which is the ones we're discussing about.

I'm beginning to think that there is no reason at all to have an uwtable attribute, given that the -funwind-tables is propagated to the back-end AND if we emit the table for one function we should do it for all.


I believe the intent is:
  -fexceptions/-fno-exceptions controls whether we generate code that copes with exceptions passing through it.

Right. Landing pads, cleanups, etc. We'll need those for emitting the EH tables, but not the unwind tables, so for this particular discussion, we don't need to worry.

 
  -fcxx-exceptions/-fno-cxx-exceptions controls whether we allow exception constructs in C++ code (throw, catch, try) and whether we validate exception specifications (both during compilation and at runtime).
  -fobjc-exceptions/-fno-objc-exceptions controls whether we allow exception constructs in ObjC code (@throw, @try, @catch).

Language-specific stuff, not even important to the EH tables (since in the back end we don't care what constructs you use in the language, only the IR basic block structure).


  -fno-exceptions implies -fno-cxx-exceptions and -fno-objc-exceptions
  -fcxx-exceptions and -fobjc-exceptions require -fexceptions

Will -fcxx-exceptions also include -fexceptions? I mean, if the user specify -fcxx-exceptions in C, will that also turn on all the internal flags that -fexception would?

If so, we really don't need to worry at all about them.


-funwind-tables appears to be an entirely orthogonal flag, which is by default determined based on the target (with some -f flags to override the default), entirely ignoring the -fexceptions flags and language mode.

Right. They do clash in the back-end, since one generates EH unwinding and the other might only generate Dwarf unwinding. We need to clear that confusion in the back-end, but I don't think that the front-end should even care on how it gets implemented in the end, as long as it works.


This does not appear to be a flag that an end-user should touch, under most circumstances, but it's far from clear to me that we're getting the default right here (maybe it should depend on -fexceptions?).

I think that both -fexceptions and -g should turn -funwind-tables by default. The third user is the backtrace which doesn't need debug or EH info (just the unwind table), and you need the -funwind-tables IFF your target doesn't have it on by default.

I can only think about GPU targets that won't need any of that, but they're not using Dwarf or EHABI handlers, so we shouldn't concern about that. Embedded CPUs might want them disabled to save space, and for that we should actively disable (-fno-unwind-tables or -Os/z).


The 'nounwind' attribute is set if -fexceptions is specified, or if we have some other way of knowing the function does not throw.

You mean -fno-exceptions, I believe. I think this behaviour is correct.


The 'uwtable' attribute is set based on the value we determined for -funwind-tables (either through an explicit flag or from the target).

Seems reasonable, though unnecessary in most cases.


This seems wrong -- in C with -fexceptions we do not want nounwind, and sometimes want uwtable (depending on ABI).

Yes, I agree, I was wrong. Unwind tables are almost entirely orthogonal to EH and Dwarf.


Thanks everyone for the enlightening responses, I'll have to digest everything again and see if I remember any of it tomorrow... :)

I managed to get a definite step out of this (http://llvm.org/PR18758), and I think we can safely ignore the -fexceptions flags for now.

My revised plan:

0. Get Keith's patch in to have unwinding without EH
1. Connect -funwind-tables with EHABI
2. Abstract the unwind code where both EH and the Dwarf producers can make use of
3. Disable unwind tables if -fno-unwind-tables on ARM
4. Apply CFI unwinding if -funwind-tables AND -fno-exceptions on EHABI

I'm not sure why we're using .save/.push and not CFI with EHABI, but step 2 would be a lot simpler if we could unify both exception handling classes, and step 4 would completely disappear. Anton/Logan?

cheers,
--renato

_______________________________________________
LLVM Developers mailing list
[hidden email]         http://llvm.cs.uiuc.edu
http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev
Reply | Threaded
Open this post in threaded view
|

Re: Unwind behaviour in Clang/LLVM

Richard Smith-33
On Thu, Feb 6, 2014 at 1:27 PM, Renato Golin <[hidden email]> wrote:
On 6 February 2014 19:21, Richard Smith <[hidden email]> wrote:
if (nounwind)
  can't unwind

can't unwind == unwind table + no EH directives + no EH table


if (uwtable || (!nounwind && need uwtable to unwind))
  unwind table

"need unwind table to unwind" is probably true in almost all cases. At least in all where ARMException and DwarfCFIException are concerned, which is the ones we're discussing about.

I'm beginning to think that there is no reason at all to have an uwtable attribute, given that the -funwind-tables is propagated to the back-end AND if we emit the table for one function we should do it for all.


I believe the intent is:
  -fexceptions/-fno-exceptions controls whether we generate code that copes with exceptions passing through it.

Right. Landing pads, cleanups, etc. We'll need those for emitting the EH tables, but not the unwind tables, so for this particular discussion, we don't need to worry.

 
  -fcxx-exceptions/-fno-cxx-exceptions controls whether we allow exception constructs in C++ code (throw, catch, try) and whether we validate exception specifications (both during compilation and at runtime).
  -fobjc-exceptions/-fno-objc-exceptions controls whether we allow exception constructs in ObjC code (@throw, @try, @catch).

Language-specific stuff, not even important to the EH tables (since in the back end we don't care what constructs you use in the language, only the IR basic block structure).


  -fno-exceptions implies -fno-cxx-exceptions and -fno-objc-exceptions
  -fcxx-exceptions and -fobjc-exceptions require -fexceptions

Will -fcxx-exceptions also include -fexceptions? I mean, if the user specify -fcxx-exceptions in C, will that also turn on all the internal flags that -fexception would?

If so, we really don't need to worry at all about them.

-fcxx-exceptions implies -fexceptions if the input kind is C++ and is ignored if not.
-fobjc-exceptions implies -fexceptions if the input kind is ObjC(++) and is ignored if not.

Which isn't quite what you asked, but I think the conclusion is the same (you don't need to care, the driver does the right thing).
 
-funwind-tables appears to be an entirely orthogonal flag, which is by default determined based on the target (with some -f flags to override the default), entirely ignoring the -fexceptions flags and language mode.

Right. They do clash in the back-end, since one generates EH unwinding and the other might only generate Dwarf unwinding. We need to clear that confusion in the back-end, but I don't think that the front-end should even care on how it gets implemented in the end, as long as it works. 
This does not appear to be a flag that an end-user should touch, under most circumstances, but it's far from clear to me that we're getting the default right here (maybe it should depend on -fexceptions?).

I think that both -fexceptions and -g should turn -funwind-tables by default. The third user is the backtrace which doesn't need debug or EH info (just the unwind table), and you need the -funwind-tables IFF your target doesn't have it on by default.

I can only think about GPU targets that won't need any of that, but they're not using Dwarf or EHABI handlers, so we shouldn't concern about that. Embedded CPUs might want them disabled to save space, and for that we should actively disable (-fno-unwind-tables or -Os/z).

This (-fexceptions and -g imply -funwind-tables) seems like it's probably the right thing for most targets. With SjLj exceptions, -fexceptions probably doesn't need -funwind-tables.

The 'nounwind' attribute is set if -fexceptions is specified, or if we have some other way of knowing the function does not throw.

You mean -fno-exceptions, I believe. I think this behaviour is correct.
The 'uwtable' attribute is set based on the value we determined for -funwind-tables (either through an explicit flag or from the target).

Seems reasonable, though unnecessary in most cases.


This seems wrong -- in C with -fexceptions we do not want nounwind, and sometimes want uwtable (depending on ABI).

Yes, I agree, I was wrong. Unwind tables are almost entirely orthogonal to EH and Dwarf.


Thanks everyone for the enlightening responses, I'll have to digest everything again and see if I remember any of it tomorrow... :)

I managed to get a definite step out of this (http://llvm.org/PR18758), and I think we can safely ignore the -fexceptions flags for now.

My revised plan:

0. Get Keith's patch in to have unwinding without EH
1. Connect -funwind-tables with EHABI
2. Abstract the unwind code where both EH and the Dwarf producers can make use of
3. Disable unwind tables if -fno-unwind-tables on ARM
4. Apply CFI unwinding if -funwind-tables AND -fno-exceptions on EHABI

I'm not sure why we're using .save/.push and not CFI with EHABI, but step 2 would be a lot simpler if we could unify both exception handling classes, and step 4 would completely disappear. Anton/Logan?

cheers,
--renato


_______________________________________________
LLVM Developers mailing list
[hidden email]         http://llvm.cs.uiuc.edu
http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev
Reply | Threaded
Open this post in threaded view
|

Re: Unwind behaviour in Clang/LLVM

Renato Golin-2
On 7 February 2014 00:19, Richard Smith <[hidden email]> wrote:
This (-fexceptions and -g imply -funwind-tables) seems like it's probably the right thing for most targets. With SjLj exceptions, -fexceptions probably doesn't need -funwind-tables.

Thanks, I think that's the general consensus, yes.

Do we have such logic in Clang at the moment?

My original point was that the back-end shouldn't try to guess, so front-ends should pass this information down, either via function attributes or flags. Attributes would be better for multi-stage compilation process, but if the default target description is shared between front and back ends, than we might not need this, and flags become the preferred method.

This is another reason to proceed with a separate library for target description (that deals with triples, -m flags, defaults, etc), to be used by both front and back ends, so then we don't have to worry about changing all sides whenever a default changes.

cheers,
--renato

_______________________________________________
LLVM Developers mailing list
[hidden email]         http://llvm.cs.uiuc.edu
http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev
Reply | Threaded
Open this post in threaded view
|

Re: Unwind behaviour in Clang/LLVM

Renato Golin-2
On 7 February 2014 09:35, Renato Golin <[hidden email]> wrote:
Do we have such logic in Clang at the moment?

Let me answer my own question. Right now, both -funwind-tables and -fno-unwind-tables only enable the -muniwind-tables for -cc1, and either lack or presence of that flag in -cc1 has the same behaviour on C++ code: they both generate .eh_frame sections.

The only behaviour I found is that -munwind-tables will add uwtable to functions, which had no effect on x86_64. Is that because x86_64 mandates unwind tables?

If the semantics is that uwtable turns on tables on targets that don't require it (SjLj), but not that it turns off if missing on targets that mandate it, I can't use it to disable them on ARM. To be honest, recently, I'm not even sure I need, or want to disable. 

With Keith's patch to generate Dwarf unwind, the -arm-disable-ehabi flag could possibly be removed clean, and we can go directly to step 2.

Keith, Reid, are you happy with always generating unwind tables on ARM regardless?

cheers,
--renato

_______________________________________________
LLVM Developers mailing list
[hidden email]         http://llvm.cs.uiuc.edu
http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev
Reply | Threaded
Open this post in threaded view
|

Re: Unwind behaviour in Clang/LLVM

Jim Grosbach

On Feb 7, 2014, at 3:35 AM, Renato Golin <[hidden email]> wrote:

On 7 February 2014 09:35, Renato Golin <[hidden email]> wrote:
Do we have such logic in Clang at the moment?

Let me answer my own question. Right now, both -funwind-tables and -fno-unwind-tables only enable the -muniwind-tables for -cc1, and either lack or presence of that flag in -cc1 has the same behaviour on C++ code: they both generate .eh_frame sections.

The only behaviour I found is that -munwind-tables will add uwtable to functions, which had no effect on x86_64. Is that because x86_64 mandates unwind tables?

If the semantics is that uwtable turns on tables on targets that don't require it (SjLj), but not that it turns off if missing on targets that mandate it, I can't use it to disable them on ARM. To be honest, recently, I'm not even sure I need, or want to disable. 

With Keith's patch to generate Dwarf unwind, the -arm-disable-ehabi flag could possibly be removed clean, and we can go directly to step 2.

Keith, Reid, are you happy with always generating unwind tables on ARM regardless?

Just to double check, none of this will change the current behavior on Darwin, right?

-Jim


_______________________________________________
LLVM Developers mailing list
[hidden email]         http://llvm.cs.uiuc.edu
http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev
Reply | Threaded
Open this post in threaded view
|

Re: Unwind behaviour in Clang/LLVM

Renato Golin-2
On 7 February 2014 17:46, Jim Grosbach <[hidden email]> wrote:
Just to double check, none of this will change the current behavior on Darwin, right?

Right! Unless Darwin starts using EHABI. ;)

--renato

_______________________________________________
LLVM Developers mailing list
[hidden email]         http://llvm.cs.uiuc.edu
http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev
Reply | Threaded
Open this post in threaded view
|

Re: Unwind behaviour in Clang/LLVM

Jim Grosbach

On Feb 7, 2014, at 10:03 AM, Renato Golin <[hidden email]> wrote:

On 7 February 2014 17:46, Jim Grosbach <[hidden email]> wrote:
Just to double check, none of this will change the current behavior on Darwin, right?

Right! Unless Darwin starts using EHABI. ;)

Perfect. Thanks!

-Jim


_______________________________________________
LLVM Developers mailing list
[hidden email]         http://llvm.cs.uiuc.edu
http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev
Reply | Threaded
Open this post in threaded view
|

Re: [cfe-dev] Unwind behaviour in Clang/LLVM

Rafael Espíndola
In reply to this post by Renato Golin-2
On 6 February 2014 08:29, Renato Golin <[hidden email]> wrote:

> Folks,
>
> We're having some discussions about the behaviour of exception handling and
> Dwarf sharing unwind logic, tables, etc. and it seems that the code around
> it wasn't designed with any particular goal in mind, but evolved (like the
> EHABI) and now we're seeing the results from it.
>
> The problems below are assuming C vs. C++, but it actually apply to any
> possibly-exceptional vs. never-exceptional cases.
>
>
> 1. C vs. C++
>
> We have two unwind flags: nounwind, which flags functions that can't unwind
> (leaf, nothrow, etc) and uwtable, which forces generation of the table
> regardless of nounwind. It seems sensible that C++ code with exceptions
> enabled should generate the tables for all functions, in case they're called
> by (or call) external functions. In C we don't want any of that.

Depends on the ABI. On X86-64 we should produce the tables even with C
according to the ABI.

Cheers,
Rafael
_______________________________________________
LLVM Developers mailing list
[hidden email]         http://llvm.cs.uiuc.edu
http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev
Reply | Threaded
Open this post in threaded view
|

Re: [cfe-dev] Unwind behaviour in Clang/LLVM

Rafael Espíndola
In reply to this post by Joerg Sonnenberger
> I disagree on this. Table emission by itself doesn't involve code
> generation and I don't think it makes sense as a per function attribute
> either. You either want it for all functions or only when needed (e.g.
> exceptions are possible). As such, it makes perfect sense to me as a
> global flag.

It has to be an attribute because of LTO. You can LTO a file compiled
with -fasynchronous-unwind-tables and one with
-fno-asynchronous-unwind-tables. That is why we have the uwtable
attribute.

Cheers,
Rafael
_______________________________________________
LLVM Developers mailing list
[hidden email]         http://llvm.cs.uiuc.edu
http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev
12