Re: libgo patch committed: Implement reflect.MakeFunc for amd64

2013-11-12 Thread H.J. Lu
On Fri, Sep 27, 2013 at 10:54 AM, Ian Lance Taylor i...@google.com wrote:
 The Go standard library has an interesting function named
 reflect.MakeFunc.  It takes a Go function F that accepts and returns a
 slice of reflect.Value, and a function type T, and returns a pointer to
 a function of type T that converts its arguments to reflect.Value, calls
 F, and converts the returned reflect.Value into the appropriate return
 types.  In effect this is the reverse of libffi: instead of describing a
 function and calling it, we describe a function and permit it to be
 called.

 For gccgo I tried to implement this generically using the builtin
 varargs functions, but that failed because I had no way to handle the
 return type.  Many Go functions return multiple values, which in gccgo
 is represented as returning a struct, and, of course, in some cases a
 struct is returned by passing a hidden pointer as the first argument,
 and in other cases is handled by splitting up the struct into different
 register classes.  So handling this generically is essentially
 impossible, at least without adding some more builtin functions to
 somehow handle the return value, builtin functions that I couldn't
 figure out how to even represent.

 So I gave up and went for a processor-specific approach.  The idea is
 that processor-specific assembly code will save all the relevant
 registers into a struct, and pass them to processor-specific Go code
 which will implement the calling convention.  This has the advantage
 that I only need to deal with Go types, which in particular means no
 worries about vector types.

 This patch implements this approach for x86_64.  Bootstrapped and ran Go
 testsuite on x86_64-unknown-linux-gnu.  Committed to mainline and 4.8
 branch.


Hi Ian,

TestMakeFunc failed on x32:

FAIL: TestMakeFunc (0.00 seconds)
all_test.go:1457: Call returned 10, 20, 30, [40 0], 60, 70, 80; want 10,
 20, 30, [40, 50], 60, 70, 80

The difference in x32 is x32 puts 2 pointers (32-bit) in one 64-git
register.  Somehow, the second pointer in

type two [2]uintptr

isn't returned properly.. Do you know what I should check for x32?

Thanks.

-- 
H.J.


Re: libgo patch committed: Implement reflect.MakeFunc for amd64

2013-11-12 Thread H.J. Lu
On Tue, Nov 12, 2013 at 1:40 PM, H.J. Lu hjl.to...@gmail.com wrote:
 On Fri, Sep 27, 2013 at 10:54 AM, Ian Lance Taylor i...@google.com wrote:
 The Go standard library has an interesting function named
 reflect.MakeFunc.  It takes a Go function F that accepts and returns a
 slice of reflect.Value, and a function type T, and returns a pointer to
 a function of type T that converts its arguments to reflect.Value, calls
 F, and converts the returned reflect.Value into the appropriate return
 types.  In effect this is the reverse of libffi: instead of describing a
 function and calling it, we describe a function and permit it to be
 called.

 For gccgo I tried to implement this generically using the builtin
 varargs functions, but that failed because I had no way to handle the
 return type.  Many Go functions return multiple values, which in gccgo
 is represented as returning a struct, and, of course, in some cases a
 struct is returned by passing a hidden pointer as the first argument,
 and in other cases is handled by splitting up the struct into different
 register classes.  So handling this generically is essentially
 impossible, at least without adding some more builtin functions to
 somehow handle the return value, builtin functions that I couldn't
 figure out how to even represent.

 So I gave up and went for a processor-specific approach.  The idea is
 that processor-specific assembly code will save all the relevant
 registers into a struct, and pass them to processor-specific Go code
 which will implement the calling convention.  This has the advantage
 that I only need to deal with Go types, which in particular means no
 worries about vector types.

 This patch implements this approach for x86_64.  Bootstrapped and ran Go
 testsuite on x86_64-unknown-linux-gnu.  Committed to mainline and 4.8
 branch.


 Hi Ian,

 TestMakeFunc failed on x32:

 FAIL: TestMakeFunc (0.00 seconds)
 all_test.go:1457: Call returned 10, 20, 30, [40 0], 60, 70, 80; want 10,
  20, 30, [40, 50], 60, 70, 80

 The difference in x32 is x32 puts 2 pointers (32-bit) in one 64-git
 register.  Somehow, the second pointer in

 type two [2]uintptr

 isn't returned properly.. Do you know what I should check for x32?


type two [2]uintptr

is an array.  It should pass and return in memory for x32.

-- 
H.J.


Re: [gofrontend-dev] Re: libgo patch committed: Implement reflect.MakeFunc for amd64

2013-11-12 Thread Ian Lance Taylor
On Tue, Nov 12, 2013 at 1:40 PM, H.J. Lu hjl.to...@gmail.com wrote:

 TestMakeFunc failed on x32:

 FAIL: TestMakeFunc (0.00 seconds)
 all_test.go:1457: Call returned 10, 20, 30, [40 0], 60, 70, 80; want 10,
  20, 30, [40, 50], 60, 70, 80

 The difference in x32 is x32 puts 2 pointers (32-bit) in one 64-git
 register.  Somehow, the second pointer in

 type two [2]uintptr

 isn't returned properly.. Do you know what I should check for x32?

We'll need some code for x32 support in libgo.  Right now there is
none.  For this specific problem we'll need files makefunc_x32.S and
makefuncgo_x32.go.  I don't know how the x32 ABI differs from the
x86_64 ABI, but those changes will need to be reflected there.

Please open a entry for this in bugzilla.

Ian


Re: [gofrontend-dev] Re: libgo patch committed: Implement reflect.MakeFunc for amd64

2013-11-12 Thread H.J. Lu
On Tue, Nov 12, 2013 at 2:23 PM, Ian Lance Taylor i...@google.com wrote:
 On Tue, Nov 12, 2013 at 1:40 PM, H.J. Lu hjl.to...@gmail.com wrote:

 TestMakeFunc failed on x32:

 FAIL: TestMakeFunc (0.00 seconds)
 all_test.go:1457: Call returned 10, 20, 30, [40 0], 60, 70, 80; want 10,
  20, 30, [40, 50], 60, 70, 80

 The difference in x32 is x32 puts 2 pointers (32-bit) in one 64-git
 register.  Somehow, the second pointer in

 type two [2]uintptr

 isn't returned properly.. Do you know what I should check for x32?

 We'll need some code for x32 support in libgo.  Right now there is
 none.  For this specific problem we'll need files makefunc_x32.S and
 makefuncgo_x32.go.  I don't know how the x32 ABI differs from the
 x86_64 ABI, but those changes will need to be reflected there.

X32 info can be found at

https://sites.google.com/site/x32abi/

X32 is very close to x86-64.  The main difference is
pointer and long are 32 bits in x32.

 Please open a entry for this in bugzilla.


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=59095

Thanks.

-- 
H.J.


libgo patch committed: Implement reflect.MakeFunc for amd64

2013-09-27 Thread Ian Lance Taylor
The Go standard library has an interesting function named
reflect.MakeFunc.  It takes a Go function F that accepts and returns a
slice of reflect.Value, and a function type T, and returns a pointer to
a function of type T that converts its arguments to reflect.Value, calls
F, and converts the returned reflect.Value into the appropriate return
types.  In effect this is the reverse of libffi: instead of describing a
function and calling it, we describe a function and permit it to be
called.

For gccgo I tried to implement this generically using the builtin
varargs functions, but that failed because I had no way to handle the
return type.  Many Go functions return multiple values, which in gccgo
is represented as returning a struct, and, of course, in some cases a
struct is returned by passing a hidden pointer as the first argument,
and in other cases is handled by splitting up the struct into different
register classes.  So handling this generically is essentially
impossible, at least without adding some more builtin functions to
somehow handle the return value, builtin functions that I couldn't
figure out how to even represent.

So I gave up and went for a processor-specific approach.  The idea is
that processor-specific assembly code will save all the relevant
registers into a struct, and pass them to processor-specific Go code
which will implement the calling convention.  This has the advantage
that I only need to deal with Go types, which in particular means no
worries about vector types.

This patch implements this approach for x86_64.  Bootstrapped and ran Go
testsuite on x86_64-unknown-linux-gnu.  Committed to mainline and 4.8
branch.

Ian

diff -r 024105249263 libgo/Makefile.am
--- a/libgo/Makefile.am	Tue Sep 24 20:26:38 2013 -0700
+++ b/libgo/Makefile.am	Fri Sep 27 08:06:13 2013 -0700
@@ -895,9 +895,21 @@
 	go/path/match.go \
 	go/path/path.go
 
+if LIBGO_IS_X86_64
+go_reflect_makefunc_file = \
+	go/reflect/makefuncgo_amd64.go
+go_reflect_makefunc_s_file = \
+	go/reflect/makefunc_amd64.S
+else
+go_reflect_makefunc_file =
+go_reflect_makefunc_s_file = \
+	go/reflect/makefunc_dummy.c
+endif
+
 go_reflect_files = \
 	go/reflect/deepequal.go \
 	go/reflect/makefunc.go \
+	$(go_reflect_makefunc_file) \
 	go/reflect/type.go \
 	go/reflect/value.go
 
@@ -1761,6 +1773,7 @@
 	os.lo \
 	path.lo \
 	reflect-go.lo \
+	reflect/makefunc.lo \
 	regexp.lo \
 	runtime-go.lo \
 	sort.lo \
@@ -2147,6 +2160,9 @@
 	$(BUILDPACKAGE)
 reflect/check: $(CHECK_DEPS)
 	@$(CHECK)
+reflect/makefunc.lo: $(go_reflect_makefunc_s_file)
+	@$(MKDIR_P) reflect
+	$(LTCOMPILE) -c -o $@ $
 .PHONY: reflect/check
 
 @go_include@ regexp.lo.dep
diff -r 024105249263 libgo/go/reflect/all_test.go
--- a/libgo/go/reflect/all_test.go	Tue Sep 24 20:26:38 2013 -0700
+++ b/libgo/go/reflect/all_test.go	Fri Sep 27 08:06:13 2013 -0700
@@ -1430,11 +1430,13 @@
 	}
 }
 
-/*
-
-Not yet implemented for gccgo.
-
 func TestMakeFunc(t *testing.T) {
+	switch runtime.GOARCH {
+	case amd64:
+	default:
+		t.Skip(MakeFunc not implemented for  + runtime.GOARCH)
+	}
+
 	f := dummy
 	fv := MakeFunc(TypeOf(f), func(in []Value) []Value { return in })
 	ValueOf(f).Elem().Set(fv)
@@ -1452,8 +1454,6 @@
 	}
 }
 
-*/
-
 type Point struct {
 	x, y int
 }
diff -r 024105249263 libgo/go/reflect/makefunc.go
--- a/libgo/go/reflect/makefunc.go	Tue Sep 24 20:26:38 2013 -0700
+++ b/libgo/go/reflect/makefunc.go	Fri Sep 27 08:06:13 2013 -0700
@@ -7,6 +7,7 @@
 package reflect
 
 import (
+	runtime
 	unsafe
 )
 
@@ -45,14 +46,33 @@
 		panic(reflect: call of MakeFunc with non-Func type)
 	}
 
+	switch runtime.GOARCH {
+	case amd64:
+	default:
+		panic(reflect.MakeFunc not implemented for  + runtime.GOARCH)
+	}
+
 	t := typ.common()
 	ftyp := (*funcType)(unsafe.Pointer(t))
 
-	_, _ = t, ftyp
+	// Indirect Go func value (dummy) to obtain
+	// actual code address. (A Go func value is a pointer
+	// to a C function pointer. http://golang.org/s/go11func.)
+	dummy := makeFuncStub
+	code := **(**uintptr)(unsafe.Pointer(dummy))
 
-	panic(reflect MakeFunc not implemented)
+	impl := makeFuncImpl{code: code, typ: ftyp, fn: fn}
+
+	return Value{t, unsafe.Pointer(impl), flag(Func)  flagKindShift}
 }
 
+// makeFuncStub is an assembly function that is the code half of
+// the function returned from MakeFunc. It expects a *callReflectFunc
+// as its context register, and its job is to invoke callReflect(ctxt, frame)
+// where ctxt is the context register and frame is a pointer to the first
+// word in the passed-in argument frame.
+func makeFuncStub()
+
 // makeMethodValue converts v from the rcvr+method index representation
 // of a method value to an actual method func value, which is
 // basically the receiver value with a special bit set, into a true
diff -r 024105249263 libgo/go/reflect/makefunc_amd64.S
--- /dev/null	Thu Jan 01 00:00:00 1970 +
+++ b/libgo/go/reflect/makefunc_amd64.S	Fri Sep 27 08:06:13 2013 -0700
@@ -0,0 +1,107 @@
+# Copyright 2013 The Go Authors. All rights reserved.
+# Use of