2014-07-22 Dominik Vogt <vogt@linux.vnet.ibm.com>
* src/types.c (FFI_TYPEDEF, FFI_NONCONST_TYPEDEF): Merge the macros by adding another argument that controls whether the result is const or not (FFI_LDBL_CONST): Temporary macro to reduce ifdef confusion * src/prep_cif.c (ffi_prep_cif_core): Replace list of systems with new macro FFI_TARGET_SPECIFIC_STACK_SPACE_ALLOCATION * src/pa/ffitarget.h (FFI_TARGET_SPECIFIC_STACK_SPACE_ALLOCATION): Define. * src/s390/ffitarget.h (FFI_TARGET_SPECIFIC_STACK_SPACE_ALLOCATION): Define. * src/x86/ffitarget.h (FFI_TARGET_SPECIFIC_STACK_SPACE_ALLOCATION): Define. 2014-07-22 Dominik Vogt <vogt@linux.vnet.ibm.com> * doc/libffi.texi (Primitive Types): Document ffi_type_complex_float, ffi_type_complex_double and ffi_type_complex_longdouble (Complex Types): New subsection. (Complex Type Example): Ditto. * testsuite/libffi.call/cls_align_complex_double.c: New FFI_TYPE_COMPLEX test. * testsuite/libffi.call/cls_align_complex_float.c: Ditto. * testsuite/libffi.call/cls_align_complex_longdouble.c: Ditto. * testsuite/libffi.call/cls_complex_double.c: Ditto. * testsuite/libffi.call/cls_complex_float.c: Ditto. * testsuite/libffi.call/cls_complex_longdouble.c: Ditto. * testsuite/libffi.call/cls_complex_struct_double.c: Ditto. * testsuite/libffi.call/cls_complex_struct_float.c: Ditto. * testsuite/libffi.call/cls_complex_struct_longdouble.c: Ditto. * testsuite/libffi.call/cls_complex_va_double.c: Ditto. * testsuite/libffi.call/cls_complex_va_float.c: Ditto. * testsuite/libffi.call/cls_complex_va_longdouble.c: Ditto. * testsuite/libffi.call/complex_double.c: Ditto. * testsuite/libffi.call/complex_defs_double.c: Ditto. * testsuite/libffi.call/complex_float.c: Ditto. * testsuite/libffi.call/complex_defs_float.c: Ditto. * testsuite/libffi.call/complex_longdouble.c: Ditto. * testsuite/libffi.call/complex_defs_longdouble.c: Ditto. * testsuite/libffi.call/complex_int.c: Ditto. * testsuite/libffi.call/many_complex_double.c: Ditto. * testsuite/libffi.call/many_complex_float.c: Ditto. * testsuite/libffi.call/many_complex_longdouble.c: Ditto. * testsuite/libffi.call/return_complex1_double.c: Ditto. * testsuite/libffi.call/return_complex1_float.c: Ditto. * testsuite/libffi.call/return_complex1_longdouble.c: Ditto. * testsuite/libffi.call/return_complex2_double.c: Ditto. * testsuite/libffi.call/return_complex2_float.c: Ditto. * testsuite/libffi.call/return_complex2_longdouble.c: Ditto. * testsuite/libffi.call/return_complex_double.c: Ditto. * testsuite/libffi.call/return_complex_float.c: Ditto. * testsuite/libffi.call/return_complex_longdouble.c: Ditto. * src/raw_api.c (ffi_raw_to_ptrarray): Handle FFI_TYPE_COMPLEX (ffi_ptrarray_to_raw): Ditto. * src/prep_cif.c (ffi_prep_cif_core): Abort if FFI_TYPE_COMPLEX is not implemented in libffi for the target. * src/java_raw_api.c (ffi_java_raw_size): FFI_TYPE_COMPLEX not supported yet (abort). (ffi_java_raw_to_ptrarray): Ditto. (ffi_java_rvalue_to_raw): Ditto. (ffi_java_raw_to_rvalue): Ditto. * src/debug.c (ffi_type_test): Add debug tests for complex types. * include/ffi.h.in (FFI_TYPE_COMPLEX): Add new FFI_TYPE_COMPLEX. (FFI_TYPE_LAST): Bump. (ffi_type_complex_float): Add new ffi_type_.... (ffi_type_complex_double): Ditto. (ffi_type_complex_longdouble): Ditto. 2014-07-22 Dominik Vogt <vogt@linux.vnet.ibm.com> * src/s390/ffitarget.h (FFI_TARGET_HAS_COMPLEX_TYPE): Define to provide FFI_TYPE_COMPLEX support. * src/s390/ffi.c (ffi_check_struct_type): Implement FFI_TYPE_COMPLEX (ffi_prep_args): Ditto. (ffi_prep_cif_machdep): Ditto. (ffi_closure_helper_SYSV): Ditto.
This commit is contained in:
committed by
Anthony Green
parent
4c5c4088aa
commit
6e8a446083
145
doc/libffi.texi
145
doc/libffi.texi
@@ -247,6 +247,8 @@ int main()
|
||||
* Primitive Types:: Built-in types.
|
||||
* Structures:: Structure types.
|
||||
* Type Example:: Structure type example.
|
||||
* Complex:: Complex types.
|
||||
* Complex Type Example:: Complex type example.
|
||||
@end menu
|
||||
|
||||
@node Primitive Types
|
||||
@@ -345,6 +347,20 @@ On other platforms, it is not.
|
||||
@tindex ffi_type_pointer
|
||||
A generic @code{void *} pointer. You should use this for all
|
||||
pointers, regardless of their real type.
|
||||
|
||||
@item ffi_type_complex_float
|
||||
@tindex ffi_type_complex_float
|
||||
The C @code{_Complex float} type.
|
||||
|
||||
@item ffi_type_complex_double
|
||||
@tindex ffi_type_complex_double
|
||||
The C @code{_Complex double} type.
|
||||
|
||||
@item ffi_type_complex_longdouble
|
||||
@tindex ffi_type_complex_longdouble
|
||||
The C @code{_Complex long double} type.
|
||||
On platforms that have a C @code{long double} type, this is defined.
|
||||
On other platforms, it is not.
|
||||
@end table
|
||||
|
||||
Each of these is of type @code{ffi_type}, so you must take the address
|
||||
@@ -429,6 +445,135 @@ Here is the corresponding code to describe this struct to
|
||||
@}
|
||||
@end example
|
||||
|
||||
@node Complex
|
||||
@subsection Complex Types
|
||||
|
||||
@samp{libffi} supports the complex types defined by the C99
|
||||
standard (@code{_Complex float}, @code{_Complex double} and
|
||||
@code{_Complex long double} with the built-in type descriptors
|
||||
@code{ffi_type_complex_float}, @code{ffi_type_complex_double} and
|
||||
@code{ffi_type_complex_longdouble}.
|
||||
|
||||
Custom complex types like @code{_Complex int} can also be used.
|
||||
An @code{ffi_type} object has to be defined to describe the
|
||||
complex type to @samp{libffi}.
|
||||
|
||||
@tindex ffi_type
|
||||
@deftp {Data type} ffi_type
|
||||
@table @code
|
||||
@item size_t size
|
||||
This must be manually set to the size of the complex type.
|
||||
|
||||
@item unsigned short alignment
|
||||
This must be manually set to the alignment of the complex type.
|
||||
|
||||
@item unsigned short type
|
||||
For a complex type, this must be set to @code{FFI_TYPE_COMPLEX}.
|
||||
|
||||
@item ffi_type **elements
|
||||
|
||||
This is a @samp{NULL}-terminated array of pointers to
|
||||
@code{ffi_type} objects. The first element is set to the
|
||||
@code{ffi_type} of the complex's base type. The second element
|
||||
must be set to @code{NULL}.
|
||||
@end table
|
||||
@end deftp
|
||||
|
||||
The section @ref{Complex Type Example} shows a way to determine
|
||||
the @code{size} and @code{alignment} members in a platform
|
||||
independent way.
|
||||
|
||||
For platforms that have no complex support in @code{libffi} yet,
|
||||
the functions @code{ffi_prep_cif} and @code{ffi_prep_args} abort
|
||||
the program if they encounter a complex type.
|
||||
|
||||
@node Complex Type Example
|
||||
@subsection Complex Type Example
|
||||
|
||||
This example demonstrates how to use complex types:
|
||||
|
||||
@example
|
||||
#include <stdio.h>
|
||||
#include <ffi.h>
|
||||
#include <complex.h>
|
||||
|
||||
void complex_fn(_Complex float cf,
|
||||
_Complex double cd,
|
||||
_Complex long double cld)
|
||||
@{
|
||||
printf("cf=%f+%fi\ncd=%f+%fi\ncld=%f+%fi\n",
|
||||
(float)creal (cf), (float)cimag (cf),
|
||||
(float)creal (cd), (float)cimag (cd),
|
||||
(float)creal (cld), (float)cimag (cld));
|
||||
@}
|
||||
|
||||
int main()
|
||||
@{
|
||||
ffi_cif cif;
|
||||
ffi_type *args[3];
|
||||
void *values[3];
|
||||
_Complex float cf;
|
||||
_Complex double cd;
|
||||
_Complex long double cld;
|
||||
|
||||
/* Initialize the argument info vectors */
|
||||
args[0] = &ffi_type_complex_float;
|
||||
args[1] = &ffi_type_complex_double;
|
||||
args[2] = &ffi_type_complex_longdouble;
|
||||
values[0] = &cf;
|
||||
values[1] = &cd;
|
||||
values[2] = &cld;
|
||||
|
||||
/* Initialize the cif */
|
||||
if (ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 3,
|
||||
&ffi_type_void, args) == FFI_OK)
|
||||
@{
|
||||
cf = 1.0 + 20.0 * I;
|
||||
cd = 300.0 + 4000.0 * I;
|
||||
cld = 50000.0 + 600000.0 * I;
|
||||
/* Call the function */
|
||||
ffi_call(&cif, (void (*)(void))complex_fn, 0, values);
|
||||
@}
|
||||
|
||||
return 0;
|
||||
@}
|
||||
@end example
|
||||
|
||||
This is an example for defining a custom complex type descriptor
|
||||
for compilers that support them:
|
||||
|
||||
@example
|
||||
/*
|
||||
* This macro can be used to define new complex type descriptors
|
||||
* in a platform independent way.
|
||||
*
|
||||
* name: Name of the new descriptor is ffi_type_complex_<name>.
|
||||
* type: The C base type of the complex type.
|
||||
*/
|
||||
#define FFI_COMPLEX_TYPEDEF(name, type, ffitype) \
|
||||
static ffi_type *ffi_elements_complex_##name [2] = @{ \
|
||||
(ffi_type *)(&ffitype), NULL \
|
||||
@}; \
|
||||
struct struct_align_complex_##name @{ \
|
||||
char c; \
|
||||
_Complex type x; \
|
||||
@}; \
|
||||
ffi_type ffi_type_complex_##name = @{ \
|
||||
sizeof(_Complex type), \
|
||||
offsetof(struct struct_align_complex_##name, x), \
|
||||
FFI_TYPE_COMPLEX, \
|
||||
(ffi_type **)ffi_elements_complex_##name \
|
||||
@}
|
||||
|
||||
/* Define new complex type descriptors using the macro: */
|
||||
/* ffi_type_complex_sint */
|
||||
FFI_COMPLEX_TYPEDEF(sint, int, ffi_type_sint);
|
||||
/* ffi_type_complex_uchar */
|
||||
FFI_COMPLEX_TYPEDEF(uchar, unsigned char, ffi_type_uint8);
|
||||
@end example
|
||||
|
||||
The new type descriptors can then be used like one of the built-in
|
||||
type descriptors in the previous example.
|
||||
|
||||
@node Multiple ABIs
|
||||
@section Multiple ABIs
|
||||
|
||||
@@ -199,6 +199,16 @@ FFI_EXTERN ffi_type ffi_type_longdouble;
|
||||
#else
|
||||
#define ffi_type_longdouble ffi_type_double
|
||||
#endif
|
||||
|
||||
#ifdef FFI_TARGET_HAS_COMPLEX_TYPE
|
||||
FFI_EXTERN ffi_type ffi_type_complex_float;
|
||||
FFI_EXTERN ffi_type ffi_type_complex_double;
|
||||
#if @HAVE_LONG_DOUBLE@
|
||||
FFI_EXTERN ffi_type ffi_type_complex_longdouble;
|
||||
#else
|
||||
#define ffi_type_complex_longdouble ffi_type_complex_double
|
||||
#endif
|
||||
#endif
|
||||
#endif /* LIBFFI_HIDE_BASIC_TYPES */
|
||||
|
||||
typedef enum {
|
||||
@@ -465,9 +475,10 @@ void ffi_call(ffi_cif *cif,
|
||||
#define FFI_TYPE_SINT64 12
|
||||
#define FFI_TYPE_STRUCT 13
|
||||
#define FFI_TYPE_POINTER 14
|
||||
#define FFI_TYPE_COMPLEX 15
|
||||
|
||||
/* This should always refer to the last type code (for sanity checks) */
|
||||
#define FFI_TYPE_LAST FFI_TYPE_POINTER
|
||||
#define FFI_TYPE_LAST FFI_TYPE_COMPLEX
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@@ -54,6 +54,11 @@ void ffi_type_test(ffi_type *a, char *file, int line)
|
||||
FFI_ASSERT_AT(a->type <= FFI_TYPE_LAST, file, line);
|
||||
FFI_ASSERT_AT(a->type == FFI_TYPE_VOID || a->size > 0, file, line);
|
||||
FFI_ASSERT_AT(a->type == FFI_TYPE_VOID || a->alignment > 0, file, line);
|
||||
FFI_ASSERT_AT(a->type != FFI_TYPE_STRUCT || a->elements != NULL, file, line);
|
||||
FFI_ASSERT_AT((a->type != FFI_TYPE_STRUCT && a->type != FFI_TYPE_COMPLEX)
|
||||
|| a->elements != NULL, file, line);
|
||||
FFI_ASSERT_AT(a->type != FFI_TYPE_COMPLEX
|
||||
|| (a->elements != NULL
|
||||
&& a->elements[0] != NULL && a->elements[1] == NULL),
|
||||
file, line);
|
||||
|
||||
}
|
||||
|
||||
@@ -60,6 +60,9 @@ ffi_java_raw_size (ffi_cif *cif)
|
||||
case FFI_TYPE_STRUCT:
|
||||
/* No structure parameters in Java. */
|
||||
abort();
|
||||
case FFI_TYPE_COMPLEX:
|
||||
/* Not supported yet. */
|
||||
abort();
|
||||
default:
|
||||
result += FFI_SIZEOF_JAVA_RAW;
|
||||
}
|
||||
@@ -104,6 +107,10 @@ ffi_java_raw_to_ptrarray (ffi_cif *cif, ffi_java_raw *raw, void **args)
|
||||
*args = (void*) &(raw++)->ptr;
|
||||
break;
|
||||
|
||||
case FFI_TYPE_COMPLEX:
|
||||
/* Not supported yet. */
|
||||
abort();
|
||||
|
||||
default:
|
||||
*args = raw;
|
||||
raw +=
|
||||
@@ -126,6 +133,9 @@ ffi_java_raw_to_ptrarray (ffi_cif *cif, ffi_java_raw *raw, void **args)
|
||||
*args = (void*) raw;
|
||||
raw += 2;
|
||||
break;
|
||||
case FFI_TYPE_COMPLEX:
|
||||
/* Not supported yet. */
|
||||
abort();
|
||||
default:
|
||||
*args = (void*) raw++;
|
||||
}
|
||||
@@ -254,6 +264,10 @@ ffi_java_rvalue_to_raw (ffi_cif *cif, void *rvalue)
|
||||
*(SINT64 *)rvalue <<= 32;
|
||||
break;
|
||||
|
||||
case FFI_TYPE_COMPLEX:
|
||||
/* Not supported yet. */
|
||||
abort();
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -279,6 +293,10 @@ ffi_java_raw_to_rvalue (ffi_cif *cif, void *rvalue)
|
||||
*(SINT64 *)rvalue >>= 32;
|
||||
break;
|
||||
|
||||
case FFI_TYPE_COMPLEX:
|
||||
/* Not supported yet. */
|
||||
abort();
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -62,6 +62,8 @@ typedef enum ffi_abi {
|
||||
} ffi_abi;
|
||||
#endif
|
||||
|
||||
#define FFI_TARGET_SPECIFIC_STACK_SPACE_ALLOCATION
|
||||
|
||||
/* ---- Definitions for closures ----------------------------------------- */
|
||||
|
||||
#define FFI_CLOSURES 1
|
||||
|
||||
@@ -136,11 +136,15 @@ ffi_status FFI_HIDDEN ffi_prep_cif_core(ffi_cif *cif, ffi_abi abi,
|
||||
if ((cif->rtype->size == 0) && (initialize_aggregate(cif->rtype) != FFI_OK))
|
||||
return FFI_BAD_TYPEDEF;
|
||||
|
||||
#ifndef FFI_TARGET_HAS_COMPLEX_TYPE
|
||||
if (rtype->type == FFI_TYPE_COMPLEX)
|
||||
abort();
|
||||
#endif
|
||||
/* Perform a sanity check on the return type */
|
||||
FFI_ASSERT_VALID_TYPE(cif->rtype);
|
||||
|
||||
/* x86, x86-64 and s390 stack space allocation is handled in prep_machdep. */
|
||||
#if !defined M68K && !defined X86_ANY && !defined S390 && !defined PA
|
||||
#if !defined FFI_TARGET_SPECIFIC_STACK_SPACE_ALLOCATION
|
||||
/* Make space for the return structure pointer */
|
||||
if (cif->rtype->type == FFI_TYPE_STRUCT
|
||||
#ifdef SPARC
|
||||
@@ -166,11 +170,15 @@ ffi_status FFI_HIDDEN ffi_prep_cif_core(ffi_cif *cif, ffi_abi abi,
|
||||
if (((*ptr)->size == 0) && (initialize_aggregate((*ptr)) != FFI_OK))
|
||||
return FFI_BAD_TYPEDEF;
|
||||
|
||||
#ifndef FFI_TARGET_HAS_COMPLEX_TYPE
|
||||
if ((*ptr)->type == FFI_TYPE_COMPLEX)
|
||||
abort();
|
||||
#endif
|
||||
/* Perform a sanity check on the argument type, do this
|
||||
check after the initialization. */
|
||||
FFI_ASSERT_VALID_TYPE(*ptr);
|
||||
|
||||
#if !defined X86_ANY && !defined S390 && !defined PA
|
||||
#if !defined FFI_TARGET_SPECIFIC_STACK_SPACE_ALLOCATION
|
||||
#ifdef SPARC
|
||||
if (((*ptr)->type == FFI_TYPE_STRUCT
|
||||
&& ((*ptr)->size > 16 || cif->abi != FFI_V9))
|
||||
|
||||
@@ -88,6 +88,10 @@ ffi_raw_to_ptrarray (ffi_cif *cif, ffi_raw *raw, void **args)
|
||||
break;
|
||||
#endif
|
||||
|
||||
case FFI_TYPE_COMPLEX:
|
||||
*args = (raw++)->ptr;
|
||||
break;
|
||||
|
||||
case FFI_TYPE_POINTER:
|
||||
*args = (void*) &(raw++)->ptr;
|
||||
break;
|
||||
@@ -112,6 +116,11 @@ ffi_raw_to_ptrarray (ffi_cif *cif, ffi_raw *raw, void **args)
|
||||
}
|
||||
else
|
||||
#endif
|
||||
if ((*tp)->type == FFI_TYPE_COMPLEX)
|
||||
{
|
||||
*args = (raw++)->ptr;
|
||||
}
|
||||
else
|
||||
{
|
||||
*args = (void*) raw;
|
||||
raw += ALIGN ((*tp)->size, sizeof (void*)) / sizeof (void*);
|
||||
@@ -167,6 +176,10 @@ ffi_ptrarray_to_raw (ffi_cif *cif, void **args, ffi_raw *raw)
|
||||
break;
|
||||
#endif
|
||||
|
||||
case FFI_TYPE_COMPLEX:
|
||||
(raw++)->ptr = *args;
|
||||
break;
|
||||
|
||||
case FFI_TYPE_POINTER:
|
||||
(raw++)->ptr = **(void***) args;
|
||||
break;
|
||||
|
||||
@@ -215,9 +215,12 @@ ffi_prep_args (unsigned char *stack, extended_cif *ecif)
|
||||
#endif
|
||||
|
||||
/* Check how a structure type is passed. */
|
||||
if (type == FFI_TYPE_STRUCT)
|
||||
if (type == FFI_TYPE_STRUCT || type == FFI_TYPE_COMPLEX)
|
||||
{
|
||||
type = ffi_check_struct_type (*ptr);
|
||||
if (type == FFI_TYPE_COMPLEX)
|
||||
type = FFI_TYPE_POINTER;
|
||||
else
|
||||
type = ffi_check_struct_type (*ptr);
|
||||
|
||||
/* If we pass the struct via pointer, copy the data. */
|
||||
if (type == FFI_TYPE_POINTER)
|
||||
@@ -356,8 +359,9 @@ ffi_prep_cif_machdep(ffi_cif *cif)
|
||||
cif->flags = FFI390_RET_VOID;
|
||||
break;
|
||||
|
||||
/* Structures are returned via a hidden pointer. */
|
||||
/* Structures and complex are returned via a hidden pointer. */
|
||||
case FFI_TYPE_STRUCT:
|
||||
case FFI_TYPE_COMPLEX:
|
||||
cif->flags = FFI390_RET_STRUCT;
|
||||
n_gpr++; /* We need one GPR to pass the pointer. */
|
||||
break;
|
||||
@@ -420,9 +424,12 @@ ffi_prep_cif_machdep(ffi_cif *cif)
|
||||
#endif
|
||||
|
||||
/* Check how a structure type is passed. */
|
||||
if (type == FFI_TYPE_STRUCT)
|
||||
if (type == FFI_TYPE_STRUCT || type == FFI_TYPE_COMPLEX)
|
||||
{
|
||||
type = ffi_check_struct_type (*ptr);
|
||||
if (type == FFI_TYPE_COMPLEX)
|
||||
type = FFI_TYPE_POINTER;
|
||||
else
|
||||
type = ffi_check_struct_type (*ptr);
|
||||
|
||||
/* If we pass the struct via pointer, we must reserve space
|
||||
to copy its data for proper call-by-value semantics. */
|
||||
@@ -588,9 +595,12 @@ ffi_closure_helper_SYSV (ffi_closure *closure,
|
||||
#endif
|
||||
|
||||
/* Check how a structure type is passed. */
|
||||
if (type == FFI_TYPE_STRUCT)
|
||||
if (type == FFI_TYPE_STRUCT || type == FFI_TYPE_COMPLEX)
|
||||
{
|
||||
type = ffi_check_struct_type (*ptr);
|
||||
if (type == FFI_TYPE_COMPLEX)
|
||||
type = FFI_TYPE_POINTER;
|
||||
else
|
||||
type = ffi_check_struct_type (*ptr);
|
||||
|
||||
/* If we pass the struct via pointer, remember to
|
||||
retrieve the pointer later. */
|
||||
@@ -687,6 +697,7 @@ ffi_closure_helper_SYSV (ffi_closure *closure,
|
||||
/* Void is easy, and so is struct. */
|
||||
case FFI_TYPE_VOID:
|
||||
case FFI_TYPE_STRUCT:
|
||||
case FFI_TYPE_COMPLEX:
|
||||
#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
|
||||
case FFI_TYPE_LONGDOUBLE:
|
||||
#endif
|
||||
|
||||
@@ -52,6 +52,8 @@ typedef enum ffi_abi {
|
||||
} ffi_abi;
|
||||
#endif
|
||||
|
||||
#define FFI_TARGET_SPECIFIC_STACK_SPACE_ALLOCATION
|
||||
#define FFI_TARGET_HAS_COMPLEX_TYPE
|
||||
|
||||
/* ---- Definitions for closures ----------------------------------------- */
|
||||
|
||||
|
||||
68
src/types.c
68
src/types.c
@@ -33,26 +33,30 @@
|
||||
|
||||
/* Type definitions */
|
||||
|
||||
#define FFI_TYPEDEF(name, type, id) \
|
||||
#define FFI_TYPEDEF(name, type, id, maybe_const)\
|
||||
struct struct_align_##name { \
|
||||
char c; \
|
||||
type x; \
|
||||
}; \
|
||||
const ffi_type ffi_type_##name = { \
|
||||
maybe_const ffi_type ffi_type_##name = { \
|
||||
sizeof(type), \
|
||||
offsetof(struct struct_align_##name, x), \
|
||||
id, NULL \
|
||||
}
|
||||
|
||||
#define FFI_NONCONST_TYPEDEF(name, type, id) \
|
||||
struct struct_align_##name { \
|
||||
char c; \
|
||||
type x; \
|
||||
}; \
|
||||
ffi_type ffi_type_##name = { \
|
||||
sizeof(type), \
|
||||
offsetof(struct struct_align_##name, x), \
|
||||
id, NULL \
|
||||
#define FFI_COMPLEX_TYPEDEF(name, type, maybe_const) \
|
||||
static ffi_type *ffi_elements_complex_##name [2] = { \
|
||||
(ffi_type *)(&ffi_type_##name), NULL \
|
||||
}; \
|
||||
struct struct_align_complex_##name { \
|
||||
char c; \
|
||||
_Complex type x; \
|
||||
}; \
|
||||
maybe_const ffi_type ffi_type_complex_##name = { \
|
||||
sizeof(_Complex type), \
|
||||
offsetof(struct struct_align_complex_##name, x), \
|
||||
FFI_TYPE_COMPLEX, \
|
||||
(ffi_type **)ffi_elements_complex_##name \
|
||||
}
|
||||
|
||||
/* Size and alignment are fake here. They must not be 0. */
|
||||
@@ -60,19 +64,25 @@ const ffi_type ffi_type_void = {
|
||||
1, 1, FFI_TYPE_VOID, NULL
|
||||
};
|
||||
|
||||
FFI_TYPEDEF(uint8, UINT8, FFI_TYPE_UINT8);
|
||||
FFI_TYPEDEF(sint8, SINT8, FFI_TYPE_SINT8);
|
||||
FFI_TYPEDEF(uint16, UINT16, FFI_TYPE_UINT16);
|
||||
FFI_TYPEDEF(sint16, SINT16, FFI_TYPE_SINT16);
|
||||
FFI_TYPEDEF(uint32, UINT32, FFI_TYPE_UINT32);
|
||||
FFI_TYPEDEF(sint32, SINT32, FFI_TYPE_SINT32);
|
||||
FFI_TYPEDEF(uint64, UINT64, FFI_TYPE_UINT64);
|
||||
FFI_TYPEDEF(sint64, SINT64, FFI_TYPE_SINT64);
|
||||
FFI_TYPEDEF(uint8, UINT8, FFI_TYPE_UINT8, const);
|
||||
FFI_TYPEDEF(sint8, SINT8, FFI_TYPE_SINT8, const);
|
||||
FFI_TYPEDEF(uint16, UINT16, FFI_TYPE_UINT16, const);
|
||||
FFI_TYPEDEF(sint16, SINT16, FFI_TYPE_SINT16, const);
|
||||
FFI_TYPEDEF(uint32, UINT32, FFI_TYPE_UINT32, const);
|
||||
FFI_TYPEDEF(sint32, SINT32, FFI_TYPE_SINT32, const);
|
||||
FFI_TYPEDEF(uint64, UINT64, FFI_TYPE_UINT64, const);
|
||||
FFI_TYPEDEF(sint64, SINT64, FFI_TYPE_SINT64, const);
|
||||
|
||||
FFI_TYPEDEF(pointer, void*, FFI_TYPE_POINTER);
|
||||
FFI_TYPEDEF(pointer, void*, FFI_TYPE_POINTER, const);
|
||||
|
||||
FFI_TYPEDEF(float, float, FFI_TYPE_FLOAT);
|
||||
FFI_TYPEDEF(double, double, FFI_TYPE_DOUBLE);
|
||||
FFI_TYPEDEF(float, float, FFI_TYPE_FLOAT, const);
|
||||
FFI_TYPEDEF(double, double, FFI_TYPE_DOUBLE, const);
|
||||
|
||||
#if !defined HAVE_LONG_DOUBLE_VARIANT || defined __alpha__
|
||||
#define FFI_LDBL_CONST const
|
||||
#else
|
||||
#define FFI_LDBL_CONST
|
||||
#endif
|
||||
|
||||
#ifdef __alpha__
|
||||
/* Even if we're not configured to default to 128-bit long double,
|
||||
@@ -84,9 +94,13 @@ FFI_TYPEDEF(double, double, FFI_TYPE_DOUBLE);
|
||||
# endif
|
||||
const ffi_type ffi_type_longdouble = { 16, 16, 4, NULL };
|
||||
#elif FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
|
||||
# if HAVE_LONG_DOUBLE_VARIANT
|
||||
FFI_NONCONST_TYPEDEF(longdouble, long double, FFI_TYPE_LONGDOUBLE);
|
||||
# else
|
||||
FFI_TYPEDEF(longdouble, long double, FFI_TYPE_LONGDOUBLE);
|
||||
# endif
|
||||
FFI_TYPEDEF(longdouble, long double, FFI_TYPE_LONGDOUBLE, FFI_LDBL_CONST);
|
||||
#endif
|
||||
|
||||
#ifdef FFI_TARGET_HAS_COMPLEX_TYPE
|
||||
FFI_COMPLEX_TYPEDEF(float, float, const);
|
||||
FFI_COMPLEX_TYPEDEF(double, double, const);
|
||||
#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
|
||||
FFI_COMPLEX_TYPEDEF(longdouble, long double, FFI_LDBL_CONST);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -49,6 +49,8 @@
|
||||
#define USE_BUILTIN_FFS 0 /* not yet implemented in mingw-64 */
|
||||
#endif
|
||||
|
||||
#define FFI_TARGET_SPECIFIC_STACK_SPACE_ALLOCATION
|
||||
|
||||
/* ---- Generic type definitions ----------------------------------------- */
|
||||
|
||||
#ifndef LIBFFI_ASM
|
||||
|
||||
91
testsuite/libffi.call/cls_align_complex.inc
Normal file
91
testsuite/libffi.call/cls_align_complex.inc
Normal file
@@ -0,0 +1,91 @@
|
||||
/* -*-c-*- */
|
||||
#include "ffitest.h"
|
||||
#include <complex.h>
|
||||
|
||||
typedef struct cls_struct_align {
|
||||
unsigned char a;
|
||||
_Complex T_C_TYPE b;
|
||||
unsigned char c;
|
||||
} cls_struct_align;
|
||||
|
||||
cls_struct_align cls_struct_align_fn(
|
||||
struct cls_struct_align a1, struct cls_struct_align a2)
|
||||
{
|
||||
struct cls_struct_align result;
|
||||
|
||||
result.a = a1.a + a2.a;
|
||||
result.b = a1.b + a2.b;
|
||||
result.c = a1.c + a2.c;
|
||||
|
||||
printf("%d %f,%fi %d %d %f,%fi %d: %d %f,%fi %d\n",
|
||||
a1.a, T_CONV creal (a1.b), T_CONV cimag (a1.b), a1.c,
|
||||
a2.a, T_CONV creal (a2.b), T_CONV cimag (a2.b), a2.c,
|
||||
result.a, T_CONV creal (result.b), T_CONV cimag (result.b), result.c);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static void
|
||||
cls_struct_align_gn(ffi_cif* cif __UNUSED__, void* resp, void** args,
|
||||
void* userdata __UNUSED__)
|
||||
{
|
||||
|
||||
struct cls_struct_align a1, a2;
|
||||
|
||||
a1 = *(struct cls_struct_align*)(args[0]);
|
||||
a2 = *(struct cls_struct_align*)(args[1]);
|
||||
|
||||
*(cls_struct_align*)resp = cls_struct_align_fn(a1, a2);
|
||||
}
|
||||
|
||||
int main (void)
|
||||
{
|
||||
ffi_cif cif;
|
||||
void *code;
|
||||
ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
|
||||
void* args_c[5];
|
||||
ffi_type* cls_struct_fields[4];
|
||||
ffi_type cls_struct_type;
|
||||
ffi_type* c_arg_types[5];
|
||||
|
||||
struct cls_struct_align g_c = { 12, 4951 + 7 * I, 127 };
|
||||
struct cls_struct_align f_c = { 1, 9320 + 1 * I, 13 };
|
||||
struct cls_struct_align res_c;
|
||||
|
||||
cls_struct_type.size = 0;
|
||||
cls_struct_type.alignment = 0;
|
||||
cls_struct_type.type = FFI_TYPE_STRUCT;
|
||||
cls_struct_type.elements = cls_struct_fields;
|
||||
|
||||
cls_struct_fields[0] = &ffi_type_uchar;
|
||||
cls_struct_fields[1] = &T_FFI_TYPE;
|
||||
cls_struct_fields[2] = &ffi_type_uchar;
|
||||
cls_struct_fields[3] = NULL;
|
||||
|
||||
c_arg_types[0] = &cls_struct_type;
|
||||
c_arg_types[1] = &cls_struct_type;
|
||||
c_arg_types[2] = NULL;
|
||||
|
||||
CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &cls_struct_type,
|
||||
c_arg_types) == FFI_OK);
|
||||
|
||||
args_c[0] = &g_c;
|
||||
args_c[1] = &f_c;
|
||||
args_c[2] = NULL;
|
||||
|
||||
ffi_call(&cif, FFI_FN(cls_struct_align_fn), &res_c, args_c);
|
||||
/* { dg-output "12 4951,7i 127 1 9320,1i 13: 13 14271,8i 140" } */
|
||||
printf("res: %d %f,%fi %d\n",
|
||||
res_c.a, T_CONV creal (res_c.b), T_CONV cimag (res_c.b), res_c.c);
|
||||
/* { dg-output "\nres: 13 14271,8i 140" } */
|
||||
|
||||
CHECK(ffi_prep_closure_loc(pcl, &cif, cls_struct_align_gn, NULL, code) == FFI_OK);
|
||||
|
||||
res_c = ((cls_struct_align(*)(cls_struct_align, cls_struct_align))(code))(g_c, f_c);
|
||||
/* { dg-output "\n12 4951,7i 127 1 9320,1i 13: 13 14271,8i 140" } */
|
||||
printf("res: %d %f,%fi %d\n",
|
||||
res_c.a, T_CONV creal (res_c.b), T_CONV cimag (res_c.b), res_c.c);
|
||||
/* { dg-output "\nres: 13 14271,8i 140" } */
|
||||
|
||||
exit(0);
|
||||
}
|
||||
10
testsuite/libffi.call/cls_align_complex_double.c
Normal file
10
testsuite/libffi.call/cls_align_complex_double.c
Normal file
@@ -0,0 +1,10 @@
|
||||
/* Area: ffi_call, closure_call
|
||||
Purpose: Check structure alignment of complex.
|
||||
Limitations: none.
|
||||
PR: none.
|
||||
Originator: <vogt@linux.vnet.ibm.com>. */
|
||||
|
||||
/* { dg-do run } */
|
||||
|
||||
#include "complex_defs_double.inc"
|
||||
#include "cls_align_complex.inc"
|
||||
10
testsuite/libffi.call/cls_align_complex_float.c
Normal file
10
testsuite/libffi.call/cls_align_complex_float.c
Normal file
@@ -0,0 +1,10 @@
|
||||
/* Area: ffi_call, closure_call
|
||||
Purpose: Check structure alignment of complex.
|
||||
Limitations: none.
|
||||
PR: none.
|
||||
Originator: <vogt@linux.vnet.ibm.com>. */
|
||||
|
||||
/* { dg-do run } */
|
||||
|
||||
#include "complex_defs_float.inc"
|
||||
#include "cls_align_complex.inc"
|
||||
10
testsuite/libffi.call/cls_align_complex_longdouble.c
Normal file
10
testsuite/libffi.call/cls_align_complex_longdouble.c
Normal file
@@ -0,0 +1,10 @@
|
||||
/* Area: ffi_call, closure_call
|
||||
Purpose: Check structure alignment of complex.
|
||||
Limitations: none.
|
||||
PR: none.
|
||||
Originator: <vogt@linux.vnet.ibm.com>. */
|
||||
|
||||
/* { dg-do run } */
|
||||
|
||||
#include "complex_defs_longdouble.inc"
|
||||
#include "cls_align_complex.inc"
|
||||
42
testsuite/libffi.call/cls_complex.inc
Normal file
42
testsuite/libffi.call/cls_complex.inc
Normal file
@@ -0,0 +1,42 @@
|
||||
/* -*-c-*- */
|
||||
#include "ffitest.h"
|
||||
#include <complex.h>
|
||||
|
||||
static void cls_ret_complex_fn(ffi_cif* cif __UNUSED__, void* resp, void** args,
|
||||
void* userdata __UNUSED__)
|
||||
{
|
||||
_Complex T_C_TYPE *pa;
|
||||
_Complex T_C_TYPE *pr;
|
||||
pa = (_Complex T_C_TYPE *)args[0];
|
||||
pr = (_Complex T_C_TYPE *)resp;
|
||||
*pr = *pa;
|
||||
|
||||
printf("%.6f,%.6fi: %.6f,%.6fi\n",
|
||||
T_CONV creal (*pa), T_CONV cimag (*pa),
|
||||
T_CONV creal (*pr), T_CONV cimag (*pr));
|
||||
}
|
||||
typedef _Complex T_C_TYPE (*cls_ret_complex)(_Complex T_C_TYPE);
|
||||
|
||||
int main (void)
|
||||
{
|
||||
ffi_cif cif;
|
||||
void *code;
|
||||
ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
|
||||
ffi_type * cl_arg_types[2];
|
||||
_Complex T_C_TYPE res;
|
||||
|
||||
cl_arg_types[0] = &T_FFI_TYPE;
|
||||
cl_arg_types[1] = NULL;
|
||||
|
||||
/* Initialize the cif */
|
||||
CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1,
|
||||
&T_FFI_TYPE, cl_arg_types) == FFI_OK);
|
||||
|
||||
CHECK(ffi_prep_closure_loc(pcl, &cif, cls_ret_complex_fn, NULL, code) == FFI_OK);
|
||||
|
||||
res = (*((cls_ret_complex)code))(0.125 + 128.0 * I);
|
||||
printf("res: %.6f,%.6fi\n", T_CONV creal (res), T_CONV cimag (res));
|
||||
CHECK (res == (0.125 + 128.0 * I));
|
||||
|
||||
exit(0);
|
||||
}
|
||||
10
testsuite/libffi.call/cls_complex_double.c
Normal file
10
testsuite/libffi.call/cls_complex_double.c
Normal file
@@ -0,0 +1,10 @@
|
||||
/* Area: closure_call
|
||||
Purpose: Check return value complex.
|
||||
Limitations: none.
|
||||
PR: none.
|
||||
Originator: <vogt@linux.vnet.ibm.com>. */
|
||||
|
||||
/* { dg-do run } */
|
||||
|
||||
#include "complex_defs_double.inc"
|
||||
#include "cls_complex.inc"
|
||||
10
testsuite/libffi.call/cls_complex_float.c
Normal file
10
testsuite/libffi.call/cls_complex_float.c
Normal file
@@ -0,0 +1,10 @@
|
||||
/* Area: closure_call
|
||||
Purpose: Check return value complex.
|
||||
Limitations: none.
|
||||
PR: none.
|
||||
Originator: <vogt@linux.vnet.ibm.com>. */
|
||||
|
||||
/* { dg-do run } */
|
||||
|
||||
#include "complex_defs_float.inc"
|
||||
#include "cls_complex.inc"
|
||||
10
testsuite/libffi.call/cls_complex_longdouble.c
Normal file
10
testsuite/libffi.call/cls_complex_longdouble.c
Normal file
@@ -0,0 +1,10 @@
|
||||
/* Area: closure_call
|
||||
Purpose: Check return value complex.
|
||||
Limitations: none.
|
||||
PR: none.
|
||||
Originator: <vogt@linux.vnet.ibm.com>. */
|
||||
|
||||
/* { dg-do run } */
|
||||
|
||||
#include "complex_defs_longdouble.inc"
|
||||
#include "cls_complex.inc"
|
||||
71
testsuite/libffi.call/cls_complex_struct.inc
Normal file
71
testsuite/libffi.call/cls_complex_struct.inc
Normal file
@@ -0,0 +1,71 @@
|
||||
/* -*-c-*- */
|
||||
#include "ffitest.h"
|
||||
#include <complex.h>
|
||||
|
||||
typedef struct Cs {
|
||||
_Complex T_C_TYPE x;
|
||||
_Complex T_C_TYPE y;
|
||||
} Cs;
|
||||
|
||||
Cs gc;
|
||||
|
||||
void
|
||||
closure_test_fn(Cs p)
|
||||
{
|
||||
printf("%.1f,%.1fi %.1f,%.1fi\n",
|
||||
T_CONV creal (p.x), T_CONV cimag (p.x),
|
||||
T_CONV creal (p.y), T_CONV cimag (p.y));
|
||||
gc = p;
|
||||
}
|
||||
|
||||
void
|
||||
closure_test_gn(ffi_cif* cif __UNUSED__, void* resp __UNUSED__,
|
||||
void** args, void* userdata __UNUSED__)
|
||||
{
|
||||
closure_test_fn(*(Cs*)args[0]);
|
||||
}
|
||||
|
||||
int main(int argc __UNUSED__, char** argv __UNUSED__)
|
||||
{
|
||||
ffi_cif cif;
|
||||
|
||||
void *code;
|
||||
ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
|
||||
ffi_type *cl_arg_types[1];
|
||||
|
||||
ffi_type ts1_type;
|
||||
ffi_type* ts1_type_elements[4];
|
||||
|
||||
Cs arg = { 1.0 + 11.0 * I, 2.0 + 22.0 * I};
|
||||
|
||||
ts1_type.size = 0;
|
||||
ts1_type.alignment = 0;
|
||||
ts1_type.type = FFI_TYPE_STRUCT;
|
||||
ts1_type.elements = ts1_type_elements;
|
||||
|
||||
ts1_type_elements[0] = &T_FFI_TYPE;
|
||||
ts1_type_elements[1] = &T_FFI_TYPE;
|
||||
ts1_type_elements[2] = NULL;
|
||||
|
||||
cl_arg_types[0] = &ts1_type;
|
||||
|
||||
/* Initialize the cif */
|
||||
CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1,
|
||||
&ffi_type_void, cl_arg_types) == FFI_OK);
|
||||
|
||||
CHECK(ffi_prep_closure_loc(pcl, &cif, closure_test_gn, NULL, code) == FFI_OK);
|
||||
|
||||
gc.x = 0.0 + 0.0 * I;
|
||||
gc.y = 0.0 + 0.0 * I;
|
||||
((void*(*)(Cs))(code))(arg);
|
||||
/* { dg-output "1.0,11.0i 2.0,22.0i\n" } */
|
||||
CHECK (gc.x == arg.x && gc.y == arg.y);
|
||||
|
||||
gc.x = 0.0 + 0.0 * I;
|
||||
gc.y = 0.0 + 0.0 * I;
|
||||
closure_test_fn(arg);
|
||||
/* { dg-output "1.0,11.0i 2.0,22.0i\n" } */
|
||||
CHECK (gc.x == arg.x && gc.y == arg.y);
|
||||
|
||||
return 0;
|
||||
}
|
||||
10
testsuite/libffi.call/cls_complex_struct_double.c
Normal file
10
testsuite/libffi.call/cls_complex_struct_double.c
Normal file
@@ -0,0 +1,10 @@
|
||||
/* Area: ffi_call, closure_call
|
||||
Purpose: Check complex arguments in structs.
|
||||
Limitations: none.
|
||||
PR: none.
|
||||
Originator: <vogt@linux.vnet.ibm.com>. */
|
||||
|
||||
/* { dg-do run } */
|
||||
|
||||
#include "complex_defs_double.inc"
|
||||
#include "cls_complex_struct.inc"
|
||||
10
testsuite/libffi.call/cls_complex_struct_float.c
Normal file
10
testsuite/libffi.call/cls_complex_struct_float.c
Normal file
@@ -0,0 +1,10 @@
|
||||
/* Area: ffi_call, closure_call
|
||||
Purpose: Check complex arguments in structs.
|
||||
Limitations: none.
|
||||
PR: none.
|
||||
Originator: <vogt@linux.vnet.ibm.com>. */
|
||||
|
||||
/* { dg-do run } */
|
||||
|
||||
#include "complex_defs_float.inc"
|
||||
#include "cls_complex_struct.inc"
|
||||
10
testsuite/libffi.call/cls_complex_struct_longdouble.c
Normal file
10
testsuite/libffi.call/cls_complex_struct_longdouble.c
Normal file
@@ -0,0 +1,10 @@
|
||||
/* Area: ffi_call, closure_call
|
||||
Purpose: Check complex arguments in structs.
|
||||
Limitations: none.
|
||||
PR: none.
|
||||
Originator: <vogt@linux.vnet.ibm.com>. */
|
||||
|
||||
/* { dg-do run } */
|
||||
|
||||
#include "complex_defs_longdouble.inc"
|
||||
#include "cls_complex_struct.inc"
|
||||
80
testsuite/libffi.call/cls_complex_va.inc
Normal file
80
testsuite/libffi.call/cls_complex_va.inc
Normal file
@@ -0,0 +1,80 @@
|
||||
/* -*-c-*- */
|
||||
#include "ffitest.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
#include <complex.h>
|
||||
|
||||
static _Complex T_C_TYPE gComplexValue1 = 1 + 2 * I;
|
||||
static _Complex T_C_TYPE gComplexValue2 = 3 + 4 * I;
|
||||
|
||||
static int cls_variadic(const char *format, ...)
|
||||
{
|
||||
va_list ap;
|
||||
_Complex T_C_TYPE p1, p2;
|
||||
|
||||
va_start (ap, format);
|
||||
p1 = va_arg (ap, _Complex T_C_TYPE);
|
||||
p2 = va_arg (ap, _Complex T_C_TYPE);
|
||||
va_end (ap);
|
||||
|
||||
return printf(format, T_CONV creal (p1), T_CONV cimag (p1),
|
||||
T_CONV creal (p2), T_CONV cimag (p2));
|
||||
}
|
||||
|
||||
static void
|
||||
cls_complex_va_fn(ffi_cif* cif __UNUSED__, void* resp,
|
||||
void** args, void* userdata __UNUSED__)
|
||||
{
|
||||
char* format = *(char**)args[0];
|
||||
gComplexValue1 = *(_Complex T_C_TYPE*)args[1];
|
||||
gComplexValue2 = *(_Complex T_C_TYPE*)args[2];
|
||||
|
||||
*(ffi_arg*)resp =
|
||||
printf(format,
|
||||
T_CONV creal (gComplexValue1), T_CONV cimag (gComplexValue1),
|
||||
T_CONV creal (gComplexValue2), T_CONV cimag (gComplexValue2));
|
||||
}
|
||||
|
||||
int main (void)
|
||||
{
|
||||
ffi_cif cif;
|
||||
void *code;
|
||||
ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
|
||||
void* args[4];
|
||||
ffi_type* arg_types[4];
|
||||
char *format = "%.1f,%.1fi %.1f,%.1fi\n";
|
||||
|
||||
_Complex T_C_TYPE complexArg1 = 1.0 + 22.0 *I;
|
||||
_Complex T_C_TYPE complexArg2 = 333.0 + 4444.0 *I;
|
||||
ffi_arg res = 0;
|
||||
|
||||
arg_types[0] = &ffi_type_pointer;
|
||||
arg_types[1] = &T_FFI_TYPE;
|
||||
arg_types[2] = &T_FFI_TYPE;
|
||||
arg_types[3] = NULL;
|
||||
|
||||
/* This printf call is variadic */
|
||||
CHECK(ffi_prep_cif_var(&cif, FFI_DEFAULT_ABI, 1, 3, &ffi_type_sint,
|
||||
arg_types) == FFI_OK);
|
||||
|
||||
args[0] = &format;
|
||||
args[1] = &complexArg1;
|
||||
args[2] = &complexArg2;
|
||||
args[3] = NULL;
|
||||
|
||||
ffi_call(&cif, FFI_FN(cls_variadic), &res, args);
|
||||
printf("res: %d\n", (int) res);
|
||||
CHECK (res == 24);
|
||||
|
||||
CHECK(ffi_prep_closure_loc(pcl, &cif, cls_complex_va_fn, NULL, code)
|
||||
== FFI_OK);
|
||||
|
||||
res = ((int(*)(char *, ...))(code))(format, complexArg1, complexArg2);
|
||||
CHECK (gComplexValue1 == complexArg1);
|
||||
CHECK (gComplexValue2 == complexArg2);
|
||||
printf("res: %d\n", (int) res);
|
||||
CHECK (res == 24);
|
||||
|
||||
exit(0);
|
||||
}
|
||||
10
testsuite/libffi.call/cls_complex_va_double.c
Normal file
10
testsuite/libffi.call/cls_complex_va_double.c
Normal file
@@ -0,0 +1,10 @@
|
||||
/* Area: ffi_call, closure_call
|
||||
Purpose: Test complex' passed in variable argument lists.
|
||||
Limitations: none.
|
||||
PR: none.
|
||||
Originator: <vogt@linux.vnet.ibm.com>. */
|
||||
|
||||
/* { dg-do run } */
|
||||
|
||||
#include "complex_defs_double.inc"
|
||||
#include "cls_complex_va.inc"
|
||||
10
testsuite/libffi.call/cls_complex_va_float.c
Normal file
10
testsuite/libffi.call/cls_complex_va_float.c
Normal file
@@ -0,0 +1,10 @@
|
||||
/* Area: ffi_call, closure_call
|
||||
Purpose: Test complex' passed in variable argument lists.
|
||||
Limitations: none.
|
||||
PR: none.
|
||||
Originator: <vogt@linux.vnet.ibm.com>. */
|
||||
|
||||
/* { dg-do run } */
|
||||
|
||||
#include "complex_defs_float.inc"
|
||||
#include "cls_complex_va.inc"
|
||||
10
testsuite/libffi.call/cls_complex_va_longdouble.c
Normal file
10
testsuite/libffi.call/cls_complex_va_longdouble.c
Normal file
@@ -0,0 +1,10 @@
|
||||
/* Area: ffi_call, closure_call
|
||||
Purpose: Test complex' passed in variable argument lists.
|
||||
Limitations: none.
|
||||
PR: none.
|
||||
Originator: <vogt@linux.vnet.ibm.com>. */
|
||||
|
||||
/* { dg-do run } */
|
||||
|
||||
#include "complex_defs_longdouble.inc"
|
||||
#include "cls_complex_va.inc"
|
||||
51
testsuite/libffi.call/complex.inc
Normal file
51
testsuite/libffi.call/complex.inc
Normal file
@@ -0,0 +1,51 @@
|
||||
/* -*-c-*-*/
|
||||
#include "ffitest.h"
|
||||
#include <complex.h>
|
||||
|
||||
static _Complex T_C_TYPE f_complex(_Complex T_C_TYPE c, int x, int *py)
|
||||
{
|
||||
c = -(2 * creal (c)) + (cimag (c) + 1)* I;
|
||||
*py += x;
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
int main (void)
|
||||
{
|
||||
ffi_cif cif;
|
||||
ffi_type *args[MAX_ARGS];
|
||||
void *values[MAX_ARGS];
|
||||
|
||||
_Complex T_C_TYPE tc_arg;
|
||||
_Complex T_C_TYPE tc_result;
|
||||
int tc_int_arg_x;
|
||||
int tc_y;
|
||||
int *tc_ptr_arg_y = &tc_y;
|
||||
|
||||
args[0] = &T_FFI_TYPE;
|
||||
args[1] = &ffi_type_sint;
|
||||
args[2] = &ffi_type_pointer;
|
||||
values[0] = &tc_arg;
|
||||
values[1] = &tc_int_arg_x;
|
||||
values[2] = &tc_ptr_arg_y;
|
||||
|
||||
/* Initialize the cif */
|
||||
CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 3,
|
||||
&T_FFI_TYPE, args) == FFI_OK);
|
||||
|
||||
tc_arg = 1 + 7 * I;
|
||||
tc_int_arg_x = 1234;
|
||||
tc_y = 9876;
|
||||
ffi_call(&cif, FFI_FN(f_complex), &tc_result, values);
|
||||
|
||||
printf ("%f,%fi %f,%fi, x %d 1234, y %d 11110\n",
|
||||
T_CONV creal (tc_result), T_CONV cimag (tc_result),
|
||||
T_CONV creal (2.0), T_CONV creal (8.0), tc_int_arg_x, tc_y);
|
||||
|
||||
CHECK (creal (tc_result) == -2);
|
||||
CHECK (cimag (tc_result) == 8);
|
||||
CHECK (tc_int_arg_x == 1234);
|
||||
CHECK (*tc_ptr_arg_y == 11110);
|
||||
|
||||
exit(0);
|
||||
}
|
||||
7
testsuite/libffi.call/complex_defs_double.inc
Normal file
7
testsuite/libffi.call/complex_defs_double.inc
Normal file
@@ -0,0 +1,7 @@
|
||||
/* -*-c-*- */
|
||||
/* Complex base type. */
|
||||
#define T_FFI_TYPE ffi_type_complex_double
|
||||
/* C type corresponding to the base type. */
|
||||
#define T_C_TYPE double
|
||||
/* C cast for a value of type T_C_TYPE that is passed to printf. */
|
||||
#define T_CONV
|
||||
7
testsuite/libffi.call/complex_defs_float.inc
Normal file
7
testsuite/libffi.call/complex_defs_float.inc
Normal file
@@ -0,0 +1,7 @@
|
||||
/* -*-c-*- */
|
||||
/* Complex base type. */
|
||||
#define T_FFI_TYPE ffi_type_complex_float
|
||||
/* C type corresponding to the base type. */
|
||||
#define T_C_TYPE float
|
||||
/* C cast for a value of type T_C_TYPE that is passed to printf. */
|
||||
#define T_CONV (double)
|
||||
7
testsuite/libffi.call/complex_defs_longdouble.inc
Normal file
7
testsuite/libffi.call/complex_defs_longdouble.inc
Normal file
@@ -0,0 +1,7 @@
|
||||
/* -*-c-*- */
|
||||
/* Complex base type. */
|
||||
#define T_FFI_TYPE ffi_type_complex_longdouble
|
||||
/* C type corresponding to the base type. */
|
||||
#define T_C_TYPE long double
|
||||
/* C cast for a value of type T_C_TYPE that is passed to printf. */
|
||||
#define T_CONV
|
||||
10
testsuite/libffi.call/complex_double.c
Normal file
10
testsuite/libffi.call/complex_double.c
Normal file
@@ -0,0 +1,10 @@
|
||||
/* Area: ffi_call
|
||||
Purpose: Check complex types.
|
||||
Limitations: none.
|
||||
PR: none.
|
||||
Originator: <vogt@linux.vnet.ibm.com>. */
|
||||
|
||||
/* { dg-do run } */
|
||||
|
||||
#include "complex_defs_double.inc"
|
||||
#include "complex.inc"
|
||||
10
testsuite/libffi.call/complex_float.c
Normal file
10
testsuite/libffi.call/complex_float.c
Normal file
@@ -0,0 +1,10 @@
|
||||
/* Area: ffi_call
|
||||
Purpose: Check complex types.
|
||||
Limitations: none.
|
||||
PR: none.
|
||||
Originator: <vogt@linux.vnet.ibm.com>. */
|
||||
|
||||
/* { dg-do run } */
|
||||
|
||||
#include "complex_defs_float.inc"
|
||||
#include "complex.inc"
|
||||
86
testsuite/libffi.call/complex_int.c
Normal file
86
testsuite/libffi.call/complex_int.c
Normal file
@@ -0,0 +1,86 @@
|
||||
/* Area: ffi_call
|
||||
Purpose: Check non-standard complex types.
|
||||
Limitations: none.
|
||||
PR: none.
|
||||
Originator: <vogt@linux.vnet.ibm.com>. */
|
||||
|
||||
/* { dg-do run } */
|
||||
|
||||
#include "ffitest.h"
|
||||
#include "ffi.h"
|
||||
#include <complex.h>
|
||||
|
||||
_Complex int f_complex(_Complex int c, int x, int *py)
|
||||
{
|
||||
c = -(2 * creal (c)) + (cimag (c) + 1)* I;
|
||||
*py += x;
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
/*
|
||||
* This macro can be used to define new complex type descriptors
|
||||
* in a platform independent way.
|
||||
*
|
||||
* name: Name of the new descriptor is ffi_type_complex_<name>.
|
||||
* type: The C base type of the complex type.
|
||||
*/
|
||||
#define FFI_COMPLEX_TYPEDEF(name, type, ffitype) \
|
||||
static ffi_type *ffi_elements_complex_##name [2] = { \
|
||||
(ffi_type *)(&ffitype), NULL \
|
||||
}; \
|
||||
struct struct_align_complex_##name { \
|
||||
char c; \
|
||||
_Complex type x; \
|
||||
}; \
|
||||
ffi_type ffi_type_complex_##name = { \
|
||||
sizeof(_Complex type), \
|
||||
offsetof(struct struct_align_complex_##name, x), \
|
||||
FFI_TYPE_COMPLEX, \
|
||||
(ffi_type **)ffi_elements_complex_##name \
|
||||
}
|
||||
|
||||
/* Define new complex type descriptors using the macro: */
|
||||
/* ffi_type_complex_sint */
|
||||
FFI_COMPLEX_TYPEDEF(sint, int, ffi_type_sint);
|
||||
/* ffi_type_complex_uchar */
|
||||
FFI_COMPLEX_TYPEDEF(uchar, unsigned char, ffi_type_uint8);
|
||||
|
||||
int main (void)
|
||||
{
|
||||
ffi_cif cif;
|
||||
ffi_type *args[MAX_ARGS];
|
||||
void *values[MAX_ARGS];
|
||||
|
||||
_Complex int tc_arg;
|
||||
_Complex int tc_result;
|
||||
int tc_int_arg_x;
|
||||
int tc_y;
|
||||
int *tc_ptr_arg_y = &tc_y;
|
||||
|
||||
args[0] = &ffi_type_complex_sint;
|
||||
args[1] = &ffi_type_sint;
|
||||
args[2] = &ffi_type_pointer;
|
||||
values[0] = &tc_arg;
|
||||
values[1] = &tc_int_arg_x;
|
||||
values[2] = &tc_ptr_arg_y;
|
||||
|
||||
/* Initialize the cif */
|
||||
CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 3, &ffi_type_complex_sint, args)
|
||||
== FFI_OK);
|
||||
|
||||
tc_arg = 1 + 7 * I;
|
||||
tc_int_arg_x = 1234;
|
||||
tc_y = 9876;
|
||||
ffi_call(&cif, FFI_FN(f_complex), &tc_result, values);
|
||||
|
||||
printf ("%d,%di %d,%di, x %d 1234, y %d 11110\n",
|
||||
(int)tc_result, (int)(tc_result * -I), 2, 8, tc_int_arg_x, tc_y);
|
||||
/* dg-output "-2,8i 2,8i, x 1234 1234, y 11110 11110" */
|
||||
CHECK (creal (tc_result) == -2);
|
||||
CHECK (cimag (tc_result) == 8);
|
||||
CHECK (tc_int_arg_x == 1234);
|
||||
CHECK (*tc_ptr_arg_y == 11110);
|
||||
|
||||
exit(0);
|
||||
}
|
||||
10
testsuite/libffi.call/complex_longdouble.c
Normal file
10
testsuite/libffi.call/complex_longdouble.c
Normal file
@@ -0,0 +1,10 @@
|
||||
/* Area: ffi_call
|
||||
Purpose: Check complex types.
|
||||
Limitations: none.
|
||||
PR: none.
|
||||
Originator: <vogt@linux.vnet.ibm.com>. */
|
||||
|
||||
/* { dg-do run } */
|
||||
|
||||
#include "complex_defs_longdouble.inc"
|
||||
#include "complex.inc"
|
||||
78
testsuite/libffi.call/many_complex.inc
Normal file
78
testsuite/libffi.call/many_complex.inc
Normal file
@@ -0,0 +1,78 @@
|
||||
/* -*-c-*- */
|
||||
#include "ffitest.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <complex.h>
|
||||
|
||||
static _Complex T_C_TYPE many(_Complex T_C_TYPE c1,
|
||||
_Complex T_C_TYPE c2,
|
||||
_Complex T_C_TYPE c3,
|
||||
_Complex T_C_TYPE c4,
|
||||
_Complex T_C_TYPE c5,
|
||||
_Complex T_C_TYPE c6,
|
||||
_Complex T_C_TYPE c7,
|
||||
_Complex T_C_TYPE c8,
|
||||
_Complex T_C_TYPE c9,
|
||||
_Complex T_C_TYPE c10,
|
||||
_Complex T_C_TYPE c11,
|
||||
_Complex T_C_TYPE c12,
|
||||
_Complex T_C_TYPE c13)
|
||||
{
|
||||
printf("0 :%f,%fi\n"
|
||||
"1 :%f,%fi\n"
|
||||
"2 :%f,%fi\n"
|
||||
"3 :%f,%fi\n"
|
||||
"4 :%f,%fi\n"
|
||||
"5 :%f,%fi\n"
|
||||
"6 :%f,%fi\n"
|
||||
"7 :%f,%fi\n"
|
||||
"8 :%f,%fi\n"
|
||||
"9 :%f,%fi\n"
|
||||
"10:%f,%fi\n"
|
||||
"11:%f,%fi\n"
|
||||
"12:%f,%fi\n",
|
||||
T_CONV creal (c1), T_CONV cimag (c1),
|
||||
T_CONV creal (c2), T_CONV cimag (c2),
|
||||
T_CONV creal (c3), T_CONV cimag (c3),
|
||||
T_CONV creal (c4), T_CONV cimag (c4),
|
||||
T_CONV creal (c5), T_CONV cimag (c5),
|
||||
T_CONV creal (c6), T_CONV cimag (c6),
|
||||
T_CONV creal (c7), T_CONV cimag (c7),
|
||||
T_CONV creal (c8), T_CONV cimag (c8),
|
||||
T_CONV creal (c9), T_CONV cimag (c9),
|
||||
T_CONV creal (c10), T_CONV cimag (c10),
|
||||
T_CONV creal (c11), T_CONV cimag (c11),
|
||||
T_CONV creal (c12), T_CONV cimag (c12),
|
||||
T_CONV creal (c13), T_CONV cimag (c13));
|
||||
|
||||
return (c1+c2-c3-c4+c5+c6+c7-c8-c9-c10-c11+c12+c13);
|
||||
}
|
||||
|
||||
int main (void)
|
||||
{
|
||||
ffi_cif cif;
|
||||
ffi_type *args[13];
|
||||
void *values[13];
|
||||
_Complex T_C_TYPE ca[13];
|
||||
_Complex T_C_TYPE c, cc;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 13; i++)
|
||||
{
|
||||
args[i] = &T_FFI_TYPE;
|
||||
values[i] = &ca[i];
|
||||
ca[i] = i + (-20 - i) * I;
|
||||
}
|
||||
|
||||
/* Initialize the cif */
|
||||
CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 13, &T_FFI_TYPE, args) == FFI_OK);
|
||||
|
||||
ffi_call(&cif, FFI_FN(many), &c, values);
|
||||
|
||||
cc = many(ca[0], ca[1], ca[2], ca[3], ca[4], ca[5], ca[6], ca[7], ca[8],
|
||||
ca[9], ca[10], ca[11], ca[12]);
|
||||
CHECK(creal (cc) == creal (c));
|
||||
CHECK(cimag (cc) == cimag (c));
|
||||
|
||||
exit(0);
|
||||
}
|
||||
10
testsuite/libffi.call/many_complex_double.c
Normal file
10
testsuite/libffi.call/many_complex_double.c
Normal file
@@ -0,0 +1,10 @@
|
||||
/* Area: ffi_call
|
||||
Purpose: Check return value complex, with many arguments
|
||||
Limitations: none.
|
||||
PR: none.
|
||||
Originator: <vogt@linux.vnet.ibm.com>. */
|
||||
|
||||
/* { dg-do run } */
|
||||
|
||||
#include "complex_defs_double.inc"
|
||||
#include "many_complex.inc"
|
||||
10
testsuite/libffi.call/many_complex_float.c
Normal file
10
testsuite/libffi.call/many_complex_float.c
Normal file
@@ -0,0 +1,10 @@
|
||||
/* Area: ffi_call
|
||||
Purpose: Check return value complex, with many arguments
|
||||
Limitations: none.
|
||||
PR: none.
|
||||
Originator: <vogt@linux.vnet.ibm.com>. */
|
||||
|
||||
/* { dg-do run } */
|
||||
|
||||
#include "complex_defs_float.inc"
|
||||
#include "many_complex.inc"
|
||||
10
testsuite/libffi.call/many_complex_longdouble.c
Normal file
10
testsuite/libffi.call/many_complex_longdouble.c
Normal file
@@ -0,0 +1,10 @@
|
||||
/* Area: ffi_call
|
||||
Purpose: Check return value complex, with many arguments
|
||||
Limitations: none.
|
||||
PR: none.
|
||||
Originator: <vogt@linux.vnet.ibm.com>. */
|
||||
|
||||
/* { dg-do run } */
|
||||
|
||||
#include "complex_defs_longdouble.inc"
|
||||
#include "many_complex.inc"
|
||||
37
testsuite/libffi.call/return_complex.inc
Normal file
37
testsuite/libffi.call/return_complex.inc
Normal file
@@ -0,0 +1,37 @@
|
||||
/* -*-c-*- */
|
||||
#include "ffitest.h"
|
||||
#include <complex.h>
|
||||
|
||||
static _Complex T_C_TYPE return_c(_Complex T_C_TYPE c)
|
||||
{
|
||||
printf ("%f,%fi\n", T_CONV creal (c), T_CONV cimag (c));
|
||||
return 2 * c;
|
||||
}
|
||||
int main (void)
|
||||
{
|
||||
ffi_cif cif;
|
||||
ffi_type *args[MAX_ARGS];
|
||||
void *values[MAX_ARGS];
|
||||
_Complex T_C_TYPE c, rc, rc2;
|
||||
T_C_TYPE cr, ci;
|
||||
|
||||
args[0] = &T_FFI_TYPE;
|
||||
values[0] = &c;
|
||||
|
||||
/* Initialize the cif */
|
||||
CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1,
|
||||
&T_FFI_TYPE, args) == FFI_OK);
|
||||
|
||||
for (cr = -127.0; cr < 127; cr++)
|
||||
{
|
||||
ci = 1000.0 - cr;
|
||||
c = cr + ci * I;
|
||||
ffi_call(&cif, FFI_FN(return_c), &rc, values);
|
||||
rc2 = return_c(c);
|
||||
printf ("%f,%fi vs %f,%fi\n",
|
||||
T_CONV creal (rc), T_CONV cimag (rc),
|
||||
T_CONV creal (rc2), T_CONV cimag (rc2));
|
||||
CHECK(rc == 2 * c);
|
||||
}
|
||||
exit(0);
|
||||
}
|
||||
41
testsuite/libffi.call/return_complex1.inc
Normal file
41
testsuite/libffi.call/return_complex1.inc
Normal file
@@ -0,0 +1,41 @@
|
||||
/* -*-c-*- */
|
||||
#include "ffitest.h"
|
||||
#include <complex.h>
|
||||
|
||||
static _Complex T_C_TYPE return_c(_Complex T_C_TYPE c1, float fl2, unsigned int in3, _Complex T_C_TYPE c4)
|
||||
{
|
||||
return c1 + fl2 + in3 + c4;
|
||||
}
|
||||
int main (void)
|
||||
{
|
||||
ffi_cif cif;
|
||||
ffi_type *args[MAX_ARGS];
|
||||
void *values[MAX_ARGS];
|
||||
_Complex T_C_TYPE c1, c4, rc, rc2;
|
||||
float fl2;
|
||||
unsigned int in3;
|
||||
args[0] = &T_FFI_TYPE;
|
||||
args[1] = &ffi_type_float;
|
||||
args[2] = &ffi_type_uint;
|
||||
args[3] = &T_FFI_TYPE;
|
||||
values[0] = &c1;
|
||||
values[1] = &fl2;
|
||||
values[2] = &in3;
|
||||
values[3] = &c4;
|
||||
|
||||
/* Initialize the cif */
|
||||
CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 4,
|
||||
&T_FFI_TYPE, args) == FFI_OK);
|
||||
c1 = 127.0 + 255.0 * I;
|
||||
fl2 = 128.0;
|
||||
in3 = 255;
|
||||
c4 = 512.7 + 1024.1 * I;
|
||||
|
||||
ffi_call(&cif, FFI_FN(return_c), &rc, values);
|
||||
rc2 = return_c(c1, fl2, in3, c4);
|
||||
printf ("%f,%fi vs %f,%fi\n",
|
||||
T_CONV creal (rc), T_CONV cimag (rc),
|
||||
T_CONV creal (rc2), T_CONV cimag (rc2));
|
||||
CHECK(rc == rc2);
|
||||
exit(0);
|
||||
}
|
||||
10
testsuite/libffi.call/return_complex1_double.c
Normal file
10
testsuite/libffi.call/return_complex1_double.c
Normal file
@@ -0,0 +1,10 @@
|
||||
/* Area: ffi_call
|
||||
Purpose: Check return value complex.
|
||||
Limitations: none.
|
||||
PR: none.
|
||||
Originator: <vogt@linux.vnet.ibm.com>. */
|
||||
|
||||
/* { dg-do run } */
|
||||
|
||||
#include "complex_defs_double.inc"
|
||||
#include "return_complex1.inc"
|
||||
10
testsuite/libffi.call/return_complex1_float.c
Normal file
10
testsuite/libffi.call/return_complex1_float.c
Normal file
@@ -0,0 +1,10 @@
|
||||
/* Area: ffi_call
|
||||
Purpose: Check return value complex.
|
||||
Limitations: none.
|
||||
PR: none.
|
||||
Originator: <vogt@linux.vnet.ibm.com>. */
|
||||
|
||||
/* { dg-do run } */
|
||||
|
||||
#include "complex_defs_float.inc"
|
||||
#include "return_complex1.inc"
|
||||
10
testsuite/libffi.call/return_complex1_longdouble.c
Normal file
10
testsuite/libffi.call/return_complex1_longdouble.c
Normal file
@@ -0,0 +1,10 @@
|
||||
/* Area: ffi_call
|
||||
Purpose: Check return value complex.
|
||||
Limitations: none.
|
||||
PR: none.
|
||||
Originator: <vogt@linux.vnet.ibm.com>. */
|
||||
|
||||
/* { dg-do run } */
|
||||
|
||||
#include "complex_defs_longdouble.inc"
|
||||
#include "return_complex1.inc"
|
||||
40
testsuite/libffi.call/return_complex2.inc
Normal file
40
testsuite/libffi.call/return_complex2.inc
Normal file
@@ -0,0 +1,40 @@
|
||||
/* -*-c-*- */
|
||||
#include "ffitest.h"
|
||||
#include <complex.h>
|
||||
|
||||
static _Complex T_C_TYPE return_c(_Complex T_C_TYPE c1, _Complex T_C_TYPE c2, unsigned int in3, _Complex T_C_TYPE c4)
|
||||
{
|
||||
return c1 + c2 + in3 + c4;
|
||||
}
|
||||
int main (void)
|
||||
{
|
||||
ffi_cif cif;
|
||||
ffi_type *args[MAX_ARGS];
|
||||
void *values[MAX_ARGS];
|
||||
_Complex T_C_TYPE c1, c2, c4, rc, rc2;
|
||||
unsigned int in3;
|
||||
args[0] = &T_FFI_TYPE;
|
||||
args[1] = &T_FFI_TYPE;
|
||||
args[2] = &ffi_type_uint;
|
||||
args[3] = &T_FFI_TYPE;
|
||||
values[0] = &c1;
|
||||
values[1] = &c2;
|
||||
values[2] = &in3;
|
||||
values[3] = &c4;
|
||||
|
||||
/* Initialize the cif */
|
||||
CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 4,
|
||||
&T_FFI_TYPE, args) == FFI_OK);
|
||||
c1 = 127.0 + 255.0 * I;
|
||||
c2 = 128.0 + 256.0;
|
||||
in3 = 255;
|
||||
c4 = 512.7 + 1024.1 * I;
|
||||
|
||||
ffi_call(&cif, FFI_FN(return_c), &rc, values);
|
||||
rc2 = return_c(c1, c2, in3, c4);
|
||||
printf ("%f,%fi vs %f,%fi\n",
|
||||
T_CONV creal (rc), T_CONV cimag (rc),
|
||||
T_CONV creal (rc2), T_CONV cimag (rc2));
|
||||
CHECK(rc == c1 + c2 + in3 + c4);
|
||||
exit(0);
|
||||
}
|
||||
10
testsuite/libffi.call/return_complex2_double.c
Normal file
10
testsuite/libffi.call/return_complex2_double.c
Normal file
@@ -0,0 +1,10 @@
|
||||
/* Area: ffi_call
|
||||
Purpose: Check return value complex.
|
||||
Limitations: none.
|
||||
PR: none.
|
||||
Originator: <vogt@linux.vnet.ibm.com>. */
|
||||
|
||||
/* { dg-do run } */
|
||||
|
||||
#include "complex_defs_double.inc"
|
||||
#include "return_complex2.inc"
|
||||
10
testsuite/libffi.call/return_complex2_float.c
Normal file
10
testsuite/libffi.call/return_complex2_float.c
Normal file
@@ -0,0 +1,10 @@
|
||||
/* Area: ffi_call
|
||||
Purpose: Check return value complex.
|
||||
Limitations: none.
|
||||
PR: none.
|
||||
Originator: <vogt@linux.vnet.ibm.com>. */
|
||||
|
||||
/* { dg-do run } */
|
||||
|
||||
#include "complex_defs_float.inc"
|
||||
#include "return_complex2.inc"
|
||||
10
testsuite/libffi.call/return_complex2_longdouble.c
Normal file
10
testsuite/libffi.call/return_complex2_longdouble.c
Normal file
@@ -0,0 +1,10 @@
|
||||
/* Area: ffi_call
|
||||
Purpose: Check return value complex.
|
||||
Limitations: none.
|
||||
PR: none.
|
||||
Originator: <vogt@linux.vnet.ibm.com>. */
|
||||
|
||||
/* { dg-do run } */
|
||||
|
||||
#include "complex_defs_longdouble.inc"
|
||||
#include "return_complex2.inc"
|
||||
10
testsuite/libffi.call/return_complex_double.c
Normal file
10
testsuite/libffi.call/return_complex_double.c
Normal file
@@ -0,0 +1,10 @@
|
||||
/* Area: ffi_call
|
||||
Purpose: Check return value complex.
|
||||
Limitations: none.
|
||||
PR: none.
|
||||
Originator: <vogt@linux.vnet.ibm.com>. */
|
||||
|
||||
/* { dg-do run } */
|
||||
|
||||
#include "complex_defs_double.inc"
|
||||
#include "return_complex.inc"
|
||||
10
testsuite/libffi.call/return_complex_float.c
Normal file
10
testsuite/libffi.call/return_complex_float.c
Normal file
@@ -0,0 +1,10 @@
|
||||
/* Area: ffi_call
|
||||
Purpose: Check return value complex.
|
||||
Limitations: none.
|
||||
PR: none.
|
||||
Originator: <vogt@linux.vnet.ibm.com>. */
|
||||
|
||||
/* { dg-do run } */
|
||||
|
||||
#include "complex_defs_float.inc"
|
||||
#include "return_complex.inc"
|
||||
10
testsuite/libffi.call/return_complex_longdouble.c
Normal file
10
testsuite/libffi.call/return_complex_longdouble.c
Normal file
@@ -0,0 +1,10 @@
|
||||
/* Area: ffi_call
|
||||
Purpose: Check return value complex.
|
||||
Limitations: none.
|
||||
PR: none.
|
||||
Originator: <vogt@linux.vnet.ibm.com>. */
|
||||
|
||||
/* { dg-do run } */
|
||||
|
||||
#include "complex_defs_longdouble.inc"
|
||||
#include "return_complex.inc"
|
||||
Reference in New Issue
Block a user