public inbox for libffi-discuss@sourceware.org
 help / color / mirror / Atom feed
* Change in libffi behaviour -- large struct args
@ 2022-05-28 13:40 Anthony Green
  2022-05-28 15:38 ` dancol
                   ` (2 more replies)
  0 siblings, 3 replies; 9+ messages in thread
From: Anthony Green @ 2022-05-28 13:40 UTC (permalink / raw)
  To: libffi-discuss

As has been discussed in various github PRs recently, I'd like to
change libffi's behaviour regarding large struct arguments.

When passing a struct by value, most (all?) ABI definitions ask that
you try to fit structs up to a certain size into registers, and if
they are too large, make a copy and pass them on the stack.
Libffi's current behaviour is to fit small structs in registers, but
then if something is too large, pass it by reference, leaving it as an
exercise for the user to make their own copies.   Many libffi users,
like cpython, do this special work themselves.   I don't like this
because it exposes this ABI detail, the threshold for struct sizes, to
the libffi caller.   Libffi should be making this copy itself.

The struct_by_value_big.c test checks for this, and most ports fail
today   Changing this behaviour won't introduce regressions for libffi
users, and eventually they will be able to remove their special
handling of large struct args.

AG

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: Change in libffi behaviour -- large struct args
  2022-05-28 13:40 Change in libffi behaviour -- large struct args Anthony Green
@ 2022-05-28 15:38 ` dancol
  2022-05-28 15:50   ` Anthony Green
  2022-05-29 14:09 ` Anthony Green
  2022-05-31 15:53 ` DJ Delorie
  2 siblings, 1 reply; 9+ messages in thread
From: dancol @ 2022-05-28 15:38 UTC (permalink / raw)
  To: Anthony Green, libffi-discuss

On May 28, 2022 09:40:34 Anthony Green <green@moxielogic.com> wrote:

> As has been discussed in various github PRs recently, I'd like to
> change libffi's behaviour regarding large struct arguments.
>
> When passing a struct by value, most (all?) ABI definitions ask that
> you try to fit structs up to a certain size into registers, and if
> they are too large, make a copy and pass them on the stack.
> Libffi's current behaviour is to fit small structs in registers, but
> then if something is too large, pass it by reference, leaving it as an
> exercise for the user to make their own copies.   Many libffi users,
> like cpython, do this special work themselves.   I don't like this
> because it exposes this ABI detail, the threshold for struct sizes, to
> the libffi caller.   Libffi should be making this copy itself.
>
> The struct_by_value_big.c test checks for this, and most ports fail
> today   Changing this behaviour won't introduce regressions for libffi
> users, and eventually they will be able to remove their special
> handling of large struct args.
>
> AG

How might this change interact with, say, C++ types tagged with 
clang::trivial_abi? Not all types are trivially memcpy-moveable, sadly.


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: Change in libffi behaviour -- large struct args
  2022-05-28 15:38 ` dancol
@ 2022-05-28 15:50   ` Anthony Green
  0 siblings, 0 replies; 9+ messages in thread
From: Anthony Green @ 2022-05-28 15:50 UTC (permalink / raw)
  To: dancol; +Cc: libffi-discuss

On Sat, May 28, 2022 at 11:38 AM <dancol@dancol.org> wrote:
> How might this change interact with, say, C++ types tagged with clang::trivial_abi? Not all types are trivially memcpy-moveable, sadly.

Mapping C++ semantics to the C ABI has always been an exercise for the
libffi user.

AG

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: Change in libffi behaviour -- large struct args
  2022-05-28 13:40 Change in libffi behaviour -- large struct args Anthony Green
  2022-05-28 15:38 ` dancol
@ 2022-05-29 14:09 ` Anthony Green
  2022-05-31 15:53 ` DJ Delorie
  2 siblings, 0 replies; 9+ messages in thread
From: Anthony Green @ 2022-05-29 14:09 UTC (permalink / raw)
  To: libffi-discuss

Interestingly, the powerpc-unknown-eabisim port mostly got this right,
except that it never passed small structs in registers as it should.
Does anybody care about the 32-bit embedded Power port anymore?

AG

On Sat, May 28, 2022 at 9:40 AM Anthony Green <green@moxielogic.com> wrote:
>
> As has been discussed in various github PRs recently, I'd like to
> change libffi's behaviour regarding large struct arguments.
>
> When passing a struct by value, most (all?) ABI definitions ask that
> you try to fit structs up to a certain size into registers, and if
> they are too large, make a copy and pass them on the stack.
> Libffi's current behaviour is to fit small structs in registers, but
> then if something is too large, pass it by reference, leaving it as an
> exercise for the user to make their own copies.   Many libffi users,
> like cpython, do this special work themselves.   I don't like this
> because it exposes this ABI detail, the threshold for struct sizes, to
> the libffi caller.   Libffi should be making this copy itself.
>
> The struct_by_value_big.c test checks for this, and most ports fail
> today   Changing this behaviour won't introduce regressions for libffi
> users, and eventually they will be able to remove their special
> handling of large struct args.
>
> AG

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: Change in libffi behaviour -- large struct args
  2022-05-28 13:40 Change in libffi behaviour -- large struct args Anthony Green
  2022-05-28 15:38 ` dancol
  2022-05-29 14:09 ` Anthony Green
@ 2022-05-31 15:53 ` DJ Delorie
  2022-05-31 16:47   ` dancol
  2022-05-31 18:59   ` Anthony Green
  2 siblings, 2 replies; 9+ messages in thread
From: DJ Delorie @ 2022-05-31 15:53 UTC (permalink / raw)
  To: Anthony Green; +Cc: libffi-discuss


While this is technically an ABI change, if the "old" ABI never worked,
I can't see how this would break anything by changing.

I will add that passing structs is likely more complex than you think ;-)


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: Change in libffi behaviour -- large struct args
  2022-05-31 15:53 ` DJ Delorie
@ 2022-05-31 16:47   ` dancol
  2022-05-31 16:55     ` Kaz Kylheku
  2022-05-31 18:59   ` Anthony Green
  1 sibling, 1 reply; 9+ messages in thread
From: dancol @ 2022-05-31 16:47 UTC (permalink / raw)
  To: DJ Delorie, Anthony Green, DJ Delorie via Libffi-discuss; +Cc: libffi-discuss

On May 31, 2022 11:53:56 DJ Delorie via Libffi-discuss 
<libffi-discuss@sourceware.org> wrote:

> While this is technically an ABI change, if the "old" ABI never worked,
> I can't see how this would break anything by changing.
>
> I will add that passing structs is likely more complex than you think ;-)

The problem is that whether the old API was broken or not, changing it can 
break working code. What do the libffi people think about using symbol 
versioning?

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: Change in libffi behaviour -- large struct args
  2022-05-31 16:47   ` dancol
@ 2022-05-31 16:55     ` Kaz Kylheku
  0 siblings, 0 replies; 9+ messages in thread
From: Kaz Kylheku @ 2022-05-31 16:55 UTC (permalink / raw)
  To: dancol; +Cc: DJ Delorie, Anthony Green, DJ Delorie via Libffi-discuss

On 2022-05-31 09:47, dancol@dancol.org wrote:
> On May 31, 2022 11:53:56 DJ Delorie via Libffi-discuss <libffi-discuss@sourceware.org> wrote:
> 
>> While this is technically an ABI change, if the "old" ABI never worked,
>> I can't see how this would break anything by changing.
>>
>> I will add that passing structs is likely more complex than you think ;-)
> 
> The problem is that whether the old API was broken or not, changing it can break working code. What do the libffi people think about using symbol versioning?

ELF symbol versioning keeps old binaries working.

Newly recompiled programs will break in cases when recompilation
alone doesn't fix the issue.

Versioning works really well for things like new members being added to
a structure, where newly recompiled code picks up the new declaration
and so recompiling == fixing.

It won't work in a situation where some FFI-using code has worked around
for some libffi behavior and expects that not to be moving target;
then someone has to fix the code. People recompile code all the time without
fixing anything in it.





^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: Change in libffi behaviour -- large struct args
  2022-05-31 15:53 ` DJ Delorie
  2022-05-31 16:47   ` dancol
@ 2022-05-31 18:59   ` Anthony Green
  2022-05-31 23:16     ` DJ Delorie
  1 sibling, 1 reply; 9+ messages in thread
From: Anthony Green @ 2022-05-31 18:59 UTC (permalink / raw)
  To: DJ Delorie; +Cc: libffi-discuss

On Tue, May 31, 2022 at 11:53 AM DJ Delorie <dj@redhat.com> wrote:
> While this is technically an ABI change, if the "old" ABI never worked,
> I can't see how this would break anything by changing.

I wouldn't even call this an ABI change.   The new implementation will
be ABI compatible.  This is really a bug fix.   In fact, some ports
have always done the right thing.

> I will add that passing structs is likely more complex than you think ;-)

The rules about passing small structs in registers can be complex, but
libffi always did that right.  AFAICT, the only complexity around
passing large structs in memory has to do with structure alignment,
but we have all of the info needed to do that right.

I really think this is worth fixing, even after all of these years.
Users currently need to know the threshold size for structures to pass
in memory vs registers, and this varies per target, and per ABI.
It's an abstraction leak that we can easily fix without causing too
much pain (if any).

AG

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: Change in libffi behaviour -- large struct args
  2022-05-31 18:59   ` Anthony Green
@ 2022-05-31 23:16     ` DJ Delorie
  0 siblings, 0 replies; 9+ messages in thread
From: DJ Delorie @ 2022-05-31 23:16 UTC (permalink / raw)
  To: Anthony Green; +Cc: libffi-discuss

Anthony Green <green@moxielogic.com> writes:
>> While this is technically an ABI change, if the "old" ABI never worked,
>> I can't see how this would break anything by changing.
>
> I wouldn't even call this an ABI change.   The new implementation will
> be ABI compatible.  This is really a bug fix.   In fact, some ports
> have always done the right thing.

Right, I was using ABI to mean "the ABI of the target we're composing a
foreign call for", not the call ABI of the libffi library.

If we could not correctly call functions that took large structures, and
now we can, we have changed the target ABI but shouldn't break any
existing software that worked correctly before.

I agree it's worth fixing, we just must be careful we actually *don't*
break any currently-working program.


^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2022-05-31 23:16 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-05-28 13:40 Change in libffi behaviour -- large struct args Anthony Green
2022-05-28 15:38 ` dancol
2022-05-28 15:50   ` Anthony Green
2022-05-29 14:09 ` Anthony Green
2022-05-31 15:53 ` DJ Delorie
2022-05-31 16:47   ` dancol
2022-05-31 16:55     ` Kaz Kylheku
2022-05-31 18:59   ` Anthony Green
2022-05-31 23:16     ` DJ Delorie

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).