diff mbox

Pass floating point values on powerpc64 as per ABI

Message ID 20131116115443.GM22514@bubble.grove.modra.org
State New
Headers show

Commit Message

Alan Modra Nov. 16, 2013, 11:54 a.m. UTC
The powerpc64 support opted to pass floating point values both in the
fpr area and the parameter save area, necessary when the backend
doesn't know if a function argument corresponds to the ellipsis
arguments of a variadic function.  This patch adds powerpc support for
variadic functions, and changes the code to only pass fp in the ABI
mandated area.  ELFv2 needs this change since the parameter save area
may not exist there.

This also fixes two faulty tests that used a non-variadic function
cast to call a variadic function, and spuriously reasoned that this is
somehow necessary for static functions..

The whitespace changes, and comment changes in the tests, are to make
the gcc versions of these files mirror upstream libffi.

	* src/powerpc/ffitarget.h (FFI_TARGET_SPECIFIC_VARIADIC): Define.
	(FFI_EXTRA_CIF_FIELDS): Define.
	* src/powerpc/ffi.c (ffi_prep_args64): Save fprs as per the
	ABI, not to both fpr and param save area.
	(ffi_prep_cif_machdep_core): Renamed from ffi_prep_cif_machdep.
	Keep initial flags.  Formatting.  Remove dead FFI_LINUX_SOFT_FLOAT
	code.
	(ffi_prep_cif_machdep, ffi_prep_cif_machdep_var): New functions.
	(ffi_closure_helper_LINUX64): Pass floating point as per ABI,
	not to both fpr and parameter save areas.

	* libffi/testsuite/libffi.call/cls_double_va.c (main): Correct
	function cast and don't call ffi_prep_cif.
	* libffi/testsuite/libffi.call/cls_longdouble_va.c (main): Likewise.

Comments

Andreas Schwab Nov. 18, 2013, 9:10 a.m. UTC | #1
Alan Modra <amodra@gmail.com> writes:

> diff -urp gcc3/libffi/testsuite/libffi.call/cls_double_va.c gcc4/libffi/testsuite/libffi.call/cls_double_va.c
> --- gcc3/libffi/testsuite/libffi.call/cls_double_va.c	2013-11-15 23:03:07.193964372 +1030
> +++ gcc4/libffi/testsuite/libffi.call/cls_double_va.c	2013-11-15 23:22:51.383884118 +1030
> @@ -38,26 +38,24 @@ int main (void)
>  
>  	/* This printf call is variadic */
>  	CHECK(ffi_prep_cif_var(&cif, FFI_DEFAULT_ABI, 1, 2, &ffi_type_sint,
> -		arg_types) == FFI_OK);
> +			       arg_types) == FFI_OK);
>  
>  	args[0] = &format;
>  	args[1] = &doubleArg;
>  	args[2] = NULL;
>  
>  	ffi_call(&cif, FFI_FN(printf), &res, args);
> -	// { dg-output "7.0" }
> +	/* { dg-output "7.0" } */
>  	printf("res: %d\n", (int) res);
> -	// { dg-output "\nres: 4" }
> +	/* { 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);

This breaks ia64:

FAIL: libffi.call/cls_double_va.c -O0 -W -Wall output pattern test, is 7.0
res: 4
0.0
res: 4
, should match 7.0?
res: 4?
7.0?
res: 4

FAIL: libffi.call/cls_longdouble_va.c -O0 -W -Wall output pattern test, is 7.0
res: 4
0.0
res: 4
, should match 7.0?
res: 4?
7.0?
res: 4

Andreas.
Alan Modra Nov. 18, 2013, 11:31 p.m. UTC | #2
On Mon, Nov 18, 2013 at 10:10:39AM +0100, Andreas Schwab wrote:
> Alan Modra <amodra@gmail.com> writes:
> 
> > -	/* 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);
> 
> This breaks ia64:
> 
> FAIL: libffi.call/cls_double_va.c -O0 -W -Wall output pattern test, is 7.0
> res: 4
> 0.0
> res: 4
> , should match 7.0?
> res: 4?
> 7.0?
> res: 4

This indicates a real error in the ia64 libffi support.  The test was
bogus before, in exactly the same way as if you defined a function as
int f(char *, ...)
but declared it and called it in another file as
int f(char *, double)
To add to the confusion, someone wrote a comment that it had to be
that way because "cls_double_va_fn is static"..
Andreas Schwab Nov. 19, 2013, 12:27 a.m. UTC | #3
Alan Modra <amodra@gmail.com> writes:

> On Mon, Nov 18, 2013 at 10:10:39AM +0100, Andreas Schwab wrote:
>> Alan Modra <amodra@gmail.com> writes:
>> 
>> > -	/* 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);
>> 
>> This breaks ia64:
>> 
>> FAIL: libffi.call/cls_double_va.c -O0 -W -Wall output pattern test, is 7.0
>> res: 4
>> 0.0
>> res: 4
>> , should match 7.0?
>> res: 4?
>> 7.0?
>> res: 4
>
> This indicates a real error in the ia64 libffi support.  The test was
> bogus before, in exactly the same way as if you defined a function as
> int f(char *, ...)
> but declared it and called it in another file as
> int f(char *, double)

Where does it call a varargs function?

Andreas.
Alan Modra Nov. 19, 2013, 12:46 a.m. UTC | #4
On Tue, Nov 19, 2013 at 01:27:39AM +0100, Andreas Schwab wrote:
> Alan Modra <amodra@gmail.com> writes:
> 
> > On Mon, Nov 18, 2013 at 10:10:39AM +0100, Andreas Schwab wrote:
> >> Alan Modra <amodra@gmail.com> writes:
> >> 
> >> > -	/* 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);
> >> 
> >> This breaks ia64:
> >> 
> >> FAIL: libffi.call/cls_double_va.c -O0 -W -Wall output pattern test, is 7.0
> >> res: 4
> >> 0.0
> >> res: 4
> >> , should match 7.0?
> >> res: 4?
> >> 7.0?
> >> res: 4
> >
> > This indicates a real error in the ia64 libffi support.  The test was
> > bogus before, in exactly the same way as if you defined a function as
> > int f(char *, ...)
> > but declared it and called it in another file as
> > int f(char *, double)
> 
> Where does it call a varargs function?

printf
Alan Modra Nov. 19, 2013, 12:57 a.m. UTC | #5
On Tue, Nov 19, 2013 at 11:16:26AM +1030, Alan Modra wrote:
> On Tue, Nov 19, 2013 at 01:27:39AM +0100, Andreas Schwab wrote:
> > Where does it call a varargs function?
> 
> printf

Sorry that wasn't such a helpful response.

Here, really:
	res = ((int(*)(char*, ...))(code))(format, doubleArg);

Prior to that point ffi_prep_cif_var and ffi_prep_closure_loc have set
things up to expect a varargs function.  The old test didn't test a
closure call with variable arguments.  Actually that makes my claims
about calling functions differently to the way they were defined
wrong.  The old test didn't actually do that, since there was another
ffi_prep_cif call that said the closure was not varargs, and the call
matched that.
Andreas Schwab Nov. 19, 2013, 9:16 a.m. UTC | #6
Alan Modra <amodra@gmail.com> writes:

> On Tue, Nov 19, 2013 at 11:16:26AM +1030, Alan Modra wrote:
>> On Tue, Nov 19, 2013 at 01:27:39AM +0100, Andreas Schwab wrote:
>> > Where does it call a varargs function?
>> 
>> printf
>
> Sorry that wasn't such a helpful response.
>
> Here, really:
> 	res = ((int(*)(char*, ...))(code))(format, doubleArg);

But cls_double_va_fn doesn't expect a varargs call.

Andreas.
Alan Modra Nov. 25, 2013, 9:54 a.m. UTC | #7
On Tue, Nov 19, 2013 at 10:16:31AM +0100, Andreas Schwab wrote:
> Alan Modra <amodra@gmail.com> writes:
> 
> > On Tue, Nov 19, 2013 at 11:16:26AM +1030, Alan Modra wrote:
> >> On Tue, Nov 19, 2013 at 01:27:39AM +0100, Andreas Schwab wrote:
> >> > Where does it call a varargs function?
> >> 
> >> printf
> >
> > Sorry that wasn't such a helpful response.
> >
> > Here, really:
> > 	res = ((int(*)(char*, ...))(code))(format, doubleArg);
> 
> But cls_double_va_fn doesn't expect a varargs call.

It works this way:  The call shown above sets up arguments as for a
call to printf, and transfers control to a trampoline.  On powerpc64
the trampoline bounces to ffi_closure_LINUX64.  This assembly function
saves parameter passing registers to memory and calls some C code,
ffi_closure_helper_LINUX64, that uses information set up by
ffi_prep_cif_var to extract the arguments and package them up for
cls_double_va_fn.  So it is ffi_closure_helper_LINUX64 that expects a
varargs call, under control of ffi_prep_cif_var.

It looks to me like the new libffi test failures on ia64 are due to
libffi on ia64 not differentiating between varargs and normal calls,
yet ia64 passes passes fp differently for varargs if I'm reading
gcc/config/ia64.c function_arg correctly.
diff mbox

Patch

diff -urp gcc3/libffi/src/powerpc/ffitarget.h gcc4/libffi/src/powerpc/ffitarget.h
--- gcc3/libffi/src/powerpc/ffitarget.h	2013-11-15 23:03:07.313959745 +1030
+++ gcc4/libffi/src/powerpc/ffitarget.h	2013-11-15 23:19:21.692053339 +1030
@@ -106,6 +106,10 @@  typedef enum ffi_abi {
 
 #define FFI_CLOSURES 1
 #define FFI_NATIVE_RAW_API 0
+#if defined (POWERPC) || defined (POWERPC_FREEBSD)
+# define FFI_TARGET_SPECIFIC_VARIADIC 1
+# define FFI_EXTRA_CIF_FIELDS unsigned nfixedargs
+#endif
 
 /* For additional types like the below, take care about the order in
    ppc_closures.S. They must follow after the FFI_TYPE_LAST.  */
diff -urp gcc3/libffi/src/powerpc/ffi.c gcc4/libffi/src/powerpc/ffi.c
--- gcc3/libffi/src/powerpc/ffi.c	2013-11-15 23:06:57.313036827 +1030
+++ gcc4/libffi/src/powerpc/ffi.c	2013-11-15 23:47:24.402296569 +1030
@@ -443,9 +443,9 @@  ffi_prep_args64 (extended_cif *ecif, uns
   /* 'fpr_base' points at the space for fpr3, and grows upwards as
      we use FPR registers.  */
   valp fpr_base;
-  int fparg_count;
+  unsigned int fparg_count;
 
-  int i, words;
+  unsigned int i, words, nargs, nfixedargs;
   ffi_type **ptr;
   double double_tmp;
   union {
@@ -482,30 +482,34 @@  ffi_prep_args64 (extended_cif *ecif, uns
 
   /* Now for the arguments.  */
   p_argv.v = ecif->avalue;
-  for (ptr = ecif->cif->arg_types, i = ecif->cif->nargs;
-       i > 0;
-       i--, ptr++, p_argv.v++)
+  nargs = ecif->cif->nargs;
+  nfixedargs = ecif->cif->nfixedargs;
+  for (ptr = ecif->cif->arg_types, i = 0;
+       i < nargs;
+       i++, ptr++, p_argv.v++)
     {
       switch ((*ptr)->type)
 	{
 	case FFI_TYPE_FLOAT:
 	  double_tmp = **p_argv.f;
-	  *next_arg.f = (float) double_tmp;
+	  if (fparg_count < NUM_FPR_ARG_REGISTERS64 && i < nfixedargs)
+	    *fpr_base.d++ = double_tmp;
+	  else
+	    *next_arg.f = (float) double_tmp;
 	  if (++next_arg.ul == gpr_end.ul)
 	    next_arg.ul = rest.ul;
-	  if (fparg_count < NUM_FPR_ARG_REGISTERS64)
-	    *fpr_base.d++ = double_tmp;
 	  fparg_count++;
 	  FFI_ASSERT (flags & FLAG_FP_ARGUMENTS);
 	  break;
 
 	case FFI_TYPE_DOUBLE:
 	  double_tmp = **p_argv.d;
-	  *next_arg.d = double_tmp;
+	  if (fparg_count < NUM_FPR_ARG_REGISTERS64 && i < nfixedargs)
+	    *fpr_base.d++ = double_tmp;
+	  else
+	    *next_arg.d = double_tmp;
 	  if (++next_arg.ul == gpr_end.ul)
 	    next_arg.ul = rest.ul;
-	  if (fparg_count < NUM_FPR_ARG_REGISTERS64)
-	    *fpr_base.d++ = double_tmp;
 	  fparg_count++;
 	  FFI_ASSERT (flags & FLAG_FP_ARGUMENTS);
 	  break;
@@ -513,18 +517,20 @@  ffi_prep_args64 (extended_cif *ecif, uns
 #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
 	case FFI_TYPE_LONGDOUBLE:
 	  double_tmp = (*p_argv.d)[0];
-	  *next_arg.d = double_tmp;
+	  if (fparg_count < NUM_FPR_ARG_REGISTERS64 && i < nfixedargs)
+	    *fpr_base.d++ = double_tmp;
+	  else
+	    *next_arg.d = double_tmp;
 	  if (++next_arg.ul == gpr_end.ul)
 	    next_arg.ul = rest.ul;
-	  if (fparg_count < NUM_FPR_ARG_REGISTERS64)
-	    *fpr_base.d++ = double_tmp;
 	  fparg_count++;
 	  double_tmp = (*p_argv.d)[1];
-	  *next_arg.d = double_tmp;
+	  if (fparg_count < NUM_FPR_ARG_REGISTERS64 && i < nfixedargs)
+	    *fpr_base.d++ = double_tmp;
+	  else
+	    *next_arg.d = double_tmp;
 	  if (++next_arg.ul == gpr_end.ul)
 	    next_arg.ul = rest.ul;
-	  if (fparg_count < NUM_FPR_ARG_REGISTERS64)
-	    *fpr_base.d++ = double_tmp;
 	  fparg_count++;
 	  FFI_ASSERT (__LDBL_MANT_DIG__ == 106);
 	  FFI_ASSERT (flags & FLAG_FP_ARGUMENTS);
@@ -597,15 +603,14 @@  ffi_prep_args64 (extended_cif *ecif, uns
 
 
 /* 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)
 {
   /* All this is for the SYSV and LINUX64 ABI.  */
-  int i;
   ffi_type **ptr;
   unsigned bytes;
-  int fparg_count = 0, intarg_count = 0;
-  unsigned flags = 0;
+  unsigned i, fparg_count = 0, intarg_count = 0;
+  unsigned flags = cif->flags;
   unsigned struct_copy_size = 0;
   unsigned type = cif->rtype->type;
   unsigned size = cif->rtype->size;
@@ -650,19 +655,23 @@  ffi_prep_cif_machdep (ffi_cif *cif)
      - soft-float float/doubles are treated as UINT32/UINT64 respectivley.
      - soft-float long doubles are returned in gpr3-gpr6.  */
   /* First translate for softfloat/nonlinux */
-  if (cif->abi == FFI_LINUX_SOFT_FLOAT) {
-	if (type == FFI_TYPE_FLOAT)
-		type = FFI_TYPE_UINT32;
-	if (type == FFI_TYPE_DOUBLE)
-		type = FFI_TYPE_UINT64;
-	if (type == FFI_TYPE_LONGDOUBLE)
-		type = FFI_TYPE_UINT128;
-  } else if (cif->abi != FFI_LINUX && cif->abi != FFI_LINUX64) {
+  if (cif->abi == FFI_LINUX_SOFT_FLOAT)
+    {
+      if (type == FFI_TYPE_FLOAT)
+	type = FFI_TYPE_UINT32;
+      if (type == FFI_TYPE_DOUBLE)
+	type = FFI_TYPE_UINT64;
+      if (type == FFI_TYPE_LONGDOUBLE)
+	type = FFI_TYPE_UINT128;
+    }
+  else if (cif->abi != FFI_LINUX
+	   && cif->abi != FFI_LINUX64)
+    {
 #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
-	if (type == FFI_TYPE_LONGDOUBLE)
-		type = FFI_TYPE_STRUCT;
+      if (type == FFI_TYPE_LONGDOUBLE)
+	type = FFI_TYPE_STRUCT;
 #endif
-  }
+    }
 
   switch (type)
     {
@@ -823,13 +832,8 @@  ffi_prep_cif_machdep (ffi_cif *cif)
 	  {
 #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
 	  case FFI_TYPE_LONGDOUBLE:
-	    if (cif->abi == FFI_LINUX_SOFT_FLOAT)
-	      intarg_count += 4;
-	    else
-	      {
-		fparg_count += 2;
-		intarg_count += 2;
-	      }
+	    fparg_count += 2;
+	    intarg_count += 2;
 	    break;
 #endif
 	  case FFI_TYPE_FLOAT:
@@ -911,6 +915,22 @@  ffi_prep_cif_machdep (ffi_cif *cif)
   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 MAYBE_UNUSED)
+{
+  cif->nfixedargs = nfixedargs;
+  return ffi_prep_cif_machdep_core (cif);
+}
+
 extern void ffi_call_SYSV(extended_cif *, unsigned, unsigned, unsigned *,
 			  void (*fn)(void));
 extern void FFI_HIDDEN ffi_call_LINUX64(extended_cif *, unsigned long,
@@ -1238,6 +1258,7 @@  ffi_closure_helper_SYSV (ffi_closure *cl
 	    }
 	  break;
 #endif
+
 	case FFI_TYPE_SINT16:
 	case FFI_TYPE_UINT16:
 #ifndef __LITTLE_ENDIAN__
@@ -1255,6 +1276,7 @@  ffi_closure_helper_SYSV (ffi_closure *cl
 	    }
 	  break;
 #endif
+
 	case FFI_TYPE_SINT32:
 	case FFI_TYPE_UINT32:
 	case FFI_TYPE_POINTER:
@@ -1358,7 +1380,7 @@  ffi_closure_helper_LINUX64 (ffi_closure
 
   void **avalue;
   ffi_type **arg_types;
-  long i, avn;
+  unsigned long i, avn, nfixedargs;
   ffi_cif *cif;
   ffi_dblfl *end_pfr = pfr + NUM_FPR_ARG_REGISTERS64;
 
@@ -1375,6 +1397,7 @@  ffi_closure_helper_LINUX64 (ffi_closure
 
   i = 0;
   avn = cif->nargs;
+  nfixedargs = cif->nfixedargs;
   arg_types = cif->arg_types;
 
   /* Grab the addresses of the arguments from the stack frame.  */
@@ -1389,6 +1412,7 @@  ffi_closure_helper_LINUX64 (ffi_closure
 	  pst++;
 	  break;
 #endif
+
 	case FFI_TYPE_SINT16:
 	case FFI_TYPE_UINT16:
 #ifndef __LITTLE_ENDIAN__
@@ -1396,6 +1420,7 @@  ffi_closure_helper_LINUX64 (ffi_closure
 	  pst++;
 	  break;
 #endif
+
 	case FFI_TYPE_SINT32:
 	case FFI_TYPE_UINT32:
 #ifndef __LITTLE_ENDIAN__
@@ -1403,6 +1428,7 @@  ffi_closure_helper_LINUX64 (ffi_closure
 	  pst++;
 	  break;
 #endif
+
 	case FFI_TYPE_SINT64:
 	case FFI_TYPE_UINT64:
 	case FFI_TYPE_POINTER:
@@ -1430,7 +1456,7 @@  ffi_closure_helper_LINUX64 (ffi_closure
 
 	  /* there are 13 64bit floating point registers */
 
-	  if (pfr < end_pfr)
+	  if (pfr < end_pfr && i < nfixedargs)
 	    {
 	      double temp = pfr->d;
 	      pfr->f = (float) temp;
@@ -1446,7 +1472,7 @@  ffi_closure_helper_LINUX64 (ffi_closure
 	  /* On the outgoing stack all values are aligned to 8 */
 	  /* there are 13 64bit floating point registers */
 
-	  if (pfr < end_pfr)
+	  if (pfr < end_pfr && i < nfixedargs)
 	    {
 	      avalue[i] = pfr;
 	      pfr++;
@@ -1458,14 +1484,14 @@  ffi_closure_helper_LINUX64 (ffi_closure
 
 #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
 	case FFI_TYPE_LONGDOUBLE:
-	  if (pfr + 1 < end_pfr)
+	  if (pfr + 1 < end_pfr && i + 1 < nfixedargs)
 	    {
 	      avalue[i] = pfr;
 	      pfr += 2;
 	    }
 	  else
 	    {
-	      if (pfr < end_pfr)
+	      if (pfr < end_pfr && i < nfixedargs)
 		{
 		  /* Passed partly in f13 and partly on the stack.
 		     Move it all to the stack.  */
diff -urp gcc3/libffi/testsuite/libffi.call/cls_double_va.c gcc4/libffi/testsuite/libffi.call/cls_double_va.c
--- gcc3/libffi/testsuite/libffi.call/cls_double_va.c	2013-11-15 23:03:07.193964372 +1030
+++ gcc4/libffi/testsuite/libffi.call/cls_double_va.c	2013-11-15 23:22:51.383884118 +1030
@@ -38,26 +38,24 @@  int main (void)
 
 	/* This printf call is variadic */
 	CHECK(ffi_prep_cif_var(&cif, FFI_DEFAULT_ABI, 1, 2, &ffi_type_sint,
-		arg_types) == FFI_OK);
+			       arg_types) == FFI_OK);
 
 	args[0] = &format;
 	args[1] = &doubleArg;
 	args[2] = NULL;
 
 	ffi_call(&cif, FFI_FN(printf), &res, args);
-	// { dg-output "7.0" }
+	/* { dg-output "7.0" } */
 	printf("res: %d\n", (int) res);
-	// { dg-output "\nres: 4" }
+	/* { 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);
 
-	CHECK(ffi_prep_closure_loc(pcl, &cif, cls_double_va_fn, NULL, code) == FFI_OK);
-
-	res	= ((int(*)(char*, double))(code))(format, doubleArg);
-	// { dg-output "\n7.0" }
+	res = ((int(*)(char*, ...))(code))(format, doubleArg);
+	/* { dg-output "\n7.0" } */
 	printf("res: %d\n", (int) res);
-	// { dg-output "\nres: 4" }
+	/* { dg-output "\nres: 4" } */
 
 	exit(0);
 }
diff -urp gcc3/libffi/testsuite/libffi.call/cls_longdouble_va.c gcc4/libffi/testsuite/libffi.call/cls_longdouble_va.c
--- gcc3/libffi/testsuite/libffi.call/cls_longdouble_va.c	2013-11-15 23:03:07.205963908 +1030
+++ gcc4/libffi/testsuite/libffi.call/cls_longdouble_va.c	2013-11-15 23:24:19.372455652 +1030
@@ -38,27 +38,24 @@  int main (void)
 
 	/* This printf call is variadic */
 	CHECK(ffi_prep_cif_var(&cif, FFI_DEFAULT_ABI, 1, 2, &ffi_type_sint,
-		arg_types) == FFI_OK);
+			       arg_types) == FFI_OK);
 
 	args[0] = &format;
 	args[1] = &ldArg;
 	args[2] = NULL;
 
 	ffi_call(&cif, FFI_FN(printf), &res, args);
-	// { dg-output "7.0" }
+	/* { dg-output "7.0" } */
 	printf("res: %d\n", (int) res);
-	// { dg-output "\nres: 4" }
+	/* { 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);
 
-	CHECK(ffi_prep_closure_loc(pcl, &cif, cls_longdouble_va_fn, NULL, code) == FFI_OK);
-
-	res	= ((int(*)(char*, long double))(code))(format, ldArg);
-	// { dg-output "\n7.0" }
+	res = ((int(*)(char*, ...))(code))(format, ldArg);
+	/* { dg-output "\n7.0" } */
 	printf("res: %d\n", (int) res);
-	// { dg-output "\nres: 4" }
+	/* { dg-output "\nres: 4" } */
 
 	exit(0);
 }