From 37067ec5036f2a6ed7a4799f83f8f53160460344 Mon Sep 17 00:00:00 2001 From: David Schneider Date: Tue, 12 Nov 2013 19:49:01 +0100 Subject: [PATCH 1/4] mark all vfp registers as used when done. To avoid assigning registers the would fit, once arguments have been on the stack, we mark all registers as used once we do not find a free register for the first time. --- src/arm/ffi.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/arm/ffi.c b/src/arm/ffi.c index d52ad022..a8444c3c 100644 --- a/src/arm/ffi.c +++ b/src/arm/ffi.c @@ -897,6 +897,9 @@ static void place_vfp_arg (ffi_cif *cif, ffi_type *t) return; next_reg: ; } + // done mark all regs as used + cif->vfp_reg_free = 16; + cif->vfp_used = 0xFFFF; } static void layout_vfp_args (ffi_cif *cif) From 77f823e31ffb557a466b24f7fba845fbf7831798 Mon Sep 17 00:00:00 2001 From: David Schneider Date: Wed, 13 Nov 2013 14:26:57 +0100 Subject: [PATCH 2/4] stop trying to assing vfp regs once we are done with the registers --- src/arm/ffi.c | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/src/arm/ffi.c b/src/arm/ffi.c index a8444c3c..09883b17 100644 --- a/src/arm/ffi.c +++ b/src/arm/ffi.c @@ -861,7 +861,7 @@ static int vfp_type_p (ffi_type *t) return 0; } -static void place_vfp_arg (ffi_cif *cif, ffi_type *t) +static int place_vfp_arg (ffi_cif *cif, ffi_type *t) { int reg = cif->vfp_reg_free; int nregs = t->size / sizeof (float); @@ -894,12 +894,13 @@ static void place_vfp_arg (ffi_cif *cif, ffi_type *t) reg += 1; cif->vfp_reg_free = reg; } - return; + return 0; next_reg: ; } - // done mark all regs as used - cif->vfp_reg_free = 16; - cif->vfp_used = 0xFFFF; + // done, mark all regs as used + cif->vfp_reg_free = 16; + cif->vfp_used = 0xFFFF; + return 1; } static void layout_vfp_args (ffi_cif *cif) @@ -914,7 +915,9 @@ static void layout_vfp_args (ffi_cif *cif) for (i = 0; i < cif->nargs; i++) { ffi_type *t = cif->arg_types[i]; - if (vfp_type_p (t)) - place_vfp_arg (cif, t); + if (vfp_type_p (t) && place_vfp_arg (cif, t) == 1) + { + break; + } } } From cdf405d574f479b782454516366bd4f4b9b3415e Mon Sep 17 00:00:00 2001 From: David Schneider Date: Wed, 13 Nov 2013 15:50:21 +0100 Subject: [PATCH 3/4] add a testcase for the double/float issue on ARMHF --- .../libffi.call/cls_many_mixed_float_double.c | 55 +++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 testsuite/libffi.call/cls_many_mixed_float_double.c diff --git a/testsuite/libffi.call/cls_many_mixed_float_double.c b/testsuite/libffi.call/cls_many_mixed_float_double.c new file mode 100644 index 00000000..62b0697a --- /dev/null +++ b/testsuite/libffi.call/cls_many_mixed_float_double.c @@ -0,0 +1,55 @@ +/* Area: closure_call + Purpose: Check register allocation for closure calls with many float and double arguments + Limitations: none. + PR: none. + Originator: */ + +/* { dg-do run } */ +#include "ffitest.h" +#include +#include + +#define NARGS 16 + +static void cls_mixed_float_double_fn(ffi_cif* cif , void* ret, void** args, + void* userdata __UNUSED__) +{ + double r = 0; + unsigned int i; + double t; + for(i=0; i < cif->nargs; i++) + { + if(cif->arg_types[i] == &ffi_type_double) { + t = *(((double**)(args))[i]); + } else { + t = *(((float**)(args))[i]); + } + r += t; + } + *((double*)ret) = r; +} +typedef double (*cls_mixed)(double, float, double, double, double, double, double, float, float, double, float, float); + +int main (void) +{ + ffi_cif cif; + ffi_closure *closure; + void* code; + ffi_type *argtypes[12] = {&ffi_type_double, &ffi_type_float, &ffi_type_double, + &ffi_type_double, &ffi_type_double, &ffi_type_double, + &ffi_type_double, &ffi_type_float, &ffi_type_float, + &ffi_type_double, &ffi_type_float, &ffi_type_float}; + + + closure = ffi_closure_alloc(sizeof(ffi_closure), (void**)&code); + if(closure ==NULL) + abort(); + CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 12, &ffi_type_double, argtypes) == FFI_OK); + CHECK(ffi_prep_closure_loc(closure, &cif, cls_mixed_float_double_fn, NULL, code) == FFI_OK); + double ret = ((cls_mixed)code)(0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0, 1.1, 1.2); + ffi_closure_free(closure); + if(fabs(ret - 7.8) < FLT_EPSILON) + exit(0); + else + abort(); +} From f3657da278dd63afcdd8762894a9bdaea8ef028a Mon Sep 17 00:00:00 2001 From: David Schneider Date: Thu, 14 Nov 2013 13:02:16 +0100 Subject: [PATCH 4/4] update Changelog --- ChangeLog | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/ChangeLog b/ChangeLog index 87a979af..a589fd9c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2013-11-14 David Schneider + + * src/arm/ffi.c: Fix register allocation for mixed float and doubles. + * testsuite/libffi.call/cls_many_mixed_float_double.c: Testcase for many + mixed float and double arguments. + 2013-11-09 Anthony Green * m4/libtool.m4: Refresh.