[cfe-dev] Are __builtin_setjmp / __builtin_longjmp part of the ABI?

Hal Finkel hfinkel at anl.gov
Tue Mar 3 00:54:16 PST 2015


----- Original Message -----
> From: "John McCall" <rjmccall at gmail.com>
> To: "Hal Finkel" <hfinkel at anl.gov>
> Cc: "Joerg Sonnenberger" <joerg at britannica.bec.de>, "<hans at hanshq.net>" <hans at hanshq.net>, "cfe-commits"
> <cfe-commits at cs.uiuc.edu>
> Sent: Tuesday, March 3, 2015 2:05:53 AM
> Subject: Re: r230255 - Only lower __builtin_setjmp / __builtin_longjmp to
> 
> On Mar 2, 2015, at 11:22 PM, Hal Finkel <hfinkel at anl.gov> wrote:
> > 
> > ----- Original Message -----
> >> From: "Joerg Sonnenberger" <joerg at britannica.bec.de>
> >> To: "John McCall" <rjmccall at gmail.com>
> >> Cc: hans at hanshq.net, "cfe-commits" <cfe-commits at cs.uiuc.edu>
> >> Sent: Tuesday, March 3, 2015 1:07:20 AM
> >> Subject: Re: r230255 - Only lower __builtin_setjmp /
> >> __builtin_longjmp to
> >> 
> >>> On Mon, Mar 02, 2015 at 06:02:32PM -0800, John McCall wrote:
> >>> This patch is pretty scary.  __builtin_setjmp/longjmp are
> >>> definitely not
> >>> just libc functions with a __builtin_ prefix attached.  They do
> >>> not
> >>> interoperate with setjmp/longjmp and expect a significantly
> >>> smaller
> >>> buffer,
> >>> so silently rewriting them to setjmp/longjmp is ABI-breaking.
> >>>  This
> >>> might
> >>> fix Ruby, but only if Ruby is actually passing a full jmp_buf,
> >>> and
> >>> only if
> >>> everything that does a __builtin_setjmp/__builtin_longjmp is
> >>> recompiled in
> >>> a way that does the rewrite.  I'm very concerned about this
> >>> introducing ABI
> >>> problems for a Clang-compiled Ruby with GCC-compiled extensions
> >>> or
> >>> vice-versa.  FWIW, Ruby seems to already have target-specific
> >>> configuration
> >>> logic for when to use them.
> >> 
> >> Ruby has no target-specific configuration.
> 
> Literally the first google result for "Ruby __builtin_setjmp" is a
> core commit turning it off for a target.  Am I misunderstanding
> something?
> 
> GCC implements this builtin with much more generality than we do,
> probably because GCC predates widespread adoption of libUnwind and
> we don't.  Hal's comment about not trying to match GCC on PPC aside
> (and I find that comment pretty troubling!),

Hi John,

Fair enough; let's move this question of whether __builtin_setjmp / __builtin_longjmp are part of the ABI to a separate thread. When implementing these for the PowerPC backend, I followed the same scheme as is used by the X86 backend, and so while this is likely compatible with GCC, I did not consider GCC compatibility a specific goal. Speed and correctness were all I cared about.

My rational for not considering them to be part of the ABI is that:

 1. They don't appear in any system header
 2. They don't appear in the system ABI documentation
 3. They're not universally supported by all compilers targeting the architecture

Generically, our implementation of __builtin_* (__builtin_<math func> for example) differs in observable ways from GCC's implementation. This does mean that passing a jmp_buf filled in by __builtin_setjmp across an interface boundary is a bad idea, but I never would have considered that to be a good idea anyway (because you already need to know it can only be used with __builtin_longjmp and not longjmp).

To be clear, I do consider the format of jmp_buf used by setjmp/longjmp to be part of the ABI, but the GCC implementation of __builtin_setjmp / __builtin_longjmp, AFAIK, and our X86 implementation, differ from that (by design) anyway.

Thanks again,
Hal

> my understanding of the
> general intent of this builtin is that's for implementing extremely
> lightweight context-saving (on the assumption that the platform
> doesn't have that many callee-save registers; it would probably be
> awful on e.g. AArch64) and that the amount of state it saves is so
> small (PC, SP, FP if it's not rederivable from SP) that there's no
> reason [i]not[/i] to match GCC.
> 
> The fact that it's poorly documented and poorly implemented doesn't
> mean that breaking compatibility arbitrarily is acceptable.  It
> might be an unfortunate and obscure bit of ABI, but absent other
> information, I consider it ABI.  So I am not inclined to accept
> this, for trunk or for the branch.  I think it would be a much more
> modest and reasonable fix to just implement the builtin correctly in
> the ARM backend and wherever else you see the need.  Presumably Ruby
> is using this because they actually care about the performance.
> 
> But if you can get the LLVM list to agree with Hal that compatibility
> (even across compiler versions) is a non-goal, and you can show me
> more convincingly that e.g. Ruby only uses this in their core
> implementation and it is not used directly in the compiled code of
> native gems, then I am willing to change my mind.
> 
> John.
> 
> >> if that works, it picks them. Given that the current
> >> __builtin_setjmp
> >> /
> >> __builtin_longjmp code is completely broken unless the backend has
> >> explicit logic for that, the configure test in ruby will pass on
> >> all
> >> ARM
> >> platforms except Darwin (where is might hit an assert or not).
> >> 
> >> No, they are not libc functions with a prefix as they are allowed
> >> to
> >> be
> >> lowered to a different format. The builtin documentation is scarce
> >> at
> >> best. It is a typically badly designed GCC builtin. There is a
> >> half
> >> sentence in gccint.info about the buffer being 5 longs long, but
> >> even
> >> the test suite is not consistent in that regard. It looks like a
> >> completely messed up state.
> >> 
> >> Concerning ABI use: AFAICT, Ruby is the only thing outside an EH
> >> implementation which actually tries to use them. It provides a
> >> correct
> >> jmpbuf_t, so it gets a large enough buffer.
> > 
> > Generically, these builtins are used in lightweight task-switching
> > runtimes (that's why I implemented them in the PowerPC backend; it
> > had nothing to do with EH) -- they're an order of magnitude faster
> > than the function calls.
> > 
> > Also, as far as the PowerPC implementation is concerned, gcc
> > compatibility is a non-goal. These are compiler builtins, and I
> > don't consider them to be part of the ABI.
> > 
> > FWIW, I think that defaulting to the library implementation is
> > reasonable, it does provide a valid (albeit slow) implementation.
> > 
> > -Hal
> > 
> >> 
> >>> Therefore, if we don't actually consistently support these
> >>> builtins
> >>> in the
> >>> backend in a GCC-compatible way (quite plausible), I would be
> >>> much
> >>> more
> >>> comfortable diagnosing that than silently rewriting them to
> >>> setjmp/longjmp,
> >>> unless there are platforms where GCC does actually rewrite them.
> >>> Have you
> >>> done that investigation?
> >> 
> >> I have been discussing the approach and the lowering to a
> >> known-to-work
> >> sj/lj seemed the least broken approach. I don't care enough about
> >> not
> >> just bailing out in the frontend either. It is hard to tell what
> >> the
> >> many different GCC configs are doing, I gave up.
> >> 
> >> Joerg
> >> _______________________________________________
> >> cfe-commits mailing list
> >> cfe-commits at cs.uiuc.edu
> >> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
> > 
> > --
> > Hal Finkel
> > Assistant Computational Scientist
> > Leadership Computing Facility
> > Argonne National Laboratory
> 

-- 
Hal Finkel
Assistant Computational Scientist
Leadership Computing Facility
Argonne National Laboratory



More information about the cfe-dev mailing list