[cfe-dev] [LLVMdev] RFC: Replace __cxa_begin_catch/__cxa_end_catch with intrinsics

John McCall rjmccall at apple.com
Tue Feb 3 11:56:31 PST 2015


> On Feb 3, 2015, at 9:56 AM, Reid Kleckner <rnk at google.com> wrote:
> On Mon, Feb 2, 2015 at 7:05 PM, John McCall <rjmccall at apple.com <mailto:rjmccall at apple.com>> wrote:
> > On Feb 2, 2015, at 6:04 PM, Reid Kleckner <rnk at google.com <mailto:rnk at google.com>> 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.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-dev/attachments/20150203/ed048c3c/attachment.html>


More information about the cfe-dev mailing list