summaryrefslogtreecommitdiffstats
path: root/libffi
diff options
context:
space:
mode:
authorAlan Modra <amodra@gmail.com>2018-05-04 23:17:11 +0930
committerAlan Modra <amodra@gcc.gnu.org>2018-05-04 23:17:11 +0930
commit71d372eba9d83660d02d03e9f3d6f2872b8bd972 (patch)
tree8640270aa588400317c2731ffbea77b72b12cfe2 /libffi
parentbb-reorder.c (sanitize_hot_paths): Release hot_bbs_to_check. (diff)
downloadgcc-71d372eba9d83660d02d03e9f3d6f2872b8bd972.tar.gz
gcc-71d372eba9d83660d02d03e9f3d6f2872b8bd972.tar.bz2
gcc-71d372eba9d83660d02d03e9f3d6f2872b8bd972.tar.xz
libffi PowerPC64 ELFv1 fp arg fixes
The ELFv1 ABI says: "Single precision floating point values are mapped to the second word in a single doubleword" and also "Floating point registers f1 through f13 are used consecutively to pass up to 13 floating point values, one member aggregates passed by value containing a floating point value, and to pass complex floating point values". libffi wasn't expecting float args in the second word, and wasn't passing one member aggregates in fp registers. This patch fixes those problems, making use of the existing ELFv2 homogeneous aggregate support since a one element fp struct is a special case of an homogeneous aggregate. I've also set a flag when returning pointers that might be used one day. This is just a tidy since the ppc64 assembly support code currently doesn't test FLAG_RETURNS_64BITS for integer types.. * 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. From-SVN: r259934
Diffstat (limited to 'libffi')
-rw-r--r--libffi/ChangeLog13
-rw-r--r--libffi/src/powerpc/ffi_linux64.c61
2 files changed, 58 insertions, 16 deletions
diff --git a/libffi/ChangeLog b/libffi/ChangeLog
index eaface5ef2f..837b7701355 100644
--- a/libffi/ChangeLog
+++ b/libffi/ChangeLog
@@ -1,3 +1,16 @@
12018-05-04 Alan Modra <amodra@gmail.com>
2
3 Import from upstream
4 * src/powerpc/ffi_linux64.c (discover_homogeneous_aggregate):
5 Compile for ELFv1 too, handling single element aggregates.
6 (ffi_prep_cif_linux64_core): Call discover_homogeneous_aggregate
7 for ELFv1. Set FLAG_RETURNS_64BITS for FFI_TYPE_POINTER return.
8 (ffi_prep_args64): Call discover_homogeneous_aggregate for ELFv1,
9 and handle single element structs containing float or double
10 as if the element wasn't wrapped in a struct. Store floats in
11 second word of doubleword slot when big-endian.
12 (ffi_closure_helper_LINUX64): Similarly.
13
12018-04-18 David Malcolm <dmalcolm@redhat.com> 142018-04-18 David Malcolm <dmalcolm@redhat.com>
2 15
3 PR jit/85384 16 PR jit/85384
diff --git a/libffi/src/powerpc/ffi_linux64.c b/libffi/src/powerpc/ffi_linux64.c
index b84b91fb237..ef0361b24ee 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)
62#endif 62#endif
63 63
64 64
65#if _CALL_ELF == 2
66static unsigned int 65static unsigned int
67discover_homogeneous_aggregate (const ffi_type *t, unsigned int *elnum) 66discover_homogeneous_aggregate (const ffi_type *t, unsigned int *elnum)
68{ 67{
@@ -86,8 +85,13 @@ discover_homogeneous_aggregate (const ffi_type *t, unsigned int *elnum)
86 return 0; 85 return 0;
87 base_elt = el_elt; 86 base_elt = el_elt;
88 total_elnum += el_elnum; 87 total_elnum += el_elnum;
88#if _CALL_ELF == 2
89 if (total_elnum > 8) 89 if (total_elnum > 8)
90 return 0; 90 return 0;
91#else
92 if (total_elnum > 1)
93 return 0;
94#endif
91 el++; 95 el++;
92 } 96 }
93 *elnum = total_elnum; 97 *elnum = total_elnum;
@@ -98,7 +102,6 @@ discover_homogeneous_aggregate (const ffi_type *t, unsigned int *elnum)
98 return 0; 102 return 0;
99 } 103 }
100} 104}
101#endif
102 105
103 106
104/* Perform machine dependent cif processing */ 107/* Perform machine dependent cif processing */
@@ -109,9 +112,7 @@ ffi_prep_cif_linux64_core (ffi_cif *cif)
109 unsigned bytes; 112 unsigned bytes;
110 unsigned i, fparg_count = 0, intarg_count = 0; 113 unsigned i, fparg_count = 0, intarg_count = 0;
111 unsigned flags = cif->flags; 114 unsigned flags = cif->flags;
112#if _CALL_ELF == 2
113 unsigned int elt, elnum; 115 unsigned int elt, elnum;
114#endif
115 116
116#if FFI_TYPE_LONGDOUBLE == FFI_TYPE_DOUBLE 117#if FFI_TYPE_LONGDOUBLE == FFI_TYPE_DOUBLE
117 /* If compiled without long double support.. */ 118 /* If compiled without long double support.. */
@@ -157,6 +158,7 @@ ffi_prep_cif_linux64_core (ffi_cif *cif)
157 /* Fall through. */ 158 /* Fall through. */
158 case FFI_TYPE_UINT64: 159 case FFI_TYPE_UINT64:
159 case FFI_TYPE_SINT64: 160 case FFI_TYPE_SINT64:
161 case FFI_TYPE_POINTER:
160 flags |= FLAG_RETURNS_64BITS; 162 flags |= FLAG_RETURNS_64BITS;
161 break; 163 break;
162 164
@@ -222,7 +224,6 @@ ffi_prep_cif_linux64_core (ffi_cif *cif)
222 intarg_count = ALIGN (intarg_count, align); 224 intarg_count = ALIGN (intarg_count, align);
223 } 225 }
224 intarg_count += ((*ptr)->size + 7) / 8; 226 intarg_count += ((*ptr)->size + 7) / 8;
225#if _CALL_ELF == 2
226 elt = discover_homogeneous_aggregate (*ptr, &elnum); 227 elt = discover_homogeneous_aggregate (*ptr, &elnum);
227 if (elt) 228 if (elt)
228 { 229 {
@@ -231,7 +232,6 @@ ffi_prep_cif_linux64_core (ffi_cif *cif)
231 flags |= FLAG_ARG_NEEDS_PSAVE; 232 flags |= FLAG_ARG_NEEDS_PSAVE;
232 } 233 }
233 else 234 else
234#endif
235 { 235 {
236 if (intarg_count > NUM_GPR_ARG_REGISTERS64) 236 if (intarg_count > NUM_GPR_ARG_REGISTERS64)
237 flags |= FLAG_ARG_NEEDS_PSAVE; 237 flags |= FLAG_ARG_NEEDS_PSAVE;
@@ -449,9 +449,7 @@ ffi_prep_args64 (extended_cif *ecif, unsigned long *const stack)
449 i < nargs; 449 i < nargs;
450 i++, ptr++, p_argv.v++) 450 i++, ptr++, p_argv.v++)
451 { 451 {
452#if _CALL_ELF == 2
453 unsigned int elt, elnum; 452 unsigned int elt, elnum;
454#endif
455 453
456 switch ((*ptr)->type) 454 switch ((*ptr)->type)
457 { 455 {
@@ -494,6 +492,7 @@ ffi_prep_args64 (extended_cif *ecif, unsigned long *const stack)
494 /* Fall through. */ 492 /* Fall through. */
495#endif 493#endif
496 case FFI_TYPE_DOUBLE: 494 case FFI_TYPE_DOUBLE:
495 do_double:
497 double_tmp = **p_argv.d; 496 double_tmp = **p_argv.d;
498 if (fparg_count < NUM_FPR_ARG_REGISTERS64 && i < nfixedargs) 497 if (fparg_count < NUM_FPR_ARG_REGISTERS64 && i < nfixedargs)
499 { 498 {
@@ -512,17 +511,30 @@ ffi_prep_args64 (extended_cif *ecif, unsigned long *const stack)
512 break; 511 break;
513 512
514 case FFI_TYPE_FLOAT: 513 case FFI_TYPE_FLOAT:
514 do_float:
515 double_tmp = **p_argv.f; 515 double_tmp = **p_argv.f;
516 if (fparg_count < NUM_FPR_ARG_REGISTERS64 && i < nfixedargs) 516 if (fparg_count < NUM_FPR_ARG_REGISTERS64 && i < nfixedargs)
517 { 517 {
518 *fpr_base.d++ = double_tmp; 518 *fpr_base.d++ = double_tmp;
519#if _CALL_ELF != 2 519#if _CALL_ELF != 2
520 if ((flags & FLAG_COMPAT) != 0) 520 if ((flags & FLAG_COMPAT) != 0)
521 *next_arg.f = (float) double_tmp; 521 {
522# ifndef __LITTLE_ENDIAN__
523 next_arg.f[1] = (float) double_tmp;
524# else
525 next_arg.f[0] = (float) double_tmp;
526# endif
527 }
522#endif 528#endif
523 } 529 }
524 else 530 else
525 *next_arg.f = (float) double_tmp; 531 {
532# ifndef __LITTLE_ENDIAN__
533 next_arg.f[1] = (float) double_tmp;
534# else
535 next_arg.f[0] = (float) double_tmp;
536# endif
537 }
526 if (++next_arg.ul == gpr_end.ul) 538 if (++next_arg.ul == gpr_end.ul)
527 next_arg.ul = rest.ul; 539 next_arg.ul = rest.ul;
528 fparg_count++; 540 fparg_count++;
@@ -538,10 +550,10 @@ ffi_prep_args64 (extended_cif *ecif, unsigned long *const stack)
538 if (align > 1) 550 if (align > 1)
539 next_arg.p = ALIGN (next_arg.p, align); 551 next_arg.p = ALIGN (next_arg.p, align);
540 } 552 }
541#if _CALL_ELF == 2
542 elt = discover_homogeneous_aggregate (*ptr, &elnum); 553 elt = discover_homogeneous_aggregate (*ptr, &elnum);
543 if (elt) 554 if (elt)
544 { 555 {
556#if _CALL_ELF == 2
545 union { 557 union {
546 void *v; 558 void *v;
547 float *f; 559 float *f;
@@ -583,9 +595,14 @@ ffi_prep_args64 (extended_cif *ecif, unsigned long *const stack)
583 fparg_count++; 595 fparg_count++;
584 } 596 }
585 while (--elnum != 0); 597 while (--elnum != 0);
598#else
599 if (elt == FFI_TYPE_FLOAT)
600 goto do_float;
601 else
602 goto do_double;
603#endif
586 } 604 }
587 else 605 else
588#endif
589 { 606 {
590 words = ((*ptr)->size + 7) / 8; 607 words = ((*ptr)->size + 7) / 8;
591 if (next_arg.ul >= gpr_base.ul && next_arg.ul + words > gpr_end.ul) 608 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,
796 if (align > 1) 813 if (align > 1)
797 pst = (unsigned long *) ALIGN ((size_t) pst, align); 814 pst = (unsigned long *) ALIGN ((size_t) pst, align);
798 } 815 }
799 elt = 0;
800#if _CALL_ELF == 2
801 elt = discover_homogeneous_aggregate (arg_types[i], &elnum); 816 elt = discover_homogeneous_aggregate (arg_types[i], &elnum);
802#endif
803 if (elt) 817 if (elt)
804 { 818 {
819#if _CALL_ELF == 2
805 union { 820 union {
806 void *v; 821 void *v;
807 unsigned long *ul; 822 unsigned long *ul;
@@ -853,6 +868,12 @@ ffi_closure_helper_LINUX64 (ffi_cif *cif,
853 } 868 }
854 while (--elnum != 0); 869 while (--elnum != 0);
855 } 870 }
871#else
872 if (elt == FFI_TYPE_FLOAT)
873 goto do_float;
874 else
875 goto do_double;
876#endif
856 } 877 }
857 else 878 else
858 { 879 {
@@ -894,6 +915,7 @@ ffi_closure_helper_LINUX64 (ffi_cif *cif,
894 /* Fall through. */ 915 /* Fall through. */
895#endif 916#endif
896 case FFI_TYPE_DOUBLE: 917 case FFI_TYPE_DOUBLE:
918 do_double:
897 /* On the outgoing stack all values are aligned to 8 */ 919 /* On the outgoing stack all values are aligned to 8 */
898 /* there are 13 64bit floating point registers */ 920 /* there are 13 64bit floating point registers */
899 921
@@ -908,6 +930,7 @@ ffi_closure_helper_LINUX64 (ffi_cif *cif,
908 break; 930 break;
909 931
910 case FFI_TYPE_FLOAT: 932 case FFI_TYPE_FLOAT:
933 do_float:
911 if (pfr < end_pfr && i < nfixedargs) 934 if (pfr < end_pfr && i < nfixedargs)
912 { 935 {
913 /* Float values are stored as doubles in the 936 /* Float values are stored as doubles in the
@@ -917,7 +940,13 @@ ffi_closure_helper_LINUX64 (ffi_cif *cif,
917 pfr++; 940 pfr++;
918 } 941 }
919 else 942 else
920 avalue[i] = pst; 943 {
944#ifndef __LITTLE_ENDIAN__
945 avalue[i] = (char *) pst + 4;
946#else
947 avalue[i] = pst;
948#endif
949 }
921 pst++; 950 pst++;
922 break; 951 break;
923 952