From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 27252 invoked by alias); 22 Jul 2014 09:36:20 -0000 Mailing-List: contact libffi-discuss-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: libffi-discuss-owner@sourceware.org Received: (qmail 27211 invoked by uid 89); 22 Jul 2014 09:36:18 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-2.4 required=5.0 tests=AWL,BAYES_00,RP_MATCHES_RCVD autolearn=ham version=3.3.2 X-HELO: e06smtp17.uk.ibm.com Received: from e06smtp17.uk.ibm.com (HELO e06smtp17.uk.ibm.com) (195.75.94.113) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES256-SHA encrypted) ESMTPS; Tue, 22 Jul 2014 09:36:13 +0000 Received: from /spool/local by e06smtp17.uk.ibm.com with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted for from ; Tue, 22 Jul 2014 10:36:10 +0100 Received: from d06dlp03.portsmouth.uk.ibm.com (9.149.20.15) by e06smtp17.uk.ibm.com (192.168.101.147) with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted; Tue, 22 Jul 2014 10:36:07 +0100 Received: from b06cxnps3075.portsmouth.uk.ibm.com (d06relay10.portsmouth.uk.ibm.com [9.149.109.195]) by d06dlp03.portsmouth.uk.ibm.com (Postfix) with ESMTP id 928F51B08023 for ; Tue, 22 Jul 2014 10:36:50 +0100 (BST) Received: from d06av04.portsmouth.uk.ibm.com (d06av04.portsmouth.uk.ibm.com [9.149.37.216]) by b06cxnps3075.portsmouth.uk.ibm.com (8.13.8/8.13.8/NCO v10.0) with ESMTP id s6M9a7xc29163650 for ; Tue, 22 Jul 2014 09:36:07 GMT Received: from d06av04.portsmouth.uk.ibm.com (localhost [127.0.0.1]) by d06av04.portsmouth.uk.ibm.com (8.14.4/8.14.4/NCO v10.0 AVout) with ESMTP id s6M9a617011693 for ; Tue, 22 Jul 2014 03:36:06 -0600 Received: from bl3ahm9f.de.ibm.com (dyn-9-152-212-179.boeblingen.de.ibm.com [9.152.212.179]) by d06av04.portsmouth.uk.ibm.com (8.14.4/8.14.4/NCO v10.0 AVin) with ESMTP id s6M9a5Mc011552 (version=TLSv1/SSLv3 cipher=AES256-SHA bits=256 verify=NO) for ; Tue, 22 Jul 2014 03:36:05 -0600 Received: from dvogt by bl3ahm9f.de.ibm.com with local (Exim 4.76) (envelope-from ) id 1X9WUO-0007sc-JO; Tue, 22 Jul 2014 11:36:04 +0200 Date: Tue, 22 Jul 2014 09:36:00 -0000 From: Dominik Vogt To: libffi-discuss@sourceware.org Subject: [RFC][PATCH 2/3] Complex type support (FFI_TYPE_COMPLEX) Message-ID: <20140722093604.GB30068@linux.vnet.ibm.com> Reply-To: vogt@linux.vnet.ibm.com References: <20140722092734.GA23937@linux.vnet.ibm.com> MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="4bRzO86E/ozDv8r1" Content-Disposition: inline In-Reply-To: <20140722092734.GA23937@linux.vnet.ibm.com> User-Agent: Mutt/1.5.21 (2010-09-15) X-TM-AS-MML: disable X-Content-Scanned: Fidelis XPS MAILER x-cbid: 14072209-0542-0000-0000-0000001E9D0F X-IsSubscribed: yes X-SW-Source: 2014/txt/msg00073.txt.bz2 --4bRzO86E/ozDv8r1 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline Content-length: 2791 ChangeLog: -- 2014-07-22 Dominik Vogt * 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. -- Ciao Dominik ^_^ ^_^ -- Dominik Vogt IBM Germany --4bRzO86E/ozDv8r1 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="0002-FFI_TYPE_COMPLEX-framework.patch" Content-length: 50223 >From ac37948b28d4a62f34705df6835d8bdf539e6d62 Mon Sep 17 00:00:00 2001 From: Dominik Vogt Date: Tue, 22 Jul 2014 10:02:07 +0100 Subject: [PATCH 2/3] FFI_TYPE_COMPLEX framework --- doc/libffi.texi | 145 +++++++++++++++++++++ include/ffi.h.in | 13 +- src/debug.c | 7 +- src/java_raw_api.c | 18 +++ src/prep_cif.c | 8 ++ src/raw_api.c | 13 ++ src/types.c | 23 ++++ testsuite/libffi.call/cls_align_complex.inc | 91 +++++++++++++ testsuite/libffi.call/cls_align_complex_double.c | 10 ++ testsuite/libffi.call/cls_align_complex_float.c | 10 ++ .../libffi.call/cls_align_complex_longdouble.c | 10 ++ testsuite/libffi.call/cls_complex.inc | 42 ++++++ testsuite/libffi.call/cls_complex_double.c | 10 ++ testsuite/libffi.call/cls_complex_float.c | 10 ++ testsuite/libffi.call/cls_complex_longdouble.c | 10 ++ testsuite/libffi.call/cls_complex_struct.inc | 71 ++++++++++ testsuite/libffi.call/cls_complex_struct_double.c | 10 ++ testsuite/libffi.call/cls_complex_struct_float.c | 10 ++ .../libffi.call/cls_complex_struct_longdouble.c | 10 ++ testsuite/libffi.call/cls_complex_va.inc | 80 ++++++++++++ testsuite/libffi.call/cls_complex_va_double.c | 10 ++ testsuite/libffi.call/cls_complex_va_float.c | 10 ++ testsuite/libffi.call/cls_complex_va_longdouble.c | 10 ++ testsuite/libffi.call/complex.inc | 51 ++++++++ testsuite/libffi.call/complex_defs_double.inc | 7 + testsuite/libffi.call/complex_defs_float.inc | 7 + testsuite/libffi.call/complex_defs_longdouble.inc | 7 + testsuite/libffi.call/complex_double.c | 10 ++ testsuite/libffi.call/complex_float.c | 10 ++ testsuite/libffi.call/complex_int.c | 86 ++++++++++++ testsuite/libffi.call/complex_longdouble.c | 10 ++ testsuite/libffi.call/many_complex.inc | 78 +++++++++++ testsuite/libffi.call/many_complex_double.c | 10 ++ testsuite/libffi.call/many_complex_float.c | 10 ++ testsuite/libffi.call/many_complex_longdouble.c | 10 ++ testsuite/libffi.call/return_complex.inc | 37 ++++++ testsuite/libffi.call/return_complex1.inc | 41 ++++++ testsuite/libffi.call/return_complex1_double.c | 10 ++ testsuite/libffi.call/return_complex1_float.c | 10 ++ testsuite/libffi.call/return_complex1_longdouble.c | 10 ++ testsuite/libffi.call/return_complex2.inc | 40 ++++++ testsuite/libffi.call/return_complex2_double.c | 10 ++ testsuite/libffi.call/return_complex2_float.c | 10 ++ testsuite/libffi.call/return_complex2_longdouble.c | 10 ++ testsuite/libffi.call/return_complex_double.c | 10 ++ testsuite/libffi.call/return_complex_float.c | 10 ++ testsuite/libffi.call/return_complex_longdouble.c | 10 ++ 47 files changed, 1133 insertions(+), 2 deletions(-) create mode 100644 testsuite/libffi.call/cls_align_complex.inc create mode 100644 testsuite/libffi.call/cls_align_complex_double.c create mode 100644 testsuite/libffi.call/cls_align_complex_float.c create mode 100644 testsuite/libffi.call/cls_align_complex_longdouble.c create mode 100644 testsuite/libffi.call/cls_complex.inc create mode 100644 testsuite/libffi.call/cls_complex_double.c create mode 100644 testsuite/libffi.call/cls_complex_float.c create mode 100644 testsuite/libffi.call/cls_complex_longdouble.c create mode 100644 testsuite/libffi.call/cls_complex_struct.inc create mode 100644 testsuite/libffi.call/cls_complex_struct_double.c create mode 100644 testsuite/libffi.call/cls_complex_struct_float.c create mode 100644 testsuite/libffi.call/cls_complex_struct_longdouble.c create mode 100644 testsuite/libffi.call/cls_complex_va.inc create mode 100644 testsuite/libffi.call/cls_complex_va_double.c create mode 100644 testsuite/libffi.call/cls_complex_va_float.c create mode 100644 testsuite/libffi.call/cls_complex_va_longdouble.c create mode 100644 testsuite/libffi.call/complex.inc create mode 100644 testsuite/libffi.call/complex_defs_double.inc create mode 100644 testsuite/libffi.call/complex_defs_float.inc create mode 100644 testsuite/libffi.call/complex_defs_longdouble.inc create mode 100644 testsuite/libffi.call/complex_double.c create mode 100644 testsuite/libffi.call/complex_float.c create mode 100644 testsuite/libffi.call/complex_int.c create mode 100644 testsuite/libffi.call/complex_longdouble.c create mode 100644 testsuite/libffi.call/many_complex.inc create mode 100644 testsuite/libffi.call/many_complex_double.c create mode 100644 testsuite/libffi.call/many_complex_float.c create mode 100644 testsuite/libffi.call/many_complex_longdouble.c create mode 100644 testsuite/libffi.call/return_complex.inc create mode 100644 testsuite/libffi.call/return_complex1.inc create mode 100644 testsuite/libffi.call/return_complex1_double.c create mode 100644 testsuite/libffi.call/return_complex1_float.c create mode 100644 testsuite/libffi.call/return_complex1_longdouble.c create mode 100644 testsuite/libffi.call/return_complex2.inc create mode 100644 testsuite/libffi.call/return_complex2_double.c create mode 100644 testsuite/libffi.call/return_complex2_float.c create mode 100644 testsuite/libffi.call/return_complex2_longdouble.c create mode 100644 testsuite/libffi.call/return_complex_double.c create mode 100644 testsuite/libffi.call/return_complex_float.c create mode 100644 testsuite/libffi.call/return_complex_longdouble.c diff --git a/doc/libffi.texi b/doc/libffi.texi index a2b1242..b1c9bc3 100644 --- a/doc/libffi.texi +++ b/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 +#include +#include + +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_. + * 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 diff --git a/include/ffi.h.in b/include/ffi.h.in index 70c6179..fa6963a 100644 --- a/include/ffi.h.in +++ b/include/ffi.h.in @@ -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 } diff --git a/src/debug.c b/src/debug.c index 51dcfcf..f3172b1 100644 --- a/src/debug.c +++ b/src/debug.c @@ -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); } diff --git a/src/java_raw_api.c b/src/java_raw_api.c index 522c8bf..15664b4 100644 --- a/src/java_raw_api.c +++ b/src/java_raw_api.c @@ -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; } diff --git a/src/prep_cif.c b/src/prep_cif.c index 955bac1..be5eae3 100644 --- a/src/prep_cif.c +++ b/src/prep_cif.c @@ -136,6 +136,10 @@ 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); @@ -166,6 +170,10 @@ 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); diff --git a/src/raw_api.c b/src/raw_api.c index ce21372..276cb22 100644 --- a/src/raw_api.c +++ b/src/raw_api.c @@ -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; diff --git a/src/types.c b/src/types.c index e32e111..7e80aec 100644 --- a/src/types.c +++ b/src/types.c @@ -44,6 +44,21 @@ maybe_const ffi_type ffi_type_##name = { \ 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. */ const ffi_type ffi_type_void = { 1, 1, FFI_TYPE_VOID, NULL @@ -81,3 +96,11 @@ const ffi_type ffi_type_longdouble = { 16, 16, 4, NULL }; #elif FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE 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 diff --git a/testsuite/libffi.call/cls_align_complex.inc b/testsuite/libffi.call/cls_align_complex.inc new file mode 100644 index 0000000..4a812ed --- /dev/null +++ b/testsuite/libffi.call/cls_align_complex.inc @@ -0,0 +1,91 @@ +/* -*-c-*- */ +#include "ffitest.h" +#include + +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); +} diff --git a/testsuite/libffi.call/cls_align_complex_double.c b/testsuite/libffi.call/cls_align_complex_double.c new file mode 100644 index 0000000..0dff23a --- /dev/null +++ b/testsuite/libffi.call/cls_align_complex_double.c @@ -0,0 +1,10 @@ +/* Area: ffi_call, closure_call + Purpose: Check structure alignment of complex. + Limitations: none. + PR: none. + Originator: . */ + +/* { dg-do run } */ + +#include "complex_defs_double.inc" +#include "cls_align_complex.inc" diff --git a/testsuite/libffi.call/cls_align_complex_float.c b/testsuite/libffi.call/cls_align_complex_float.c new file mode 100644 index 0000000..0affbd0 --- /dev/null +++ b/testsuite/libffi.call/cls_align_complex_float.c @@ -0,0 +1,10 @@ +/* Area: ffi_call, closure_call + Purpose: Check structure alignment of complex. + Limitations: none. + PR: none. + Originator: . */ + +/* { dg-do run } */ + +#include "complex_defs_float.inc" +#include "cls_align_complex.inc" diff --git a/testsuite/libffi.call/cls_align_complex_longdouble.c b/testsuite/libffi.call/cls_align_complex_longdouble.c new file mode 100644 index 0000000..7889ba8 --- /dev/null +++ b/testsuite/libffi.call/cls_align_complex_longdouble.c @@ -0,0 +1,10 @@ +/* Area: ffi_call, closure_call + Purpose: Check structure alignment of complex. + Limitations: none. + PR: none. + Originator: . */ + +/* { dg-do run } */ + +#include "complex_defs_longdouble.inc" +#include "cls_align_complex.inc" diff --git a/testsuite/libffi.call/cls_complex.inc b/testsuite/libffi.call/cls_complex.inc new file mode 100644 index 0000000..f937404 --- /dev/null +++ b/testsuite/libffi.call/cls_complex.inc @@ -0,0 +1,42 @@ +/* -*-c-*- */ +#include "ffitest.h" +#include + +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); +} diff --git a/testsuite/libffi.call/cls_complex_double.c b/testsuite/libffi.call/cls_complex_double.c new file mode 100644 index 0000000..05e3534 --- /dev/null +++ b/testsuite/libffi.call/cls_complex_double.c @@ -0,0 +1,10 @@ +/* Area: closure_call + Purpose: Check return value complex. + Limitations: none. + PR: none. + Originator: . */ + +/* { dg-do run } */ + +#include "complex_defs_double.inc" +#include "cls_complex.inc" diff --git a/testsuite/libffi.call/cls_complex_float.c b/testsuite/libffi.call/cls_complex_float.c new file mode 100644 index 0000000..5df7849 --- /dev/null +++ b/testsuite/libffi.call/cls_complex_float.c @@ -0,0 +1,10 @@ +/* Area: closure_call + Purpose: Check return value complex. + Limitations: none. + PR: none. + Originator: . */ + +/* { dg-do run } */ + +#include "complex_defs_float.inc" +#include "cls_complex.inc" diff --git a/testsuite/libffi.call/cls_complex_longdouble.c b/testsuite/libffi.call/cls_complex_longdouble.c new file mode 100644 index 0000000..2b1c320 --- /dev/null +++ b/testsuite/libffi.call/cls_complex_longdouble.c @@ -0,0 +1,10 @@ +/* Area: closure_call + Purpose: Check return value complex. + Limitations: none. + PR: none. + Originator: . */ + +/* { dg-do run } */ + +#include "complex_defs_longdouble.inc" +#include "cls_complex.inc" diff --git a/testsuite/libffi.call/cls_complex_struct.inc b/testsuite/libffi.call/cls_complex_struct.inc new file mode 100644 index 0000000..df8708d --- /dev/null +++ b/testsuite/libffi.call/cls_complex_struct.inc @@ -0,0 +1,71 @@ +/* -*-c-*- */ +#include "ffitest.h" +#include + +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; +} diff --git a/testsuite/libffi.call/cls_complex_struct_double.c b/testsuite/libffi.call/cls_complex_struct_double.c new file mode 100644 index 0000000..ec71346 --- /dev/null +++ b/testsuite/libffi.call/cls_complex_struct_double.c @@ -0,0 +1,10 @@ +/* Area: ffi_call, closure_call + Purpose: Check complex arguments in structs. + Limitations: none. + PR: none. + Originator: . */ + +/* { dg-do run } */ + +#include "complex_defs_double.inc" +#include "cls_complex_struct.inc" diff --git a/testsuite/libffi.call/cls_complex_struct_float.c b/testsuite/libffi.call/cls_complex_struct_float.c new file mode 100644 index 0000000..96fdf75 --- /dev/null +++ b/testsuite/libffi.call/cls_complex_struct_float.c @@ -0,0 +1,10 @@ +/* Area: ffi_call, closure_call + Purpose: Check complex arguments in structs. + Limitations: none. + PR: none. + Originator: . */ + +/* { dg-do run } */ + +#include "complex_defs_float.inc" +#include "cls_complex_struct.inc" diff --git a/testsuite/libffi.call/cls_complex_struct_longdouble.c b/testsuite/libffi.call/cls_complex_struct_longdouble.c new file mode 100644 index 0000000..005b467 --- /dev/null +++ b/testsuite/libffi.call/cls_complex_struct_longdouble.c @@ -0,0 +1,10 @@ +/* Area: ffi_call, closure_call + Purpose: Check complex arguments in structs. + Limitations: none. + PR: none. + Originator: . */ + +/* { dg-do run } */ + +#include "complex_defs_longdouble.inc" +#include "cls_complex_struct.inc" diff --git a/testsuite/libffi.call/cls_complex_va.inc b/testsuite/libffi.call/cls_complex_va.inc new file mode 100644 index 0000000..8a3e15f --- /dev/null +++ b/testsuite/libffi.call/cls_complex_va.inc @@ -0,0 +1,80 @@ +/* -*-c-*- */ +#include "ffitest.h" +#include +#include +#include +#include + +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); +} diff --git a/testsuite/libffi.call/cls_complex_va_double.c b/testsuite/libffi.call/cls_complex_va_double.c new file mode 100644 index 0000000..879ccf3 --- /dev/null +++ b/testsuite/libffi.call/cls_complex_va_double.c @@ -0,0 +1,10 @@ +/* Area: ffi_call, closure_call + Purpose: Test complex' passed in variable argument lists. + Limitations: none. + PR: none. + Originator: . */ + +/* { dg-do run } */ + +#include "complex_defs_double.inc" +#include "cls_complex_va.inc" diff --git a/testsuite/libffi.call/cls_complex_va_float.c b/testsuite/libffi.call/cls_complex_va_float.c new file mode 100644 index 0000000..0b79979 --- /dev/null +++ b/testsuite/libffi.call/cls_complex_va_float.c @@ -0,0 +1,10 @@ +/* Area: ffi_call, closure_call + Purpose: Test complex' passed in variable argument lists. + Limitations: none. + PR: none. + Originator: . */ + +/* { dg-do run } */ + +#include "complex_defs_float.inc" +#include "cls_complex_va.inc" diff --git a/testsuite/libffi.call/cls_complex_va_longdouble.c b/testsuite/libffi.call/cls_complex_va_longdouble.c new file mode 100644 index 0000000..6eca965 --- /dev/null +++ b/testsuite/libffi.call/cls_complex_va_longdouble.c @@ -0,0 +1,10 @@ +/* Area: ffi_call, closure_call + Purpose: Test complex' passed in variable argument lists. + Limitations: none. + PR: none. + Originator: . */ + +/* { dg-do run } */ + +#include "complex_defs_longdouble.inc" +#include "cls_complex_va.inc" diff --git a/testsuite/libffi.call/complex.inc b/testsuite/libffi.call/complex.inc new file mode 100644 index 0000000..515ae3e --- /dev/null +++ b/testsuite/libffi.call/complex.inc @@ -0,0 +1,51 @@ +/* -*-c-*-*/ +#include "ffitest.h" +#include + +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); +} diff --git a/testsuite/libffi.call/complex_defs_double.inc b/testsuite/libffi.call/complex_defs_double.inc new file mode 100644 index 0000000..3583e16 --- /dev/null +++ b/testsuite/libffi.call/complex_defs_double.inc @@ -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 diff --git a/testsuite/libffi.call/complex_defs_float.inc b/testsuite/libffi.call/complex_defs_float.inc new file mode 100644 index 0000000..bbd9375 --- /dev/null +++ b/testsuite/libffi.call/complex_defs_float.inc @@ -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) diff --git a/testsuite/libffi.call/complex_defs_longdouble.inc b/testsuite/libffi.call/complex_defs_longdouble.inc new file mode 100644 index 0000000..14b9f24 --- /dev/null +++ b/testsuite/libffi.call/complex_defs_longdouble.inc @@ -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 diff --git a/testsuite/libffi.call/complex_double.c b/testsuite/libffi.call/complex_double.c new file mode 100644 index 0000000..8a3297b --- /dev/null +++ b/testsuite/libffi.call/complex_double.c @@ -0,0 +1,10 @@ +/* Area: ffi_call + Purpose: Check complex types. + Limitations: none. + PR: none. + Originator: . */ + +/* { dg-do run } */ + +#include "complex_defs_double.inc" +#include "complex.inc" diff --git a/testsuite/libffi.call/complex_float.c b/testsuite/libffi.call/complex_float.c new file mode 100644 index 0000000..5044ebb --- /dev/null +++ b/testsuite/libffi.call/complex_float.c @@ -0,0 +1,10 @@ +/* Area: ffi_call + Purpose: Check complex types. + Limitations: none. + PR: none. + Originator: . */ + +/* { dg-do run } */ + +#include "complex_defs_float.inc" +#include "complex.inc" diff --git a/testsuite/libffi.call/complex_int.c b/testsuite/libffi.call/complex_int.c new file mode 100644 index 0000000..4c8e864 --- /dev/null +++ b/testsuite/libffi.call/complex_int.c @@ -0,0 +1,86 @@ +/* Area: ffi_call + Purpose: Check non-standard complex types. + Limitations: none. + PR: none. + Originator: . */ + +/* { dg-do run } */ + +#include "ffitest.h" +#include "ffi.h" +#include + +_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_. + * 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); +} diff --git a/testsuite/libffi.call/complex_longdouble.c b/testsuite/libffi.call/complex_longdouble.c new file mode 100644 index 0000000..7e78366 --- /dev/null +++ b/testsuite/libffi.call/complex_longdouble.c @@ -0,0 +1,10 @@ +/* Area: ffi_call + Purpose: Check complex types. + Limitations: none. + PR: none. + Originator: . */ + +/* { dg-do run } */ + +#include "complex_defs_longdouble.inc" +#include "complex.inc" diff --git a/testsuite/libffi.call/many_complex.inc b/testsuite/libffi.call/many_complex.inc new file mode 100644 index 0000000..e37a774 --- /dev/null +++ b/testsuite/libffi.call/many_complex.inc @@ -0,0 +1,78 @@ +/* -*-c-*- */ +#include "ffitest.h" + +#include +#include + +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); +} diff --git a/testsuite/libffi.call/many_complex_double.c b/testsuite/libffi.call/many_complex_double.c new file mode 100644 index 0000000..3fd53c3 --- /dev/null +++ b/testsuite/libffi.call/many_complex_double.c @@ -0,0 +1,10 @@ +/* Area: ffi_call + Purpose: Check return value complex, with many arguments + Limitations: none. + PR: none. + Originator: . */ + +/* { dg-do run } */ + +#include "complex_defs_double.inc" +#include "many_complex.inc" diff --git a/testsuite/libffi.call/many_complex_float.c b/testsuite/libffi.call/many_complex_float.c new file mode 100644 index 0000000..c43d21c --- /dev/null +++ b/testsuite/libffi.call/many_complex_float.c @@ -0,0 +1,10 @@ +/* Area: ffi_call + Purpose: Check return value complex, with many arguments + Limitations: none. + PR: none. + Originator: . */ + +/* { dg-do run } */ + +#include "complex_defs_float.inc" +#include "many_complex.inc" diff --git a/testsuite/libffi.call/many_complex_longdouble.c b/testsuite/libffi.call/many_complex_longdouble.c new file mode 100644 index 0000000..dbab723 --- /dev/null +++ b/testsuite/libffi.call/many_complex_longdouble.c @@ -0,0 +1,10 @@ +/* Area: ffi_call + Purpose: Check return value complex, with many arguments + Limitations: none. + PR: none. + Originator: . */ + +/* { dg-do run } */ + +#include "complex_defs_longdouble.inc" +#include "many_complex.inc" diff --git a/testsuite/libffi.call/return_complex.inc b/testsuite/libffi.call/return_complex.inc new file mode 100644 index 0000000..8bf0c1f --- /dev/null +++ b/testsuite/libffi.call/return_complex.inc @@ -0,0 +1,37 @@ +/* -*-c-*- */ +#include "ffitest.h" +#include + +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); +} diff --git a/testsuite/libffi.call/return_complex1.inc b/testsuite/libffi.call/return_complex1.inc new file mode 100644 index 0000000..7cecc0f --- /dev/null +++ b/testsuite/libffi.call/return_complex1.inc @@ -0,0 +1,41 @@ +/* -*-c-*- */ +#include "ffitest.h" +#include + +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); +} diff --git a/testsuite/libffi.call/return_complex1_double.c b/testsuite/libffi.call/return_complex1_double.c new file mode 100644 index 0000000..727410d --- /dev/null +++ b/testsuite/libffi.call/return_complex1_double.c @@ -0,0 +1,10 @@ +/* Area: ffi_call + Purpose: Check return value complex. + Limitations: none. + PR: none. + Originator: . */ + +/* { dg-do run } */ + +#include "complex_defs_double.inc" +#include "return_complex1.inc" diff --git a/testsuite/libffi.call/return_complex1_float.c b/testsuite/libffi.call/return_complex1_float.c new file mode 100644 index 0000000..a2aeada --- /dev/null +++ b/testsuite/libffi.call/return_complex1_float.c @@ -0,0 +1,10 @@ +/* Area: ffi_call + Purpose: Check return value complex. + Limitations: none. + PR: none. + Originator: . */ + +/* { dg-do run } */ + +#include "complex_defs_float.inc" +#include "return_complex1.inc" diff --git a/testsuite/libffi.call/return_complex1_longdouble.c b/testsuite/libffi.call/return_complex1_longdouble.c new file mode 100644 index 0000000..103504b --- /dev/null +++ b/testsuite/libffi.call/return_complex1_longdouble.c @@ -0,0 +1,10 @@ +/* Area: ffi_call + Purpose: Check return value complex. + Limitations: none. + PR: none. + Originator: . */ + +/* { dg-do run } */ + +#include "complex_defs_longdouble.inc" +#include "return_complex1.inc" diff --git a/testsuite/libffi.call/return_complex2.inc b/testsuite/libffi.call/return_complex2.inc new file mode 100644 index 0000000..dad4a0f --- /dev/null +++ b/testsuite/libffi.call/return_complex2.inc @@ -0,0 +1,40 @@ +/* -*-c-*- */ +#include "ffitest.h" +#include + +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); +} diff --git a/testsuite/libffi.call/return_complex2_double.c b/testsuite/libffi.call/return_complex2_double.c new file mode 100644 index 0000000..ab9efac --- /dev/null +++ b/testsuite/libffi.call/return_complex2_double.c @@ -0,0 +1,10 @@ +/* Area: ffi_call + Purpose: Check return value complex. + Limitations: none. + PR: none. + Originator: . */ + +/* { dg-do run } */ + +#include "complex_defs_double.inc" +#include "return_complex2.inc" diff --git a/testsuite/libffi.call/return_complex2_float.c b/testsuite/libffi.call/return_complex2_float.c new file mode 100644 index 0000000..d7f22c2 --- /dev/null +++ b/testsuite/libffi.call/return_complex2_float.c @@ -0,0 +1,10 @@ +/* Area: ffi_call + Purpose: Check return value complex. + Limitations: none. + PR: none. + Originator: . */ + +/* { dg-do run } */ + +#include "complex_defs_float.inc" +#include "return_complex2.inc" diff --git a/testsuite/libffi.call/return_complex2_longdouble.c b/testsuite/libffi.call/return_complex2_longdouble.c new file mode 100644 index 0000000..3edea62 --- /dev/null +++ b/testsuite/libffi.call/return_complex2_longdouble.c @@ -0,0 +1,10 @@ +/* Area: ffi_call + Purpose: Check return value complex. + Limitations: none. + PR: none. + Originator: . */ + +/* { dg-do run } */ + +#include "complex_defs_longdouble.inc" +#include "return_complex2.inc" diff --git a/testsuite/libffi.call/return_complex_double.c b/testsuite/libffi.call/return_complex_double.c new file mode 100644 index 0000000..e2497cc --- /dev/null +++ b/testsuite/libffi.call/return_complex_double.c @@ -0,0 +1,10 @@ +/* Area: ffi_call + Purpose: Check return value complex. + Limitations: none. + PR: none. + Originator: . */ + +/* { dg-do run } */ + +#include "complex_defs_double.inc" +#include "return_complex.inc" diff --git a/testsuite/libffi.call/return_complex_float.c b/testsuite/libffi.call/return_complex_float.c new file mode 100644 index 0000000..a35528f --- /dev/null +++ b/testsuite/libffi.call/return_complex_float.c @@ -0,0 +1,10 @@ +/* Area: ffi_call + Purpose: Check return value complex. + Limitations: none. + PR: none. + Originator: . */ + +/* { dg-do run } */ + +#include "complex_defs_float.inc" +#include "return_complex.inc" diff --git a/testsuite/libffi.call/return_complex_longdouble.c b/testsuite/libffi.call/return_complex_longdouble.c new file mode 100644 index 0000000..142d7be --- /dev/null +++ b/testsuite/libffi.call/return_complex_longdouble.c @@ -0,0 +1,10 @@ +/* Area: ffi_call + Purpose: Check return value complex. + Limitations: none. + PR: none. + Originator: . */ + +/* { dg-do run } */ + +#include "complex_defs_longdouble.inc" +#include "return_complex.inc" -- 1.8.4.2 --4bRzO86E/ozDv8r1--