github.com/llvm-mirror/llgo@v0.0.0-20190322182713-bf6f0a60fce1/third_party/gofrontend/libgo/go/reflect/makefunc_ffi.go (about)

     1  // Copyright 2014 The Go Authors.  All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package reflect
     6  
     7  import (
     8  	"unsafe"
     9  )
    10  
    11  // The makeFuncFFI function, written in C, fills in an FFI closure.
    12  // It arranges for ffiCall to be invoked directly from FFI.
    13  func makeFuncFFI(ftyp *funcType, impl unsafe.Pointer)
    14  
    15  // FFICallbackGo implements the Go side of the libffi callback.
    16  // It is exported so that C code can call it.
    17  //
    18  // The call chain arriving here looks like
    19  //   some_go_caller
    20  //   ->some_ffi_internals
    21  //     ->ffi_callback (in C)
    22  //       ->FFICallbackGo
    23  //
    24  // The ffi_callback handles __go_makefunc_can_recover, and
    25  // then passes off the data as received from ffi here.
    26  
    27  func FFICallbackGo(results unsafe.Pointer, params unsafe.Pointer, impl *makeFuncImpl) {
    28  	ftyp := impl.typ
    29  	in := make([]Value, 0, len(ftyp.in))
    30  	ap := params
    31  	for _, rt := range ftyp.in {
    32  		p := unsafe_New(rt)
    33  		memmove(p, *(*unsafe.Pointer)(ap), rt.size)
    34  		v := Value{rt, p, flag(rt.Kind()) | flagIndir}
    35  		in = append(in, v)
    36  		ap = (unsafe.Pointer)(uintptr(ap) + ptrSize)
    37  	}
    38  
    39  	out := impl.call(in)
    40  
    41  	off := uintptr(0)
    42  	for i, typ := range ftyp.out {
    43  		v := out[i]
    44  		if v.typ != typ {
    45  			panic("reflect: function created by MakeFunc using " + funcName(impl.fn) +
    46  				" returned wrong type: have " +
    47  				out[i].typ.String() + " for " + typ.String())
    48  		}
    49  		if v.flag&flagRO != 0 {
    50  			panic("reflect: function created by MakeFunc using " + funcName(impl.fn) +
    51  				" returned value obtained from unexported field")
    52  		}
    53  
    54  		off = align(off, uintptr(typ.fieldAlign))
    55  		addr := unsafe.Pointer(uintptr(results) + off)
    56  		if v.flag&flagIndir == 0 && (v.kind() == Ptr || v.kind() == UnsafePointer) {
    57  			*(*unsafe.Pointer)(addr) = v.ptr
    58  		} else {
    59  			memmove(addr, v.ptr, typ.size)
    60  		}
    61  		off += typ.size
    62  	}
    63  }