Commit 248d745a by Eric Botcazou Committed by Eric Botcazou

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
parent 583a9919
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> 2014-02-13 Eric Botcazou <ebotcazou@adacore.com>
PR libffi/60073 PR libffi/60073
......
/* ----------------------------------------------------------------------- /* -----------------------------------------------------------------------
ffi.c - Copyright (c) 2011 Anthony Green ffi.c - Copyright (c) 2011 Anthony Green
Copyright (c) 1996, 2003-2004, 2007-2008 Red Hat, Inc. Copyright (c) 1996, 2003-2004, 2007-2008 Red Hat, Inc.
SPARC Foreign Function Interface SPARC Foreign Function Interface
Permission is hereby granted, free of charge, to any person obtaining Permission is hereby granted, free of charge, to any person obtaining
...@@ -34,93 +34,10 @@ ...@@ -34,93 +34,10 @@
/* ffi_prep_args is called by the assembly routine once stack space /* ffi_prep_args is called by the assembly routine once stack space
has been allocated for the function's arguments */ has been allocated for the function's arguments */
void ffi_prep_args_v8(char *stack, extended_cif *ecif) #ifdef SPARC64
{
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;
}
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 i, ret = 0;
int tmp; int tmp;
...@@ -248,12 +165,105 @@ int ffi_prep_args_v9(char *stack, extended_cif *ecif) ...@@ -248,12 +165,105 @@ int ffi_prep_args_v9(char *stack, extended_cif *ecif)
return ret; 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 */ /* 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; int wordsize;
if (cif->abi != FFI_V9) if (!V9_ABI_P (cif->abi))
{ {
wordsize = 4; wordsize = 4;
...@@ -303,7 +313,7 @@ static ffi_status ffi_prep_cif_machdep_core(ffi_cif *cif) ...@@ -303,7 +313,7 @@ static ffi_status ffi_prep_cif_machdep_core(ffi_cif *cif)
break; break;
case FFI_TYPE_STRUCT: 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; cif->flags = FFI_TYPE_VOID;
else else
cif->flags = FFI_TYPE_STRUCT; cif->flags = FFI_TYPE_STRUCT;
...@@ -313,7 +323,7 @@ static ffi_status ffi_prep_cif_machdep_core(ffi_cif *cif) ...@@ -313,7 +323,7 @@ static ffi_status ffi_prep_cif_machdep_core(ffi_cif *cif)
case FFI_TYPE_UINT8: case FFI_TYPE_UINT8:
case FFI_TYPE_SINT16: case FFI_TYPE_SINT16:
case FFI_TYPE_UINT16: case FFI_TYPE_UINT16:
if (cif->abi == FFI_V9) if (V9_ABI_P (cif->abi))
cif->flags = FFI_TYPE_INT; cif->flags = FFI_TYPE_INT;
else else
cif->flags = cif->rtype->type; cif->flags = cif->rtype->type;
...@@ -321,7 +331,7 @@ static ffi_status ffi_prep_cif_machdep_core(ffi_cif *cif) ...@@ -321,7 +331,7 @@ static ffi_status ffi_prep_cif_machdep_core(ffi_cif *cif)
case FFI_TYPE_SINT64: case FFI_TYPE_SINT64:
case FFI_TYPE_UINT64: case FFI_TYPE_UINT64:
if (cif->abi == FFI_V9) if (V9_ABI_P (cif->abi))
cif->flags = FFI_TYPE_INT; cif->flags = FFI_TYPE_INT;
else else
cif->flags = FFI_TYPE_SINT64; cif->flags = FFI_TYPE_SINT64;
...@@ -334,20 +344,31 @@ static ffi_status ffi_prep_cif_machdep_core(ffi_cif *cif) ...@@ -334,20 +344,31 @@ static ffi_status ffi_prep_cif_machdep_core(ffi_cif *cif)
return FFI_OK; 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); return ffi_prep_cif_machdep_core (cif);
} }
ffi_status ffi_prep_cif_machdep_var(ffi_cif *cif, unsigned int nfixedargs, ffi_status
unsigned int ntotalargs) 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); 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]; 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 ...@@ -380,6 +401,7 @@ int ffi_v9_layout_struct(ffi_type *arg, int off, char *ret, char *intg, char *fl
return off; return off;
} }
#endif
#ifdef SPARC64 #ifdef SPARC64
extern int ffi_call_v9(void *, extended_cif *, unsigned, extern int ffi_call_v9(void *, extended_cif *, unsigned,
...@@ -389,33 +411,37 @@ extern int ffi_call_v8(void *, extended_cif *, unsigned, ...@@ -389,33 +411,37 @@ extern int ffi_call_v8(void *, extended_cif *, unsigned,
unsigned, unsigned *, void (*fn)(void)); unsigned, unsigned *, void (*fn)(void));
#endif #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; extended_cif ecif;
#ifdef SPARC64
void *rval = rvalue; void *rval = rvalue;
#endif
ecif.cif = cif; ecif.cif = cif;
ecif.avalue = avalue; 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; 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 (cif->rtype->type == FFI_TYPE_STRUCT)
{ {
if (ecif.rvalue == NULL)
ecif.rvalue = alloca(cif->rtype->size);
#ifdef SPARC64
if (cif->rtype->size <= 32) if (cif->rtype->size <= 32)
rval = alloca(64); rval = alloca(64);
else else
{ rval = NULL;
rval = NULL; #endif
if (rvalue == NULL)
ecif.rvalue = alloca(cif->rtype->size);
}
} }
switch (cif->abi) switch (cif->abi)
{ {
case FFI_V8: case FFI_V8:
case FFI_V8PLUS:
#ifdef SPARC64 #ifdef SPARC64
/* We don't yet support calling 32bit code from 64bit */ /* We don't yet support calling 32bit code from 64bit */
FFI_ASSERT(0); FFI_ASSERT(0);
...@@ -430,7 +456,7 @@ void ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue) ...@@ -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. */ /* behind "call", so we alloc some executable space for it. */
/* l7 is used, we need to make sure v8.S doesn't use %l7. */ /* l7 is used, we need to make sure v8.S doesn't use %l7. */
unsigned int *call_struct = NULL; unsigned int *call_struct = NULL;
ffi_closure_alloc(32, &call_struct); ffi_closure_alloc(32, (void **)&call_struct);
if (call_struct) if (call_struct)
{ {
unsigned long f = (unsigned long)fn; unsigned long f = (unsigned long)fn;
...@@ -450,7 +476,7 @@ void ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue) ...@@ -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 */ /* SPARC v8 requires 5 instructions for flush to be visible */
asm volatile ("nop; nop; nop; nop; nop"); asm volatile ("nop; nop; nop; nop; nop");
ffi_call_v8(ffi_prep_args_v8, &ecif, cif->bytes, 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); ffi_closure_free(call_struct);
} }
else else
...@@ -466,12 +492,13 @@ void ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue) ...@@ -466,12 +492,13 @@ void ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
} }
#endif #endif
break; break;
case FFI_COMPAT_V9:
case FFI_V9: case FFI_V9:
#ifdef SPARC64 #ifdef SPARC64
ffi_call_v9(ffi_prep_args_v9, &ecif, cif->bytes, ffi_call_v9(ffi_prep_args_v9, &ecif, cif->bytes, cif->flags, rval, fn);
cif->flags, rval, fn);
if (rvalue && rval && cif->rtype->type == FFI_TYPE_STRUCT) 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 #else
/* And vice versa */ /* And vice versa */
FFI_ASSERT(0); FFI_ASSERT(0);
...@@ -502,7 +529,7 @@ ffi_prep_closure_loc (ffi_closure* closure, ...@@ -502,7 +529,7 @@ ffi_prep_closure_loc (ffi_closure* closure,
#ifdef SPARC64 #ifdef SPARC64
/* Trampoline address is equal to the closure address. We take advantage /* Trampoline address is equal to the closure address. We take advantage
of that to reduce the trampoline size by 8 bytes. */ 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; return FFI_BAD_ABI;
fn = (unsigned long) ffi_closure_v9; fn = (unsigned long) ffi_closure_v9;
tramp[0] = 0x83414000; /* rd %pc, %g1 */ tramp[0] = 0x83414000; /* rd %pc, %g1 */
...@@ -512,7 +539,7 @@ ffi_prep_closure_loc (ffi_closure* closure, ...@@ -512,7 +539,7 @@ ffi_prep_closure_loc (ffi_closure* closure,
*((unsigned long *) &tramp[4]) = fn; *((unsigned long *) &tramp[4]) = fn;
#else #else
unsigned long ctx = (unsigned long) codeloc; unsigned long ctx = (unsigned long) codeloc;
if (cif->abi != FFI_V8) if (!V8_ABI_P (cif->abi))
return FFI_BAD_ABI; return FFI_BAD_ABI;
fn = (unsigned long) ffi_closure_v8; fn = (unsigned long) ffi_closure_v8;
tramp[0] = 0x03000000 | fn >> 10; /* sethi %hi(fn), %g1 */ tramp[0] = 0x03000000 | fn >> 10; /* sethi %hi(fn), %g1 */
...@@ -537,74 +564,11 @@ ffi_prep_closure_loc (ffi_closure* closure, ...@@ -537,74 +564,11 @@ ffi_prep_closure_loc (ffi_closure* closure,
return FFI_OK; return FFI_OK;
} }
int #ifdef SPARC64
ffi_closure_sparc_inner_v8(ffi_closure *closure,
void *rvalue, unsigned long *gpr, unsigned long *scratch)
{
ffi_cif *cif;
ffi_type **arg_types;
void **avalue;
int i, argn;
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_STRUCT
#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
|| cif->flags == FFI_TYPE_LONGDOUBLE
#endif
)
rvalue = (void *) gpr[0];
/* Always skip the structure return address. */
argn = 1;
/* Grab the addresses of the arguments from the stack frame. */
for (i = 0; i < cif->nargs; i++)
{
if (arg_types[i]->type == FFI_TYPE_STRUCT
#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
|| arg_types[i]->type == FFI_TYPE_LONGDOUBLE
#endif
)
{
/* Straight copy of invisible reference. */
avalue[i] = (void *)gpr[argn++];
}
else if ((arg_types[i]->type == FFI_TYPE_DOUBLE
|| arg_types[i]->type == FFI_TYPE_SINT64
|| arg_types[i]->type == FFI_TYPE_UINT64)
/* gpr is 8-byte aligned. */
&& (argn % 2) != 0)
{
/* Align on a 8-byte boundary. */
scratch[0] = gpr[argn];
scratch[1] = gpr[argn+1];
avalue[i] = scratch;
scratch -= 2;
argn += 2;
}
else
{
/* Always right-justify. */
argn += ALIGN(arg_types[i]->size, FFI_SIZEOF_ARG) / FFI_SIZEOF_ARG;
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;
}
int int
ffi_closure_sparc_inner_v9(ffi_closure *closure, ffi_closure_sparc_inner_v9(ffi_closure *closure, void *rvalue,
void *rvalue, unsigned long *gpr, double *fpr) unsigned long *gpr, double *fpr)
{ {
ffi_cif *cif; ffi_cif *cif;
ffi_type **arg_types; ffi_type **arg_types;
...@@ -633,7 +597,8 @@ ffi_closure_sparc_inner_v9(ffi_closure *closure, ...@@ -633,7 +597,8 @@ ffi_closure_sparc_inner_v9(ffi_closure *closure,
{ {
/* If the function is variadic, FP arguments are passed in FP /* If the function is variadic, FP arguments are passed in FP
registers only if the corresponding parameter is named. */ registers only if the corresponding parameter is named. */
const int named = (i < cif->nfixedargs); const int named
= (cif->abi == FFI_COMPAT_V9 ? 1 : i < cif->nfixedargs);
if (arg_types[i]->type == FFI_TYPE_STRUCT) if (arg_types[i]->type == FFI_TYPE_STRUCT)
{ {
...@@ -653,7 +618,8 @@ ffi_closure_sparc_inner_v9(ffi_closure *closure, ...@@ -653,7 +618,8 @@ ffi_closure_sparc_inner_v9(ffi_closure *closure,
? (char *) &fpr[argn] ? (char *) &fpr[argn]
: (char *) &gpr[argn]); : (char *) &gpr[argn]);
avalue[i] = &gpr[argn]; avalue[i] = &gpr[argn];
argn += ALIGN(arg_types[i]->size, FFI_SIZEOF_ARG) / FFI_SIZEOF_ARG; argn
+= ALIGN(arg_types[i]->size, FFI_SIZEOF_ARG) / FFI_SIZEOF_ARG;
} }
} }
else else
...@@ -686,3 +652,72 @@ ffi_closure_sparc_inner_v9(ffi_closure *closure, ...@@ -686,3 +652,72 @@ ffi_closure_sparc_inner_v9(ffi_closure *closure,
/* Tell ffi_closure_sparc how to perform return type promotions. */ /* Tell ffi_closure_sparc how to perform return type promotions. */
return cif->rtype->type; 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;
void **avalue;
int i, argn;
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_STRUCT
#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
|| cif->flags == FFI_TYPE_LONGDOUBLE
#endif
)
rvalue = (void *) gpr[0];
/* Always skip the structure return address. */
argn = 1;
/* Grab the addresses of the arguments from the stack frame. */
for (i = 0; i < cif->nargs; i++)
{
if (arg_types[i]->type == FFI_TYPE_STRUCT
#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
|| arg_types[i]->type == FFI_TYPE_LONGDOUBLE
#endif
)
{
/* Straight copy of invisible reference. */
avalue[i] = (void *)gpr[argn++];
}
else if ((arg_types[i]->type == FFI_TYPE_DOUBLE
|| arg_types[i]->type == FFI_TYPE_SINT64
|| arg_types[i]->type == FFI_TYPE_UINT64)
/* gpr is 8-byte aligned. */
&& (argn % 2) != 0)
{
/* Align on a 8-byte boundary. */
scratch[0] = gpr[argn];
scratch[1] = gpr[argn+1];
avalue[i] = scratch;
scratch -= 2;
argn += 2;
}
else
{
/* Always right-justify. */
argn += ALIGN(arg_types[i]->size, FFI_SIZEOF_ARG) / FFI_SIZEOF_ARG;
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 { ...@@ -48,6 +48,8 @@ typedef enum ffi_abi {
FFI_FIRST_ABI = 0, FFI_FIRST_ABI = 0,
FFI_V8, FFI_V8,
FFI_V8PLUS, FFI_V8PLUS,
/* See below for the COMPAT_V9 rationale. */
FFI_COMPAT_V9,
FFI_V9, FFI_V9,
FFI_LAST_ABI, FFI_LAST_ABI,
#ifdef SPARC64 #ifdef SPARC64
...@@ -58,8 +60,19 @@ typedef enum ffi_abi { ...@@ -58,8 +60,19 @@ typedef enum ffi_abi {
} ffi_abi; } ffi_abi;
#endif #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 #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 #define FFI_EXTRA_CIF_FIELDS unsigned int nfixedargs
#endif
/* ---- Definitions for closures ----------------------------------------- */ /* ---- Definitions for closures ----------------------------------------- */
......
/* ----------------------------------------------------------------------- /* -----------------------------------------------------------------------
v8.S - Copyright (c) 1996, 1997, 2003, 2004, 2008 Red Hat, Inc. v8.S - Copyright (c) 1996, 1997, 2003, 2004, 2008 Red Hat, Inc.
SPARC Foreign Function Interface SPARC Foreign Function Interface
Permission is hereby granted, free of charge, to any person obtaining Permission is hereby granted, free of charge, to any person obtaining
...@@ -28,6 +28,8 @@ ...@@ -28,6 +28,8 @@
#include <fficonfig.h> #include <fficonfig.h>
#include <ffi.h> #include <ffi.h>
#ifndef SPARC64
#define STACKFRAME 96 /* Minimum stack framesize for SPARC */ #define STACKFRAME 96 /* Minimum stack framesize for SPARC */
#define ARGS (64+4) /* Offset of register area in frame */ #define ARGS (64+4) /* Offset of register area in frame */
...@@ -307,6 +309,7 @@ done2: ...@@ -307,6 +309,7 @@ done2:
.byte 0x1f ! uleb128 0x1f .byte 0x1f ! uleb128 0x1f
.align WS .align WS
.LLEFDE2: .LLEFDE2:
#endif
#if defined __ELF__ && defined __linux__ #if defined __ELF__ && defined __linux__
.section .note.GNU-stack,"",@progbits .section .note.GNU-stack,"",@progbits
......
/* ----------------------------------------------------------------------- /* -----------------------------------------------------------------------
v9.S - Copyright (c) 2000, 2003, 2004, 2008 Red Hat, Inc. v9.S - Copyright (c) 2000, 2003, 2004, 2008 Red Hat, Inc.
SPARC 64-bit Foreign Function Interface SPARC 64-bit Foreign Function Interface
Permission is hereby granted, free of charge, to any person obtaining Permission is hereby granted, free of charge, to any person obtaining
...@@ -29,8 +29,6 @@ ...@@ -29,8 +29,6 @@
#include <ffi.h> #include <ffi.h>
#ifdef SPARC64 #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 STACKFRAME 176 /* Minimum stack framesize for SPARC 64-bit */
#define STACK_BIAS 2047 #define STACK_BIAS 2047
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment