|  | /* ----------------------------------------------------------------------- | 
|  | java_raw_api.c - Copyright (c) 1999, 2007, 2008  Red Hat, Inc. | 
|  |  | 
|  | Cloned from raw_api.c | 
|  |  | 
|  | Raw_api.c author: Kresten Krab Thorup <krab@gnu.org> | 
|  | Java_raw_api.c author: Hans-J. Boehm <hboehm@hpl.hp.com> | 
|  |  | 
|  | $Id $ | 
|  |  | 
|  | 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 defines a Java- and 64-bit specific variant of the raw API.	*/ | 
|  | /* It assumes that "raw" argument blocks look like Java stacks on a	*/ | 
|  | /* 64-bit machine.  Arguments that can be stored in a single stack	*/ | 
|  | /* stack slots (longs, doubles) occupy 128 bits, but only the first	*/ | 
|  | /* 64 bits are actually used.						*/ | 
|  |  | 
|  | #include <ffi.h> | 
|  | #include <ffi_common.h> | 
|  | #include <stdlib.h> | 
|  |  | 
|  | #if !defined(NO_JAVA_RAW_API) | 
|  |  | 
|  | size_t | 
|  | ffi_java_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++) | 
|  | { | 
|  | switch((*at) -> type) { | 
|  | case FFI_TYPE_UINT64: | 
|  | case FFI_TYPE_SINT64: | 
|  | case FFI_TYPE_DOUBLE: | 
|  | result += 2 * FFI_SIZEOF_JAVA_RAW; | 
|  | break; | 
|  | case FFI_TYPE_STRUCT: | 
|  | /* No structure parameters in Java.	*/ | 
|  | abort(); | 
|  | case FFI_TYPE_COMPLEX: | 
|  | /* Not supported yet.  */ | 
|  | abort(); | 
|  | default: | 
|  | result += FFI_SIZEOF_JAVA_RAW; | 
|  | } | 
|  | } | 
|  |  | 
|  | return result; | 
|  | } | 
|  |  | 
|  |  | 
|  | void | 
|  | ffi_java_raw_to_ptrarray (ffi_cif *cif, ffi_java_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++) + 3); | 
|  | break; | 
|  |  | 
|  | case FFI_TYPE_UINT16: | 
|  | case FFI_TYPE_SINT16: | 
|  | *args = (void*) ((char*)(raw++) + 2); | 
|  | break; | 
|  |  | 
|  | #if FFI_SIZEOF_JAVA_RAW == 8 | 
|  | case FFI_TYPE_UINT64: | 
|  | case FFI_TYPE_SINT64: | 
|  | case FFI_TYPE_DOUBLE: | 
|  | *args = (void *)raw; | 
|  | raw += 2; | 
|  | break; | 
|  | #endif | 
|  |  | 
|  | case FFI_TYPE_POINTER: | 
|  | *args = (void*) &(raw++)->ptr; | 
|  | break; | 
|  |  | 
|  | case FFI_TYPE_COMPLEX: | 
|  | /* Not supported yet.  */ | 
|  | abort(); | 
|  |  | 
|  | default: | 
|  | *args = raw; | 
|  | raw += | 
|  | ALIGN ((*tp)->size, sizeof(ffi_java_raw)) / sizeof(ffi_java_raw); | 
|  | } | 
|  | } | 
|  |  | 
|  | #else /* WORDS_BIGENDIAN */ | 
|  |  | 
|  | #if !PDP | 
|  |  | 
|  | /* then assume little endian */ | 
|  | for (i = 0; i < cif->nargs; i++, tp++, args++) | 
|  | { | 
|  | #if FFI_SIZEOF_JAVA_RAW == 8 | 
|  | switch((*tp)->type) { | 
|  | case FFI_TYPE_UINT64: | 
|  | case FFI_TYPE_SINT64: | 
|  | case FFI_TYPE_DOUBLE: | 
|  | *args = (void*) raw; | 
|  | raw += 2; | 
|  | break; | 
|  | case FFI_TYPE_COMPLEX: | 
|  | /* Not supported yet.  */ | 
|  | abort(); | 
|  | default: | 
|  | *args = (void*) raw++; | 
|  | } | 
|  | #else /* FFI_SIZEOF_JAVA_RAW != 8 */ | 
|  | *args = (void*) raw; | 
|  | raw += | 
|  | ALIGN ((*tp)->size, sizeof(ffi_java_raw)) / sizeof(ffi_java_raw); | 
|  | #endif /* FFI_SIZEOF_JAVA_RAW == 8 */ | 
|  | } | 
|  |  | 
|  | #else | 
|  | #error "pdp endian not supported" | 
|  | #endif /* ! PDP */ | 
|  |  | 
|  | #endif /* WORDS_BIGENDIAN */ | 
|  | } | 
|  |  | 
|  | void | 
|  | ffi_java_ptrarray_to_raw (ffi_cif *cif, void **args, ffi_java_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: | 
|  | #if WORDS_BIGENDIAN | 
|  | *(UINT32*)(raw++) = *(UINT8*) (*args); | 
|  | #else | 
|  | (raw++)->uint = *(UINT8*) (*args); | 
|  | #endif | 
|  | break; | 
|  |  | 
|  | case FFI_TYPE_SINT8: | 
|  | #if WORDS_BIGENDIAN | 
|  | *(SINT32*)(raw++) = *(SINT8*) (*args); | 
|  | #else | 
|  | (raw++)->sint = *(SINT8*) (*args); | 
|  | #endif | 
|  | break; | 
|  |  | 
|  | case FFI_TYPE_UINT16: | 
|  | #if WORDS_BIGENDIAN | 
|  | *(UINT32*)(raw++) = *(UINT16*) (*args); | 
|  | #else | 
|  | (raw++)->uint = *(UINT16*) (*args); | 
|  | #endif | 
|  | break; | 
|  |  | 
|  | case FFI_TYPE_SINT16: | 
|  | #if WORDS_BIGENDIAN | 
|  | *(SINT32*)(raw++) = *(SINT16*) (*args); | 
|  | #else | 
|  | (raw++)->sint = *(SINT16*) (*args); | 
|  | #endif | 
|  | break; | 
|  |  | 
|  | case FFI_TYPE_UINT32: | 
|  | #if WORDS_BIGENDIAN | 
|  | *(UINT32*)(raw++) = *(UINT32*) (*args); | 
|  | #else | 
|  | (raw++)->uint = *(UINT32*) (*args); | 
|  | #endif | 
|  | break; | 
|  |  | 
|  | case FFI_TYPE_SINT32: | 
|  | #if WORDS_BIGENDIAN | 
|  | *(SINT32*)(raw++) = *(SINT32*) (*args); | 
|  | #else | 
|  | (raw++)->sint = *(SINT32*) (*args); | 
|  | #endif | 
|  | break; | 
|  |  | 
|  | case FFI_TYPE_FLOAT: | 
|  | (raw++)->flt = *(FLOAT32*) (*args); | 
|  | break; | 
|  |  | 
|  | #if FFI_SIZEOF_JAVA_RAW == 8 | 
|  | case FFI_TYPE_UINT64: | 
|  | case FFI_TYPE_SINT64: | 
|  | case FFI_TYPE_DOUBLE: | 
|  | raw->uint = *(UINT64*) (*args); | 
|  | raw += 2; | 
|  | break; | 
|  | #endif | 
|  |  | 
|  | case FFI_TYPE_POINTER: | 
|  | (raw++)->ptr = **(void***) args; | 
|  | break; | 
|  |  | 
|  | default: | 
|  | #if FFI_SIZEOF_JAVA_RAW == 8 | 
|  | FFI_ASSERT(0);	/* Should have covered all cases */ | 
|  | #else | 
|  | memcpy ((void*) raw->data, (void*)*args, (*tp)->size); | 
|  | raw += | 
|  | ALIGN ((*tp)->size, sizeof(ffi_java_raw)) / sizeof(ffi_java_raw); | 
|  | #endif | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | #if !FFI_NATIVE_RAW_API | 
|  |  | 
|  | static void | 
|  | ffi_java_rvalue_to_raw (ffi_cif *cif, void *rvalue) | 
|  | { | 
|  | #if WORDS_BIGENDIAN && FFI_SIZEOF_ARG == 8 | 
|  | switch (cif->rtype->type) | 
|  | { | 
|  | case FFI_TYPE_UINT8: | 
|  | case FFI_TYPE_UINT16: | 
|  | case FFI_TYPE_UINT32: | 
|  | *(UINT64 *)rvalue <<= 32; | 
|  | break; | 
|  |  | 
|  | case FFI_TYPE_SINT8: | 
|  | case FFI_TYPE_SINT16: | 
|  | case FFI_TYPE_SINT32: | 
|  | case FFI_TYPE_INT: | 
|  | #if FFI_SIZEOF_JAVA_RAW == 4 | 
|  | case FFI_TYPE_POINTER: | 
|  | #endif | 
|  | *(SINT64 *)rvalue <<= 32; | 
|  | break; | 
|  |  | 
|  | case FFI_TYPE_COMPLEX: | 
|  | /* Not supported yet.  */ | 
|  | abort(); | 
|  |  | 
|  | default: | 
|  | break; | 
|  | } | 
|  | #endif | 
|  | } | 
|  |  | 
|  | static void | 
|  | ffi_java_raw_to_rvalue (ffi_cif *cif, void *rvalue) | 
|  | { | 
|  | #if WORDS_BIGENDIAN && FFI_SIZEOF_ARG == 8 | 
|  | switch (cif->rtype->type) | 
|  | { | 
|  | case FFI_TYPE_UINT8: | 
|  | case FFI_TYPE_UINT16: | 
|  | case FFI_TYPE_UINT32: | 
|  | *(UINT64 *)rvalue >>= 32; | 
|  | break; | 
|  |  | 
|  | case FFI_TYPE_SINT8: | 
|  | case FFI_TYPE_SINT16: | 
|  | case FFI_TYPE_SINT32: | 
|  | case FFI_TYPE_INT: | 
|  | *(SINT64 *)rvalue >>= 32; | 
|  | break; | 
|  |  | 
|  | case FFI_TYPE_COMPLEX: | 
|  | /* Not supported yet.  */ | 
|  | abort(); | 
|  |  | 
|  | default: | 
|  | break; | 
|  | } | 
|  | #endif | 
|  | } | 
|  |  | 
|  | /* 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_java_raw_call (ffi_cif *cif, void (*fn)(void), void *rvalue, | 
|  | ffi_java_raw *raw) | 
|  | { | 
|  | void **avalue = (void**) alloca (cif->nargs * sizeof (void*)); | 
|  | ffi_java_raw_to_ptrarray (cif, raw, avalue); | 
|  | ffi_call (cif, fn, rvalue, avalue); | 
|  | ffi_java_rvalue_to_raw (cif, rvalue); | 
|  | } | 
|  |  | 
|  | #if FFI_CLOSURES		/* base system provides closures */ | 
|  |  | 
|  | static void | 
|  | ffi_java_translate_args (ffi_cif *cif, void *rvalue, | 
|  | void **avalue, void *user_data) | 
|  | { | 
|  | ffi_java_raw *raw = (ffi_java_raw*)alloca (ffi_java_raw_size (cif)); | 
|  | ffi_raw_closure *cl = (ffi_raw_closure*)user_data; | 
|  |  | 
|  | ffi_java_ptrarray_to_raw (cif, avalue, raw); | 
|  | (*cl->fun) (cif, rvalue, (ffi_raw*)raw, cl->user_data); | 
|  | ffi_java_raw_to_rvalue (cif, rvalue); | 
|  | } | 
|  |  | 
|  | ffi_status | 
|  | ffi_prep_java_raw_closure_loc (ffi_java_raw_closure* cl, | 
|  | ffi_cif *cif, | 
|  | void (*fun)(ffi_cif*,void*,ffi_java_raw*,void*), | 
|  | void *user_data, | 
|  | void *codeloc) | 
|  | { | 
|  | ffi_status status; | 
|  |  | 
|  | status = ffi_prep_closure_loc ((ffi_closure*) cl, | 
|  | cif, | 
|  | &ffi_java_translate_args, | 
|  | codeloc, | 
|  | codeloc); | 
|  | if (status == FFI_OK) | 
|  | { | 
|  | cl->fun       = fun; | 
|  | cl->user_data = user_data; | 
|  | } | 
|  |  | 
|  | return status; | 
|  | } | 
|  |  | 
|  | /* 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_java_raw_closure (ffi_java_raw_closure* cl, | 
|  | ffi_cif *cif, | 
|  | void (*fun)(ffi_cif*,void*,ffi_java_raw*,void*), | 
|  | void *user_data) | 
|  | { | 
|  | return ffi_prep_java_raw_closure_loc (cl, cif, fun, user_data, cl); | 
|  | } | 
|  |  | 
|  | #endif /* FFI_CLOSURES */ | 
|  | #endif /* !FFI_NATIVE_RAW_API */ | 
|  | #endif /* !NO_JAVA_RAW_API */ |