The powerpc64 ABIs align structs passed by value, a fact ignored by
gcc for quite some time. Since gcc now does the correct alignment, libffi needs to follow suit. This ought to be made selectable via a new abi value, and the #ifdefs removed from ffi.c along with many other #ifdefs present there and in assembly. I'll do that with a followup patch sometime. This is a revised version of https://sourceware.org/ml/libffi-discuss/2013/msg00162.html
This commit is contained in:
committed by
Anthony Green
parent
a97cf1fae5
commit
1c06515d92
@@ -1,3 +1,10 @@
|
|||||||
|
2013-11-16 Alan Modra <amodra@gmail.com>
|
||||||
|
|
||||||
|
* src/powerpc/ffi.c (ffi_prep_args64): Align struct parameters
|
||||||
|
according to __STRUCT_PARM_ALIGN__.
|
||||||
|
(ffi_prep_cif_machdep_core): Likewise.
|
||||||
|
(ffi_closure_helper_LINUX64): Likewise.
|
||||||
|
|
||||||
2013-11-16 Alan Modra <amodra@gmail.com>
|
2013-11-16 Alan Modra <amodra@gmail.com>
|
||||||
|
|
||||||
* src/powerpc/linux64.S (ffi_call_LINUX64): Tweak restore of r28.
|
* src/powerpc/linux64.S (ffi_call_LINUX64): Tweak restore of r28.
|
||||||
|
|||||||
@@ -439,6 +439,7 @@ ffi_prep_args64 (extended_cif *ecif, unsigned long *const stack)
|
|||||||
unsigned long *ul;
|
unsigned long *ul;
|
||||||
float *f;
|
float *f;
|
||||||
double *d;
|
double *d;
|
||||||
|
size_t p;
|
||||||
} valp;
|
} valp;
|
||||||
|
|
||||||
/* 'stacktop' points at the previous backchain pointer. */
|
/* 'stacktop' points at the previous backchain pointer. */
|
||||||
@@ -473,6 +474,9 @@ ffi_prep_args64 (extended_cif *ecif, unsigned long *const stack)
|
|||||||
double **d;
|
double **d;
|
||||||
} p_argv;
|
} p_argv;
|
||||||
unsigned long gprvalue;
|
unsigned long gprvalue;
|
||||||
|
#ifdef __STRUCT_PARM_ALIGN__
|
||||||
|
unsigned long align;
|
||||||
|
#endif
|
||||||
|
|
||||||
stacktop.c = (char *) stack + bytes;
|
stacktop.c = (char *) stack + bytes;
|
||||||
gpr_base.ul = stacktop.ul - ASM_NEEDS_REGISTERS64 - NUM_GPR_ARG_REGISTERS64;
|
gpr_base.ul = stacktop.ul - ASM_NEEDS_REGISTERS64 - NUM_GPR_ARG_REGISTERS64;
|
||||||
@@ -549,6 +553,13 @@ ffi_prep_args64 (extended_cif *ecif, unsigned long *const stack)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
case FFI_TYPE_STRUCT:
|
case FFI_TYPE_STRUCT:
|
||||||
|
#ifdef __STRUCT_PARM_ALIGN__
|
||||||
|
align = (*ptr)->alignment;
|
||||||
|
if (align > __STRUCT_PARM_ALIGN__)
|
||||||
|
align = __STRUCT_PARM_ALIGN__;
|
||||||
|
if (align > 1)
|
||||||
|
next_arg.p = ALIGN (next_arg.p, align);
|
||||||
|
#endif
|
||||||
words = ((*ptr)->size + 7) / 8;
|
words = ((*ptr)->size + 7) / 8;
|
||||||
if (next_arg.ul >= gpr_base.ul && next_arg.ul + words > gpr_end.ul)
|
if (next_arg.ul >= gpr_base.ul && next_arg.ul + words > gpr_end.ul)
|
||||||
{
|
{
|
||||||
@@ -853,6 +864,10 @@ ffi_prep_cif_machdep_core (ffi_cif *cif)
|
|||||||
else
|
else
|
||||||
for (ptr = cif->arg_types, i = cif->nargs; i > 0; i--, ptr++)
|
for (ptr = cif->arg_types, i = cif->nargs; i > 0; i--, ptr++)
|
||||||
{
|
{
|
||||||
|
#ifdef __STRUCT_PARM_ALIGN__
|
||||||
|
unsigned int align;
|
||||||
|
#endif
|
||||||
|
|
||||||
switch ((*ptr)->type)
|
switch ((*ptr)->type)
|
||||||
{
|
{
|
||||||
#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
|
#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
|
||||||
@@ -868,6 +883,14 @@ ffi_prep_cif_machdep_core (ffi_cif *cif)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case FFI_TYPE_STRUCT:
|
case FFI_TYPE_STRUCT:
|
||||||
|
#ifdef __STRUCT_PARM_ALIGN__
|
||||||
|
align = (*ptr)->alignment;
|
||||||
|
if (align > __STRUCT_PARM_ALIGN__)
|
||||||
|
align = __STRUCT_PARM_ALIGN__;
|
||||||
|
align = align / 8;
|
||||||
|
if (align > 1)
|
||||||
|
intarg_count = ALIGN (intarg_count, align);
|
||||||
|
#endif
|
||||||
intarg_count += ((*ptr)->size + 7) / 8;
|
intarg_count += ((*ptr)->size + 7) / 8;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -1399,6 +1422,9 @@ ffi_closure_helper_LINUX64 (ffi_closure *closure, void *rvalue,
|
|||||||
unsigned long i, avn, nfixedargs;
|
unsigned long i, avn, nfixedargs;
|
||||||
ffi_cif *cif;
|
ffi_cif *cif;
|
||||||
ffi_dblfl *end_pfr = pfr + NUM_FPR_ARG_REGISTERS64;
|
ffi_dblfl *end_pfr = pfr + NUM_FPR_ARG_REGISTERS64;
|
||||||
|
#ifdef __STRUCT_PARM_ALIGN__
|
||||||
|
unsigned long align;
|
||||||
|
#endif
|
||||||
|
|
||||||
cif = closure->cif;
|
cif = closure->cif;
|
||||||
avalue = alloca (cif->nargs * sizeof (void *));
|
avalue = alloca (cif->nargs * sizeof (void *));
|
||||||
@@ -1453,6 +1479,13 @@ ffi_closure_helper_LINUX64 (ffi_closure *closure, void *rvalue,
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case FFI_TYPE_STRUCT:
|
case FFI_TYPE_STRUCT:
|
||||||
|
#ifdef __STRUCT_PARM_ALIGN__
|
||||||
|
align = arg_types[i]->alignment;
|
||||||
|
if (align > __STRUCT_PARM_ALIGN__)
|
||||||
|
align = __STRUCT_PARM_ALIGN__;
|
||||||
|
if (align > 1)
|
||||||
|
pst = (unsigned long *) ALIGN ((size_t) pst, align);
|
||||||
|
#endif
|
||||||
#ifndef __LITTLE_ENDIAN__
|
#ifndef __LITTLE_ENDIAN__
|
||||||
/* Structures with size less than eight bytes are passed
|
/* Structures with size less than eight bytes are passed
|
||||||
left-padded. */
|
left-padded. */
|
||||||
|
|||||||
Reference in New Issue
Block a user