RFC: Replace __cxa_begin_catch/__cxa_end_catch with intrinsics

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

RFC: Replace __cxa_begin_catch/__cxa_end_catch with intrinsics

Kaylor, Andrew

Hi all,

 

I brought this up last week in an LLVMDev discussion of C++ EH support on Windows, but I thought I should float it again with a subject that would be less likely to be missed by people who don’t have a direct interest in Windows support.

 

I would like to introduce two new intrinsics, llvm.eh.begincatch and llvm.eh.endcatch, to take the place of __cxa_begin_catch and __cxa_end_catch in the IR prior to the CodeGen prepare passes.  For the majority of platforms the intrinsics will be directly mapped to the existing function calls during one of the CodeGen prepare passes.  For MSVC-environment Windows targets there is no equivalent function call to be made, but these intrinsics will be extremely useful during the WinEHPrepare pass as a means of identifying the limits of catch-specific code.

 

If there is a reason why I should not introduce intrinsics for this purpose, please give me feedback now.  Otherwise, I’m going to begin work on a patch to support this in the back end with the expectation that a corresponding change will be made in the clang front end when the intrinsic support is ready.

 

Thanks,

Andy

 


_______________________________________________
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] RFC: Replace __cxa_begin_catch/__cxa_end_catch with intrinsics

Reid Kleckner-3
This seems reasonable to me. Adding John explicitly...

On Mon, Feb 2, 2015 at 4:03 PM, Kaylor, Andrew <[hidden email]> wrote:

Hi all,

 

I brought this up last week in an LLVMDev discussion of C++ EH support on Windows, but I thought I should float it again with a subject that would be less likely to be missed by people who don’t have a direct interest in Windows support.

 

I would like to introduce two new intrinsics, llvm.eh.begincatch and llvm.eh.endcatch, to take the place of __cxa_begin_catch and __cxa_end_catch in the IR prior to the CodeGen prepare passes.  For the majority of platforms the intrinsics will be directly mapped to the existing function calls during one of the CodeGen prepare passes.  For MSVC-environment Windows targets there is no equivalent function call to be made, but these intrinsics will be extremely useful during the WinEHPrepare pass as a means of identifying the limits of catch-specific code.

 

If there is a reason why I should not introduce intrinsics for this purpose, please give me feedback now.  Otherwise, I’m going to begin work on a patch to support this in the back end with the expectation that a corresponding change will be made in the clang front end when the intrinsic support is ready.

 

Thanks,

Andy

 


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



_______________________________________________
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] RFC: Replace __cxa_begin_catch/__cxa_end_catch with intrinsics

John McCall
> On Feb 2, 2015, at 4:53 PM, Reid Kleckner <[hidden email]> wrote:
> This seems reasonable to me. Adding John explicitly…

Thanks, Reid.

Andy, I understand why Windows EH needs custom lowering here, and using intrinsics seems like a fine approach, but I don’t understand why you’re proposing changing the Itanium code generation pattern.  There’s no reason for backends to have special knowledge of __cxa_begin_catch, and it’s actually not a good idea for them to do so, because that’s unnecessarily language-specific and personality-specific; even today, Objective-C EH implementations do use separate personality and different begin/end catch functions.

If we ever decide to support a libUnwind personality function that relies on function outlining — and I do have that as an eventual goal — it’ll probably want a slightly different code-generation pattern anyway.  So write your code generally where you can, but don’t worry about creating some sort of ultimate unified backend EH lowering.

John.
_______________________________________________
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] RFC: Replace __cxa_begin_catch/__cxa_end_catch with intrinsics

Kaylor, Andrew
Hi John,

Thanks for the feedback.

I'm fine not using the proposed intrinsics everywhere.  It just seemed to me like a reasonable step since the back end is already taking a fair bit of action based on the personality function.  Also, if I do introduce the intrinsics for one target/personality function it seems like it may be a source of confusion when other targets don't use them.  I suppose that is easily enough solved with proper documentation though.  Perhaps I can even drop a "win" in the name somewhere.

To be clear, are you OK with introducing these intrinsics for WinEH+__CxxFrameHandler3 personality function use?

-Andy

-----Original Message-----
From: John McCall [mailto:[hidden email]]
Sent: Monday, February 02, 2015 5:18 PM
To: Reid Kleckner
Cc: Kaylor, Andrew; LLVM Developers Mailing List; clang-dev Developers ([hidden email])
Subject: Re: [LLVMdev] RFC: Replace __cxa_begin_catch/__cxa_end_catch with intrinsics

> On Feb 2, 2015, at 4:53 PM, Reid Kleckner <[hidden email]> wrote:
> This seems reasonable to me. Adding John explicitly…

Thanks, Reid.

Andy, I understand why Windows EH needs custom lowering here, and using intrinsics seems like a fine approach, but I don’t understand why you’re proposing changing the Itanium code generation pattern.  There’s no reason for backends to have special knowledge of __cxa_begin_catch, and it’s actually not a good idea for them to do so, because that’s unnecessarily language-specific and personality-specific; even today, Objective-C EH implementations do use separate personality and different begin/end catch functions.

If we ever decide to support a libUnwind personality function that relies on function outlining — and I do have that as an eventual goal — it’ll probably want a slightly different code-generation pattern anyway.  So write your code generally where you can, but don’t worry about creating some sort of ultimate unified backend EH lowering.

John.

_______________________________________________
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] RFC: Replace __cxa_begin_catch/__cxa_end_catch with intrinsics

Reid Kleckner-3
In reply to this post by John McCall
I actually like the unified intrinsic approach here. The backend already has to know things about the personality function. Until recently we would assume that the personality function wants an Itanium LSDA, for example, and dump that out into a target-specific section. Now on Windows we look at the personality function and try to figure out what kind of preparation and tables it wants.

It seems reasonable then that we could continue along the lines of classifying some personalities as "Itanium" personalities and lowering these new intrinsics out to __cxa_begin_catch / end_catch. We already do it for resume -> _Unwind_Resume.

I think this is better than relying on the target to "know" what wants, which is what we have today with SjLj vs. CFI-driven EH. IMO it would be cleaner if the backend knew that __g??_personality_sj0 meant it should run the SjLjEHPrepare pass.

What do you think?

On Mon, Feb 2, 2015 at 5:17 PM, John McCall <[hidden email]> wrote:
> On Feb 2, 2015, at 4:53 PM, Reid Kleckner <[hidden email]> wrote:
> This seems reasonable to me. Adding John explicitly…

Thanks, Reid.

Andy, I understand why Windows EH needs custom lowering here, and using intrinsics seems like a fine approach, but I don’t understand why you’re proposing changing the Itanium code generation pattern.  There’s no reason for backends to have special knowledge of __cxa_begin_catch, and it’s actually not a good idea for them to do so, because that’s unnecessarily language-specific and personality-specific; even today, Objective-C EH implementations do use separate personality and different begin/end catch functions.

If we ever decide to support a libUnwind personality function that relies on function outlining — and I do have that as an eventual goal — it’ll probably want a slightly different code-generation pattern anyway.  So write your code generally where you can, but don’t worry about creating some sort of ultimate unified backend EH lowering.

John.


_______________________________________________
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] RFC: Replace __cxa_begin_catch/__cxa_end_catch with intrinsics

John McCall
> On Feb 2, 2015, at 6:04 PM, Reid Kleckner <[hidden email]> wrote:
> I actually like the unified intrinsic approach here. The backend already has to know things about the personality function. Until recently we would assume that the personality function wants an Itanium LSDA, for example, and dump that out into a target-specific section. Now on Windows we look at the personality function and try to figure out what kind of preparation and tables it wants.
>
> It seems reasonable then that we could continue along the lines of classifying some personalities as "Itanium" personalities and lowering these new intrinsics out to __cxa_begin_catch / end_catch.

You are over-estimating how similar the code-generation patterns are going to be here.  The information flow from the unwind mechanism to the catch clause can differ quite wildly.

Go look at what happens in the different ABIs when an exception with a non-trivial copy constructor is caught.  There’s an entire copy-construction that’s explicit in Itanium but which I believe is done implicitly by the personality equivalent in MSVC (necessarily, if you understand the purpose of __cxa_begin_catch/__cxa_end_catch).

I agree that we should be more explicit about modeling the differences in personality-mandated code generation.  Perhaps if we did this, people would stop talking about the “Itanium LSDA” when they mean the gcc/g++ LSDA.  I just think there is zero benefit in pretending that we can actually model every useful difference between personalities with the name of the personality function.

> We already do it for resume -> _Unwind_Resume.

resume was specifically designed to be unwinder-agnostic.  This is why it takes all the data from the landingpad even though _Unwind_Resume only needs the exception pointer.

John.
_______________________________________________
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] RFC: Replace __cxa_begin_catch/__cxa_end_catch with intrinsics

John McCall
In reply to this post by Kaylor, Andrew
> On Feb 2, 2015, at 5:39 PM, Kaylor, Andrew <[hidden email]> wrote:
> Hi John,
>
> Thanks for the feedback.
>
> I'm fine not using the proposed intrinsics everywhere.  It just seemed to me like a reasonable step since the back end is already taking a fair bit of action based on the personality function.  Also, if I do introduce the intrinsics for one target/personality function it seems like it may be a source of confusion when other targets don't use them.  I suppose that is easily enough solved with proper documentation though.  Perhaps I can even drop a "win" in the name somewhere.

Well, don’t make them deliberately unportable. :)  The g++ personality doesn’t use subfunction extraction, but at some point I’d like to switch to a personality which does, mostly in the interests of code size.  I would just encourage you to design these intrinsics specifically around the problems of personality-directed subfunction extraction, and understand that you’re going to end up hardcoding a lot of Windows-specific behavior whether you mean to or not.  We can figure out how to make them more general when we have multiple personalities that need subfunction extraction.

> To be clear, are you OK with introducing these intrinsics for WinEH+__CxxFrameHandler3 personality function use?

Yes.

John.
_______________________________________________
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] RFC: Replace __cxa_begin_catch/__cxa_end_catch with intrinsics

Reid Kleckner-3
In reply to this post by John McCall
On Mon, Feb 2, 2015 at 7:05 PM, John McCall <[hidden email]> wrote:
> On Feb 2, 2015, at 6:04 PM, Reid Kleckner <[hidden email]> wrote:
> I actually like the unified intrinsic approach here. The backend already has to know things about the personality function. Until recently we would assume that the personality function wants an Itanium LSDA, for example, and dump that out into a target-specific section. Now on Windows we look at the personality function and try to figure out what kind of preparation and tables it wants.
>
> It seems reasonable then that we could continue along the lines of classifying some personalities as "Itanium" personalities and lowering these new intrinsics out to __cxa_begin_catch / end_catch.

You are over-estimating how similar the code-generation patterns are going to be here.  The information flow from the unwind mechanism to the catch clause can differ quite wildly.

Go look at what happens in the different ABIs when an exception with a non-trivial copy constructor is caught.  There’s an entire copy-construction that’s explicit in Itanium but which I believe is done implicitly by the personality equivalent in MSVC (necessarily, if you understand the purpose of __cxa_begin_catch/__cxa_end_catch).

Makes sense. LLVM shouldn't be too heroic about papering over the differences.

I agree that we should be more explicit about modeling the differences in personality-mandated code generation.  Perhaps if we did this, people would stop talking about the “Itanium LSDA” when they mean the gcc/g++ LSDA.  I just think there is zero benefit in pretending that we can actually model every useful difference between personalities with the name of the personality function.

I guess that was my misunderstanding and I'm guilty of promoting that terminology. :) The document leads one to believe that the tables are covered later, but now that I look again, I see there is very little information.

_______________________________________________
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] RFC: Replace __cxa_begin_catch/__cxa_end_catch with intrinsics

John McCall
On Feb 3, 2015, at 9:56 AM, Reid Kleckner <[hidden email]> wrote:
On Mon, Feb 2, 2015 at 7:05 PM, John McCall <[hidden email]> wrote:
> On Feb 2, 2015, at 6:04 PM, Reid Kleckner <[hidden email]> wrote:
> I actually like the unified intrinsic approach here. The backend already has to know things about the personality function. Until recently we would assume that the personality function wants an Itanium LSDA, for example, and dump that out into a target-specific section. Now on Windows we look at the personality function and try to figure out what kind of preparation and tables it wants.
>
> It seems reasonable then that we could continue along the lines of classifying some personalities as "Itanium" personalities and lowering these new intrinsics out to __cxa_begin_catch / end_catch.

You are over-estimating how similar the code-generation patterns are going to be here.  The information flow from the unwind mechanism to the catch clause can differ quite wildly.

Go look at what happens in the different ABIs when an exception with a non-trivial copy constructor is caught.  There’s an entire copy-construction that’s explicit in Itanium but which I believe is done implicitly by the personality equivalent in MSVC (necessarily, if you understand the purpose of __cxa_begin_catch/__cxa_end_catch).

Makes sense. LLVM shouldn't be too heroic about papering over the differences.

I agree that we should be more explicit about modeling the differences in personality-mandated code generation.  Perhaps if we did this, people would stop talking about the “Itanium LSDA” when they mean the gcc/g++ LSDA.  I just think there is zero benefit in pretending that we can actually model every useful difference between personalities with the name of the personality function.

I guess that was my misunderstanding and I'm guilty of promoting that terminology. :)

No worries.  I actually want to apologize for my tone in that email; looking back, it feels over-the-top and rude.  I’m sorry about that.  You'd asked for my opinion in an area where I have a lot of expertise, which is supposed to be a reasonable thing to do. :)

The document leads one to believe that the tables are covered later, but now that I look again, I see there is very little information.

If I remember correctly, ARM actually documents their C++ LSDA layout, but that’s really just ARM indulging their habit of over-documenting stuff.

The key point here is to understand the designed separation between the C++ ABI, libUnwind, and the C++ runtime.  It’s easy to conflate them; the first two were really designed together, and in fact are specified together, and the compiler has to know about several different parts simultaneously.

It’s best to think of libUnwind (the “base exceptions ABI”, in the Itanium ABI’s terminology) as being its own, independent thing.  It’s deliberately designed to be language-independent, even to the point of supporting exception mechanisms (continuable exceptions) that AFAIK aren’t needed by any of the languages they were directly trying to support (C++, Ada).  libUnwind dictates some things as platform ABI, but only what it absolutely needs:
  - the process through which EH tables are found at all,
  - the CFI header on the EH tables, which includes basic information on how to unwind and where to find the personality function,
  - the basic structure of a language-independent exception object, and
  - the basic runtime interface to the unwind library.

Itanium then adds only a pretty small amount of extra, C++-specific ABI to this:
  - some additional structure of C++ exception objects and
  - some additional runtime functions which wrap libUnwind and track whether an exception is currently unwinding (for the purposes of std::uncaught_exception()).

Crucially, Itanium doesn’t describe the language-specific area of C++ EH tables.  Now, this is a part of the ABI document that’s sometimes just incomplete, but in this case, I’m fairly certain that not specifying the layout is intentional.  The ABI specifies the additional structure of C++ exception objects, with the intent that that should be sufficient for an arbitrary personality function to correctly recognize and handle a C++ exception, which is important for language interoperation.  I think the Itanium committee was more concerned about Ada/C++ interop, but to use an example closer to my heart:  consider the Objective-C personality function, which is used even in Objective-C++ modes and must therefore allow both Objective-C and C++ exceptions to be caught.

The C++ runtime library then just implements those functions.  libsupc++ / libc++abi also provide a default personality function, which then implies a particular LSDA layout; we decided to use the same LSDA layout as libsupc++ when implementing libc++abi because it simplified deployment and didn’t require additional compiler support.  But there’s no reason that you couldn’t have multiple “competing” C++ personality functions, because there’s not supposed to be a private contract between the C++ runtime and its personality function; that would preclude other languages from compatibly working with C++ exception objects.

The only things preventing us from using a new personality function for clang are:
  - deployment issues; the new function wouldn’t be guaranteed to exist in the C++ library, so we’d either need to provide it in compiler-rt or restrict it by deployment target, and
  - the usual small issues of finding time to design and implement a new LSDA layout. :)

John.

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