aboutsummaryrefslogtreecommitdiffstats
path: root/gcc-4.8/libgo/go/reflect/makefunc.go
diff options
context:
space:
mode:
Diffstat (limited to 'gcc-4.8/libgo/go/reflect/makefunc.go')
-rw-r--r--gcc-4.8/libgo/go/reflect/makefunc.go90
1 files changed, 87 insertions, 3 deletions
diff --git a/gcc-4.8/libgo/go/reflect/makefunc.go b/gcc-4.8/libgo/go/reflect/makefunc.go
index 3e8085bec..9f150ea65 100644
--- a/gcc-4.8/libgo/go/reflect/makefunc.go
+++ b/gcc-4.8/libgo/go/reflect/makefunc.go
@@ -17,6 +17,11 @@ type makeFuncImpl struct {
code uintptr
typ *funcType
fn func([]Value) []Value
+
+ // For gccgo we use the same entry point for functions and for
+ // method values.
+ method int
+ rcvr Value
}
// MakeFunc returns a new function of the given Type
@@ -61,7 +66,7 @@ func MakeFunc(typ Type, fn func(args []Value) (results []Value)) Value {
dummy := makeFuncStub
code := **(**uintptr)(unsafe.Pointer(&dummy))
- impl := &makeFuncImpl{code: code, typ: ftyp, fn: fn}
+ impl := &makeFuncImpl{code: code, typ: ftyp, fn: fn, method: -1}
return Value{t, unsafe.Pointer(&impl), flag(Func<<flagKindShift) | flagIndir}
}
@@ -85,15 +90,94 @@ func makeMethodValue(op string, v Value) Value {
panic("reflect: internal error: invalid use of makePartialFunc")
}
+ switch runtime.GOARCH {
+ case "amd64", "386":
+ default:
+ panic("reflect.makeMethodValue not implemented for " + runtime.GOARCH)
+ }
+
// Ignoring the flagMethod bit, v describes the receiver, not the method type.
fl := v.flag & (flagRO | flagAddr | flagIndir)
fl |= flag(v.typ.Kind()) << flagKindShift
rcvr := Value{v.typ, v.val, fl}
+ // v.Type returns the actual type of the method value.
+ ft := v.Type().(*rtype)
+
+ // 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))
+
// Cause panic if method is not appropriate.
// The panic would still happen during the call if we omit this,
// but we want Interface() and other operations to fail early.
- methodReceiver(op, rcvr, int(v.flag)>>flagMethodShift)
+ t, _, _ := methodReceiver(op, rcvr, int(v.flag)>>flagMethodShift)
+
+ fv := &makeFuncImpl{
+ code: code,
+ typ: (*funcType)(unsafe.Pointer(t)),
+ method: int(v.flag) >> flagMethodShift,
+ rcvr: rcvr,
+ }
+
+ return Value{ft, unsafe.Pointer(&fv), v.flag&flagRO | flag(Func)<<flagKindShift | flagIndir}
+}
+
+// makeValueMethod takes a method function and returns a function that
+// takes a value receiver and calls the real method with a pointer to
+// it.
+func makeValueMethod(v Value) Value {
+ typ := v.typ
+ if typ.Kind() != Func {
+ panic("reflect: call of makeValueMethod with non-Func type")
+ }
+ if v.flag&flagMethodFn == 0 {
+ panic("reflect: call of makeValueMethod with non-MethodFn")
+ }
- panic("reflect makeMethodValue not implemented")
+ switch runtime.GOARCH {
+ case "amd64", "386":
+ default:
+ panic("reflect.makeValueMethod not implemented for " + runtime.GOARCH)
+ }
+
+ t := typ.common()
+ ftyp := (*funcType)(unsafe.Pointer(t))
+
+ // 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))
+
+ impl := &makeFuncImpl{
+ code: code,
+ typ: ftyp,
+ method: -2,
+ rcvr: v,
+ }
+
+ return Value{t, unsafe.Pointer(&impl), flag(Func<<flagKindShift) | flagIndir}
+}
+
+// Call the function represented by a makeFuncImpl.
+func (c *makeFuncImpl) call(in []Value) []Value {
+ if c.method == -1 {
+ return c.fn(in)
+ } else if c.method == -2 {
+ if c.typ.IsVariadic() {
+ return c.rcvr.CallSlice(in)
+ } else {
+ return c.rcvr.Call(in)
+ }
+ } else {
+ m := c.rcvr.Method(c.method)
+ if c.typ.IsVariadic() {
+ return m.CallSlice(in)
+ } else {
+ return m.Call(in)
+ }
+ }
}