This is the mail archive of the libffi-discuss@sourceware.org mailing list for the libffi project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: test results on many platforms


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.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]