This is the mail archive of the
libffi-discuss@sourceware.org
mailing list for the libffi project.
Re: test results on many platforms
- From: "Kaz Kylheku (libffi)" <382-725-6798 at kylheku dot com>
- To: Bruno Haible <bruno at clisp dot org>
- Cc: libffi-discuss at sourceware dot org
- Date: Sun, 22 Oct 2017 11:28:14 -0700
- Subject: Re: test results on many platforms
- Authentication-results: sourceware.org; auth=none
- References: <2437301.0N14NqkuRT@omega>
Hi Bruno,
I suspect that some of your ffi_call bug reports on 64 bits may be
invalid.
The return value on 64 bits, of small types, requires special treatment
due to known quirk/design flaw in the API. It was originally not
documented,
and then it was just documented as is. The way your code is doing it
is how it *should* be, but isn't.
Firstly, you must allocate a full "ffi_arg" word for the return value.
You can't just use a &int_variable pointer for the return value of
type int. The "ffi_arg" is in fact a 64 bit word.
Secondly, the return value comes out aligned funny inside this word on
big endian platforms. It is not at the base address as it would be
on little endian, but rather the value of the wider ffi_arg word is
the return value: in other words, the "int" is in the high order bytes
which are four bytes above the base address.
This situation bears some resemblance to promotion in the C language!
Or, rather, not the type promotion from char/short to int as much as
the widening in old-style calls: how char and short arguments are
actually
int arguments:
int old_style(arg)
char arg;
{
/*...*/
}
the argument is really of type int. When we call old_style((char) 42),
promotion dove-tails with this: the char expression promotes to int,
and so the correct call is generated, nonexistence of prototype
notwithstanding.
In libffi return value passage, every integer type smaller than ffi_arg
is "promoted" to ffi_arg.
Naively written code will appear to work fine on little endian 64 bit,
such as x86_64, and then flop on, say, PPC64.
I ran into this in the TXR Lisp FFI, resulting in this commit:
http://www.kylheku.com/cgit/txr/commit/ffi.c?id=10507446389cff9b072c25aa86ba35834a786fe5
My FFI type systems's virtual functions for doing "put" and "get" memory
operations had to be split into "put", "rput", "get" and "rget" with the
"r" variants doing the right thing for return values. The pad_retval
macro calculates a padded size for any given type if it is used as a
return value.
Many thanks to the helpful hints from this mailing list.