re PR libffi/60073 (64-bit libffi.call/cls_double_va.c FAILs after recent modification)
PR libffi/60073 * src/sparc/v8.S: Assemble only if !SPARC64. * src/sparc/v9.S: Remove obsolete comment. * src/sparc/ffitarget.h (enum ffi_abi): Add FFI_COMPAT_V9. (V8_ABI_P): New macro. (V9_ABI_P): Likewise. (FFI_EXTRA_CIF_FIELDS): Define only if SPARC64. * src/sparc/ffi.c (ffi_prep_args_v8): Compile only if !SPARC64. (ffi_prep_args_v9): Compile only if SPARC64. (ffi_prep_cif_machdep_core): Use V9_ABI_P predicate. (ffi_prep_cif_machdep): Guard access to nfixedargs field. (ffi_prep_cif_machdep_var): Likewise. (ffi_v9_layout_struct): Compile only if SPARC64. (ffi_call): Deal with FFI_V8PLUS and FFI_COMPAT_V9 and fix warnings. (ffi_prep_closure_loc): Use V9_ABI_P and V8_ABI_P predicates. (ffi_closure_sparc_inner_v8): Compile only if !SPARC64. (ffi_closure_sparc_inner_v9): Compile only if SPARC64. Guard access to nfixedargs field. From-SVN: r207822
This commit is contained in:
parent
583a9919ad
commit
248d745ac2
5 changed files with 276 additions and 206 deletions
|
@ -1,3 +1,24 @@
|
|||
2014-02-17 Eric Botcazou <ebotcazou@adacore.com>
|
||||
|
||||
PR libffi/60073
|
||||
* src/sparc/v8.S: Assemble only if !SPARC64.
|
||||
* src/sparc/v9.S: Remove obsolete comment.
|
||||
* src/sparc/ffitarget.h (enum ffi_abi): Add FFI_COMPAT_V9.
|
||||
(V8_ABI_P): New macro.
|
||||
(V9_ABI_P): Likewise.
|
||||
(FFI_EXTRA_CIF_FIELDS): Define only if SPARC64.
|
||||
* src/sparc/ffi.c (ffi_prep_args_v8): Compile only if !SPARC64.
|
||||
(ffi_prep_args_v9): Compile only if SPARC64.
|
||||
(ffi_prep_cif_machdep_core): Use V9_ABI_P predicate.
|
||||
(ffi_prep_cif_machdep): Guard access to nfixedargs field.
|
||||
(ffi_prep_cif_machdep_var): Likewise.
|
||||
(ffi_v9_layout_struct): Compile only if SPARC64.
|
||||
(ffi_call): Deal with FFI_V8PLUS and FFI_COMPAT_V9 and fix warnings.
|
||||
(ffi_prep_closure_loc): Use V9_ABI_P and V8_ABI_P predicates.
|
||||
(ffi_closure_sparc_inner_v8): Compile only if !SPARC64.
|
||||
(ffi_closure_sparc_inner_v9): Compile only if SPARC64. Guard access
|
||||
to nfixedargs field.
|
||||
|
||||
2014-02-13 Eric Botcazou <ebotcazou@adacore.com>
|
||||
|
||||
PR libffi/60073
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/* -----------------------------------------------------------------------
|
||||
ffi.c - Copyright (c) 2011 Anthony Green
|
||||
Copyright (c) 1996, 2003-2004, 2007-2008 Red Hat, Inc.
|
||||
|
||||
|
||||
SPARC Foreign Function Interface
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
|
@ -34,93 +34,10 @@
|
|||
/* ffi_prep_args is called by the assembly routine once stack space
|
||||
has been allocated for the function's arguments */
|
||||
|
||||
void ffi_prep_args_v8(char *stack, extended_cif *ecif)
|
||||
{
|
||||
int i;
|
||||
void **p_argv;
|
||||
char *argp;
|
||||
ffi_type **p_arg;
|
||||
#ifdef SPARC64
|
||||
|
||||
/* Skip 16 words for the window save area */
|
||||
argp = stack + 16*sizeof(int);
|
||||
|
||||
/* This should only really be done when we are returning a structure,
|
||||
however, it's faster just to do it all the time...
|
||||
|
||||
if ( ecif->cif->rtype->type == FFI_TYPE_STRUCT ) */
|
||||
*(int *) argp = (long)ecif->rvalue;
|
||||
|
||||
/* And 1 word for the structure return value. */
|
||||
argp += sizeof(int);
|
||||
|
||||
#ifdef USING_PURIFY
|
||||
/* Purify will probably complain in our assembly routine, unless we
|
||||
zero out this memory. */
|
||||
|
||||
((int*)argp)[0] = 0;
|
||||
((int*)argp)[1] = 0;
|
||||
((int*)argp)[2] = 0;
|
||||
((int*)argp)[3] = 0;
|
||||
((int*)argp)[4] = 0;
|
||||
((int*)argp)[5] = 0;
|
||||
#endif
|
||||
|
||||
p_argv = ecif->avalue;
|
||||
|
||||
for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types; i; i--, p_arg++)
|
||||
{
|
||||
size_t z;
|
||||
|
||||
if ((*p_arg)->type == FFI_TYPE_STRUCT
|
||||
#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
|
||||
|| (*p_arg)->type == FFI_TYPE_LONGDOUBLE
|
||||
#endif
|
||||
)
|
||||
{
|
||||
*(unsigned int *) argp = (unsigned long)(* p_argv);
|
||||
z = sizeof(int);
|
||||
}
|
||||
else
|
||||
{
|
||||
z = (*p_arg)->size;
|
||||
if (z < sizeof(int))
|
||||
{
|
||||
z = sizeof(int);
|
||||
switch ((*p_arg)->type)
|
||||
{
|
||||
case FFI_TYPE_SINT8:
|
||||
*(signed int *) argp = *(SINT8 *)(* p_argv);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_UINT8:
|
||||
*(unsigned int *) argp = *(UINT8 *)(* p_argv);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_SINT16:
|
||||
*(signed int *) argp = *(SINT16 *)(* p_argv);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_UINT16:
|
||||
*(unsigned int *) argp = *(UINT16 *)(* p_argv);
|
||||
break;
|
||||
|
||||
default:
|
||||
FFI_ASSERT(0);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy(argp, *p_argv, z);
|
||||
}
|
||||
}
|
||||
p_argv++;
|
||||
argp += z;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
int ffi_prep_args_v9(char *stack, extended_cif *ecif)
|
||||
int
|
||||
ffi_prep_args_v9(char *stack, extended_cif *ecif)
|
||||
{
|
||||
int i, ret = 0;
|
||||
int tmp;
|
||||
|
@ -248,12 +165,105 @@ int ffi_prep_args_v9(char *stack, extended_cif *ecif)
|
|||
return ret;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
void
|
||||
ffi_prep_args_v8(char *stack, extended_cif *ecif)
|
||||
{
|
||||
int i;
|
||||
void **p_argv;
|
||||
char *argp;
|
||||
ffi_type **p_arg;
|
||||
|
||||
/* Skip 16 words for the window save area */
|
||||
argp = stack + 16*sizeof(int);
|
||||
|
||||
/* This should only really be done when we are returning a structure,
|
||||
however, it's faster just to do it all the time...
|
||||
|
||||
if ( ecif->cif->rtype->type == FFI_TYPE_STRUCT ) */
|
||||
*(int *) argp = (long)ecif->rvalue;
|
||||
|
||||
/* And 1 word for the structure return value. */
|
||||
argp += sizeof(int);
|
||||
|
||||
#ifdef USING_PURIFY
|
||||
/* Purify will probably complain in our assembly routine, unless we
|
||||
zero out this memory. */
|
||||
|
||||
((int*)argp)[0] = 0;
|
||||
((int*)argp)[1] = 0;
|
||||
((int*)argp)[2] = 0;
|
||||
((int*)argp)[3] = 0;
|
||||
((int*)argp)[4] = 0;
|
||||
((int*)argp)[5] = 0;
|
||||
#endif
|
||||
|
||||
p_argv = ecif->avalue;
|
||||
|
||||
for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types; i; i--, p_arg++)
|
||||
{
|
||||
size_t z;
|
||||
|
||||
if ((*p_arg)->type == FFI_TYPE_STRUCT
|
||||
#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
|
||||
|| (*p_arg)->type == FFI_TYPE_LONGDOUBLE
|
||||
#endif
|
||||
)
|
||||
{
|
||||
*(unsigned int *) argp = (unsigned long)(* p_argv);
|
||||
z = sizeof(int);
|
||||
}
|
||||
else
|
||||
{
|
||||
z = (*p_arg)->size;
|
||||
if (z < sizeof(int))
|
||||
{
|
||||
z = sizeof(int);
|
||||
switch ((*p_arg)->type)
|
||||
{
|
||||
case FFI_TYPE_SINT8:
|
||||
*(signed int *) argp = *(SINT8 *)(* p_argv);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_UINT8:
|
||||
*(unsigned int *) argp = *(UINT8 *)(* p_argv);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_SINT16:
|
||||
*(signed int *) argp = *(SINT16 *)(* p_argv);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_UINT16:
|
||||
*(unsigned int *) argp = *(UINT16 *)(* p_argv);
|
||||
break;
|
||||
|
||||
default:
|
||||
FFI_ASSERT(0);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy(argp, *p_argv, z);
|
||||
}
|
||||
}
|
||||
p_argv++;
|
||||
argp += z;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/* Perform machine dependent cif processing */
|
||||
static ffi_status ffi_prep_cif_machdep_core(ffi_cif *cif)
|
||||
|
||||
static
|
||||
ffi_status ffi_prep_cif_machdep_core(ffi_cif *cif)
|
||||
{
|
||||
int wordsize;
|
||||
|
||||
if (cif->abi != FFI_V9)
|
||||
if (!V9_ABI_P (cif->abi))
|
||||
{
|
||||
wordsize = 4;
|
||||
|
||||
|
@ -303,7 +313,7 @@ static ffi_status ffi_prep_cif_machdep_core(ffi_cif *cif)
|
|||
break;
|
||||
|
||||
case FFI_TYPE_STRUCT:
|
||||
if (cif->abi == FFI_V9 && cif->rtype->size > 32)
|
||||
if (V9_ABI_P (cif->abi) && cif->rtype->size > 32)
|
||||
cif->flags = FFI_TYPE_VOID;
|
||||
else
|
||||
cif->flags = FFI_TYPE_STRUCT;
|
||||
|
@ -313,7 +323,7 @@ static ffi_status ffi_prep_cif_machdep_core(ffi_cif *cif)
|
|||
case FFI_TYPE_UINT8:
|
||||
case FFI_TYPE_SINT16:
|
||||
case FFI_TYPE_UINT16:
|
||||
if (cif->abi == FFI_V9)
|
||||
if (V9_ABI_P (cif->abi))
|
||||
cif->flags = FFI_TYPE_INT;
|
||||
else
|
||||
cif->flags = cif->rtype->type;
|
||||
|
@ -321,7 +331,7 @@ static ffi_status ffi_prep_cif_machdep_core(ffi_cif *cif)
|
|||
|
||||
case FFI_TYPE_SINT64:
|
||||
case FFI_TYPE_UINT64:
|
||||
if (cif->abi == FFI_V9)
|
||||
if (V9_ABI_P (cif->abi))
|
||||
cif->flags = FFI_TYPE_INT;
|
||||
else
|
||||
cif->flags = FFI_TYPE_SINT64;
|
||||
|
@ -334,20 +344,31 @@ static ffi_status ffi_prep_cif_machdep_core(ffi_cif *cif)
|
|||
return FFI_OK;
|
||||
}
|
||||
|
||||
ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
|
||||
ffi_status
|
||||
ffi_prep_cif_machdep(ffi_cif *cif)
|
||||
{
|
||||
cif->nfixedargs = cif->nargs;
|
||||
#ifdef SPARC64
|
||||
if (cif->abi != FFI_COMPAT_V9)
|
||||
cif->nfixedargs = cif->nargs;
|
||||
#endif
|
||||
return ffi_prep_cif_machdep_core (cif);
|
||||
}
|
||||
|
||||
ffi_status ffi_prep_cif_machdep_var(ffi_cif *cif, unsigned int nfixedargs,
|
||||
unsigned int ntotalargs)
|
||||
ffi_status
|
||||
ffi_prep_cif_machdep_var(ffi_cif *cif, unsigned int nfixedargs,
|
||||
unsigned int ntotalargs)
|
||||
{
|
||||
cif->nfixedargs = nfixedargs;
|
||||
#ifdef SPARC64
|
||||
if (cif->abi != FFI_COMPAT_V9)
|
||||
cif->nfixedargs = nfixedargs;
|
||||
#endif
|
||||
return ffi_prep_cif_machdep_core (cif);
|
||||
}
|
||||
|
||||
int ffi_v9_layout_struct(ffi_type *arg, int off, char *ret, char *intg, char *flt)
|
||||
#ifdef SPARC64
|
||||
|
||||
int
|
||||
ffi_v9_layout_struct(ffi_type *arg, int off, char *ret, char *intg, char *flt)
|
||||
{
|
||||
ffi_type **ptr = &arg->elements[0];
|
||||
|
||||
|
@ -380,6 +401,7 @@ int ffi_v9_layout_struct(ffi_type *arg, int off, char *ret, char *intg, char *fl
|
|||
return off;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef SPARC64
|
||||
extern int ffi_call_v9(void *, extended_cif *, unsigned,
|
||||
|
@ -389,33 +411,37 @@ extern int ffi_call_v8(void *, extended_cif *, unsigned,
|
|||
unsigned, unsigned *, void (*fn)(void));
|
||||
#endif
|
||||
|
||||
void ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
|
||||
void
|
||||
ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
|
||||
{
|
||||
extended_cif ecif;
|
||||
#ifdef SPARC64
|
||||
void *rval = rvalue;
|
||||
#endif
|
||||
|
||||
ecif.cif = cif;
|
||||
ecif.avalue = avalue;
|
||||
|
||||
/* If the return value is a struct and we don't have a return */
|
||||
/* value address then we need to make one */
|
||||
|
||||
ecif.rvalue = rvalue;
|
||||
|
||||
/* If the return value is a struct and we don't have a return value address,
|
||||
then we need to make one. */
|
||||
if (cif->rtype->type == FFI_TYPE_STRUCT)
|
||||
{
|
||||
if (ecif.rvalue == NULL)
|
||||
ecif.rvalue = alloca(cif->rtype->size);
|
||||
|
||||
#ifdef SPARC64
|
||||
if (cif->rtype->size <= 32)
|
||||
rval = alloca(64);
|
||||
else
|
||||
{
|
||||
rval = NULL;
|
||||
if (rvalue == NULL)
|
||||
ecif.rvalue = alloca(cif->rtype->size);
|
||||
}
|
||||
rval = NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
switch (cif->abi)
|
||||
{
|
||||
case FFI_V8:
|
||||
case FFI_V8PLUS:
|
||||
#ifdef SPARC64
|
||||
/* We don't yet support calling 32bit code from 64bit */
|
||||
FFI_ASSERT(0);
|
||||
|
@ -430,7 +456,7 @@ void ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
|
|||
/* behind "call", so we alloc some executable space for it. */
|
||||
/* l7 is used, we need to make sure v8.S doesn't use %l7. */
|
||||
unsigned int *call_struct = NULL;
|
||||
ffi_closure_alloc(32, &call_struct);
|
||||
ffi_closure_alloc(32, (void **)&call_struct);
|
||||
if (call_struct)
|
||||
{
|
||||
unsigned long f = (unsigned long)fn;
|
||||
|
@ -450,7 +476,7 @@ void ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
|
|||
/* SPARC v8 requires 5 instructions for flush to be visible */
|
||||
asm volatile ("nop; nop; nop; nop; nop");
|
||||
ffi_call_v8(ffi_prep_args_v8, &ecif, cif->bytes,
|
||||
cif->flags, rvalue, call_struct);
|
||||
cif->flags, rvalue, (void (*)(void)) call_struct);
|
||||
ffi_closure_free(call_struct);
|
||||
}
|
||||
else
|
||||
|
@ -466,12 +492,13 @@ void ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
|
|||
}
|
||||
#endif
|
||||
break;
|
||||
case FFI_COMPAT_V9:
|
||||
case FFI_V9:
|
||||
#ifdef SPARC64
|
||||
ffi_call_v9(ffi_prep_args_v9, &ecif, cif->bytes,
|
||||
cif->flags, rval, fn);
|
||||
ffi_call_v9(ffi_prep_args_v9, &ecif, cif->bytes, cif->flags, rval, fn);
|
||||
if (rvalue && rval && cif->rtype->type == FFI_TYPE_STRUCT)
|
||||
ffi_v9_layout_struct(cif->rtype, 0, (char *)rvalue, (char *)rval, ((char *)rval)+32);
|
||||
ffi_v9_layout_struct(cif->rtype, 0, (char *)rvalue, (char *)rval,
|
||||
((char *)rval)+32);
|
||||
#else
|
||||
/* And vice versa */
|
||||
FFI_ASSERT(0);
|
||||
|
@ -502,7 +529,7 @@ ffi_prep_closure_loc (ffi_closure* closure,
|
|||
#ifdef SPARC64
|
||||
/* Trampoline address is equal to the closure address. We take advantage
|
||||
of that to reduce the trampoline size by 8 bytes. */
|
||||
if (cif->abi != FFI_V9)
|
||||
if (!V9_ABI_P (cif->abi))
|
||||
return FFI_BAD_ABI;
|
||||
fn = (unsigned long) ffi_closure_v9;
|
||||
tramp[0] = 0x83414000; /* rd %pc, %g1 */
|
||||
|
@ -512,7 +539,7 @@ ffi_prep_closure_loc (ffi_closure* closure,
|
|||
*((unsigned long *) &tramp[4]) = fn;
|
||||
#else
|
||||
unsigned long ctx = (unsigned long) codeloc;
|
||||
if (cif->abi != FFI_V8)
|
||||
if (!V8_ABI_P (cif->abi))
|
||||
return FFI_BAD_ABI;
|
||||
fn = (unsigned long) ffi_closure_v8;
|
||||
tramp[0] = 0x03000000 | fn >> 10; /* sethi %hi(fn), %g1 */
|
||||
|
@ -537,9 +564,100 @@ ffi_prep_closure_loc (ffi_closure* closure,
|
|||
return FFI_OK;
|
||||
}
|
||||
|
||||
#ifdef SPARC64
|
||||
|
||||
int
|
||||
ffi_closure_sparc_inner_v8(ffi_closure *closure,
|
||||
void *rvalue, unsigned long *gpr, unsigned long *scratch)
|
||||
ffi_closure_sparc_inner_v9(ffi_closure *closure, void *rvalue,
|
||||
unsigned long *gpr, double *fpr)
|
||||
{
|
||||
ffi_cif *cif;
|
||||
ffi_type **arg_types;
|
||||
void **avalue;
|
||||
int i, argn, fp_slot_max;
|
||||
|
||||
cif = closure->cif;
|
||||
arg_types = cif->arg_types;
|
||||
avalue = alloca(cif->nargs * sizeof(void *));
|
||||
|
||||
/* Copy the caller's structure return address so that the closure
|
||||
returns the data directly to the caller. */
|
||||
if (cif->flags == FFI_TYPE_VOID && cif->rtype->type == FFI_TYPE_STRUCT)
|
||||
{
|
||||
rvalue = (void *) gpr[0];
|
||||
/* Skip the structure return address. */
|
||||
argn = 1;
|
||||
}
|
||||
else
|
||||
argn = 0;
|
||||
|
||||
fp_slot_max = 16 - argn;
|
||||
|
||||
/* Grab the addresses of the arguments from the stack frame. */
|
||||
for (i = 0; i < cif->nargs; i++)
|
||||
{
|
||||
/* If the function is variadic, FP arguments are passed in FP
|
||||
registers only if the corresponding parameter is named. */
|
||||
const int named
|
||||
= (cif->abi == FFI_COMPAT_V9 ? 1 : i < cif->nfixedargs);
|
||||
|
||||
if (arg_types[i]->type == FFI_TYPE_STRUCT)
|
||||
{
|
||||
if (arg_types[i]->size > 16)
|
||||
{
|
||||
/* Straight copy of invisible reference. */
|
||||
avalue[i] = (void *)gpr[argn++];
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Left-justify. */
|
||||
ffi_v9_layout_struct(arg_types[i],
|
||||
0,
|
||||
(char *) &gpr[argn],
|
||||
(char *) &gpr[argn],
|
||||
named
|
||||
? (char *) &fpr[argn]
|
||||
: (char *) &gpr[argn]);
|
||||
avalue[i] = &gpr[argn];
|
||||
argn
|
||||
+= ALIGN(arg_types[i]->size, FFI_SIZEOF_ARG) / FFI_SIZEOF_ARG;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Right-justify. */
|
||||
argn += ALIGN(arg_types[i]->size, FFI_SIZEOF_ARG) / FFI_SIZEOF_ARG;
|
||||
|
||||
/* Align on a 16-byte boundary. */
|
||||
#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
|
||||
if (arg_types[i]->type == FFI_TYPE_LONGDOUBLE && (argn % 2) != 0)
|
||||
argn++;
|
||||
#endif
|
||||
if (i < fp_slot_max
|
||||
&& named
|
||||
&& (arg_types[i]->type == FFI_TYPE_FLOAT
|
||||
|| arg_types[i]->type == FFI_TYPE_DOUBLE
|
||||
#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
|
||||
|| arg_types[i]->type == FFI_TYPE_LONGDOUBLE
|
||||
#endif
|
||||
))
|
||||
avalue[i] = ((char *) &fpr[argn]) - arg_types[i]->size;
|
||||
else
|
||||
avalue[i] = ((char *) &gpr[argn]) - arg_types[i]->size;
|
||||
}
|
||||
}
|
||||
|
||||
/* Invoke the closure. */
|
||||
closure->fun (cif, rvalue, avalue, closure->user_data);
|
||||
|
||||
/* Tell ffi_closure_sparc how to perform return type promotions. */
|
||||
return cif->rtype->type;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
int
|
||||
ffi_closure_sparc_inner_v8(ffi_closure *closure, void *rvalue,
|
||||
unsigned long *gpr, unsigned long *scratch)
|
||||
{
|
||||
ffi_cif *cif;
|
||||
ffi_type **arg_types;
|
||||
|
@ -595,94 +713,11 @@ ffi_closure_sparc_inner_v8(ffi_closure *closure,
|
|||
}
|
||||
}
|
||||
|
||||
/* Invoke the closure. */
|
||||
(closure->fun) (cif, rvalue, avalue, closure->user_data);
|
||||
|
||||
/* Tell ffi_closure_sparc how to perform return type promotions. */
|
||||
return cif->rtype->type;
|
||||
}
|
||||
|
||||
int
|
||||
ffi_closure_sparc_inner_v9(ffi_closure *closure,
|
||||
void *rvalue, unsigned long *gpr, double *fpr)
|
||||
{
|
||||
ffi_cif *cif;
|
||||
ffi_type **arg_types;
|
||||
void **avalue;
|
||||
int i, argn, fp_slot_max;
|
||||
|
||||
cif = closure->cif;
|
||||
arg_types = cif->arg_types;
|
||||
avalue = alloca(cif->nargs * sizeof(void *));
|
||||
|
||||
/* Copy the caller's structure return address so that the closure
|
||||
returns the data directly to the caller. */
|
||||
if (cif->flags == FFI_TYPE_VOID && cif->rtype->type == FFI_TYPE_STRUCT)
|
||||
{
|
||||
rvalue = (void *) gpr[0];
|
||||
/* Skip the structure return address. */
|
||||
argn = 1;
|
||||
}
|
||||
else
|
||||
argn = 0;
|
||||
|
||||
fp_slot_max = 16 - argn;
|
||||
|
||||
/* Grab the addresses of the arguments from the stack frame. */
|
||||
for (i = 0; i < cif->nargs; i++)
|
||||
{
|
||||
/* If the function is variadic, FP arguments are passed in FP
|
||||
registers only if the corresponding parameter is named. */
|
||||
const int named = (i < cif->nfixedargs);
|
||||
|
||||
if (arg_types[i]->type == FFI_TYPE_STRUCT)
|
||||
{
|
||||
if (arg_types[i]->size > 16)
|
||||
{
|
||||
/* Straight copy of invisible reference. */
|
||||
avalue[i] = (void *)gpr[argn++];
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Left-justify. */
|
||||
ffi_v9_layout_struct(arg_types[i],
|
||||
0,
|
||||
(char *) &gpr[argn],
|
||||
(char *) &gpr[argn],
|
||||
named
|
||||
? (char *) &fpr[argn]
|
||||
: (char *) &gpr[argn]);
|
||||
avalue[i] = &gpr[argn];
|
||||
argn += ALIGN(arg_types[i]->size, FFI_SIZEOF_ARG) / FFI_SIZEOF_ARG;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Right-justify. */
|
||||
argn += ALIGN(arg_types[i]->size, FFI_SIZEOF_ARG) / FFI_SIZEOF_ARG;
|
||||
|
||||
/* Align on a 16-byte boundary. */
|
||||
#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
|
||||
if (arg_types[i]->type == FFI_TYPE_LONGDOUBLE && (argn % 2) != 0)
|
||||
argn++;
|
||||
#endif
|
||||
if (i < fp_slot_max
|
||||
&& named
|
||||
&& (arg_types[i]->type == FFI_TYPE_FLOAT
|
||||
|| arg_types[i]->type == FFI_TYPE_DOUBLE
|
||||
#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
|
||||
|| arg_types[i]->type == FFI_TYPE_LONGDOUBLE
|
||||
#endif
|
||||
))
|
||||
avalue[i] = ((char *) &fpr[argn]) - arg_types[i]->size;
|
||||
else
|
||||
avalue[i] = ((char *) &gpr[argn]) - arg_types[i]->size;
|
||||
}
|
||||
}
|
||||
|
||||
/* Invoke the closure. */
|
||||
closure->fun (cif, rvalue, avalue, closure->user_data);
|
||||
|
||||
/* Tell ffi_closure_sparc how to perform return type promotions. */
|
||||
return cif->rtype->type;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -48,6 +48,8 @@ typedef enum ffi_abi {
|
|||
FFI_FIRST_ABI = 0,
|
||||
FFI_V8,
|
||||
FFI_V8PLUS,
|
||||
/* See below for the COMPAT_V9 rationale. */
|
||||
FFI_COMPAT_V9,
|
||||
FFI_V9,
|
||||
FFI_LAST_ABI,
|
||||
#ifdef SPARC64
|
||||
|
@ -58,8 +60,19 @@ typedef enum ffi_abi {
|
|||
} ffi_abi;
|
||||
#endif
|
||||
|
||||
#define V8_ABI_P(abi) ((abi) == FFI_V8 || (abi) == FFI_V8PLUS)
|
||||
#define V9_ABI_P(abi) ((abi) == FFI_COMPAT_V9 || (abi) == FFI_V9)
|
||||
|
||||
#define FFI_TARGET_SPECIFIC_VARIADIC 1
|
||||
|
||||
/* The support of variadic functions was broken in the original implementation
|
||||
of the FFI_V9 ABI. This has been fixed by adding one extra field to the
|
||||
CIF structure (nfixedargs field), which means that the ABI of libffi itself
|
||||
has changed. In order to support applications using the original ABI, we
|
||||
have renamed FFI_V9 into FFI_COMPAT_V9 and defined a new FFI_V9 value. */
|
||||
#ifdef SPARC64
|
||||
#define FFI_EXTRA_CIF_FIELDS unsigned int nfixedargs
|
||||
#endif
|
||||
|
||||
/* ---- Definitions for closures ----------------------------------------- */
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* -----------------------------------------------------------------------
|
||||
v8.S - Copyright (c) 1996, 1997, 2003, 2004, 2008 Red Hat, Inc.
|
||||
|
||||
|
||||
SPARC Foreign Function Interface
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
|
@ -28,6 +28,8 @@
|
|||
#include <fficonfig.h>
|
||||
#include <ffi.h>
|
||||
|
||||
#ifndef SPARC64
|
||||
|
||||
#define STACKFRAME 96 /* Minimum stack framesize for SPARC */
|
||||
#define ARGS (64+4) /* Offset of register area in frame */
|
||||
|
||||
|
@ -307,6 +309,7 @@ done2:
|
|||
.byte 0x1f ! uleb128 0x1f
|
||||
.align WS
|
||||
.LLEFDE2:
|
||||
#endif
|
||||
|
||||
#if defined __ELF__ && defined __linux__
|
||||
.section .note.GNU-stack,"",@progbits
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* -----------------------------------------------------------------------
|
||||
v9.S - Copyright (c) 2000, 2003, 2004, 2008 Red Hat, Inc.
|
||||
|
||||
|
||||
SPARC 64-bit Foreign Function Interface
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
|
@ -29,8 +29,6 @@
|
|||
#include <ffi.h>
|
||||
|
||||
#ifdef SPARC64
|
||||
/* Only compile this in for 64bit builds, because otherwise the object file
|
||||
will have inproper architecture due to used instructions. */
|
||||
|
||||
#define STACKFRAME 176 /* Minimum stack framesize for SPARC 64-bit */
|
||||
#define STACK_BIAS 2047
|
||||
|
|
Loading…
Add table
Reference in a new issue