+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
#endif
-#if _CALL_ELF == 2
static unsigned int
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;
return 0;
}
}
-#endif
/* Perform machine dependent cif processing */
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.. */
/* Fall through. */
case FFI_TYPE_UINT64:
case FFI_TYPE_SINT64:
+ case FFI_TYPE_POINTER:
flags |= FLAG_RETURNS_64BITS;
break;
intarg_count = ALIGN (intarg_count, align);
}
intarg_count += ((*ptr)->size + 7) / 8;
-#if _CALL_ELF == 2
elt = discover_homogeneous_aggregate (*ptr, &elnum);
if (elt)
{
flags |= FLAG_ARG_NEEDS_PSAVE;
}
else
-#endif
{
if (intarg_count > NUM_GPR_ARG_REGISTERS64)
flags |= FLAG_ARG_NEEDS_PSAVE;
i < nargs;
i++, ptr++, p_argv.v++)
{
-#if _CALL_ELF == 2
unsigned int elt, elnum;
-#endif
switch ((*ptr)->type)
{
/* Fall through. */
#endif
case FFI_TYPE_DOUBLE:
+ do_double:
double_tmp = **p_argv.d;
if (fparg_count < NUM_FPR_ARG_REGISTERS64 && i < nfixedargs)
{
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++;
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;
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)
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;
}
while (--elnum != 0);
}
+#else
+ if (elt == FFI_TYPE_FLOAT)
+ goto do_float;
+ else
+ goto do_double;
+#endif
}
else
{
/* 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 */
break;
case FFI_TYPE_FLOAT:
+ do_float:
if (pfr < end_pfr && i < nfixedargs)
{
/* Float values are stored as doubles in the
pfr++;
}
else
- avalue[i] = pst;
+ {
+#ifndef __LITTLE_ENDIAN__
+ avalue[i] = (char *) pst + 4;
+#else
+ avalue[i] = pst;
+#endif
+ }
pst++;
break;