diff mbox

Fix PR libffi/60073

Message ID 1627069.1KANd3nG1O@polaris
State New
Headers show

Commit Message

Eric Botcazou Feb. 13, 2014, 4:18 p.m. UTC
This adds proper variadic support to the SPARC port of libffi, thus fixing a 
regression in the testsuite in 64-bit mode, and fixes a small inaccuracy in 
the documentation.

Tested on SPARC/Solaris and SPARC64/Solaris, applied on the mainline.


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.
diff mbox

Patch

Index: src/sparc/ffitarget.h
===================================================================
--- src/sparc/ffitarget.h	(revision 207685)
+++ src/sparc/ffitarget.h	(working copy)
@@ -58,16 +58,17 @@  typedef enum ffi_abi {
 } ffi_abi;
 #endif
 
+#define FFI_TARGET_SPECIFIC_VARIADIC 1
+#define FFI_EXTRA_CIF_FIELDS unsigned int nfixedargs
+
 /* ---- Definitions for closures ----------------------------------------- */
 
 #define FFI_CLOSURES 1
-#define FFI_NATIVE_RAW_API 0
-
 #ifdef SPARC64
 #define FFI_TRAMPOLINE_SIZE 24
 #else
 #define FFI_TRAMPOLINE_SIZE 16
 #endif
+#define FFI_NATIVE_RAW_API 0
 
 #endif
-
Index: src/sparc/ffi.c
===================================================================
--- src/sparc/ffi.c	(revision 207685)
+++ src/sparc/ffi.c	(working copy)
@@ -249,7 +249,7 @@  int ffi_prep_args_v9(char *stack, extend
 }
 
 /* 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;
 
@@ -334,6 +334,19 @@  ffi_status ffi_prep_cif_machdep(ffi_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)
+{
+  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];
@@ -604,8 +617,7 @@  ffi_closure_sparc_inner_v9(ffi_closure *
 
   /* 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.  */
@@ -619,6 +631,10 @@  ffi_closure_sparc_inner_v9(ffi_closure *
   /* 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)
@@ -633,7 +649,9 @@  ffi_closure_sparc_inner_v9(ffi_closure *
 				   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;
 	    }
@@ -649,6 +667,7 @@  ffi_closure_sparc_inner_v9(ffi_closure *
 	    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
@@ -662,7 +681,7 @@  ffi_closure_sparc_inner_v9(ffi_closure *
     }
 
   /* 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;
Index: doc/libffi.texi
===================================================================
--- doc/libffi.texi	(revision 207685)
+++ doc/libffi.texi	(working copy)
@@ -63,14 +63,14 @@  section entitled ``GNU General Public Li
 @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