gcc/libgo/go/reflect/makefunc_ffi.go
Ian Lance Taylor 5302cd0250 runtime, reflect: rewrite Go to FFI type conversion in Go
As we move toward the Go 1.7 garbage collector, it's essential that all
    allocation of values that can contain Go pointers be done using the
    correct type descriptor.  That is simplest if we do all such allocation
    in Go code.  This rewrites the code that converts from a Go type to a
    libffi CIF into Go.
    
    Reviewed-on: https://go-review.googlesource.com/33353

From-SVN: r242578
2016-11-18 00:15:38 +00:00

67 lines
1.9 KiB
Go

// 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(cif unsafe.Pointer, impl unsafe.Pointer)
// The makeCIF function, implemented in the runtime package, allocates a CIF.
func makeCIF(ft *funcType) 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
}
}