summaryrefslogtreecommitdiff
path: root/libgo/go/reflect/makefunc_ffi.go
diff options
context:
space:
mode:
Diffstat (limited to 'libgo/go/reflect/makefunc_ffi.go')
-rw-r--r--libgo/go/reflect/makefunc_ffi.go63
1 files changed, 63 insertions, 0 deletions
diff --git a/libgo/go/reflect/makefunc_ffi.go b/libgo/go/reflect/makefunc_ffi.go
new file mode 100644
index 0000000000..c821131bab
--- /dev/null
+++ b/libgo/go/reflect/makefunc_ffi.go
@@ -0,0 +1,63 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package reflect
+
+import (
+ "unsafe"
+)
+
+// The makeFuncFFI function, written in C, fills in an FFI closure.
+// It arranges for ffiCall to be invoked directly from FFI.
+func makeFuncFFI(ftyp *funcType, impl unsafe.Pointer)
+
+// FFICallbackGo implements the Go side of the libffi callback.
+// It is exported so that C code can call it.
+//
+// The call chain arriving here looks like
+// some_go_caller
+// ->some_ffi_internals
+// ->ffi_callback (in C)
+// ->FFICallbackGo
+//
+// The ffi_callback handles __go_makefunc_can_recover, and
+// then passes off the data as received from ffi here.
+
+func FFICallbackGo(results unsafe.Pointer, params unsafe.Pointer, impl *makeFuncImpl) {
+ ftyp := impl.typ
+ in := make([]Value, 0, len(ftyp.in))
+ ap := params
+ for _, rt := range ftyp.in {
+ p := unsafe_New(rt)
+ memmove(p, *(*unsafe.Pointer)(ap), rt.size)
+ v := Value{rt, p, flag(rt.Kind()) | flagIndir}
+ in = append(in, v)
+ ap = (unsafe.Pointer)(uintptr(ap) + ptrSize)
+ }
+
+ out := impl.call(in)
+
+ off := uintptr(0)
+ for i, typ := range ftyp.out {
+ v := out[i]
+ if v.typ != typ {
+ panic("reflect: function created by MakeFunc using " + funcName(impl.fn) +
+ " returned wrong type: have " +
+ out[i].typ.String() + " for " + typ.String())
+ }
+ if v.flag&flagRO != 0 {
+ panic("reflect: function created by MakeFunc using " + funcName(impl.fn) +
+ " returned value obtained from unexported field")
+ }
+
+ off = align(off, uintptr(typ.fieldAlign))
+ addr := unsafe.Pointer(uintptr(results) + off)
+ if v.flag&flagIndir == 0 && (v.kind() == Ptr || v.kind() == UnsafePointer) {
+ *(*unsafe.Pointer)(addr) = v.ptr
+ } else {
+ memmove(addr, v.ptr, typ.size)
+ }
+ off += typ.size
+ }
+}