1 /* go-reflect-call.c -- call reflection support for Go.
3 Copyright 2009 The Go Authors. All rights reserved.
4 Use of this source code is governed by a BSD-style
5 license that can be found in the LICENSE file. */
12 #include "go-assert.h"
18 #if defined(USE_LIBFFI) && FFI_GO_CLOSURES
20 /* The functions in this file are only called from reflect_call. As
21 reflect_call calls a libffi function, which will be compiled
22 without -fsplit-stack, it will always run with a large stack. */
24 static size_t go_results_size (const struct functype
*)
25 __attribute__ ((no_split_stack
));
26 static void go_set_results (const struct functype
*, unsigned char *, void **)
27 __attribute__ ((no_split_stack
));
29 /* Get the total size required for the result parameters of a
33 go_results_size (const struct functype
*func
)
36 const struct _type
**types
;
41 count
= func
->out
.__count
;
45 types
= (const struct _type
**) func
->out
.__values
;
47 /* A single integer return value is always promoted to a full word.
48 There is similar code below and in libgo/go/reflect/makefunc_ffi.go.*/
51 switch (types
[0]->kind
& kindMask
)
60 return sizeof (ffi_arg
);
69 for (i
= 0; i
< count
; ++i
)
73 align
= types
[i
]->fieldAlign
;
76 off
= (off
+ align
- 1) & ~ (align
- 1);
77 off
+= types
[i
]->size
;
80 off
= (off
+ maxalign
- 1) & ~ (maxalign
- 1);
82 // The libffi library doesn't understand a struct with no fields.
83 // We generate a struct with a single field of type void. When used
84 // as a return value, libffi will think that requires a byte.
91 /* Copy the results of calling a function via FFI from CALL_RESULT
92 into the addresses in RESULTS. */
95 go_set_results (const struct functype
*func
, unsigned char *call_result
,
99 const struct _type
**types
;
103 count
= func
->out
.__count
;
107 types
= (const struct _type
**) func
->out
.__values
;
109 /* A single integer return value is always promoted to a full word.
110 There is similar code above and in libgo/go/reflect/makefunc_ffi.go.*/
113 switch (types
[0]->kind
& kindMask
)
125 unsigned char buf
[sizeof (ffi_arg
)];
130 __builtin_memcpy (&u
.buf
, call_result
, sizeof (ffi_arg
));
133 switch (types
[0]->size
)
140 __builtin_memcpy (results
[0], &b
, 1);
149 __builtin_memcpy (results
[0], &s
, 2);
158 __builtin_memcpy (results
[0], &w
, 4);
167 __builtin_memcpy (results
[0], &d
, 8);
183 for (i
= 0; i
< count
; ++i
)
188 align
= types
[i
]->fieldAlign
;
189 size
= types
[i
]->size
;
190 off
= (off
+ align
- 1) & ~ (align
- 1);
191 __builtin_memcpy (results
[i
], call_result
+ off
, size
);
196 /* The code that converts the Go type to an FFI type is written in Go,
197 so that it can allocate Go heap memory. */
198 extern void ffiFuncToCIF(const struct functype
*, _Bool
, _Bool
, ffi_cif
*)
199 __asm__ ("runtime.ffiFuncToCIF");
201 /* Call a function. The type of the function is FUNC_TYPE, and the
202 closure is FUNC_VAL. PARAMS is an array of parameter addresses.
203 RESULTS is an array of result addresses.
205 If IS_INTERFACE is true this is a call to an interface method and
206 the first argument is the receiver, which is always a pointer.
207 This argument, the receiver, is not described in FUNC_TYPE.
209 If IS_METHOD is true this is a call to a method expression. The
210 first argument is the receiver. It is described in FUNC_TYPE, but
211 regardless of FUNC_TYPE, it is passed as a pointer. */
214 reflect_call (const struct functype
*func_type
, FuncVal
*func_val
,
215 _Bool is_interface
, _Bool is_method
, void **params
,
219 unsigned char *call_result
;
221 __go_assert ((func_type
->typ
.kind
& kindMask
) == kindFunc
);
222 ffiFuncToCIF (func_type
, is_interface
, is_method
, &cif
);
224 call_result
= (unsigned char *) malloc (go_results_size (func_type
));
226 ffi_call_go (&cif
, (void (*)(void)) func_val
->fn
, call_result
, params
,
229 /* Some day we may need to free result values if RESULTS is
232 go_set_results (func_type
, call_result
, results
);
237 #else /* !defined(USE_LIBFFI) */
240 reflect_call (const struct functype
*func_type
__attribute__ ((unused
)),
241 FuncVal
*func_val
__attribute__ ((unused
)),
242 _Bool is_interface
__attribute__ ((unused
)),
243 _Bool is_method
__attribute__ ((unused
)),
244 void **params
__attribute__ ((unused
)),
245 void **results
__attribute__ ((unused
)))
247 /* Without FFI there is nothing we can do. */
248 runtime_throw("libgo built without FFI does not support "
249 "reflect.Call or runtime.SetFinalizer");
252 #endif /* !defined(USE_LIBFFI) */