This is the mail archive of the libffi-discuss@sourceware.org mailing list for the libffi project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [PATCH] Add variadic support


Chung-Lin Tang <cltang@linaro.org> writes:

> I think this looks fine.
> Anthony, does the patch look okay to you?

Yes, I think it's fine.  I was against adding a new API at first, but
after talking to David about it on #libffi I was convinced that there's
no reasonable alternative.  I'm going to check it into a branch on git
until 3.0.10 is done.  The branch will be called "variadic".

Thanks for you work David!

AG


>
> Thanks,
> Chung-Lin
>
>
> On 2011/3/8 03:18 AM, David Gilbert wrote:
>> Hi,
>>   Here is a rework of the previous patch, based on the previous discussion and
>> suggestions from Chung-Lin.
>> 
>> (This is relative libffi git rev cbb062cc35c518004f1ab45c847f8ec4f66069ad)
>> 
>> Dave
>> 
>> diff --git a/doc/libffi.texi b/doc/libffi.texi
>> index 5cdd667..a7c629a 100644
>> --- a/doc/libffi.texi
>> +++ b/doc/libffi.texi
>> @@ -133,8 +133,6 @@ This initializes @var{cif} according to the given
>> parameters.
>>  you want.  @ref{Multiple ABIs} for more information.
>> 
>>  @var{nargs} is the number of arguments that this function accepts.
>> -@samp{libffi} does not yet handle varargs functions; see @ref{Missing
>> -Features} for more information.
>> 
>>  @var{rtype} is a pointer to an @code{ffi_type} structure that
>>  describes the return type of the function.  @xref{Types}.
>> @@ -150,6 +148,28 @@ objects is incorrect; or @code{FFI_BAD_ABI} if
>> the @var{abi} parameter
>>  is invalid.
>>  @end defun
>> 
>> +If the function being called is variadic (varargs) then @code{ffi_prep_cif_var}
>> +must be used instead of @code{ffi_prep_cif}.
>> +
>> +@findex ffi_prep_cif_var
>> +@defun ffi_status ffi_prep_cif_var (ffi_cif *@var{cif}, ffi_abi
>> @var{abi}, unsigned int @var{nfixedargs}, unsigned int
>> @var{ntotalargs}, ffi_type *@var{rtype}, ffi_type **@var{argtypes})
>> +This initializes @var{cif} according to the given parameters for
>> +a call to a variadic function.  In general it's operation is the
>> +same as for @code{ffi_prep_cif} except that:
>> +
>> +@var{nfixedargs} is the number of fixed arguments, prior to any
>> +variadic arguments.  It must be greater than zero.
>> +
>> +@var{ntotalargs} the total number of arguments, including variadic
>> +and fixed arguments.
>> +
>> +Note that, different cif's must be prepped for calls to the same
>> +function when different numbers of arguments are passed.
>> +
>> +Also note that a call to @code{ffi_prep_cif_var} with
>> @var{nfixedargs}=@var{nototalargs}
>> +is NOT equivalent to a call to @code{ffi_prep_cif}.
>> +
>> +@end defun
>> 
>>  To call a function using an initialized @code{ffi_cif}, use the
>>  @code{ffi_call} function:
>> @@ -572,9 +592,7 @@ support for these.
>> 
>>  @itemize @bullet
>>  @item
>> -There is no support for calling varargs functions.  This may work on
>> -some platforms, depending on how the ABI is defined, but it is not
>> -reliable.
>> +Variadic closures.
>> 
>>  @item
>>  There is no support for bit fields in structures.
>> @@ -591,6 +609,7 @@ The ``raw'' API is undocumented.
>>  @c anything else?
>>  @end itemize
>> 
>> +Note that variadic support is very new and tested on a relatively
>> small number of platforms.
>> 
>>  @node Index
>>  @unnumbered Index
>> diff --git a/include/ffi.h.in b/include/ffi.h.in
>> index 96b8fd3..f27f4f3 100644
>> --- a/include/ffi.h.in
>> +++ b/include/ffi.h.in
>> @@ -203,6 +203,15 @@ typedef struct {
>>  #endif
>>  } ffi_cif;
>> 
>> +/* Used internally, but overridden by some architectures */
>> +ffi_status ffi_prep_cif_core(ffi_cif *cif,
>> +			     ffi_abi abi,
>> +			     unsigned int isvariadic,
>> +			     unsigned int nfixedargs,
>> +			     unsigned int ntotalargs,
>> +			     ffi_type *rtype,
>> +			     ffi_type **atypes);
>> +
>>  /* ---- Definitions for the raw API -------------------------------------- */
>> 
>>  #ifndef FFI_SIZEOF_ARG
>> @@ -380,6 +389,13 @@ ffi_status ffi_prep_cif(ffi_cif *cif,
>>  			ffi_type *rtype,
>>  			ffi_type **atypes);
>> 
>> +ffi_status ffi_prep_cif_var(ffi_cif *cif,
>> +			    ffi_abi abi,
>> +			    unsigned int nfixedargs,
>> +			    unsigned int ntotalargs,
>> +			    ffi_type *rtype,
>> +			    ffi_type **atypes);
>> +
>>  void ffi_call(ffi_cif *cif,
>>  	      void (*fn)(void),
>>  	      void *rvalue,
>> diff --git a/include/ffi_common.h b/include/ffi_common.h
>> index d953762..919eec2 100644
>> --- a/include/ffi_common.h
>> +++ b/include/ffi_common.h
>> @@ -75,6 +75,8 @@ void ffi_type_test(ffi_type *a, char *file, int line);
>> 
>>  /* Perform machine dependent cif processing */
>>  ffi_status ffi_prep_cif_machdep(ffi_cif *cif);
>> +ffi_status ffi_prep_cif_machdep_var(ffi_cif *cif,
>> +	 unsigned int nfixedargs, unsigned int ntotalargs);
>> 
>>  /* Extended cif, used in callback from assembly routine */
>>  typedef struct
>> diff --git a/man/Makefile.am b/man/Makefile.am
>> index 2519277..afcbfb6 100644
>> --- a/man/Makefile.am
>> +++ b/man/Makefile.am
>> @@ -2,7 +2,7 @@
>> 
>>  AUTOMAKE_OPTIONS=foreign
>> 
>> -EXTRA_DIST = ffi.3 ffi_call.3 ffi_prep_cif.3
>> +EXTRA_DIST = ffi.3 ffi_call.3 ffi_prep_cif.3 ffi_prep_cif_var.3
>> 
>> -man_MANS = ffi.3 ffi_call.3 ffi_prep_cif.3
>> +man_MANS = ffi.3 ffi_call.3 ffi_prep_cif.3 ffi_prep_cif_var.3
>> 
>> diff --git a/man/ffi.3 b/man/ffi.3
>> index 18b5d5d..1f1d303 100644
>> --- a/man/ffi.3
>> +++ b/man/ffi.3
>> @@ -16,6 +16,15 @@ libffi, -lffi
>>  .Fa "ffi_type **atypes"
>>  .Fc
>>  .Ft void
>> +.Fo ffi_prep_cif_var
>> +.Fa "ffi_cif *cif"
>> +.Fa "ffi_abi abi"
>> +.Fa "unsigned int nfixedargs"
>> +.Fa "unsigned int ntotalargs"
>> +.Fa "ffi_type *rtype"
>> +.Fa "ffi_type **atypes"
>> +.Fc
>> +.Ft void
>>  .Fo ffi_call
>>  .Fa "ffi_cif *cif"
>>  .Fa "void (*fn)(void)"
>> @@ -28,4 +37,5 @@ generate a call to another function at runtime
>> without requiring knowledge of
>>  the called function's interface at compile time.
>>  .Sh SEE ALSO
>>  .Xr ffi_prep_cif 3 ,
>> +.Xr ffi_prep_cif_var 3 ,
>>  .Xr ffi_call 3
>> diff --git a/man/ffi_prep_cif.3 b/man/ffi_prep_cif.3
>> index 9436b31..fe66452 100644
>> --- a/man/ffi_prep_cif.3
>> +++ b/man/ffi_prep_cif.3
>> @@ -37,7 +37,9 @@ structs that describe the data type, size and
>> alignment of each argument.
>>  points to an
>>  .Nm ffi_type
>>  that describes the data type, size and alignment of the
>> -return value.
>> +return value. Note that to call a variadic function
>> +.Nm ffi_prep_cif_var
>> +must be used instead.
>>  .Sh RETURN VALUES
>>  Upon successful completion,
>>  .Nm ffi_prep_cif
>> @@ -63,4 +65,5 @@ defined in
>>  .
>>  .Sh SEE ALSO
>>  .Xr ffi 3 ,
>> -.Xr ffi_call 3
>> +.Xr ffi_call 3 ,
>> +.Xr ffi_prep_cif_var 3
>> diff --git a/man/ffi_prep_cif_var.3 b/man/ffi_prep_cif_var.3
>> new file mode 100644
>> index 0000000..1b39c03
>> --- /dev/null
>> +++ b/man/ffi_prep_cif_var.3
>> @@ -0,0 +1,73 @@
>> +.Dd January 25, 2011
>> +.Dt ffi_prep_cif_var 3
>> +.Sh NAME
>> +.Nm ffi_prep_cif_var
>> +.Nd Prepare a
>> +.Nm ffi_cif
>> +structure for use with
>> +.Nm ffi_call
>> +for variadic functions.
>> +.Sh SYNOPSIS
>> +.In ffi.h
>> +.Ft ffi_status
>> +.Fo ffi_prep_cif_var
>> +.Fa "ffi_cif *cif"
>> +.Fa "ffi_abi abi"
>> +.Fa "unsigned int nfixedargs"
>> +.Fa "unsigned int ntotalargs"
>> +.Fa "ffi_type *rtype"
>> +.Fa "ffi_type **atypes"
>> +.Fc
>> +.Sh DESCRIPTION
>> +The
>> +.Nm ffi_prep_cif_var
>> +function prepares a
>> +.Nm ffi_cif
>> +structure for use with
>> +.Nm ffi_call
>> +for variadic functions.
>> +.Fa abi
>> +specifies a set of calling conventions to use.
>> +.Fa atypes
>> +is an array of
>> +.Fa ntotalargs
>> +pointers to
>> +.Nm ffi_type
>> +structs that describe the data type, size and alignment of each argument.
>> +.Fa rtype
>> +points to an
>> +.Nm ffi_type
>> +that describes the data type, size and alignment of the
>> +return value.
>> +.Fa nfixedargs
>> +must contain the number of fixed (non-variadic) arguments.
>> +Note that to call a non-variadic function
>> +.Nm ffi_prep_cif
>> +must be used.
>> +.Sh RETURN VALUES
>> +Upon successful completion,
>> +.Nm ffi_prep_cif_var
>> +returns
>> +.Nm FFI_OK .
>> +It will return
>> +.Nm FFI_BAD_TYPEDEF
>> +if
>> +.Fa cif
>> +is
>> +.Nm NULL
>> +or
>> +.Fa atypes
>> +or
>> +.Fa rtype
>> +is malformed. If
>> +.Fa abi
>> +does not refer to a valid ABI,
>> +.Nm FFI_BAD_ABI
>> +will be returned. Available ABIs are
>> +defined in
>> +.Nm <ffitarget.h>
>> +.
>> +.Sh SEE ALSO
>> +.Xr ffi 3 ,
>> +.Xr ffi_call 3 ,
>> +.Xr ffi_prep_cif 3
>> diff --git a/src/arm/ffi.c b/src/arm/ffi.c
>> index 885a9cb..c226dbd 100644
>> --- a/src/arm/ffi.c
>> +++ b/src/arm/ffi.c
>> @@ -189,6 +189,18 @@ ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
>>    return FFI_OK;
>>  }
>> 
>> +/* Perform machine dependent cif processing for variadic calls */
>> +ffi_status ffi_prep_cif_machdep_var(ffi_cif *cif,
>> +				    unsigned int nfixedargs,
>> +				    unsigned int ntotalargs)
>> +{
>> +  /* VFP variadic calls actually use the SYSV ABI */
>> +  if (cif->abi == FFI_VFP)
>> +	cif->abi = FFI_SYSV;
>> +
>> +  return ffi_prep_cif_machdep(cif);
>> +}
>> +
>>  /* Prototypes for assembly functions, in sysv.S */
>>  extern void ffi_call_SYSV (void (*fn)(void), extended_cif *,
>> unsigned, unsigned, unsigned *);
>>  extern void ffi_call_VFP (void (*fn)(void), extended_cif *, unsigned,
>> unsigned, unsigned *);
>> diff --git a/src/arm/ffitarget.h b/src/arm/ffitarget.h
>> index ce25b23..b9a0428 100644
>> --- a/src/arm/ffitarget.h
>> +++ b/src/arm/ffitarget.h
>> @@ -55,6 +55,8 @@ typedef enum ffi_abi {
>>  #define FFI_TYPE_STRUCT_VFP_FLOAT  (FFI_TYPE_LAST + 1)
>>  #define FFI_TYPE_STRUCT_VFP_DOUBLE (FFI_TYPE_LAST + 2)
>> 
>> +#define FFI_TARGET_SPECIFIC_VARIADIC
>> +
>>  /* ---- Definitions for closures ----------------------------------------- */
>> 
>>  #define FFI_CLOSURES 1
>> @@ -62,4 +64,3 @@ typedef enum ffi_abi {
>>  #define FFI_NATIVE_RAW_API 0
>> 
>>  #endif
>> -
>> diff --git a/src/cris/ffi.c b/src/cris/ffi.c
>> index f25d7b4..aaca5b1 100644
>> --- a/src/cris/ffi.c
>> +++ b/src/cris/ffi.c
>> @@ -153,21 +153,24 @@ ffi_prep_args (char *stack, extended_cif * ecif)
>>    return (struct_count);
>>  }
>> 
>> -ffi_status
>> -ffi_prep_cif (ffi_cif * cif,
>> -	      ffi_abi abi, unsigned int nargs,
>> -	      ffi_type * rtype, ffi_type ** atypes)
>> +ffi_status FFI_HIDDEN
>> +ffi_prep_cif_core (ffi_cif * cif,
>> +	           ffi_abi abi, unsigned int isvariadic,
>> +		   unsigned int nfixedargs, unsigned int ntotalargs,
>> +	           ffi_type * rtype, ffi_type ** atypes)
>>  {
>>    unsigned bytes = 0;
>>    unsigned int i;
>>    ffi_type **ptr;
>> 
>>    FFI_ASSERT (cif != NULL);
>> +  FFI_ASSERT((!isvariadic) || (nfixedargs >= 1));
>> +  FFI_ASSERT(nfixedargs <= ntotalargs);
>>    FFI_ASSERT (abi > FFI_FIRST_ABI && abi < FFI_LAST_ABI);
>> 
>>    cif->abi = abi;
>>    cif->arg_types = atypes;
>> -  cif->nargs = nargs;
>> +  cif->nargs = ntotalargs;
>>    cif->rtype = rtype;
>> 
>>    cif->flags = 0;
>> diff --git a/src/prep_cif.c b/src/prep_cif.c
>> index 8548cfd..0e2e116 100644
>> --- a/src/prep_cif.c
>> +++ b/src/prep_cif.c
>> @@ -90,20 +90,33 @@ static ffi_status initialize_aggregate(ffi_type *arg)
>>  /* Perform machine independent ffi_cif preparation, then call
>>     machine dependent routine. */
>> 
>> -ffi_status ffi_prep_cif(ffi_cif *cif, ffi_abi abi, unsigned int nargs,
>> -			ffi_type *rtype, ffi_type **atypes)
>> +/* For non variadic functions isvariadic should be 0 and
>> +   nfixedargs==ntotalargs.
>> +
>> +   For variadic calls, isvariadic should be 1 and nfixedargs
>> +   and ntotalargs set as appropriate. nfixedargs must always be >=1 */
>> +
>> +
>> +ffi_status FFI_HIDDEN ffi_prep_cif_core(ffi_cif *cif, ffi_abi abi,
>> +			     unsigned int isvariadic,
>> +                             unsigned int nfixedargs,
>> +                             unsigned int ntotalargs,
>> +			     ffi_type *rtype, ffi_type **atypes)
>>  {
>>    unsigned bytes = 0;
>>    unsigned int i;
>>    ffi_type **ptr;
>> 
>>    FFI_ASSERT(cif != NULL);
>> +  FFI_ASSERT((!isvariadic) || (nfixedargs >= 1));
>> +  FFI_ASSERT(nfixedargs <= ntotalargs);
>> +
>>    if (! (abi > FFI_FIRST_ABI && abi < FFI_LAST_ABI))
>>      return FFI_BAD_ABI;
>> 
>>    cif->abi = abi;
>>    cif->arg_types = atypes;
>> -  cif->nargs = nargs;
>> +  cif->nargs = ntotalargs;
>>    cif->rtype = rtype;
>> 
>>    cif->flags = 0;
>> @@ -159,10 +172,31 @@ ffi_status ffi_prep_cif(ffi_cif *cif, ffi_abi
>> abi, unsigned int nargs,
>>    cif->bytes = bytes;
>> 
>>    /* Perform machine dependent cif processing */
>> +#ifdef FFI_TARGET_SPECIFIC_VARIADIC
>> +  if (isvariadic)
>> +	return ffi_prep_cif_machdep_var(cif, nfixedargs, ntotalargs);
>> +#endif
>> +
>>    return ffi_prep_cif_machdep(cif);
>>  }
>>  #endif /* not __CRIS__ */
>> 
>> +ffi_status ffi_prep_cif(ffi_cif *cif, ffi_abi abi, unsigned int nargs,
>> +			     ffi_type *rtype, ffi_type **atypes)
>> +{
>> +  return ffi_prep_cif_core(cif, abi, 0, nargs, nargs, rtype, atypes);
>> +}
>> +
>> +ffi_status ffi_prep_cif_var(ffi_cif *cif,
>> +                            ffi_abi abi,
>> +                            unsigned int nfixedargs,
>> +                            unsigned int ntotalargs,
>> +                            ffi_type *rtype,
>> +                            ffi_type **atypes)
>> +{
>> +  return ffi_prep_cif_core(cif, abi, 1, nfixedargs, ntotalargs, rtype, atypes);
>> +}
>> +
>>  #if FFI_CLOSURES
>> 
>>  ffi_status
>> diff --git a/testsuite/libffi.call/cls_double_va.c
>> b/testsuite/libffi.call/cls_double_va.c
>> index 62bebbd..1a2706e 100644
>> --- a/testsuite/libffi.call/cls_double_va.c
>> +++ b/testsuite/libffi.call/cls_double_va.c
>> @@ -6,7 +6,6 @@
>> 
>>  /* { dg-do run { xfail strongarm*-*-* xscale*-*-* } } */
>>  /* { dg-output "" { xfail avr32*-*-* } } */
>> -/* { dg-skip-if "" arm*-*-* { "-mfloat-abi=hard" } { "" } } */
>> 
>>  #include "ffitest.h"
>> 
>> @@ -36,7 +35,8 @@ int main (void)
>>  	arg_types[1] = &ffi_type_double;
>>  	arg_types[2] = NULL;
>> 
>> -	CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &ffi_type_sint,
>> +	/* This printf call is variadic */
>> +	CHECK(ffi_prep_cif_var(&cif, FFI_DEFAULT_ABI, 1, 2, &ffi_type_sint,
>>  		arg_types) == FFI_OK);
>> 
>>  	args[0] = &format;
>> @@ -48,6 +48,10 @@ int main (void)
>>  	printf("res: %d\n", (int) res);
>>  	// { dg-output "\nres: 4" }
>> 
>> +	/* The call to cls_double_va_fn is static, so have to use a normal prep_cif */
>> +	CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &ffi_type_sint,
>> +		arg_types) == FFI_OK);
>> +
>>  	CHECK(ffi_prep_closure_loc(pcl, &cif, cls_double_va_fn, NULL, code)
>> == FFI_OK);
>> 
>>  	res	= ((int(*)(char*, double))(code))(format, doubleArg);
>> diff --git a/testsuite/libffi.call/cls_longdouble_va.c
>> b/testsuite/libffi.call/cls_longdouble_va.c
>> index b33b2b7..95f9ff4 100644
>> --- a/testsuite/libffi.call/cls_longdouble_va.c
>> +++ b/testsuite/libffi.call/cls_longdouble_va.c
>> @@ -6,7 +6,6 @@
>> 
>>  /* { dg-do run { xfail strongarm*-*-* xscale*-*-* } } */
>>  /* { dg-output "" { xfail avr32*-*-* x86_64-*-mingw* } } */
>> -/* { dg-skip-if "" arm*-*-* { "-mfloat-abi=hard" } { "" } } */
>> 
>>  #include "ffitest.h"
>> 
>> @@ -36,7 +35,8 @@ int main (void)
>>  	arg_types[1] = &ffi_type_longdouble;
>>  	arg_types[2] = NULL;
>> 
>> -	CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &ffi_type_sint,
>> +	/* This printf call is variadic */
>> +	CHECK(ffi_prep_cif_var(&cif, FFI_DEFAULT_ABI, 1, 2, &ffi_type_sint,
>>  		arg_types) == FFI_OK);
>> 
>>  	args[0] = &format;
>> @@ -48,6 +48,10 @@ int main (void)
>>  	printf("res: %d\n", (int) res);
>>  	// { dg-output "\nres: 4" }
>> 
>> +	/* The call to cls_longdouble_va_fn is static, so have to use a
>> normal prep_cif */
>> +	CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &ffi_type_sint,
>> +		arg_types) == FFI_OK);
>> +
>>  	CHECK(ffi_prep_closure_loc(pcl, &cif, cls_longdouble_va_fn, NULL,
>> code) == FFI_OK);
>> 
>>  	res	= ((int(*)(char*, long double))(code))(format, ldArg);
>> diff --git a/testsuite/libffi.call/float_va.c b/testsuite/libffi.call/float_va.c
>> new file mode 100644
>> index 0000000..4611969
>> --- /dev/null
>> +++ b/testsuite/libffi.call/float_va.c
>> @@ -0,0 +1,107 @@
>> +/* Area:        fp and variadics
>> +   Purpose:     check fp inputs and returns work on variadics, even
>> the fixed params
>> +   Limitations: None
>> +   PR:          none
>> +   Originator:  <david.gilbert@linaro.org> 2011-01-25
>> +
>> +   Intended to stress the difference in ABI on ARM vfp
>> +*/
>> +
>> +/* { dg-do run } */
>> +
>> +#include <stdarg.h>
>> +
>> +#include "ffitest.h"
>> +
>> +/* prints out all the parameters, and returns the sum of them all.
>> + * 'x' is the number of variadic parameters all of which are double
>> in this test
>> + */
>> +double float_va_fn(unsigned int x, double y,...)
>> +{
>> +  double total=0.0;
>> +  va_list ap;
>> +  unsigned int i;
>> +
>> +  total+=(double)x;
>> +  total+=y;
>> +
>> +  printf("%u: %.1lf :", x, y);
>> +
>> +  va_start(ap, y);
>> +  for(i=0;i<x;i++)
>> +  {
>> +    double arg=va_arg(ap, double);
>> +    total+=arg;
>> +    printf(" %d:%.1lf ", i, arg);
>> +  }
>> +  va_end(ap);
>> +
>> +  printf(" total: %.1lf\n", total);
>> +
>> +  return total;
>> +}
>> +
>> +int main (void)
>> +{
>> +  ffi_cif    cif;
>> +
>> +  ffi_type    *arg_types[5];
>> +  void        *values[5];
>> +  double        doubles[5];
>> +  unsigned int firstarg;
>> +  double        resfp;
>> +
>> +  /* First test, pass float_va_fn(0,2.0) - note there are no actual
>> +   * variadic parameters, but it's declared variadic so the ABI may be
>> +   * different. */
>> +  /* Call it statically and then via ffi */
>> +  resfp=float_va_fn(0,2.0);
>> +  // { dg-output "0: 2.0 : total: 2.0" }
>> +  printf("compiled: %.1lf\n", resfp);
>> +  // { dg-output "\ncompiled: 2.0" }
>> +
>> +  arg_types[0] = &ffi_type_uint;
>> +  arg_types[1] = &ffi_type_double;
>> +  arg_types[2] = NULL;
>> +  CHECK(ffi_prep_cif_var(&cif, FFI_DEFAULT_ABI, 2, 2,
>> +        &ffi_type_double, arg_types) == FFI_OK);
>> +
>> +  firstarg = 0;
>> +  doubles[0] = 2.0;
>> +  values[0] = &firstarg;
>> +  values[1] = &doubles[0];
>> +  ffi_call(&cif, FFI_FN(float_va_fn), &resfp, values);
>> +  // { dg-output "\n0: 2.0 : total: 2.0" }
>> +  printf("ffi: %.1lf\n", resfp);
>> +  // { dg-output "\nffi: 2.0" }
>> +
>> +  /* Second test, float_va_fn(2,2.0,3.0,4.0), now with variadic params */
>> +  /* Call it statically and then via ffi */
>> +  resfp=float_va_fn(2,2.0,3.0,4.0);
>> +  // { dg-output "\n2: 2.0 : 0:3.0  1:4.0  total: 11.0" }
>> +  printf("compiled: %.1lf\n", resfp);
>> +  // { dg-output "\ncompiled: 11.0" }
>> +
>> +  arg_types[0] = &ffi_type_uint;
>> +  arg_types[1] = &ffi_type_double;
>> +  arg_types[2] = &ffi_type_double;
>> +  arg_types[3] = &ffi_type_double;
>> +  arg_types[4] = NULL;
>> +  CHECK(ffi_prep_cif_var(&cif, FFI_DEFAULT_ABI, 2, 4,
>> +        &ffi_type_double, arg_types) == FFI_OK);
>> +
>> +  firstarg = 2;
>> +  doubles[0] = 2.0;
>> +  doubles[1] = 3.0;
>> +  doubles[2] = 4.0;
>> +  values[0] = &firstarg;
>> +  values[1] = &doubles[0];
>> +  values[2] = &doubles[1];
>> +  values[3] = &doubles[2];
>> +  ffi_call(&cif, FFI_FN(float_va_fn), &resfp, values);
>> +  // { dg-output "\n2: 2.0 : 0:3.0  1:4.0  total: 11.0" }
>> +  printf("ffi: %.1lf\n", resfp);
>> +  // { dg-output "\nffi: 11.0" }
>> +
>> +  exit(0);
>> +}


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]