mirror of
https://git.savannah.gnu.org/git/guile.git
synced 2025-04-30 11:50:28 +02:00
Fix small integer return value packing on big endian machines.
* libguile/foreign.c (pack): Add `return_value_p' parameter. Update callers. When RETURN_VALUE_P is true, assume LOC points to an `ffi_arg', and cast its results to the relevant type. This fixes packing of integer return values smaller than `int' on SPARC64 and PowerPC64. Reported by Nelson H. F. Beebe <beebe@math.utah.edu>.
This commit is contained in:
parent
d7fcaec392
commit
012062a0d6
1 changed files with 39 additions and 10 deletions
|
@ -965,9 +965,12 @@ unpack (const ffi_type *type, void *loc, SCM x)
|
||||||
}
|
}
|
||||||
#undef FUNC_NAME
|
#undef FUNC_NAME
|
||||||
|
|
||||||
/* Return a Scheme representation of the foreign value at LOC of type TYPE. */
|
/* Return a Scheme representation of the foreign value at LOC of type
|
||||||
|
TYPE. When RETURN_VALUE_P is true, LOC is assumed to point to a
|
||||||
|
return value buffer; otherwise LOC is assumed to point to an
|
||||||
|
argument buffer. */
|
||||||
static SCM
|
static SCM
|
||||||
pack (const ffi_type * type, const void *loc)
|
pack (const ffi_type * type, const void *loc, int return_value_p)
|
||||||
{
|
{
|
||||||
switch (type->type)
|
switch (type->type)
|
||||||
{
|
{
|
||||||
|
@ -977,22 +980,48 @@ pack (const ffi_type * type, const void *loc)
|
||||||
return scm_from_double (*(float *) loc);
|
return scm_from_double (*(float *) loc);
|
||||||
case FFI_TYPE_DOUBLE:
|
case FFI_TYPE_DOUBLE:
|
||||||
return scm_from_double (*(double *) loc);
|
return scm_from_double (*(double *) loc);
|
||||||
|
|
||||||
|
/* For integer return values smaller than `int', libffi stores the
|
||||||
|
result in an `ffi_arg'-long buffer, of which only the
|
||||||
|
significant bits must be kept---hence the pair of casts below.
|
||||||
|
See <http://thread.gmane.org/gmane.comp.lib.ffi.general/406>
|
||||||
|
for details. */
|
||||||
|
|
||||||
case FFI_TYPE_UINT8:
|
case FFI_TYPE_UINT8:
|
||||||
|
if (return_value_p)
|
||||||
|
return scm_from_uint8 ((scm_t_uint8) *(ffi_arg *) loc);
|
||||||
|
else
|
||||||
return scm_from_uint8 (* (scm_t_uint8 *) loc);
|
return scm_from_uint8 (* (scm_t_uint8 *) loc);
|
||||||
case FFI_TYPE_SINT8:
|
case FFI_TYPE_SINT8:
|
||||||
|
if (return_value_p)
|
||||||
|
return scm_from_int8 ((scm_t_int8) *(ffi_arg *) loc);
|
||||||
|
else
|
||||||
return scm_from_int8 (* (scm_t_int8 *) loc);
|
return scm_from_int8 (* (scm_t_int8 *) loc);
|
||||||
case FFI_TYPE_UINT16:
|
case FFI_TYPE_UINT16:
|
||||||
|
if (return_value_p)
|
||||||
|
return scm_from_uint16 ((scm_t_uint16) *(ffi_arg *) loc);
|
||||||
|
else
|
||||||
return scm_from_uint16 (* (scm_t_uint16 *) loc);
|
return scm_from_uint16 (* (scm_t_uint16 *) loc);
|
||||||
case FFI_TYPE_SINT16:
|
case FFI_TYPE_SINT16:
|
||||||
|
if (return_value_p)
|
||||||
|
return scm_from_int16 ((scm_t_int16) *(ffi_arg *) loc);
|
||||||
|
else
|
||||||
return scm_from_int16 (* (scm_t_int16 *) loc);
|
return scm_from_int16 (* (scm_t_int16 *) loc);
|
||||||
case FFI_TYPE_UINT32:
|
case FFI_TYPE_UINT32:
|
||||||
|
if (return_value_p)
|
||||||
|
return scm_from_uint32 ((scm_t_uint32) *(ffi_arg *) loc);
|
||||||
|
else
|
||||||
return scm_from_uint32 (* (scm_t_uint32 *) loc);
|
return scm_from_uint32 (* (scm_t_uint32 *) loc);
|
||||||
case FFI_TYPE_SINT32:
|
case FFI_TYPE_SINT32:
|
||||||
|
if (return_value_p)
|
||||||
|
return scm_from_int32 ((scm_t_int32) *(ffi_arg *) loc);
|
||||||
|
else
|
||||||
return scm_from_int32 (* (scm_t_int32 *) loc);
|
return scm_from_int32 (* (scm_t_int32 *) loc);
|
||||||
case FFI_TYPE_UINT64:
|
case FFI_TYPE_UINT64:
|
||||||
return scm_from_uint64 (*(scm_t_uint64 *) loc);
|
return scm_from_uint64 (*(scm_t_uint64 *) loc);
|
||||||
case FFI_TYPE_SINT64:
|
case FFI_TYPE_SINT64:
|
||||||
return scm_from_int64 (*(scm_t_int64 *) loc);
|
return scm_from_int64 (*(scm_t_int64 *) loc);
|
||||||
|
|
||||||
case FFI_TYPE_STRUCT:
|
case FFI_TYPE_STRUCT:
|
||||||
{
|
{
|
||||||
void *mem = scm_gc_malloc_pointerless (type->size, "foreign");
|
void *mem = scm_gc_malloc_pointerless (type->size, "foreign");
|
||||||
|
@ -1060,7 +1089,7 @@ scm_i_foreign_call (SCM foreign, const SCM *argv)
|
||||||
/* off we go! */
|
/* off we go! */
|
||||||
ffi_call (cif, func, rvalue, args);
|
ffi_call (cif, func, rvalue, args);
|
||||||
|
|
||||||
return pack (cif->rtype, rvalue);
|
return pack (cif->rtype, rvalue, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1082,7 +1111,7 @@ invoke_closure (ffi_cif *cif, void *ret, void **args, void *data)
|
||||||
|
|
||||||
/* Pack ARGS to SCM values, setting ARGV pointers. */
|
/* Pack ARGS to SCM values, setting ARGV pointers. */
|
||||||
for (i = 0; i < cif->nargs; i++)
|
for (i = 0; i < cif->nargs; i++)
|
||||||
argv[i] = pack (cif->arg_types[i], args[i]);
|
argv[i] = pack (cif->arg_types[i], args[i], 0);
|
||||||
|
|
||||||
result = scm_call_n (proc, argv, cif->nargs);
|
result = scm_call_n (proc, argv, cif->nargs);
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue