diff options
-rw-r--r-- | libffi/ChangeLog | 13 | ||||
-rw-r--r-- | libffi/src/powerpc/ffi_linux64.c | 61 |
2 files changed, 58 insertions, 16 deletions
diff --git a/libffi/ChangeLog b/libffi/ChangeLog index eaface5..837b770 100644 --- a/libffi/ChangeLog +++ b/libffi/ChangeLog @@ -1,3 +1,16 @@ +2018-05-04 Alan Modra <amodra@gmail.com> + + Import from upstream + * src/powerpc/ffi_linux64.c (discover_homogeneous_aggregate): + Compile for ELFv1 too, handling single element aggregates. + (ffi_prep_cif_linux64_core): Call discover_homogeneous_aggregate + for ELFv1. Set FLAG_RETURNS_64BITS for FFI_TYPE_POINTER return. + (ffi_prep_args64): Call discover_homogeneous_aggregate for ELFv1, + and handle single element structs containing float or double + as if the element wasn't wrapped in a struct. Store floats in + second word of doubleword slot when big-endian. + (ffi_closure_helper_LINUX64): Similarly. + 2018-04-18 David Malcolm <dmalcolm@redhat.com> PR jit/85384 diff --git a/libffi/src/powerpc/ffi_linux64.c b/libffi/src/powerpc/ffi_linux64.c index b84b91f..ef0361b 100644 --- a/libffi/src/powerpc/ffi_linux64.c +++ b/libffi/src/powerpc/ffi_linux64.c @@ -62,7 +62,6 @@ ffi_prep_types_linux64 (ffi_abi abi) #endif -#if _CALL_ELF == 2 static unsigned int discover_homogeneous_aggregate (const ffi_type *t, unsigned int *elnum) { @@ -86,8 +85,13 @@ discover_homogeneous_aggregate (const ffi_type *t, unsigned int *elnum) return 0; base_elt = el_elt; total_elnum += el_elnum; +#if _CALL_ELF == 2 if (total_elnum > 8) return 0; +#else + if (total_elnum > 1) + return 0; +#endif el++; } *elnum = total_elnum; @@ -98,7 +102,6 @@ discover_homogeneous_aggregate (const ffi_type *t, unsigned int *elnum) return 0; } } -#endif /* Perform machine dependent cif processing */ @@ -109,9 +112,7 @@ ffi_prep_cif_linux64_core (ffi_cif *cif) unsigned bytes; unsigned i, fparg_count = 0, intarg_count = 0; unsigned flags = cif->flags; -#if _CALL_ELF == 2 unsigned int elt, elnum; -#endif #if FFI_TYPE_LONGDOUBLE == FFI_TYPE_DOUBLE /* If compiled without long double support.. */ @@ -157,6 +158,7 @@ ffi_prep_cif_linux64_core (ffi_cif *cif) /* Fall through. */ case FFI_TYPE_UINT64: case FFI_TYPE_SINT64: + case FFI_TYPE_POINTER: flags |= FLAG_RETURNS_64BITS; break; @@ -222,7 +224,6 @@ ffi_prep_cif_linux64_core (ffi_cif *cif) intarg_count = ALIGN (intarg_count, align); } intarg_count += ((*ptr)->size + 7) / 8; -#if _CALL_ELF == 2 elt = discover_homogeneous_aggregate (*ptr, &elnum); if (elt) { @@ -231,7 +232,6 @@ ffi_prep_cif_linux64_core (ffi_cif *cif) flags |= FLAG_ARG_NEEDS_PSAVE; } else -#endif { if (intarg_count > NUM_GPR_ARG_REGISTERS64) flags |= FLAG_ARG_NEEDS_PSAVE; @@ -449,9 +449,7 @@ ffi_prep_args64 (extended_cif *ecif, unsigned long *const stack) i < nargs; i++, ptr++, p_argv.v++) { -#if _CALL_ELF == 2 unsigned int elt, elnum; -#endif switch ((*ptr)->type) { @@ -494,6 +492,7 @@ ffi_prep_args64 (extended_cif *ecif, unsigned long *const stack) /* Fall through. */ #endif case FFI_TYPE_DOUBLE: + do_double: double_tmp = **p_argv.d; if (fparg_count < NUM_FPR_ARG_REGISTERS64 && i < nfixedargs) { @@ -512,17 +511,30 @@ ffi_prep_args64 (extended_cif *ecif, unsigned long *const stack) break; case FFI_TYPE_FLOAT: + do_float: double_tmp = **p_argv.f; if (fparg_count < NUM_FPR_ARG_REGISTERS64 && i < nfixedargs) { *fpr_base.d++ = double_tmp; #if _CALL_ELF != 2 if ((flags & FLAG_COMPAT) != 0) - *next_arg.f = (float) double_tmp; + { +# ifndef __LITTLE_ENDIAN__ + next_arg.f[1] = (float) double_tmp; +# else + next_arg.f[0] = (float) double_tmp; +# endif + } #endif } else - *next_arg.f = (float) double_tmp; + { +# ifndef __LITTLE_ENDIAN__ + next_arg.f[1] = (float) double_tmp; +# else + next_arg.f[0] = (float) double_tmp; +# endif + } if (++next_arg.ul == gpr_end.ul) next_arg.ul = rest.ul; fparg_count++; @@ -538,10 +550,10 @@ ffi_prep_args64 (extended_cif *ecif, unsigned long *const stack) if (align > 1) next_arg.p = ALIGN (next_arg.p, align); } -#if _CALL_ELF == 2 elt = discover_homogeneous_aggregate (*ptr, &elnum); if (elt) { +#if _CALL_ELF == 2 union { void *v; float *f; @@ -583,9 +595,14 @@ ffi_prep_args64 (extended_cif *ecif, unsigned long *const stack) fparg_count++; } while (--elnum != 0); +#else + if (elt == FFI_TYPE_FLOAT) + goto do_float; + else + goto do_double; +#endif } else -#endif { words = ((*ptr)->size + 7) / 8; if (next_arg.ul >= gpr_base.ul && next_arg.ul + words > gpr_end.ul) @@ -796,12 +813,10 @@ ffi_closure_helper_LINUX64 (ffi_cif *cif, if (align > 1) pst = (unsigned long *) ALIGN ((size_t) pst, align); } - elt = 0; -#if _CALL_ELF == 2 elt = discover_homogeneous_aggregate (arg_types[i], &elnum); -#endif if (elt) { +#if _CALL_ELF == 2 union { void *v; unsigned long *ul; @@ -853,6 +868,12 @@ ffi_closure_helper_LINUX64 (ffi_cif *cif, } while (--elnum != 0); } +#else + if (elt == FFI_TYPE_FLOAT) + goto do_float; + else + goto do_double; +#endif } else { @@ -894,6 +915,7 @@ ffi_closure_helper_LINUX64 (ffi_cif *cif, /* Fall through. */ #endif case FFI_TYPE_DOUBLE: + do_double: /* On the outgoing stack all values are aligned to 8 */ /* there are 13 64bit floating point registers */ @@ -908,6 +930,7 @@ ffi_closure_helper_LINUX64 (ffi_cif *cif, break; case FFI_TYPE_FLOAT: + do_float: if (pfr < end_pfr && i < nfixedargs) { /* Float values are stored as doubles in the @@ -917,7 +940,13 @@ ffi_closure_helper_LINUX64 (ffi_cif *cif, pfr++; } else - avalue[i] = pst; + { +#ifndef __LITTLE_ENDIAN__ + avalue[i] = (char *) pst + 4; +#else + avalue[i] = pst; +#endif + } pst++; break; |