public inbox for libffi-discuss@sourceware.org
 help / color / mirror / Atom feed
* [PATCH 0/4] Go closures for alpha
@ 2014-10-30  3:54 Richard Henderson
  2014-10-30  3:54 ` [PATCH 3/4] alpha: Add support for complex types Richard Henderson
                   ` (3 more replies)
  0 siblings, 4 replies; 5+ messages in thread
From: Richard Henderson @ 2014-10-30  3:54 UTC (permalink / raw)
  To: libffi-discuss

A couple of minor bug fixes, then complex suppot, then Go closures.


r~


Richard Henderson (4):
  alpha: Reorganize cif flags
  alpha: Clean up conversion of float values
  alpha: Add support for complex types
  alpha: Add support for Go closures

 src/alpha/ffi.c                              | 429 +++++++++++++++++++++------
 src/alpha/ffitarget.h                        |   4 +
 src/alpha/internal.h                         |  23 ++
 src/alpha/osf.S                              | 427 ++++++++++----------------
 testsuite/libffi.call/call.exp               |  10 +-
 testsuite/libffi.call/cls_complex_va_float.c |   6 +
 6 files changed, 528 insertions(+), 371 deletions(-)
 create mode 100644 src/alpha/internal.h

-- 
1.9.3

^ permalink raw reply	[flat|nested] 5+ messages in thread

* [PATCH 2/4] alpha: Clean up conversion of float values
  2014-10-30  3:54 [PATCH 0/4] Go closures for alpha Richard Henderson
                   ` (2 preceding siblings ...)
  2014-10-30  3:54 ` [PATCH 1/4] alpha: Reorganize cif flags Richard Henderson
@ 2014-10-30  3:54 ` Richard Henderson
  3 siblings, 0 replies; 5+ messages in thread
From: Richard Henderson @ 2014-10-30  3:54 UTC (permalink / raw)
  To: libffi-discuss

Don't use "real" conversion to double, lest we raise
exceptions when passing signalling nans.
---
 src/alpha/ffi.c | 95 +++++++++++++++++++++++++++++++--------------------------
 1 file changed, 51 insertions(+), 44 deletions(-)

diff --git a/src/alpha/ffi.c b/src/alpha/ffi.c
index 519bd2c..2f9e7e5 100644
--- a/src/alpha/ffi.c
+++ b/src/alpha/ffi.c
@@ -45,6 +45,20 @@ extern void ffi_call_osf(void *, unsigned long, unsigned, void *, void (*)(void)
   FFI_HIDDEN;
 extern void ffi_closure_osf(void) FFI_HIDDEN;
 
+/* Promote a float value to its in-register double representation.
+   Unlike actually casting to double, this does not trap on NaN.  */
+static inline UINT64 lds(void *ptr)
+{
+  UINT64 ret;
+  asm("lds %0,%1" : "=f"(ret) : "m"(*(UINT32 *)ptr));
+  return ret;
+}
+
+/* And the reverse.  */
+static inline void sts(void *ptr, UINT64 val)
+{
+  asm("sts %1,%0" : "=m"(*(UINT32 *)ptr) : "f"(val));
+}
 
 ffi_status
 ffi_prep_cif_machdep(ffi_cif *cif)
@@ -127,71 +141,67 @@ ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
   avn = cif->nargs;
   arg_types = cif->arg_types;
 
-  while (i < avn)
+  for (i = 0, avn = cif->nargs; i < avn; i++)
     {
-      size_t size = (*arg_types)->size;
+      ffi_type *ty = arg_types[i];
+      void *valp = avalue[i];
+      unsigned long val;
+      size_t size;
 
-      switch ((*arg_types)->type)
+      switch (ty->type)
 	{
 	case FFI_TYPE_SINT8:
-	  *(SINT64 *) argp = *(SINT8 *)(* avalue);
+	  val = *(SINT8 *)valp;
 	  break;
 		  
 	case FFI_TYPE_UINT8:
-	  *(SINT64 *) argp = *(UINT8 *)(* avalue);
+	  val = *(UINT8 *)valp;
 	  break;
 		  
 	case FFI_TYPE_SINT16:
-	  *(SINT64 *) argp = *(SINT16 *)(* avalue);
+	  val = *(SINT16 *)valp;
 	  break;
 		  
 	case FFI_TYPE_UINT16:
-	  *(SINT64 *) argp = *(UINT16 *)(* avalue);
+	  val = *(UINT16 *)valp;
 	  break;
 		  
 	case FFI_TYPE_SINT32:
 	case FFI_TYPE_UINT32:
 	  /* Note that unsigned 32-bit quantities are sign extended.  */
-	  *(SINT64 *) argp = *(SINT32 *)(* avalue);
+	  val = *(SINT32 *)valp;
 	  break;
-		  
+
 	case FFI_TYPE_SINT64:
 	case FFI_TYPE_UINT64:
 	case FFI_TYPE_POINTER:
-	  *(UINT64 *) argp = *(UINT64 *)(* avalue);
+	case FFI_TYPE_DOUBLE:
+	  val = *(UINT64 *)valp;
+	  break;
+
+	case FFI_TYPE_LONGDOUBLE:
+	  /* Note that 128-bit long double is passed by reference.  */
+	  val = (unsigned long)valp;
 	  break;
 
 	case FFI_TYPE_FLOAT:
 	  if (argp - stack < 6)
-	    {
-	      /* Note the conversion -- all the fp regs are loaded as
-		 doubles.  The in-register format is the same.  */
-	      *(double *) argp = *(float *)(* avalue);
-	    }
+	    val = lds(valp);
 	  else
-	    *(float *) argp = *(float *)(* avalue);
-	  break;
-
-	case FFI_TYPE_DOUBLE:
-	  *(double *) argp = *(double *)(* avalue);
-	  break;
-
-	case FFI_TYPE_LONGDOUBLE:
-	  /* 128-bit long double is passed by reference.  */
-	  *(long double **) argp = (long double *)(* avalue);
-	  size = sizeof (long double *);
+	    val = *(UINT32 *)valp;
 	  break;
 
 	case FFI_TYPE_STRUCT:
-	  memcpy(argp, *avalue, (*arg_types)->size);
-	  break;
+	  size = ty->size;
+	  memcpy(argp, valp, size);
+	  argp += ALIGN(size, FFI_SIZEOF_ARG) / FFI_SIZEOF_ARG;
+	  continue;
 
 	default:
-	  FFI_ASSERT(0);
+	  abort();
 	}
 
-      argp += ALIGN(size, FFI_SIZEOF_ARG) / FFI_SIZEOF_ARG;
-      i++, arg_types++, avalue++;
+      *argp++ = val;
     }
 
   flags = (flags >> ALPHA_ST_SHIFT) & 0xff;
@@ -255,14 +265,13 @@ ffi_closure_osf_inner(ffi_closure *closure, void *rvalue, unsigned long *argp)
       argn = 1;
     }
 
-  i = 0;
-  avn = cif->nargs;
   arg_types = cif->arg_types;
   
   /* Grab the addresses of the arguments from the stack frame.  */
-  while (i < avn)
+  for (i = 0, avn = cif->nargs; i < avn; i++)
     {
       size_t size = arg_types[i]->size;
+      void *valp = &argp[argn];
 
       switch (arg_types[i]->type)
 	{
@@ -276,28 +285,26 @@ ffi_closure_osf_inner(ffi_closure *closure, void *rvalue, unsigned long *argp)
 	case FFI_TYPE_UINT64:
 	case FFI_TYPE_POINTER:
 	case FFI_TYPE_STRUCT:
-	  avalue[i] = &argp[argn];
 	  break;
 
 	case FFI_TYPE_FLOAT:
+	  /* Floats coming from registers need conversion from double
+	     back to float format.  */
 	  if (argn < 6)
 	    {
-	      /* Floats coming from registers need conversion from double
-	         back to float format.  */
-	      *(float *)&argp[argn - 6] = *(double *)&argp[argn - 6];
-	      avalue[i] = &argp[argn - 6];
+	      valp = &argp[argn - 6];
+	      sts(valp, argp[argn - 6]);
 	    }
-	  else
-	    avalue[i] = &argp[argn];
 	  break;
 
 	case FFI_TYPE_DOUBLE:
-	  avalue[i] = &argp[argn - (argn < 6 ? 6 : 0)];
+	  if (argn < 6)
+	    valp = &argp[argn - 6];
 	  break;
 
 	case FFI_TYPE_LONGDOUBLE:
 	  /* 128-bit long double is passed by reference.  */
-	  avalue[i] = (long double *) argp[argn];
+	  valp = (long double *) argp[argn];
 	  size = sizeof (long double *);
 	  break;
 
@@ -305,8 +312,8 @@ ffi_closure_osf_inner(ffi_closure *closure, void *rvalue, unsigned long *argp)
 	  abort ();
 	}
 
+      avalue[i] = valp;
       argn += ALIGN(size, FFI_SIZEOF_ARG) / FFI_SIZEOF_ARG;
-      i++;
     }
 
   /* Invoke the closure.  */
-- 
1.9.3

^ permalink raw reply	[flat|nested] 5+ messages in thread

* [PATCH 3/4] alpha: Add support for complex types
  2014-10-30  3:54 [PATCH 0/4] Go closures for alpha Richard Henderson
@ 2014-10-30  3:54 ` Richard Henderson
  2014-10-30  3:54 ` [PATCH 4/4] alpha: Add support for Go closures Richard Henderson
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 5+ messages in thread
From: Richard Henderson @ 2014-10-30  3:54 UTC (permalink / raw)
  To: libffi-discuss

---
 src/alpha/ffi.c                              | 278 +++++++++++++++++++++------
 src/alpha/ffitarget.h                        |   3 +
 src/alpha/internal.h                         |   4 +
 src/alpha/osf.S                              |  18 ++
 testsuite/libffi.call/call.exp               |  10 +-
 testsuite/libffi.call/cls_complex_va_float.c |   6 +
 6 files changed, 255 insertions(+), 64 deletions(-)

diff --git a/src/alpha/ffi.c b/src/alpha/ffi.c
index 2f9e7e5..1e5187e 100644
--- a/src/alpha/ffi.c
+++ b/src/alpha/ffi.c
@@ -1,8 +1,8 @@
 /* -----------------------------------------------------------------------
    ffi.c - Copyright (c) 2012  Anthony Green
-           Copyright (c) 1998, 2001, 2007, 2008  Red Hat, Inc.
-   
-   Alpha Foreign Function Interface 
+	   Copyright (c) 1998, 2001, 2007, 2008  Red Hat, Inc.
+
+   Alpha Foreign Function Interface
 
    Permission is hereby granted, free of charge, to any person obtaining
    a copy of this software and associated documentation files (the
@@ -60,18 +60,61 @@ static inline void sts(void *ptr, UINT64 val)
   asm("sts %1,%0" : "=m"(*(UINT32 *)ptr) : "f"(val));
 }
 
-ffi_status
+ffi_status FFI_HIDDEN
 ffi_prep_cif_machdep(ffi_cif *cif)
 {
-  int flags;
+  size_t bytes = 0;
+  int flags, i, avn;
+  ffi_type *rtype, *itype;
+
+  if (cif->abi != FFI_OSF)
+    return FFI_BAD_ABI;
+
+  /* Compute the size of the argument area.  */
+  for (i = 0, avn = cif->nargs; i < avn; i++)
+    {
+      itype = cif->arg_types[i];
+      switch (itype->type)
+	{
+	case FFI_TYPE_INT:
+	case FFI_TYPE_SINT8:
+	case FFI_TYPE_UINT8:
+	case FFI_TYPE_SINT16:
+	case FFI_TYPE_UINT16:
+	case FFI_TYPE_SINT32:
+	case FFI_TYPE_UINT32:
+	case FFI_TYPE_SINT64:
+	case FFI_TYPE_UINT64:
+	case FFI_TYPE_POINTER:
+	case FFI_TYPE_FLOAT:
+	case FFI_TYPE_DOUBLE:
+	case FFI_TYPE_LONGDOUBLE:
+	  /* All take one 8 byte slot.  */
+	  bytes += 8;
+	  break;
+
+	case FFI_TYPE_VOID:
+	case FFI_TYPE_STRUCT:
+	  /* Passed by value in N slots.  */
+	  bytes += ALIGN(itype->size, FFI_SIZEOF_ARG);
+	  break;
+
+	case FFI_TYPE_COMPLEX:
+	  /* _Complex long double passed by reference; others in 2 slots.  */
+	  if (itype->elements[0]->type == FFI_TYPE_LONGDOUBLE)
+	    bytes += 8;
+	  else
+	    bytes += 16;
+	  break;
 
-  /* Adjust cif->bytes to represent a minimum 6 words for the temporary
-     register argument loading area.  */
-  if (cif->bytes < 6*FFI_SIZEOF_ARG)
-    cif->bytes = 6*FFI_SIZEOF_ARG;
+	default:
+	  abort();
+	}
+    }
 
   /* Set the return type flag */
-  switch (cif->rtype->type)
+  rtype = cif->rtype;
+  switch (rtype->type)
     {
     case FFI_TYPE_VOID:
       flags = ALPHA_FLAGS(ALPHA_ST_VOID, ALPHA_LD_VOID);
@@ -109,22 +152,83 @@ ffi_prep_cif_machdep(ffi_cif *cif)
       /* Passed in memory, with a hidden pointer.  */
       flags = ALPHA_RET_IN_MEM;
       break;
+    case FFI_TYPE_COMPLEX:
+      itype = rtype->elements[0];
+      switch (itype->type)
+	{
+	case FFI_TYPE_FLOAT:
+	  flags = ALPHA_FLAGS(ALPHA_ST_CPLXF, ALPHA_LD_CPLXF);
+	  break;
+	case FFI_TYPE_DOUBLE:
+	  flags = ALPHA_FLAGS(ALPHA_ST_CPLXD, ALPHA_LD_CPLXD);
+	  break;
+	default:
+	  if (rtype->size <= 8)
+	    flags = ALPHA_FLAGS(ALPHA_ST_INT, ALPHA_LD_INT64);
+	  else
+	    flags = ALPHA_RET_IN_MEM;
+	  break;
+	}
+      break;
     default:
       abort();
     }
   cif->flags = flags;
-  
+
+  /* Include the hidden structure pointer in args requirement.  */
+  if (flags == ALPHA_RET_IN_MEM)
+    bytes += 8;
+  /* Minimum size is 6 slots, so that ffi_call_osf can pop them.  */
+  if (bytes < 6*8)
+    bytes = 6*8;
+  cif->bytes = bytes;
+
   return FFI_OK;
 }
 
+static unsigned long
+extend_basic_type(void *valp, int type, int argn)
+{
+  switch (type)
+    {
+    case FFI_TYPE_SINT8:
+      return *(SINT8 *)valp;
+    case FFI_TYPE_UINT8:
+      return *(UINT8 *)valp;
+    case FFI_TYPE_SINT16:
+      return *(SINT16 *)valp;
+    case FFI_TYPE_UINT16:
+      return *(UINT16 *)valp;
+
+    case FFI_TYPE_FLOAT:
+      if (argn < 6)
+	return lds(valp);
+      /* FALLTHRU */
+
+    case FFI_TYPE_INT:
+    case FFI_TYPE_SINT32:
+    case FFI_TYPE_UINT32:
+      /* Note that unsigned 32-bit quantities are sign extended.  */
+      return *(SINT32 *)valp;
+
+    case FFI_TYPE_SINT64:
+    case FFI_TYPE_UINT64:
+    case FFI_TYPE_POINTER:
+    case FFI_TYPE_DOUBLE:
+      return *(UINT64 *)valp;
+
+    default:
+      abort();
+    }
+}
 
 void
 ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
 {
-  unsigned long *stack, *argp;
-  long i, avn, flags = cif->flags;
+  unsigned long *argp;
+  long i, avn, argn, flags = cif->flags;
   ffi_type **arg_types;
-  
+
   /* If the return value is a struct and we don't have a return
      value address then we need to make one.  */
   if (rvalue == NULL && flags == ALPHA_RET_IN_MEM)
@@ -132,12 +236,12 @@ ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
 
   /* Allocate the space for the arguments, plus 4 words of temp
      space for ffi_call_osf.  */
-  argp = stack = alloca(cif->bytes + 4*FFI_SIZEOF_ARG);
+  argp = alloca(cif->bytes + 4*FFI_SIZEOF_ARG);
 
+  argn = 0;
   if (flags == ALPHA_RET_IN_MEM)
-    *argp++ = (unsigned long)rvalue;
+    argp[argn++] = (unsigned long)rvalue;
 
-  i = 0;
   avn = cif->nargs;
   arg_types = cif->arg_types;
 
@@ -145,67 +249,59 @@ ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
     {
       ffi_type *ty = arg_types[i];
       void *valp = avalue[i];
-      unsigned long val;
+      int type = ty->type;
       size_t size;
 
-      switch (ty->type)
+      switch (type)
 	{
+	case FFI_TYPE_INT:
 	case FFI_TYPE_SINT8:
-	  val = *(SINT8 *)valp;
-	  break;
-		  
 	case FFI_TYPE_UINT8:
-	  val = *(UINT8 *)valp;
-	  break;
-		  
 	case FFI_TYPE_SINT16:
-	  val = *(SINT16 *)valp;
-	  break;
-		  
 	case FFI_TYPE_UINT16:
-	  val = *(UINT16 *)valp;
-	  break;
-		  
 	case FFI_TYPE_SINT32:
 	case FFI_TYPE_UINT32:
-	  /* Note that unsigned 32-bit quantities are sign extended.  */
-	  val = *(SINT32 *)valp;
-	  break;
-
 	case FFI_TYPE_SINT64:
 	case FFI_TYPE_UINT64:
 	case FFI_TYPE_POINTER:
+	case FFI_TYPE_FLOAT:
 	case FFI_TYPE_DOUBLE:
-	  val = *(UINT64 *)valp;
+	  argp[argn] = extend_basic_type(valp, type, argn);
+	  argn++;
 	  break;
 
 	case FFI_TYPE_LONGDOUBLE:
+	by_reference:
 	  /* Note that 128-bit long double is passed by reference.  */
-	  val = (unsigned long)valp;
-	  break;
-
-	case FFI_TYPE_FLOAT:
-	  if (argp - stack < 6)
-	    val = lds(valp);
-	  else
-	    val = *(UINT32 *)valp;
+	  argp[argn++] = (unsigned long)valp;
 	  break;
 
+	case FFI_TYPE_VOID:
 	case FFI_TYPE_STRUCT:
 	  size = ty->size;
-	  memcpy(argp, valp, size);
-	  argp += ALIGN(size, FFI_SIZEOF_ARG) / FFI_SIZEOF_ARG;
-	  continue;
+	  memcpy(argp + argn, valp, size);
+	  argn += ALIGN(size, FFI_SIZEOF_ARG) / FFI_SIZEOF_ARG;
+	  break;
+
+	case FFI_TYPE_COMPLEX:
+	  type = ty->elements[0]->type;
+	  if (type == FFI_TYPE_LONGDOUBLE)
+	    goto by_reference;
+
+	  /* Most complex types passed as two separate arguments.  */
+	  size = ty->elements[0]->size;
+	  argp[argn] = extend_basic_type(valp, type, argn);
+	  argp[argn + 1] = extend_basic_type(valp + size, type, argn + 1);
+	  argn += 2;
+	  break;
 
 	default:
 	  abort();
 	}
-
-      *argp++ = val;
     }
 
   flags = (flags >> ALPHA_ST_SHIFT) & 0xff;
-  ffi_call_osf(stack, cif->bytes, flags, rvalue, fn);
+  ffi_call_osf(argp, cif->bytes, flags, rvalue, fn);
 }
 
 
@@ -243,7 +339,6 @@ ffi_prep_closure_loc (ffi_closure* closure,
   return FFI_OK;
 }
 
-
 long FFI_HIDDEN
 ffi_closure_osf_inner(ffi_closure *closure, void *rvalue, unsigned long *argp)
 {
@@ -266,15 +361,18 @@ ffi_closure_osf_inner(ffi_closure *closure, void *rvalue, unsigned long *argp)
     }
 
   arg_types = cif->arg_types;
-  
+
   /* Grab the addresses of the arguments from the stack frame.  */
   for (i = 0, avn = cif->nargs; i < avn; i++)
     {
-      size_t size = arg_types[i]->size;
+      ffi_type *ty = arg_types[i];
+      int type = ty->type;
       void *valp = &argp[argn];
+      size_t size;
 
-      switch (arg_types[i]->type)
+      switch (type)
 	{
+	case FFI_TYPE_INT:
 	case FFI_TYPE_SINT8:
 	case FFI_TYPE_UINT8:
 	case FFI_TYPE_SINT16:
@@ -284,7 +382,13 @@ ffi_closure_osf_inner(ffi_closure *closure, void *rvalue, unsigned long *argp)
 	case FFI_TYPE_SINT64:
 	case FFI_TYPE_UINT64:
 	case FFI_TYPE_POINTER:
+	  argn += 1;
+	  break;
+
+	case FFI_TYPE_VOID:
 	case FFI_TYPE_STRUCT:
+	  size = ty->size;
+	  argn += ALIGN(size, FFI_SIZEOF_ARG) / FFI_SIZEOF_ARG;
 	  break;
 
 	case FFI_TYPE_FLOAT:
@@ -295,17 +399,78 @@ ffi_closure_osf_inner(ffi_closure *closure, void *rvalue, unsigned long *argp)
 	      valp = &argp[argn - 6];
 	      sts(valp, argp[argn - 6]);
 	    }
+	  argn += 1;
 	  break;
 
 	case FFI_TYPE_DOUBLE:
 	  if (argn < 6)
 	    valp = &argp[argn - 6];
+	  argn += 1;
 	  break;
 
 	case FFI_TYPE_LONGDOUBLE:
+	by_reference:
 	  /* 128-bit long double is passed by reference.  */
-	  valp = (long double *) argp[argn];
-	  size = sizeof (long double *);
+	  valp = (void *)argp[argn];
+	  argn += 1;
+	  break;
+
+	case FFI_TYPE_COMPLEX:
+	  type = ty->elements[0]->type;
+	  switch (type)
+	    {
+	    case FFI_TYPE_SINT64:
+	    case FFI_TYPE_UINT64:
+	      /* Passed as separate arguments, but they wind up sequential.  */
+	      break;
+
+	    case FFI_TYPE_INT:
+	    case FFI_TYPE_SINT8:
+	    case FFI_TYPE_UINT8:
+	    case FFI_TYPE_SINT16:
+	    case FFI_TYPE_UINT16:
+	    case FFI_TYPE_SINT32:
+	    case FFI_TYPE_UINT32:
+	      /* Passed as separate arguments.  Disjoint, but there's room
+		 enough in one slot to hold the pair.  */
+	      size = ty->elements[0]->size;
+	      memcpy(valp + size, valp + 8, size);
+	      break;
+
+	    case FFI_TYPE_FLOAT:
+	      /* Passed as separate arguments.  Disjoint, and each piece
+		 may need conversion back to float.  */
+	      if (argn < 6)
+		{
+		  valp = &argp[argn - 6];
+		  sts(valp, argp[argn - 6]);
+		}
+	      if (argn + 1 < 6)
+		sts(valp + 4, argp[argn + 1 - 6]);
+	      else
+		*(UINT32 *)(valp + 4) = argp[argn + 1];
+	      break;
+
+	    case FFI_TYPE_DOUBLE:
+	      /* Passed as separate arguments.  Only disjoint if one part
+		 is in fp regs and the other is on the stack.  */
+	      if (argn < 5)
+		valp = &argp[argn - 6];
+	      else if (argn == 5)
+		{
+		  valp = alloca(16);
+		  ((UINT64 *)valp)[0] = argp[5 - 6];
+		  ((UINT64 *)valp)[1] = argp[6];
+		}
+	      break;
+
+	    case FFI_TYPE_LONGDOUBLE:
+	      goto by_reference;
+
+	    default:
+	      abort();
+	    }
+	  argn += 2;
 	  break;
 
 	default:
@@ -313,7 +478,6 @@ ffi_closure_osf_inner(ffi_closure *closure, void *rvalue, unsigned long *argp)
 	}
 
       avalue[i] = valp;
-      argn += ALIGN(size, FFI_SIZEOF_ARG) / FFI_SIZEOF_ARG;
     }
 
   /* Invoke the closure.  */
diff --git a/src/alpha/ffitarget.h b/src/alpha/ffitarget.h
index af145bc..60f92fd 100644
--- a/src/alpha/ffitarget.h
+++ b/src/alpha/ffitarget.h
@@ -44,6 +44,9 @@ typedef enum ffi_abi {
 } ffi_abi;
 #endif
 
+#define FFI_TARGET_SPECIFIC_STACK_SPACE_ALLOCATION
+#define FFI_TARGET_HAS_COMPLEX_TYPE
+
 /* ---- Definitions for closures ----------------------------------------- */
 
 #define FFI_CLOSURES 1
diff --git a/src/alpha/internal.h b/src/alpha/internal.h
index 664a2a6..44da192 100644
--- a/src/alpha/internal.h
+++ b/src/alpha/internal.h
@@ -2,6 +2,8 @@
 #define ALPHA_ST_INT	1
 #define ALPHA_ST_FLOAT	2
 #define ALPHA_ST_DOUBLE	3
+#define ALPHA_ST_CPLXF	4
+#define ALPHA_ST_CPLXD	5
 
 #define ALPHA_LD_VOID	0
 #define ALPHA_LD_INT64	1
@@ -12,6 +14,8 @@
 #define ALPHA_LD_SINT8	6
 #define ALPHA_LD_FLOAT	7
 #define ALPHA_LD_DOUBLE	8
+#define ALPHA_LD_CPLXF	9
+#define ALPHA_LD_CPLXD	10
 
 #define ALPHA_ST_SHIFT		0
 #define ALPHA_LD_SHIFT		8
diff --git a/src/alpha/osf.S b/src/alpha/osf.S
index fb9c595..4059f82 100644
--- a/src/alpha/osf.S
+++ b/src/alpha/osf.S
@@ -117,6 +117,14 @@ E ALPHA_ST_FLOAT
 E ALPHA_ST_DOUBLE
 	stt	$f0, 0($2)
 	ret
+E ALPHA_ST_CPLXF
+	sts	$f0, 0($2)
+	sts	$f1, 4($2)
+	ret
+E ALPHA_ST_CPLXD
+	stt	$f0, 0($2)
+	stt	$f1, 8($2)
+	ret
 
 	cfi_endproc
 	.end	ffi_call_osf
@@ -228,6 +236,16 @@ E ALPHA_LD_DOUBLE
 	ldt	$f0, 16($sp)
 	epilogue
 
+E ALPHA_LD_CPLXF
+	lds	$f0, 16($sp)
+	lds	$f1, 20($sp)
+	epilogue
+
+E ALPHA_LD_CPLXD
+	ldt	$f0, 16($sp)
+	ldt	$f1, 24($sp)
+	epilogue
+
 	cfi_endproc
 	.end	ffi_closure_osf
 
diff --git a/testsuite/libffi.call/call.exp b/testsuite/libffi.call/call.exp
index 5177f07..09f6965 100644
--- a/testsuite/libffi.call/call.exp
+++ b/testsuite/libffi.call/call.exp
@@ -24,16 +24,12 @@ set ctlist [lsearch -inline -all -glob [lsort [glob -nocomplain -- $srcdir/$subd
 
 run-many-tests $tlist ""
 
-if { ![istarget s390*] } {
-
+if { [istarget s390*] || [istarget alpha*] } {
+    run-many-tests $ctlist ""
+} else {
     foreach test $ctlist {
 	unsupported "$test"
     }
-
-} else {
-
-  run-many-tests $ctlist ""
-
 }
 
 dg-finish
diff --git a/testsuite/libffi.call/cls_complex_va_float.c b/testsuite/libffi.call/cls_complex_va_float.c
index 0b79979..2b17826 100644
--- a/testsuite/libffi.call/cls_complex_va_float.c
+++ b/testsuite/libffi.call/cls_complex_va_float.c
@@ -6,5 +6,11 @@
 
 /* { dg-do run } */
 
+/* Alpha splits _Complex into two arguments.  It's illegal to pass
+   float through varargs, so _Complex float goes badly.  In sort of
+   gets passed as _Complex double, but the compiler doesn't agree
+   with itself on this issue.  */
+/* { dg-do run { xfail alpha*-*-* } } */
+
 #include "complex_defs_float.inc"
 #include "cls_complex_va.inc"
-- 
1.9.3

^ permalink raw reply	[flat|nested] 5+ messages in thread

* [PATCH 1/4] alpha: Reorganize cif flags
  2014-10-30  3:54 [PATCH 0/4] Go closures for alpha Richard Henderson
  2014-10-30  3:54 ` [PATCH 3/4] alpha: Add support for complex types Richard Henderson
  2014-10-30  3:54 ` [PATCH 4/4] alpha: Add support for Go closures Richard Henderson
@ 2014-10-30  3:54 ` Richard Henderson
  2014-10-30  3:54 ` [PATCH 2/4] alpha: Clean up conversion of float values Richard Henderson
  3 siblings, 0 replies; 5+ messages in thread
From: Richard Henderson @ 2014-10-30  3:54 UTC (permalink / raw)
  To: libffi-discuss

Unties the backend from changes to FFI_TYPE_* constants, and allows
compilation to succeed after the addition of FFI_TYPE_COMPLEX.

Delete the hand-written unwind info.
---
 src/alpha/ffi.c      |  63 +++++++---
 src/alpha/internal.h |  19 +++
 src/alpha/osf.S      | 341 ++++++++++++++-------------------------------------
 3 files changed, 160 insertions(+), 263 deletions(-)
 create mode 100644 src/alpha/internal.h

diff --git a/src/alpha/ffi.c b/src/alpha/ffi.c
index 192f691..519bd2c 100644
--- a/src/alpha/ffi.c
+++ b/src/alpha/ffi.c
@@ -28,6 +28,7 @@
 #include <ffi.h>
 #include <ffi_common.h>
 #include <stdlib.h>
+#include "internal.h"
 
 /* Force FFI_TYPE_LONGDOUBLE to be different than FFI_TYPE_DOUBLE;
    all further uses in this file will refer to the 128-bit type.  */
@@ -48,6 +49,8 @@ extern void ffi_closure_osf(void) FFI_HIDDEN;
 ffi_status
 ffi_prep_cif_machdep(ffi_cif *cif)
 {
+  int flags;
+
   /* Adjust cif->bytes to represent a minimum 6 words for the temporary
      register argument loading area.  */
   if (cif->bytes < 6*FFI_SIZEOF_ARG)
@@ -56,21 +59,46 @@ ffi_prep_cif_machdep(ffi_cif *cif)
   /* Set the return type flag */
   switch (cif->rtype->type)
     {
-    case FFI_TYPE_STRUCT:
+    case FFI_TYPE_VOID:
+      flags = ALPHA_FLAGS(ALPHA_ST_VOID, ALPHA_LD_VOID);
+      break;
+    case FFI_TYPE_INT:
+    case FFI_TYPE_UINT32:
+    case FFI_TYPE_SINT32:
+      flags = ALPHA_FLAGS(ALPHA_ST_INT, ALPHA_LD_INT32);
+      break;
     case FFI_TYPE_FLOAT:
+      flags = ALPHA_FLAGS(ALPHA_ST_FLOAT, ALPHA_LD_FLOAT);
+      break;
     case FFI_TYPE_DOUBLE:
-      cif->flags = cif->rtype->type;
+      flags = ALPHA_FLAGS(ALPHA_ST_DOUBLE, ALPHA_LD_DOUBLE);
+      break;
+    case FFI_TYPE_UINT8:
+      flags = ALPHA_FLAGS(ALPHA_ST_INT, ALPHA_LD_UINT8);
+      break;
+    case FFI_TYPE_SINT8:
+      flags = ALPHA_FLAGS(ALPHA_ST_INT, ALPHA_LD_SINT8);
+      break;
+    case FFI_TYPE_UINT16:
+      flags = ALPHA_FLAGS(ALPHA_ST_INT, ALPHA_LD_UINT16);
+      break;
+    case FFI_TYPE_SINT16:
+      flags = ALPHA_FLAGS(ALPHA_ST_INT, ALPHA_LD_SINT16);
+      break;
+    case FFI_TYPE_UINT64:
+    case FFI_TYPE_SINT64:
+    case FFI_TYPE_POINTER:
+      flags = ALPHA_FLAGS(ALPHA_ST_INT, ALPHA_LD_INT64);
       break;
-
     case FFI_TYPE_LONGDOUBLE:
-      /* 128-bit long double is returned in memory, like a struct.  */
-      cif->flags = FFI_TYPE_STRUCT;
+    case FFI_TYPE_STRUCT:
+      /* Passed in memory, with a hidden pointer.  */
+      flags = ALPHA_RET_IN_MEM;
       break;
-
     default:
-      cif->flags = FFI_TYPE_INT;
-      break;
+      abort();
     }
+  cif->flags = flags;
   
   return FFI_OK;
 }
@@ -80,20 +108,20 @@ void
 ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
 {
   unsigned long *stack, *argp;
-  long i, avn;
+  long i, avn, flags = cif->flags;
   ffi_type **arg_types;
   
   /* If the return value is a struct and we don't have a return
      value address then we need to make one.  */
-  if (rvalue == NULL && cif->flags == FFI_TYPE_STRUCT)
+  if (rvalue == NULL && flags == ALPHA_RET_IN_MEM)
     rvalue = alloca(cif->rtype->size);
 
   /* Allocate the space for the arguments, plus 4 words of temp
      space for ffi_call_osf.  */
   argp = stack = alloca(cif->bytes + 4*FFI_SIZEOF_ARG);
 
-  if (cif->flags == FFI_TYPE_STRUCT)
-    *(void **) argp++ = rvalue;
+  if (flags == ALPHA_RET_IN_MEM)
+    *argp++ = (unsigned long)rvalue;
 
   i = 0;
   avn = cif->nargs;
@@ -166,7 +194,8 @@ ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
       i++, arg_types++, avalue++;
     }
 
-  ffi_call_osf(stack, cif->bytes, cif->flags, rvalue, fn);
+  flags = (flags >> ALPHA_ST_SHIFT) & 0xff;
+  ffi_call_osf(stack, cif->bytes, flags, rvalue, fn);
 }
 
 
@@ -211,16 +240,16 @@ ffi_closure_osf_inner(ffi_closure *closure, void *rvalue, unsigned long *argp)
   ffi_cif *cif;
   void **avalue;
   ffi_type **arg_types;
-  long i, avn, argn;
+  long i, avn, argn, flags;
 
   cif = closure->cif;
   avalue = alloca(cif->nargs * sizeof(void *));
-
+  flags = cif->flags;
   argn = 0;
 
   /* Copy the caller's structure return address to that the closure
      returns the data directly to the caller.  */
-  if (cif->flags == FFI_TYPE_STRUCT)
+  if (flags == ALPHA_RET_IN_MEM)
     {
       rvalue = (void *) argp[0];
       argn = 1;
@@ -284,5 +313,5 @@ ffi_closure_osf_inner(ffi_closure *closure, void *rvalue, unsigned long *argp)
   closure->fun (cif, rvalue, avalue, closure->user_data);
 
   /* Tell ffi_closure_osf how to perform return type promotions.  */
-  return cif->rtype->type;
+  return (flags >> ALPHA_LD_SHIFT) & 0xff;
 }
diff --git a/src/alpha/internal.h b/src/alpha/internal.h
new file mode 100644
index 0000000..664a2a6
--- /dev/null
+++ b/src/alpha/internal.h
@@ -0,0 +1,19 @@
+#define ALPHA_ST_VOID	0
+#define ALPHA_ST_INT	1
+#define ALPHA_ST_FLOAT	2
+#define ALPHA_ST_DOUBLE	3
+
+#define ALPHA_LD_VOID	0
+#define ALPHA_LD_INT64	1
+#define ALPHA_LD_INT32	2
+#define ALPHA_LD_UINT16	3
+#define ALPHA_LD_SINT16	4
+#define ALPHA_LD_UINT8	5
+#define ALPHA_LD_SINT8	6
+#define ALPHA_LD_FLOAT	7
+#define ALPHA_LD_DOUBLE	8
+
+#define ALPHA_ST_SHIFT		0
+#define ALPHA_LD_SHIFT		8
+#define ALPHA_RET_IN_MEM	0x10000
+#define ALPHA_FLAGS(S, L)	(((L) << ALPHA_LD_SHIFT) | (S))
diff --git a/src/alpha/osf.S b/src/alpha/osf.S
index 6b9f4df..fb9c595 100644
--- a/src/alpha/osf.S
+++ b/src/alpha/osf.S
@@ -1,7 +1,7 @@
 /* -----------------------------------------------------------------------
-   osf.S - Copyright (c) 1998, 2001, 2007, 2008, 2011 Red Hat
-   
-   Alpha/OSF Foreign Function Interface 
+   osf.S - Copyright (c) 1998, 2001, 2007, 2008, 2011, 2014 Red Hat
+
+   Alpha/OSF Foreign Function Interface
 
    Permission is hereby granted, free of charge, to any person obtaining
    a copy of this software and associated documentation files (the
@@ -24,13 +24,21 @@
    DEALINGS IN THE SOFTWARE.
    ----------------------------------------------------------------------- */
 
-#define LIBFFI_ASM	
+#define LIBFFI_ASM
 #include <fficonfig.h>
 #include <ffi.h>
+#include <ffi_cfi.h>
+#include "internal.h"
 
 	.arch ev6
 	.text
 
+/* Aid in building a direct addressed jump table, 4 insns per entry.  */
+.macro E index
+	.align	4
+	.org	99b + \index * 16
+.endm
+
 /* ffi_call_osf (void *args, unsigned long bytes, unsigned flags,
 		 void *raddr, void (*fnaddr)(void));
 
@@ -38,7 +46,7 @@
    for this function.  This has been allocated by ffi_call.  We also
    deallocate some of the stack that has been alloca'd.  */
 
-	.align	3
+	.align	4
 	.globl	ffi_call_osf
 	.ent	ffi_call_osf
 	FFI_HIDDEN(ffi_call_osf)
@@ -46,15 +54,17 @@
 ffi_call_osf:
 	.frame	$15, 32, $26, 0
 	.mask   0x4008000, -32
-$LFB1:
+	cfi_startproc
 	addq	$16,$17,$1
 	mov	$16, $30
 	stq	$26, 0($1)
 	stq	$15, 8($1)
 	stq	$18, 16($1)
 	mov	$1, $15
-$LCFI1:
 	.prologue 0
+	cfi_def_cfa($15, 32)
+	cfi_rel_offset($26, 0)
+	cfi_rel_offset($15, 8)
 
 	stq	$19, 24($1)
 	mov	$20, $27
@@ -77,71 +87,61 @@ $LCFI1:
 	lda	$30, 48($30)
 
 	jsr	$26, ($27), 0
-	ldgp	$29, 0($26)
-
-	# If the return value pointer is NULL, assume no return value.
-	ldq	$19, 24($15)
-	ldq	$18, 16($15)
+0:
+	ldah	$29, 0($26)		!gpdisp!1
+	ldq	$2, 24($15)
+	lda	$29, 0($29)		!gpdisp!1
+	ldq	$3, 16($15)
+	lda	$1, 99f-0b($26)
 	ldq	$26, 0($15)
-$LCFI2:
-	beq	$19, $noretval
-
-	# Store the return value out in the proper type.
-	cmpeq	$18, FFI_TYPE_INT, $1
-	bne	$1, $retint
-	cmpeq	$18, FFI_TYPE_FLOAT, $2
-	bne	$2, $retfloat
-	cmpeq	$18, FFI_TYPE_DOUBLE, $3
-	bne	$3, $retdouble
-
-	.align	3
-$noretval:
 	ldq	$15, 8($15)
-	ret
+	cfi_restore($26)
+	cfi_restore($15)
+	cfi_def_cfa($sp, 0)
+	cmoveq	$2, ALPHA_ST_VOID, $3	# mash null return to void
+	addq	$3, $3, $3
+	s8addq	$3, $1, $1		# 99f + stcode * 16
+	jmp	$31, ($1), $st_int
 
 	.align	4
-$retint:
-	stq	$0, 0($19)
-	nop
-	ldq	$15, 8($15)
+99:
+E ALPHA_ST_VOID
 	ret
-
-	.align	4
-$retfloat:
-	sts	$f0, 0($19)
-	nop
-	ldq	$15, 8($15)
+E ALPHA_ST_INT
+$st_int:
+	stq	$0, 0($2)
 	ret
-
-	.align	4
-$retdouble:
-	stt	$f0, 0($19)
-	nop
-	ldq	$15, 8($15)
+E ALPHA_ST_FLOAT
+	sts	$f0, 0($2)
+	ret
+E ALPHA_ST_DOUBLE
+	stt	$f0, 0($2)
 	ret
-$LFE1:
 
+	cfi_endproc
 	.end	ffi_call_osf
 
 /* ffi_closure_osf(...)
 
    Receives the closure argument in $1.   */
 
-	.align	3
+#define CLOSURE_FS	(16*8)
+
+	.align	4
 	.globl	ffi_closure_osf
 	.ent	ffi_closure_osf
 	FFI_HIDDEN(ffi_closure_osf)
 
 ffi_closure_osf:
-	.frame	$30, 16*8, $26, 0
-	.mask	0x4000000, -16*8
-$LFB2:
+	.frame	$30, CLOSURE_FS, $26, 0
+	.mask	0x4000000, -CLOSURE_FS
+	cfi_startproc
 	ldgp	$29, 0($27)
-	subq	$30, 16*8, $30
-$LCFI5:
+	subq	$30, CLOSURE_FS, $30
+	cfi_adjust_cfa_offset(CLOSURE_FS)
 	stq	$26, 0($30)
-$LCFI6:
 	.prologue 1
+	cfi_rel_offset($26, 0)
 
 	# Store all of the potential argument registers in va_list format.
 	stt	$f16, 4*8($30)
@@ -162,225 +162,74 @@ $LCFI6:
 	lda	$17, 2*8($30)
 	lda	$18, 10*8($30)
 	jsr	$26, ffi_closure_osf_inner
-	ldgp	$29, 0($26)
+0:
+	ldah	$29, 0($26)			!gpdisp!2
+	lda	$2, 99f-0b($26)
+	s4addq	$0, 0, $1			# ldcode * 4
+	ldq	$0, 16($30)			# preload return value
+	s4addq	$1, $2, $1			# 99f + ldcode * 16
+	lda	$29, 0($29)			!gpdisp!2
 	ldq	$26, 0($30)
-
-	# Load up the return value in the proper type.
-	lda	$1, $load_table
-	s4addq	$0, $1, $1
-	ldl	$1, 0($1)
-	addq	$1, $29, $1
+	cfi_restore($26)
 	jmp	$31, ($1), $load_32
 
-	.align 4
-$load_none:
-	addq	$30, 16*8, $30
+.macro epilogue
+	addq	$30, CLOSURE_FS, $30
+	cfi_adjust_cfa_offset(-CLOSURE_FS)
 	ret
+	.align	4
+	cfi_adjust_cfa_offset(CLOSURE_FS)
+.endm
 
 	.align 4
-$load_float:
-	lds	$f0, 16($30)
-	nop
-	addq	$30, 16*8, $30
-	ret
+99:
+E ALPHA_LD_VOID
+	epilogue
 
-	.align 4
-$load_double:
-	ldt	$f0, 16($30)
-	nop
-	addq	$30, 16*8, $30
-	ret
+E ALPHA_LD_INT64
+	epilogue
 
-	.align 4
-$load_u8:
-#ifdef __alpha_bwx__
-	ldbu	$0, 16($30)
-	nop
-#else
-	ldq	$0, 16($30)
-	and	$0, 255, $0
-#endif
-	addq	$30, 16*8, $30
-	ret
-
-	.align 4
-$load_s8:
-#ifdef __alpha_bwx__
-	ldbu	$0, 16($30)
-	sextb	$0, $0
-#else
-	ldq	$0, 16($30)
-	sll	$0, 56, $0
-	sra	$0, 56, $0
-#endif
-	addq	$30, 16*8, $30
-	ret
+E ALPHA_LD_INT32
+$load_32:
+	sextl	$0, $0
+	epilogue
 
-	.align 4
-$load_u16:
-#ifdef __alpha_bwx__
-	ldwu	$0, 16($30)
-	nop
-#else
-	ldq	$0, 16($30)
+E ALPHA_LD_UINT16
 	zapnot	$0, 3, $0
-#endif
-	addq	$30, 16*8, $30
-	ret
+	epilogue
 
-	.align 4
-$load_s16:
+E ALPHA_LD_SINT16
 #ifdef __alpha_bwx__
-	ldwu	$0, 16($30)
 	sextw	$0, $0
 #else
-	ldq	$0, 16($30)
 	sll	$0, 48, $0
 	sra	$0, 48, $0
 #endif
-	addq	$30, 16*8, $30
-	ret
+	epilogue
 
-	.align 4
-$load_32:
-	ldl	$0, 16($30)
-	nop
-	addq	$30, 16*8, $30
-	ret
+E ALPHA_LD_UINT8
+	and	$0, 0xff, $0
+	epilogue
 
-	.align 4
-$load_64:
-	ldq	$0, 16($30)
-	nop
-	addq	$30, 16*8, $30
-	ret
-$LFE2:
-
-	.end	ffi_closure_osf
-
-#ifdef __ELF__
-.section .rodata
+E ALPHA_LD_SINT8
+#ifdef __alpha_bwx__
+	sextb	$0, $0
 #else
-.rdata
-#endif
-$load_table:
-	.gprel32 $load_none	# FFI_TYPE_VOID
-	.gprel32 $load_32	# FFI_TYPE_INT
-	.gprel32 $load_float	# FFI_TYPE_FLOAT
-	.gprel32 $load_double	# FFI_TYPE_DOUBLE
-	.gprel32 $load_none	# FFI_TYPE_LONGDOUBLE
-	.gprel32 $load_u8	# FFI_TYPE_UINT8
-	.gprel32 $load_s8	# FFI_TYPE_SINT8
-	.gprel32 $load_u16	# FFI_TYPE_UINT16
-	.gprel32 $load_s16	# FFI_TYPE_SINT16
-	.gprel32 $load_32	# FFI_TYPE_UINT32
-	.gprel32 $load_32	# FFI_TYPE_SINT32
-	.gprel32 $load_64	# FFI_TYPE_UINT64
-	.gprel32 $load_64	# FFI_TYPE_SINT64
-	.gprel32 $load_none	# FFI_TYPE_STRUCT
-	.gprel32 $load_64	# FFI_TYPE_POINTER
-
-/* Assert that the table above is in sync with ffi.h.  */
-
-#if	   FFI_TYPE_FLOAT != 2		\
-	|| FFI_TYPE_DOUBLE != 3		\
-	|| FFI_TYPE_UINT8 != 5		\
-	|| FFI_TYPE_SINT8 != 6		\
-	|| FFI_TYPE_UINT16 != 7		\
-	|| FFI_TYPE_SINT16 != 8		\
-	|| FFI_TYPE_UINT32 != 9		\
-	|| FFI_TYPE_SINT32 != 10	\
-	|| FFI_TYPE_UINT64 != 11	\
-	|| FFI_TYPE_SINT64 != 12	\
-	|| FFI_TYPE_STRUCT != 13	\
-	|| FFI_TYPE_POINTER != 14	\
-	|| FFI_TYPE_LAST != 14
-#error "osf.S out of sync with ffi.h"
+	sll	$0, 56, $0
+	sra	$0, 56, $0
 #endif
+	epilogue
 
-#ifdef __ELF__
-# define UA_SI		.4byte
-# define FDE_ENCODING	0x1b	/* pcrel sdata4 */
-# define FDE_ENCODE(X)	.4byte X-.
-# define FDE_ARANGE(X)	.4byte X
-#elif defined __osf__
-# define UA_SI		.align 0; .long
-# define FDE_ENCODING	0x50	/* aligned absolute */
-# define FDE_ENCODE(X)	.align 3; .quad X
-# define FDE_ARANGE(X)	.align 0; .quad X
-#endif
+E ALPHA_LD_FLOAT
+	lds	$f0, 16($sp)
+	epilogue
 
-#ifdef __ELF__
-	.section	.eh_frame,EH_FRAME_FLAGS,@progbits
-#elif defined __osf__
-	.data
-	.align 3
-	.globl _GLOBAL__F_ffi_call_osf
-_GLOBAL__F_ffi_call_osf:
-#endif
-__FRAME_BEGIN__:
-	UA_SI	$LECIE1-$LSCIE1	# Length of Common Information Entry
-$LSCIE1:
-	UA_SI	0x0		# CIE Identifier Tag
-	.byte	0x1		# CIE Version
-	.ascii "zR\0"		# CIE Augmentation
-	.byte	0x1		# uleb128 0x1; CIE Code Alignment Factor
-	.byte	0x78		# sleb128 -8; CIE Data Alignment Factor
-	.byte	26		# CIE RA Column
-	.byte	0x1		# uleb128 0x1; Augmentation size
-	.byte	FDE_ENCODING	# FDE Encoding
-	.byte	0xc		# DW_CFA_def_cfa
-	.byte	30		# uleb128 column 30
-	.byte	0		# uleb128 offset 0
-	.align 3
-$LECIE1:
-$LSFDE1:
-	UA_SI	$LEFDE1-$LASFDE1		# FDE Length
-$LASFDE1:
-	UA_SI	$LASFDE1-__FRAME_BEGIN__	# FDE CIE offset
-	FDE_ENCODE($LFB1)			# FDE initial location
-	FDE_ARANGE($LFE1-$LFB1)			# FDE address range
-	.byte	0x0		# uleb128 0x0; Augmentation size
-
-	.byte	0x4		# DW_CFA_advance_loc4
-	UA_SI	$LCFI1-$LFB1
-	.byte	0x9a		# DW_CFA_offset, column 26
-	.byte	4		# uleb128 4*-8
-	.byte	0x8f		# DW_CFA_offset, column 15
-	.byte	0x3		# uleb128 3*-8
-	.byte	0xc		# DW_CFA_def_cfa
-	.byte	15		# uleb128 column 15
-	.byte	32		# uleb128 offset 32
-
-	.byte	0x4		# DW_CFA_advance_loc4
-	UA_SI	$LCFI2-$LCFI1
-	.byte	0xda		# DW_CFA_restore, column 26
-	.align 3
-$LEFDE1:
-
-$LSFDE3:
-	UA_SI	$LEFDE3-$LASFDE3		# FDE Length
-$LASFDE3:
-	UA_SI	$LASFDE3-__FRAME_BEGIN__	# FDE CIE offset
-	FDE_ENCODE($LFB2)			# FDE initial location
-	FDE_ARANGE($LFE2-$LFB2)			# FDE address range
-	.byte	0x0		# uleb128 0x0; Augmentation size
-
-	.byte	0x4		# DW_CFA_advance_loc4
-	UA_SI	$LCFI5-$LFB2
-	.byte	0xe		# DW_CFA_def_cfa_offset
-	.byte	0x80,0x1	# uleb128 128
-
-	.byte	0x4		# DW_CFA_advance_loc4
-	UA_SI	$LCFI6-$LCFI5
-	.byte	0x9a		# DW_CFA_offset, column 26
-	.byte	16		# uleb128 offset 16*-8
-	.align 3
-$LEFDE3:
-#if defined __osf__
-	.align 0
-	.long	0		# End of Table
-#endif
+E ALPHA_LD_DOUBLE
+	ldt	$f0, 16($sp)
+	epilogue
+
+	cfi_endproc
+	.end	ffi_closure_osf
 
 #if defined __ELF__ && defined __linux__
 	.section	.note.GNU-stack,"",@progbits
-- 
1.9.3

^ permalink raw reply	[flat|nested] 5+ messages in thread

* [PATCH 4/4] alpha: Add support for Go closures
  2014-10-30  3:54 [PATCH 0/4] Go closures for alpha Richard Henderson
  2014-10-30  3:54 ` [PATCH 3/4] alpha: Add support for complex types Richard Henderson
@ 2014-10-30  3:54 ` Richard Henderson
  2014-10-30  3:54 ` [PATCH 1/4] alpha: Reorganize cif flags Richard Henderson
  2014-10-30  3:54 ` [PATCH 2/4] alpha: Clean up conversion of float values Richard Henderson
  3 siblings, 0 replies; 5+ messages in thread
From: Richard Henderson @ 2014-10-30  3:54 UTC (permalink / raw)
  To: libffi-discuss

---
 src/alpha/ffi.c       | 53 ++++++++++++++++++++++++++-------
 src/alpha/ffitarget.h |  1 +
 src/alpha/osf.S       | 82 ++++++++++++++++++++++++++++++++++-----------------
 3 files changed, 99 insertions(+), 37 deletions(-)

diff --git a/src/alpha/ffi.c b/src/alpha/ffi.c
index 1e5187e..efae4cc 100644
--- a/src/alpha/ffi.c
+++ b/src/alpha/ffi.c
@@ -41,9 +41,11 @@
 # define FFI_TYPE_LONGDOUBLE 4
 #endif
 
-extern void ffi_call_osf(void *, unsigned long, unsigned, void *, void (*)(void))
-  FFI_HIDDEN;
+extern void ffi_call_osf(void *stack, void *frame, unsigned flags,
+			 void *raddr, void (*fn)(void), void *closure)
+	FFI_HIDDEN;
 extern void ffi_closure_osf(void) FFI_HIDDEN;
+extern void ffi_go_closure_osf(void) FFI_HIDDEN;
 
 /* Promote a float value to its in-register double representation.
    Unlike actually casting to double, this does not trap on NaN.  */
@@ -222,12 +224,14 @@ extend_basic_type(void *valp, int type, int argn)
     }
 }
 
-void
-ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
+static void
+ffi_call_int (ffi_cif *cif, void (*fn)(void), void *rvalue,
+	      void **avalue, void *closure)
 {
   unsigned long *argp;
   long i, avn, argn, flags = cif->flags;
   ffi_type **arg_types;
+  void *frame;
 
   /* If the return value is a struct and we don't have a return
      value address then we need to make one.  */
@@ -236,7 +240,8 @@ ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
 
   /* Allocate the space for the arguments, plus 4 words of temp
      space for ffi_call_osf.  */
-  argp = alloca(cif->bytes + 4*FFI_SIZEOF_ARG);
+  argp = frame = alloca(cif->bytes + 4*FFI_SIZEOF_ARG);
+  frame += cif->bytes;
 
   argn = 0;
   if (flags == ALPHA_RET_IN_MEM)
@@ -301,9 +306,21 @@ ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
     }
 
   flags = (flags >> ALPHA_ST_SHIFT) & 0xff;
-  ffi_call_osf(argp, cif->bytes, flags, rvalue, fn);
+  ffi_call_osf(argp, frame, flags, rvalue, fn, closure);
+}
+
+void
+ffi_call (ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
+{
+  ffi_call_int(cif, fn, rvalue, avalue, NULL);
 }
 
+void
+ffi_call_go (ffi_cif *cif, void (*fn)(void), void *rvalue,
+	     void **avalue, void *closure)
+{
+  ffi_call_int(cif, fn, rvalue, avalue, closure);
+}
 
 ffi_status
 ffi_prep_closure_loc (ffi_closure* closure,
@@ -339,15 +356,31 @@ ffi_prep_closure_loc (ffi_closure* closure,
   return FFI_OK;
 }
 
+ffi_status
+ffi_prep_go_closure (ffi_go_closure* closure,
+		     ffi_cif* cif,
+		     void (*fun)(ffi_cif*, void*, void**, void*))
+{
+  if (cif->abi != FFI_OSF)
+    return FFI_BAD_ABI;
+
+  closure->tramp = (void *)ffi_go_closure_osf;
+  closure->cif = cif;
+  closure->fun = fun;
+
+  return FFI_OK;
+}
+
 long FFI_HIDDEN
-ffi_closure_osf_inner(ffi_closure *closure, void *rvalue, unsigned long *argp)
+ffi_closure_osf_inner (ffi_cif *cif,
+		       void (*fun)(ffi_cif*, void*, void**, void*),
+		       void *user_data,
+		       void *rvalue, unsigned long *argp)
 {
-  ffi_cif *cif;
   void **avalue;
   ffi_type **arg_types;
   long i, avn, argn, flags;
 
-  cif = closure->cif;
   avalue = alloca(cif->nargs * sizeof(void *));
   flags = cif->flags;
   argn = 0;
@@ -481,7 +514,7 @@ ffi_closure_osf_inner(ffi_closure *closure, void *rvalue, unsigned long *argp)
     }
 
   /* Invoke the closure.  */
-  closure->fun (cif, rvalue, avalue, closure->user_data);
+  fun (cif, rvalue, avalue, user_data);
 
   /* Tell ffi_closure_osf how to perform return type promotions.  */
   return (flags >> ALPHA_LD_SHIFT) & 0xff;
diff --git a/src/alpha/ffitarget.h b/src/alpha/ffitarget.h
index 60f92fd..a02dbd0 100644
--- a/src/alpha/ffitarget.h
+++ b/src/alpha/ffitarget.h
@@ -50,6 +50,7 @@ typedef enum ffi_abi {
 /* ---- Definitions for closures ----------------------------------------- */
 
 #define FFI_CLOSURES 1
+#define FFI_GO_CLOSURES 1
 #define FFI_TRAMPOLINE_SIZE 24
 #define FFI_NATIVE_RAW_API 0
 
diff --git a/src/alpha/osf.S b/src/alpha/osf.S
index 4059f82..b031828 100644
--- a/src/alpha/osf.S
+++ b/src/alpha/osf.S
@@ -39,10 +39,10 @@
 	.org	99b + \index * 16
 .endm
 
-/* ffi_call_osf (void *args, unsigned long bytes, unsigned flags,
-		 void *raddr, void (*fnaddr)(void));
+/* ffi_call_osf (void *stack, void *frame, unsigned flags,
+		 void *raddr, void (*fnaddr)(void), void *closure)
 
-   Bit o trickiness here -- ARGS+BYTES is the base of the stack frame
+   Bit o trickiness here -- FRAME is the base of the stack frame
    for this function.  This has been allocated by ffi_call.  We also
    deallocate some of the stack that has been alloca'd.  */
 
@@ -52,22 +52,21 @@
 	FFI_HIDDEN(ffi_call_osf)
 
 ffi_call_osf:
-	.frame	$15, 32, $26, 0
-	.mask   0x4008000, -32
 	cfi_startproc
-	addq	$16,$17,$1
+	cfi_def_cfa($17, 32)
 	mov	$16, $30
-	stq	$26, 0($1)
-	stq	$15, 8($1)
-	stq	$18, 16($1)
-	mov	$1, $15
+	stq	$26, 0($17)
+	stq	$15, 8($17)
+	mov	$17, $15
 	.prologue 0
-	cfi_def_cfa($15, 32)
+	cfi_def_cfa_register($15)
 	cfi_rel_offset($26, 0)
 	cfi_rel_offset($15, 8)
 
-	stq	$19, 24($1)
-	mov	$20, $27
+	stq	$18, 16($17)		# save flags into frame
+	stq	$19, 24($17)		# save rvalue into frame
+	mov	$20, $27		# fn into place for call
+	mov	$21, $1			# closure into static chain
 
 	# Load up all of the (potential) argument registers.
 	ldq	$16, 0($30)
@@ -89,16 +88,16 @@ ffi_call_osf:
 	jsr	$26, ($27), 0
 0:
 	ldah	$29, 0($26)		!gpdisp!1
-	ldq	$2, 24($15)
+	ldq	$2, 24($15)		# reload rvalue
 	lda	$29, 0($29)		!gpdisp!1
-	ldq	$3, 16($15)
+	ldq	$3, 16($15)		# reload flags
 	lda	$1, 99f-0b($26)
 	ldq	$26, 0($15)
 	ldq	$15, 8($15)
 	cfi_restore($26)
 	cfi_restore($15)
 	cfi_def_cfa($sp, 0)
-	cmoveq	$2, ALPHA_ST_VOID, $3	# mash null return to void
+	cmoveq	$2, ALPHA_ST_VOID, $3	# mash null rvalue to void
 	addq	$3, $3, $3
 	s8addq	$3, $1, $1		# 99f + stcode * 16
 	jmp	$31, ($1), $st_int
@@ -136,13 +135,37 @@ E ALPHA_ST_CPLXD
 #define CLOSURE_FS	(16*8)
 
 	.align	4
+	.globl	ffi_go_closure_osf
+	.ent	ffi_go_closure_osf
+	FFI_HIDDEN(ffi_go_closure_osf)
+
+ffi_go_closure_osf:
+	cfi_startproc
+	ldgp	$29, 0($27)
+	subq	$30, CLOSURE_FS, $30
+	cfi_adjust_cfa_offset(CLOSURE_FS)
+	stq	$26, 0($30)
+	.prologue 1
+	cfi_rel_offset($26, 0)
+
+	stq	$16, 10*8($30)
+	stq	$17, 11*8($30)
+	stq	$18, 12*8($30)
+
+	ldq	$16, 8($1)			# load cif
+	ldq	$17, 16($1)			# load fun
+	mov	$1, $18				# closure is user_data
+	br	$do_closure
+
+	cfi_endproc
+	.end	ffi_go_closure_osf
+
+	.align	4
 	.globl	ffi_closure_osf
 	.ent	ffi_closure_osf
 	FFI_HIDDEN(ffi_closure_osf)
 
 ffi_closure_osf:
-	.frame	$30, CLOSURE_FS, $26, 0
-	.mask	0x4000000, -CLOSURE_FS
 	cfi_startproc
 	ldgp	$29, 0($27)
 	subq	$30, CLOSURE_FS, $30
@@ -152,23 +175,28 @@ ffi_closure_osf:
 	cfi_rel_offset($26, 0)
 
 	# Store all of the potential argument registers in va_list format.
-	stt	$f16, 4*8($30)
-	stt	$f17, 5*8($30)
-	stt	$f18, 6*8($30)
-	stt	$f19, 7*8($30)
-	stt	$f20, 8*8($30)
-	stt	$f21, 9*8($30)
 	stq	$16, 10*8($30)
 	stq	$17, 11*8($30)
 	stq	$18, 12*8($30)
+
+	ldq	$16, 24($1)			# load cif
+	ldq	$17, 32($1)			# load fun
+	ldq	$18, 40($1)			# load user_data
+
+$do_closure:
 	stq	$19, 13*8($30)
 	stq	$20, 14*8($30)
 	stq	$21, 15*8($30)
+	stt	$f16, 4*8($30)
+	stt	$f17, 5*8($30)
+	stt	$f18, 6*8($30)
+	stt	$f19, 7*8($30)
+	stt	$f20, 8*8($30)
+	stt	$f21, 9*8($30)
 
 	# Call ffi_closure_osf_inner to do the bulk of the work.
-	mov	$1, $16
-	lda	$17, 2*8($30)
-	lda	$18, 10*8($30)
+	lda	$19, 2*8($30)
+	lda	$20, 10*8($30)
 	jsr	$26, ffi_closure_osf_inner
 0:
 	ldah	$29, 0($26)			!gpdisp!2
-- 
1.9.3

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2014-10-30  3:54 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-10-30  3:54 [PATCH 0/4] Go closures for alpha Richard Henderson
2014-10-30  3:54 ` [PATCH 3/4] alpha: Add support for complex types Richard Henderson
2014-10-30  3:54 ` [PATCH 4/4] alpha: Add support for Go closures Richard Henderson
2014-10-30  3:54 ` [PATCH 1/4] alpha: Reorganize cif flags Richard Henderson
2014-10-30  3:54 ` [PATCH 2/4] alpha: Clean up conversion of float values Richard Henderson

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).