On Fri, Mar 1, 2013 at 7:26 PM, Ian Lance Taylor <i...@google.com> wrote:

> Right now the reflect.Call implementation is passing Go complex64 and
> complex128 types as though they were implemented as struct { float32;
> float32 } and struct { float64; float64 } respectively.  The code
> assumes that a function that takes a complex64 argument can be called
> as though it took a struct argument instead.  Apparently that does not
> work on Alpha.  So the case that fails is when the calling convention
> for a complex number differs from the calling convention for passing a
> struct.
>
> In the Alpha calling convention, how is a complex number passed?  How
> is a struct of two floats/doubles passed?

Looking at the following testcase, they are passed in integer
registers, and returned in memory.

--cut here--
typedef struct
{
  float re, im;
} cfloat_t;

cfloat_t testf (cfloat_t a, cfloat_t b)
{
  cfloat_t r;

  r.re = a.re + b.re;
  r.im = a.im + b.im;
  return r;
}

_Complex float _testf (_Complex float a, _Complex float b)
{
  return a + b;
}
--cut here--

testf:
        .frame $30,16,$26,0
        lda $30,-16($30)
        .prologue 0
        mov $16,$0
        stq $17,0($30)
        stq $18,8($30)
        lds $f10,12($30)
        lds $f11,4($30)
        lds $f12,0($30)
        bis $31,$31,$31
        adds $f11,$f10,$f11
        lds $f10,8($30)
        adds $f12,$f10,$f10
        sts $f11,4($16)
        sts $f10,0($16)
        bis $31,$31,$31
        lda $30,16($30)
        ret $31,($26),1

_testf:
        .frame $30,0,$26,0
        .prologue 0
        adds $f17,$f19,$f1
        adds $f16,$f18,$f0
        ret $31,($26),1

[the double assembly is practically the same]

> I think your suggestion of implementing complex as a struct would be
> somewhat painful to implement, because it would require generating
> complicated code for all complex arithmetic.
>
> I'm not strongly opposed to your original patch, I just think it
> overreaches in assuming that only x86 works.  What if we flip it
> around and assume that only Alpha falis?

No problem for me, the attached patch was re-tested with libgo tests
on alphaev68-pc-linux-gnu and x86_64-pc-linux-gnu {,-m32} without
errors.

Uros.
Index: go/testing/quick/quick_test.go
===================================================================
--- go/testing/quick/quick_test.go      (revision 196386)
+++ go/testing/quick/quick_test.go      (working copy)
@@ -7,6 +7,7 @@ package quick
 import (
        "math/rand"
        "reflect"
+       "runtime"
        "testing"
 )
 
@@ -72,8 +73,10 @@ func TestCheckEqual(t *testing.T) {
        reportError("fBool", CheckEqual(fBool, fBool, nil), t)
        reportError("fFloat32", CheckEqual(fFloat32, fFloat32, nil), t)
        reportError("fFloat64", CheckEqual(fFloat64, fFloat64, nil), t)
-       reportError("fComplex64", CheckEqual(fComplex64, fComplex64, nil), t)
-       reportError("fComplex128", CheckEqual(fComplex128, fComplex128, nil), t)
+       if runtime.GOARCH != "alpha" {
+               reportError("fComplex64", CheckEqual(fComplex64, fComplex64, 
nil), t)
+               reportError("fComplex128", CheckEqual(fComplex128, fComplex128, 
nil), t)
+       }
        reportError("fInt16", CheckEqual(fInt16, fInt16, nil), t)
        reportError("fInt32", CheckEqual(fInt32, fInt32, nil), t)
        reportError("fInt64", CheckEqual(fInt64, fInt64, nil), t)
Index: runtime/go-reflect-call.c
===================================================================
--- runtime/go-reflect-call.c   (revision 196386)
+++ runtime/go-reflect-call.c   (working copy)
@@ -30,7 +30,7 @@ static ffi_type *go_struct_to_ffi (const struct __
 static ffi_type *go_string_to_ffi (void) __attribute__ ((no_split_stack));
 static ffi_type *go_interface_to_ffi (void) __attribute__ ((no_split_stack));
 static ffi_type *go_complex_to_ffi (ffi_type *)
-  __attribute__ ((no_split_stack));
+  __attribute__ ((no_split_stack,unused));
 static ffi_type *go_type_to_ffi (const struct __go_type_descriptor *)
   __attribute__ ((no_split_stack));
 static ffi_type *go_func_return_ffi (const struct __go_func_type *)
@@ -185,13 +185,23 @@ go_type_to_ffi (const struct __go_type_descriptor
        return &ffi_type_double;
       abort ();
     case GO_COMPLEX64:
+#ifdef __alpha__
+      runtime_throw("the ABI does not support Complex64 type with "
+                   "reflect.Call or runtime.SetFinalizer");
+#else
       if (sizeof (float) == 4)
        return go_complex_to_ffi (&ffi_type_float);
       abort ();
+#endif
     case GO_COMPLEX128:
+#ifdef __alpha__
+      runtime_throw("the ABI does not support Complex128 type with "
+                   "reflect.Call or runtime.SetFinalizer");
+#else
       if (sizeof (double) == 8)
        return go_complex_to_ffi (&ffi_type_double);
       abort ();
+#endif
     case GO_INT16:
       return &ffi_type_sint16;
     case GO_INT32:

Reply via email to