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.
12 // The ffi function, written in C, allocates an FFI closure. It
13 // returns the code and data pointers. When the code pointer is
14 // called, it will call callback. CIF is an FFI data structure
15 // allocated as part of the closure, and is returned to ensure that
17 func ffi(ftyp
*funcType
, callback
func(unsafe
.Pointer
, unsafe
.Pointer
)) (code
uintptr, data
uintptr, cif unsafe
.Pointer
)
19 // The ffiFree function, written in C, releases the FFI closure.
22 // An ffiData holds the information needed to preserve an FFI closure
23 // for the garbage collector.
28 callback
func(unsafe
.Pointer
, unsafe
.Pointer
)
31 // The makeFuncFFI function uses libffi closures to implement
32 // reflect.MakeFunc. This is used for processors for which we don't
33 // have more efficient support.
34 func makeFuncFFI(ftyp
*funcType
, fn
func(args
[]Value
) (results
[]Value
)) (uintptr, *ffiData
) {
35 callback
:= func(params
, results unsafe
.Pointer
) {
36 ffiCall(ftyp
, fn
, params
, results
)
39 code
, data
, cif
:= ffi(ftyp
, callback
)
41 c
:= &ffiData
{code
: code
, data
: data
, cif
: cif
, callback
: callback
}
43 runtime
.SetFinalizer(c
,
51 // ffiCall takes pointers to the parameters, calls the function, and
52 // stores the results back into memory.
53 func ffiCall(ftyp
*funcType
, fn
func([]Value
) []Value
, params unsafe
.Pointer
, results unsafe
.Pointer
) {
54 in
:= make([]Value
, 0, len(ftyp
.in
))
56 for _
, rt
:= range ftyp
.in
{
58 memmove(p
, *(*unsafe
.Pointer
)(ap
), rt
.size
)
59 v
:= Value
{rt
, p
, flag(rt
.Kind()<<flagKindShift
) | flagIndir
}
61 ap
= (unsafe
.Pointer
)(uintptr(ap
) + ptrSize
)
67 for i
, typ
:= range ftyp
.out
{
70 panic("reflect: function created by MakeFunc using " + funcName(fn
) +
71 " returned wrong type: have " +
72 out
[i
].typ
.String() + " for " + typ
.String())
74 if v
.flag
&flagRO
!= 0 {
75 panic("reflect: function created by MakeFunc using " + funcName(fn
) +
76 " returned value obtained from unexported field")
79 off
= align(off
, uintptr(typ
.fieldAlign
))
80 addr
:= unsafe
.Pointer(uintptr(results
) + off
)
81 if v
.flag
&flagIndir
== 0 && (v
.kind() == Ptr || v
.kind() == UnsafePointer
) {
82 *(*unsafe
.Pointer
)(addr
) = v
.ptr
84 memmove(addr
, v
.ptr
, typ
.size
)