x86: Honor alignment of arguments

Darwin aligns long-double to 16, and thus all of the long double
tests were failing due to not honoring that.  We ought to be able
to devise a test case for GCC using __attribute__((aligned)) that
would have failed too.
This commit is contained in:
Richard Henderson
2014-11-24 12:55:43 +01:00
parent 042b8dafee
commit 1b12593d7e

View File

@@ -332,13 +332,28 @@ ffi_call_int (ffi_cif *cif, void (*fn)(void), void *rvalue,
else
{
size_t za = ALIGN (z, FFI_SIZEOF_ARG);
size_t align = FFI_SIZEOF_ARG;
/* Alignment rules for arguments are quite complex. Vectors and
structures with 16 byte alignment get it. Note that long double
on Darwin does have 16 byte alignment, and does not get this
alignment if passed directly; a structure with a long double
inside, however, would get 16 byte alignment. Since libffi does
not support vectors, we need non concern ourselves with other
cases. */
if (t == FFI_TYPE_STRUCT && ty->alignment >= 16)
align = 16;
if (dir < 0)
{
/* ??? These reverse argument ABIs are probably too old
to have cared about alignment. Someone should check. */
argp -= za;
memcpy (argp, valp, z);
}
else
{
argp = (char *)ALIGN (argp, align);
memcpy (argp, valp, z);
argp += za;
}
@@ -419,8 +434,9 @@ ffi_closure_inner (struct closure_frame *frame, char *stack)
arg_types = cif->arg_types;
for (i = 0; i < n; ++i)
{
size_t z = arg_types[i]->size;
int t = arg_types[i]->type;
ffi_type *ty = arg_types[i];
size_t z = ty->size;
int t = ty->type;
void *valp;
if (z <= FFI_SIZEOF_ARG && t != FFI_TYPE_STRUCT)
@@ -441,13 +457,22 @@ ffi_closure_inner (struct closure_frame *frame, char *stack)
else
{
size_t za = ALIGN (z, FFI_SIZEOF_ARG);
size_t align = FFI_SIZEOF_ARG;
/* See the comment in ffi_call_int. */
if (t == FFI_TYPE_STRUCT && ty->alignment >= 16)
align = 16;
if (dir < 0)
{
/* ??? These reverse argument ABIs are probably too old
to have cared about alignment. Someone should check. */
argp -= za;
valp = argp;
}
else
{
argp = (char *)ALIGN (argp, align);
valp = argp;
argp += za;
}