This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Align powerpc64 structs passed by value as per ABI
- From: Alan Modra <amodra at gmail dot com>
- To: gcc-patches at gcc dot gnu dot org, David Edelsohn <dje dot gcc at gmail dot com>
- Date: Sat, 16 Nov 2013 22:26:57 +1030
- Subject: Align powerpc64 structs passed by value as per ABI
- Authentication-results: sourceware.org; auth=none
- References: <20131116114805 dot GJ22514 at bubble dot grove dot modra dot org>
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 almost
all the other #ifdefs present there and in assembly.
* 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.
diff -urp gcc5/libffi/src/powerpc/ffi.c gcc6/libffi/src/powerpc/ffi.c
--- gcc5/libffi/src/powerpc/ffi.c 2013-11-15 23:47:31.890003986 +1030
+++ gcc6/libffi/src/powerpc/ffi.c 2013-11-15 23:47:40.153680507 +1030
@@ -428,6 +428,7 @@ ffi_prep_args64 (extended_cif *ecif, uns
unsigned long *ul;
float *f;
double *d;
+ size_t p;
} valp;
/* 'stacktop' points at the previous backchain pointer. */
@@ -462,6 +463,9 @@ ffi_prep_args64 (extended_cif *ecif, uns
double **d;
} p_argv;
unsigned long gprvalue;
+#ifdef __STRUCT_PARM_ALIGN__
+ unsigned long align;
+#endif
stacktop.c = (char *) stack + bytes;
gpr_base.ul = stacktop.ul - ASM_NEEDS_REGISTERS64 - NUM_GPR_ARG_REGISTERS64;
@@ -538,6 +542,13 @@ ffi_prep_args64 (extended_cif *ecif, uns
#endif
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;
if (next_arg.ul >= gpr_base.ul && next_arg.ul + words > gpr_end.ul)
{
@@ -828,6 +839,10 @@ ffi_prep_cif_machdep_core (ffi_cif *cif)
else
for (ptr = cif->arg_types, i = cif->nargs; i > 0; i--, ptr++)
{
+#ifdef __STRUCT_PARM_ALIGN__
+ unsigned int align;
+#endif
+
switch ((*ptr)->type)
{
#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
@@ -843,6 +858,14 @@ ffi_prep_cif_machdep_core (ffi_cif *cif)
break;
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;
break;
@@ -1383,6 +1406,9 @@ ffi_closure_helper_LINUX64 (ffi_closure
unsigned long i, avn, nfixedargs;
ffi_cif *cif;
ffi_dblfl *end_pfr = pfr + NUM_FPR_ARG_REGISTERS64;
+#ifdef __STRUCT_PARM_ALIGN__
+ unsigned long align;
+#endif
cif = closure->cif;
avalue = alloca (cif->nargs * sizeof (void *));
@@ -1437,6 +1463,13 @@ ffi_closure_helper_LINUX64 (ffi_closure
break;
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__
/* Structures with size less than eight bytes are passed
left-padded. */
--
Alan Modra
Australia Development Lab, IBM