57f542b355
2003-10-23 Andreas Tobler <a.tobler@schweiz.ch> * src/java_raw_api.c (ffi_java_ptrarray_to_raw): Replace FFI_ASSERT(FALSE) with FFI_ASSERT(0). From-SVN: r72865
341 lines
7.9 KiB
C
341 lines
7.9 KiB
C
/* -----------------------------------------------------------------------
|
|
java_raw_api.c - Copyright (c) 1999 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 CYGNUS SOLUTIONS 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) && !defined(FFI_NO_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_ARG;
|
|
break;
|
|
case FFI_TYPE_STRUCT:
|
|
/* No structure parameters in Java. */
|
|
abort();
|
|
default:
|
|
result += FFI_SIZEOF_ARG;
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
|
|
void
|
|
ffi_java_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++) + 3);
|
|
break;
|
|
|
|
case FFI_TYPE_UINT16:
|
|
case FFI_TYPE_SINT16:
|
|
*args = (void*) ((char*)(raw++) + 2);
|
|
break;
|
|
|
|
#if FFI_SIZEOF_ARG == 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;
|
|
|
|
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_SIZEOF_ARG == 8
|
|
switch((*tp)->type) {
|
|
case FFI_TYPE_UINT64:
|
|
case FFI_TYPE_SINT64:
|
|
case FFI_TYPE_DOUBLE:
|
|
*args = (void*) raw;
|
|
raw += 2;
|
|
break;
|
|
default:
|
|
*args = (void*) raw++;
|
|
}
|
|
#else /* FFI_SIZEOF_ARG != 8 */
|
|
*args = (void*) raw;
|
|
raw += ALIGN ((*tp)->size, sizeof (void*)) / sizeof (void*);
|
|
#endif /* FFI_SIZEOF_ARG == 8 */
|
|
}
|
|
|
|
#else
|
|
#error "pdp endian not supported"
|
|
#endif /* ! PDP */
|
|
|
|
#endif /* WORDS_BIGENDIAN */
|
|
}
|
|
|
|
void
|
|
ffi_java_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:
|
|
#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_ARG == 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_ARG == 8
|
|
FFI_ASSERT(0); /* Should have covered all cases */
|
|
#else
|
|
memcpy ((void*) raw->data, (void*)*args, (*tp)->size);
|
|
raw += ALIGN ((*tp)->size, FFI_SIZEOF_ARG) / FFI_SIZEOF_ARG;
|
|
#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:
|
|
*(SINT64 *)rvalue <<= 32;
|
|
break;
|
|
|
|
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;
|
|
|
|
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 (/*@dependent@*/ ffi_cif *cif,
|
|
void (*fn)(),
|
|
/*@out@*/ void *rvalue,
|
|
/*@dependent@*/ ffi_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_raw *raw = (ffi_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, raw, cl->user_data);
|
|
ffi_java_raw_to_rvalue (cif, rvalue);
|
|
}
|
|
|
|
/* 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_raw_closure* cl,
|
|
ffi_cif *cif,
|
|
void (*fun)(ffi_cif*,void*,ffi_raw*,void*),
|
|
void *user_data)
|
|
{
|
|
ffi_status status;
|
|
|
|
status = ffi_prep_closure ((ffi_closure*) cl,
|
|
cif,
|
|
&ffi_java_translate_args,
|
|
(void*)cl);
|
|
if (status == FFI_OK)
|
|
{
|
|
cl->fun = fun;
|
|
cl->user_data = user_data;
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
#endif /* FFI_CLOSURES */
|
|
#endif /* !FFI_NATIVE_RAW_API */
|
|
#endif /* !FFI_NO_RAW_API */
|