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: