diff options
author | Tom Tromey <tromey@redhat.com> | 2005-09-26 19:56:22 +0000 |
---|---|---|
committer | Tom Tromey <tromey@gcc.gnu.org> | 2005-09-26 19:56:22 +0000 |
commit | d674eb2f5c198a128ea401681e2f0937587e6369 (patch) | |
tree | 46d3d81e265f2f30ae68f0c9b3ef0bd546515080 /libffi | |
parent | 608af77dc182f5ef8a440bce31713ac11d5fa8d4 (diff) | |
download | gcc-d674eb2f5c198a128ea401681e2f0937587e6369.zip gcc-d674eb2f5c198a128ea401681e2f0937587e6369.tar.gz gcc-d674eb2f5c198a128ea401681e2f0937587e6369.tar.bz2 |
float1.c (value_type): New typedef.
* testsuite/libffi.call/float1.c (value_type): New typedef.
(CANARY): New define.
(main): Check for result buffer overflow.
* src/powerpc/linux64.S: Handle linux64 long double returns.
* src/powerpc/ffi.c (FLAG_RETURNS_128BITS): New constant.
(ffi_prep_cif_machdep): Handle linux64 long double returns.
From-SVN: r104660
Diffstat (limited to 'libffi')
-rw-r--r-- | libffi/ChangeLog | 9 | ||||
-rw-r--r-- | libffi/src/powerpc/ffi.c | 7 | ||||
-rw-r--r-- | libffi/src/powerpc/linux64.S | 6 | ||||
-rw-r--r-- | libffi/testsuite/libffi.call/float1.c | 24 |
4 files changed, 41 insertions, 5 deletions
diff --git a/libffi/ChangeLog b/libffi/ChangeLog index fd61c4b..df544ba 100644 --- a/libffi/ChangeLog +++ b/libffi/ChangeLog @@ -1,3 +1,12 @@ +2005-09-26 Tom Tromey <tromey@redhat.com> + + * testsuite/libffi.call/float1.c (value_type): New typedef. + (CANARY): New define. + (main): Check for result buffer overflow. + * src/powerpc/linux64.S: Handle linux64 long double returns. + * src/powerpc/ffi.c (FLAG_RETURNS_128BITS): New constant. + (ffi_prep_cif_machdep): Handle linux64 long double returns. + 2005-08-25 Alan Modra <amodra@bigpond.net.au> PR target/23404 diff --git a/libffi/src/powerpc/ffi.c b/libffi/src/powerpc/ffi.c index cc410bc..7d8bf3a 100644 --- a/libffi/src/powerpc/ffi.c +++ b/libffi/src/powerpc/ffi.c @@ -39,6 +39,7 @@ enum { FLAG_RETURNS_NOTHING = 1 << (31-30), /* These go in cr7 */ FLAG_RETURNS_FP = 1 << (31-29), FLAG_RETURNS_64BITS = 1 << (31-28), + FLAG_RETURNS_128BITS = 1 << (31-27), FLAG_ARG_NEEDS_COPY = 1 << (31- 7), FLAG_FP_ARGUMENTS = 1 << (31- 6), /* cr1.eq; specified by ABI */ @@ -543,6 +544,12 @@ ffi_status ffi_prep_cif_machdep(ffi_cif *cif) /* else fall through. */ #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE case FFI_TYPE_LONGDOUBLE: + if (type == FFI_TYPE_LONGDOUBLE && cif->abi == FFI_LINUX64) + { + flags |= FLAG_RETURNS_128BITS; + flags |= FLAG_RETURNS_FP; + break; + } #endif intarg_count++; flags |= FLAG_RETVAL_REFERENCE; diff --git a/libffi/src/powerpc/linux64.S b/libffi/src/powerpc/linux64.S index 18423bf..25b2c4f 100644 --- a/libffi/src/powerpc/linux64.S +++ b/libffi/src/powerpc/linux64.S @@ -120,9 +120,13 @@ ffi_call_LINUX64: blr .Lfp_return_value: + bt 27, .Lfd_return_value bf 28, .Lfloat_return_value stfd %f1, 0(%r30) - stfd %f2, 8(%r30) /* It might be a long double */ + b .Ldone_return_value +.Lfd_return_value: + stfd %f1, 0(%r30) + stfd %f2, 8(%r30) b .Ldone_return_value .Lfloat_return_value: stfs %f1, 0(%r30) diff --git a/libffi/testsuite/libffi.call/float1.c b/libffi/testsuite/libffi.call/float1.c index 94636a2..fb81d7d 100644 --- a/libffi/testsuite/libffi.call/float1.c +++ b/libffi/testsuite/libffi.call/float1.c @@ -8,6 +8,14 @@ #include "ffitest.h" #include "float.h" +typedef union +{ + double d; + unsigned char c[sizeof (double)]; +} value_type; + +#define CANARY 0xba + static double dblit(float f) { return f/3.0; @@ -19,8 +27,8 @@ int main (void) ffi_type *args[MAX_ARGS]; void *values[MAX_ARGS]; float f; - double d; - + value_type result[2]; + int i; args[0] = &ffi_type_float; values[0] = &f; @@ -31,11 +39,19 @@ int main (void) f = 3.14159; - ffi_call(&cif, FFI_FN(dblit), &d, values); + /* Put a canary in the return array. This is a regression test for + a buffer overrun. */ + memset(result[1].c, CANARY, sizeof (double)); + + ffi_call(&cif, FFI_FN(dblit), &result[0].d, values); /* These are not always the same!! Check for a reasonable delta */ - CHECK(d - dblit(f) < DBL_EPSILON); + CHECK(result[0].d - dblit(f) < DBL_EPSILON); + + /* Check the canary. */ + for (i = 0; i < sizeof (double); ++i) + CHECK(result[1].c[i] == CANARY); exit(0); |