+2014-02-13 Eric Botcazou <ebotcazou@adacore.com>
+
+ PR libffi/60073
+ * src/sparc/ffitarget.h (FFI_TARGET_SPECIFIC_VARIADIC): Define.
+ (FFI_EXTRA_CIF_FIELDS): Likewise.
+ (FFI_NATIVE_RAW_API): Move around.
+ * src/sparc/ffi.c (ffi_prep_cif_machdep_core): New function from...
+ (ffi_prep_cif_machdep): ...here. Call ffi_prep_cif_machdep_core.
+ (ffi_prep_cif_machdep_var): New function.
+ (ffi_closure_sparc_inner_v9): Do not pass anonymous FP arguments in
+ FP registers.
+ * doc/libffi.texi (Introduction): Fix inaccuracy.
+
2013-12-10 Alan Modra <amodra@gmail.com>
* src/powerpc/ffitarget.h: Import from upstream.
* src/sparc/ffi.c (ffi_prep_closure_loc): Don't ASSERT ABI test,
just return FFI_BAD_ABI when things are wrong.
-2012-02-11 Eric Botcazou <ebotcazou@adacore.com>
+2011-02-11 Eric Botcazou <ebotcazou@adacore.com>
* src/sparc/v9.S (STACKFRAME): Bump to 176.
@node Introduction
@chapter What is libffi?
-Compilers for high level languages generate code that follow certain
+Compilers for high-level languages generate code that follow certain
conventions. These conventions are necessary, in part, for separate
compilation to work. One such convention is the @dfn{calling
convention}. The calling convention is a set of assumptions made by
the compiler about where function arguments will be found on entry to
a function. A calling convention also specifies where the return
-value for a function is found. The calling convention is also
-sometimes called the @dfn{ABI} or @dfn{Application Binary Interface}.
+value for a function is found. The calling convention is part of
+what is called the @dfn{ABI} or @dfn{Application Binary Interface}.
@cindex calling convention
@cindex ABI
@cindex Application Binary Interface
}
/* Perform machine dependent cif processing */
-ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
+static ffi_status ffi_prep_cif_machdep_core(ffi_cif *cif)
{
int wordsize;
return FFI_OK;
}
+ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
+{
+ cif->nfixedargs = cif->nargs;
+ return ffi_prep_cif_machdep_core (cif);
+}
+
+ffi_status ffi_prep_cif_machdep_var(ffi_cif *cif, unsigned int nfixedargs,
+ unsigned int ntotalargs)
+{
+ cif->nfixedargs = nfixedargs;
+ return ffi_prep_cif_machdep_core (cif);
+}
+
int ffi_v9_layout_struct(ffi_type *arg, int off, char *ret, char *intg, char *flt)
{
ffi_type **ptr = &arg->elements[0];
/* 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)
+ if (cif->flags == FFI_TYPE_VOID && cif->rtype->type == FFI_TYPE_STRUCT)
{
rvalue = (void *) gpr[0];
/* Skip the structure return address. */
/* 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)
0,
(char *) &gpr[argn],
(char *) &gpr[argn],
- (char *) &fpr[argn]);
+ named
+ ? (char *) &fpr[argn]
+ : (char *) &gpr[argn]);
avalue[i] = &gpr[argn];
argn += ALIGN(arg_types[i]->size, FFI_SIZEOF_ARG) / FFI_SIZEOF_ARG;
}
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
}
/* Invoke the closure. */
- (closure->fun) (cif, rvalue, avalue, closure->user_data);
+ closure->fun (cif, rvalue, avalue, closure->user_data);
/* Tell ffi_closure_sparc how to perform return type promotions. */
return cif->rtype->type;