* 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.
268 lines
6.1 KiB
C
268 lines
6.1 KiB
C
/* -----------------------------------------------------------------------
|
|
raw_api.c - Copyright (c) 1999, 2008 Red Hat, Inc.
|
|
|
|
Author: Kresten Krab Thorup <krab@gnu.org>
|
|
|
|
Permission is hereby granted, free of charge, to any person obtaining
|
|
a copy of this software and associated documentation files (the
|
|
``Software''), to deal in the Software without restriction, including
|
|
without limitation the rights to use, copy, modify, merge, publish,
|
|
distribute, sublicense, and/or sell copies of the Software, and to
|
|
permit persons to whom the Software is furnished to do so, subject to
|
|
the following conditions:
|
|
|
|
The above copyright notice and this permission notice shall be included
|
|
in all copies or substantial portions of the Software.
|
|
|
|
THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
|
|
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
|
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
|
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
DEALINGS IN THE SOFTWARE.
|
|
----------------------------------------------------------------------- */
|
|
|
|
/* This file defines generic functions for use with the raw api. */
|
|
|
|
#include <ffi.h>
|
|
#include <ffi_common.h>
|
|
|
|
#if !FFI_NO_RAW_API
|
|
|
|
size_t
|
|
ffi_raw_size (ffi_cif *cif)
|
|
{
|
|
size_t result = 0;
|
|
int i;
|
|
|
|
ffi_type **at = cif->arg_types;
|
|
|
|
for (i = cif->nargs-1; i >= 0; i--, at++)
|
|
{
|
|
#if !FFI_NO_STRUCTS
|
|
if ((*at)->type == FFI_TYPE_STRUCT)
|
|
result += ALIGN (sizeof (void*), FFI_SIZEOF_ARG);
|
|
else
|
|
#endif
|
|
result += ALIGN ((*at)->size, FFI_SIZEOF_ARG);
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
|
|
void
|
|
ffi_raw_to_ptrarray (ffi_cif *cif, ffi_raw *raw, void **args)
|
|
{
|
|
unsigned i;
|
|
ffi_type **tp = cif->arg_types;
|
|
|
|
#if WORDS_BIGENDIAN
|
|
|
|
for (i = 0; i < cif->nargs; i++, tp++, args++)
|
|
{
|
|
switch ((*tp)->type)
|
|
{
|
|
case FFI_TYPE_UINT8:
|
|
case FFI_TYPE_SINT8:
|
|
*args = (void*) ((char*)(raw++) + FFI_SIZEOF_ARG - 1);
|
|
break;
|
|
|
|
case FFI_TYPE_UINT16:
|
|
case FFI_TYPE_SINT16:
|
|
*args = (void*) ((char*)(raw++) + FFI_SIZEOF_ARG - 2);
|
|
break;
|
|
|
|
#if FFI_SIZEOF_ARG >= 4
|
|
case FFI_TYPE_UINT32:
|
|
case FFI_TYPE_SINT32:
|
|
*args = (void*) ((char*)(raw++) + FFI_SIZEOF_ARG - 4);
|
|
break;
|
|
#endif
|
|
|
|
#if !FFI_NO_STRUCTS
|
|
case FFI_TYPE_STRUCT:
|
|
*args = (raw++)->ptr;
|
|
break;
|
|
#endif
|
|
|
|
case FFI_TYPE_COMPLEX:
|
|
*args = (raw++)->ptr;
|
|
break;
|
|
|
|
case FFI_TYPE_POINTER:
|
|
*args = (void*) &(raw++)->ptr;
|
|
break;
|
|
|
|
default:
|
|
*args = raw;
|
|
raw += ALIGN ((*tp)->size, FFI_SIZEOF_ARG) / FFI_SIZEOF_ARG;
|
|
}
|
|
}
|
|
|
|
#else /* WORDS_BIGENDIAN */
|
|
|
|
#if !PDP
|
|
|
|
/* then assume little endian */
|
|
for (i = 0; i < cif->nargs; i++, tp++, args++)
|
|
{
|
|
#if !FFI_NO_STRUCTS
|
|
if ((*tp)->type == FFI_TYPE_STRUCT)
|
|
{
|
|
*args = (raw++)->ptr;
|
|
}
|
|
else
|
|
#endif
|
|
if ((*tp)->type == FFI_TYPE_COMPLEX)
|
|
{
|
|
*args = (raw++)->ptr;
|
|
}
|
|
else
|
|
{
|
|
*args = (void*) raw;
|
|
raw += ALIGN ((*tp)->size, sizeof (void*)) / sizeof (void*);
|
|
}
|
|
}
|
|
|
|
#else
|
|
#error "pdp endian not supported"
|
|
#endif /* ! PDP */
|
|
|
|
#endif /* WORDS_BIGENDIAN */
|
|
}
|
|
|
|
void
|
|
ffi_ptrarray_to_raw (ffi_cif *cif, void **args, ffi_raw *raw)
|
|
{
|
|
unsigned i;
|
|
ffi_type **tp = cif->arg_types;
|
|
|
|
for (i = 0; i < cif->nargs; i++, tp++, args++)
|
|
{
|
|
switch ((*tp)->type)
|
|
{
|
|
case FFI_TYPE_UINT8:
|
|
(raw++)->uint = *(UINT8*) (*args);
|
|
break;
|
|
|
|
case FFI_TYPE_SINT8:
|
|
(raw++)->sint = *(SINT8*) (*args);
|
|
break;
|
|
|
|
case FFI_TYPE_UINT16:
|
|
(raw++)->uint = *(UINT16*) (*args);
|
|
break;
|
|
|
|
case FFI_TYPE_SINT16:
|
|
(raw++)->sint = *(SINT16*) (*args);
|
|
break;
|
|
|
|
#if FFI_SIZEOF_ARG >= 4
|
|
case FFI_TYPE_UINT32:
|
|
(raw++)->uint = *(UINT32*) (*args);
|
|
break;
|
|
|
|
case FFI_TYPE_SINT32:
|
|
(raw++)->sint = *(SINT32*) (*args);
|
|
break;
|
|
#endif
|
|
|
|
#if !FFI_NO_STRUCTS
|
|
case FFI_TYPE_STRUCT:
|
|
(raw++)->ptr = *args;
|
|
break;
|
|
#endif
|
|
|
|
case FFI_TYPE_COMPLEX:
|
|
(raw++)->ptr = *args;
|
|
break;
|
|
|
|
case FFI_TYPE_POINTER:
|
|
(raw++)->ptr = **(void***) args;
|
|
break;
|
|
|
|
default:
|
|
memcpy ((void*) raw->data, (void*)*args, (*tp)->size);
|
|
raw += ALIGN ((*tp)->size, FFI_SIZEOF_ARG) / FFI_SIZEOF_ARG;
|
|
}
|
|
}
|
|
}
|
|
|
|
#if !FFI_NATIVE_RAW_API
|
|
|
|
|
|
/* This is a generic definition of ffi_raw_call, to be used if the
|
|
* native system does not provide a machine-specific implementation.
|
|
* Having this, allows code to be written for the raw API, without
|
|
* the need for system-specific code to handle input in that format;
|
|
* these following couple of functions will handle the translation forth
|
|
* and back automatically. */
|
|
|
|
void ffi_raw_call (ffi_cif *cif, void (*fn)(void), void *rvalue, ffi_raw *raw)
|
|
{
|
|
void **avalue = (void**) alloca (cif->nargs * sizeof (void*));
|
|
ffi_raw_to_ptrarray (cif, raw, avalue);
|
|
ffi_call (cif, fn, rvalue, avalue);
|
|
}
|
|
|
|
#if FFI_CLOSURES /* base system provides closures */
|
|
|
|
static void
|
|
ffi_translate_args (ffi_cif *cif, void *rvalue,
|
|
void **avalue, void *user_data)
|
|
{
|
|
ffi_raw *raw = (ffi_raw*)alloca (ffi_raw_size (cif));
|
|
ffi_raw_closure *cl = (ffi_raw_closure*)user_data;
|
|
|
|
ffi_ptrarray_to_raw (cif, avalue, raw);
|
|
(*cl->fun) (cif, rvalue, raw, cl->user_data);
|
|
}
|
|
|
|
ffi_status
|
|
ffi_prep_raw_closure_loc (ffi_raw_closure* cl,
|
|
ffi_cif *cif,
|
|
void (*fun)(ffi_cif*,void*,ffi_raw*,void*),
|
|
void *user_data,
|
|
void *codeloc)
|
|
{
|
|
ffi_status status;
|
|
|
|
status = ffi_prep_closure_loc ((ffi_closure*) cl,
|
|
cif,
|
|
&ffi_translate_args,
|
|
codeloc,
|
|
codeloc);
|
|
if (status == FFI_OK)
|
|
{
|
|
cl->fun = fun;
|
|
cl->user_data = user_data;
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
#endif /* FFI_CLOSURES */
|
|
#endif /* !FFI_NATIVE_RAW_API */
|
|
|
|
#if FFI_CLOSURES
|
|
|
|
/* Again, here is the generic version of ffi_prep_raw_closure, which
|
|
* will install an intermediate "hub" for translation of arguments from
|
|
* the pointer-array format, to the raw format */
|
|
|
|
ffi_status
|
|
ffi_prep_raw_closure (ffi_raw_closure* cl,
|
|
ffi_cif *cif,
|
|
void (*fun)(ffi_cif*,void*,ffi_raw*,void*),
|
|
void *user_data)
|
|
{
|
|
return ffi_prep_raw_closure_loc (cl, cif, fun, user_data, cl);
|
|
}
|
|
|
|
#endif /* FFI_CLOSURES */
|
|
|
|
#endif /* !FFI_NO_RAW_API */
|