https://github.com/libffi/libffi/commit/d21881f55ed4a44d464c9091871e69b0bb47611a From d21881f55ed4a44d464c9091871e69b0bb47611a Mon Sep 17 00:00:00 2001 From: kellda <59569234+kellda@users.noreply.github.com> Date: Sun, 15 Sep 2024 13:29:42 +0200 Subject: [PATCH] Fix x86/ffi64 calls with 6 gp and some sse registers (#848) * Fix x86/ffi64 calls with 6 gp and some sse registers * Add test demonstating issue when mixing gp and sse registers --- src/x86/ffi64.c | 2 +- testsuite/libffi.call/struct_int_float.c | 88 ++++++++++++++++++++++++ 2 files changed, 89 insertions(+), 1 deletion(-) create mode 100644 testsuite/libffi.call/struct_int_float.c diff --git a/src/x86/ffi64.c b/src/x86/ffi64.c index 6a8e37fc5..39f0bfd33 100644 --- a/src/x86/ffi64.c +++ b/src/x86/ffi64.c @@ -651,7 +651,7 @@ ffi_call_int (ffi_cif *cif, void (*fn)(void), void *rvalue, break; default: reg_args->gpr[gprcount] = 0; - memcpy (®_args->gpr[gprcount], a, size); + memcpy (®_args->gpr[gprcount], a, sizeof(UINT64)); } gprcount++; break; diff --git a/testsuite/libffi.call/struct_int_float.c b/testsuite/libffi.call/struct_int_float.c new file mode 100644 index 000000000..dab1d1fed --- /dev/null +++ b/testsuite/libffi.call/struct_int_float.c @@ -0,0 +1,88 @@ +/* Area: ffi_call + Purpose: Demonstrate structures with integers corrupting earlier floats + Limitations: none. + PR: #848 + Originator: kellda */ + +/* { dg-do run } */ +#include "ffitest.h" + +typedef struct +{ + unsigned long i; + float f; +} test_structure_int_float; + +static float ABI_ATTR struct_int_float(test_structure_int_float ts1, + test_structure_int_float ts2, + test_structure_int_float ts3, + test_structure_int_float ts4, + test_structure_int_float ts5, + test_structure_int_float ts6) +{ + return ts1.f; +} + +int main (void) +{ + ffi_cif cif; + ffi_type *args[MAX_ARGS]; + void *values[MAX_ARGS]; + ffi_type ts_type; + ffi_type *ts_type_elements[3]; + float rfloat; + + test_structure_int_float ts_arg[6]; + + ts_type.size = 0; + ts_type.alignment = 0; + ts_type.type = FFI_TYPE_STRUCT; + ts_type.elements = ts_type_elements; + ts_type_elements[0] = &ffi_type_ulong; + ts_type_elements[1] = &ffi_type_float; + ts_type_elements[2] = NULL; + + args[0] = &ts_type; + values[0] = &ts_arg[0]; + args[1] = &ts_type; + values[1] = &ts_arg[1]; + args[2] = &ts_type; + values[2] = &ts_arg[2]; + args[3] = &ts_type; + values[3] = &ts_arg[3]; + args[4] = &ts_type; + values[4] = &ts_arg[4]; + args[5] = &ts_type; + values[5] = &ts_arg[5]; + + /* Initialize the cif */ + CHECK(ffi_prep_cif(&cif, ABI_NUM, 6, &ffi_type_float, args) == FFI_OK); + + ts_arg[0].i = 1; + ts_arg[0].f = 1.11f; + ts_arg[1].i = 2; + ts_arg[1].f = 2.22f; + ts_arg[2].i = 3; + ts_arg[2].f = 3.33f; + ts_arg[3].i = 4; + ts_arg[3].f = 4.44f; + ts_arg[4].i = 5; + ts_arg[4].f = 5.55f; + ts_arg[5].i = 6; + ts_arg[5].f = 6.66f; + + printf ("%g\n", ts_arg[0].f); + printf ("%g\n", ts_arg[1].f); + printf ("%g\n", ts_arg[2].f); + printf ("%g\n", ts_arg[3].f); + printf ("%g\n", ts_arg[4].f); + printf ("%g\n", ts_arg[5].f); + + ffi_call(&cif, FFI_FN(struct_int_float), &rfloat, values); + + printf ("%g\n", rfloat); + + CHECK(rfloat == 1.11f); + + exit(0); +}