Commit d674eb2f by Tom Tromey Committed by Tom Tromey

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
parent 608af77d
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> 2005-08-25 Alan Modra <amodra@bigpond.net.au>
PR target/23404 PR target/23404
......
...@@ -39,6 +39,7 @@ enum { ...@@ -39,6 +39,7 @@ enum {
FLAG_RETURNS_NOTHING = 1 << (31-30), /* These go in cr7 */ FLAG_RETURNS_NOTHING = 1 << (31-30), /* These go in cr7 */
FLAG_RETURNS_FP = 1 << (31-29), FLAG_RETURNS_FP = 1 << (31-29),
FLAG_RETURNS_64BITS = 1 << (31-28), FLAG_RETURNS_64BITS = 1 << (31-28),
FLAG_RETURNS_128BITS = 1 << (31-27),
FLAG_ARG_NEEDS_COPY = 1 << (31- 7), FLAG_ARG_NEEDS_COPY = 1 << (31- 7),
FLAG_FP_ARGUMENTS = 1 << (31- 6), /* cr1.eq; specified by ABI */ FLAG_FP_ARGUMENTS = 1 << (31- 6), /* cr1.eq; specified by ABI */
...@@ -543,6 +544,12 @@ ffi_status ffi_prep_cif_machdep(ffi_cif *cif) ...@@ -543,6 +544,12 @@ ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
/* else fall through. */ /* else fall through. */
#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
case FFI_TYPE_LONGDOUBLE: case FFI_TYPE_LONGDOUBLE:
if (type == FFI_TYPE_LONGDOUBLE && cif->abi == FFI_LINUX64)
{
flags |= FLAG_RETURNS_128BITS;
flags |= FLAG_RETURNS_FP;
break;
}
#endif #endif
intarg_count++; intarg_count++;
flags |= FLAG_RETVAL_REFERENCE; flags |= FLAG_RETVAL_REFERENCE;
......
...@@ -120,9 +120,13 @@ ffi_call_LINUX64: ...@@ -120,9 +120,13 @@ ffi_call_LINUX64:
blr blr
.Lfp_return_value: .Lfp_return_value:
bt 27, .Lfd_return_value
bf 28, .Lfloat_return_value bf 28, .Lfloat_return_value
stfd %f1, 0(%r30) 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 b .Ldone_return_value
.Lfloat_return_value: .Lfloat_return_value:
stfs %f1, 0(%r30) stfs %f1, 0(%r30)
......
...@@ -8,6 +8,14 @@ ...@@ -8,6 +8,14 @@
#include "ffitest.h" #include "ffitest.h"
#include "float.h" #include "float.h"
typedef union
{
double d;
unsigned char c[sizeof (double)];
} value_type;
#define CANARY 0xba
static double dblit(float f) static double dblit(float f)
{ {
return f/3.0; return f/3.0;
...@@ -19,8 +27,8 @@ int main (void) ...@@ -19,8 +27,8 @@ int main (void)
ffi_type *args[MAX_ARGS]; ffi_type *args[MAX_ARGS];
void *values[MAX_ARGS]; void *values[MAX_ARGS];
float f; float f;
double d; value_type result[2];
int i;
args[0] = &ffi_type_float; args[0] = &ffi_type_float;
values[0] = &f; values[0] = &f;
...@@ -31,11 +39,19 @@ int main (void) ...@@ -31,11 +39,19 @@ int main (void)
f = 3.14159; 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 */ /* 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); exit(0);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment