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. */
14 #include "go-assert.h"
22 /* The functions in this file are only called from reflect_call. As
23 reflect_call calls a libffi function, which will be compiled
24 without -fsplit-stack, it will always run with a large stack. */
26 static ffi_type
*go_array_to_ffi (const struct __go_array_type
*)
27 __attribute__ ((no_split_stack
));
28 static ffi_type
*go_slice_to_ffi (const struct __go_slice_type
*)
29 __attribute__ ((no_split_stack
));
30 static ffi_type
*go_struct_to_ffi (const struct __go_struct_type
*)
31 __attribute__ ((no_split_stack
));
32 static ffi_type
*go_string_to_ffi (void) __attribute__ ((no_split_stack
));
33 static ffi_type
*go_interface_to_ffi (void) __attribute__ ((no_split_stack
));
34 static ffi_type
*go_complex_to_ffi (ffi_type
*)
35 __attribute__ ((no_split_stack
));
36 static ffi_type
*go_type_to_ffi (const struct __go_type_descriptor
*)
37 __attribute__ ((no_split_stack
));
38 static ffi_type
*go_func_return_ffi (const struct __go_func_type
*)
39 __attribute__ ((no_split_stack
));
40 static void go_func_to_cif (const struct __go_func_type
*, _Bool
, _Bool
,
42 __attribute__ ((no_split_stack
));
43 static size_t go_results_size (const struct __go_func_type
*)
44 __attribute__ ((no_split_stack
));
45 static void go_set_results (const struct __go_func_type
*, unsigned char *,
47 __attribute__ ((no_split_stack
));
49 /* Return an ffi_type for a Go array type. The libffi library does
50 not have any builtin support for passing arrays as values. We work
51 around this by pretending that the array is a struct. */
54 go_array_to_ffi (const struct __go_array_type
*descriptor
)
61 ret
= (ffi_type
*) __go_alloc (sizeof (ffi_type
));
62 ret
->type
= FFI_TYPE_STRUCT
;
63 len
= descriptor
->__len
;
64 ret
->elements
= (ffi_type
**) __go_alloc ((len
+ 1) * sizeof (ffi_type
*));
65 element
= go_type_to_ffi (descriptor
->__element_type
);
66 for (i
= 0; i
< len
; ++i
)
67 ret
->elements
[i
] = element
;
68 ret
->elements
[len
] = NULL
;
72 /* Return an ffi_type for a Go slice type. This describes the
73 __go_open_array type defines in array.h. */
77 const struct __go_slice_type
*descriptor
__attribute__ ((unused
)))
81 ret
= (ffi_type
*) __go_alloc (sizeof (ffi_type
));
82 ret
->type
= FFI_TYPE_STRUCT
;
83 ret
->elements
= (ffi_type
**) __go_alloc (4 * sizeof (ffi_type
*));
84 ret
->elements
[0] = &ffi_type_pointer
;
85 ret
->elements
[1] = &ffi_type_sint
;
86 ret
->elements
[2] = &ffi_type_sint
;
87 ret
->elements
[3] = NULL
;
91 /* Return an ffi_type for a Go struct type. */
94 go_struct_to_ffi (const struct __go_struct_type
*descriptor
)
98 const struct __go_struct_field
*fields
;
101 ret
= (ffi_type
*) __go_alloc (sizeof (ffi_type
));
102 ret
->type
= FFI_TYPE_STRUCT
;
103 field_count
= descriptor
->__fields
.__count
;
104 fields
= (const struct __go_struct_field
*) descriptor
->__fields
.__values
;
105 ret
->elements
= (ffi_type
**) __go_alloc ((field_count
+ 1)
106 * sizeof (ffi_type
*));
107 for (i
= 0; i
< field_count
; ++i
)
108 ret
->elements
[i
] = go_type_to_ffi (fields
[i
].__type
);
109 ret
->elements
[field_count
] = NULL
;
113 /* Return an ffi_type for a Go string type. This describes the
114 __go_string struct. */
117 go_string_to_ffi (void)
121 ret
= (ffi_type
*) __go_alloc (sizeof (ffi_type
));
122 ret
->type
= FFI_TYPE_STRUCT
;
123 ret
->elements
= (ffi_type
**) __go_alloc (3 * sizeof (ffi_type
*));
124 ret
->elements
[0] = &ffi_type_pointer
;
125 ret
->elements
[1] = &ffi_type_sint
;
126 ret
->elements
[2] = NULL
;
130 /* Return an ffi_type for a Go interface type. This describes the
131 __go_interface and __go_empty_interface structs. */
134 go_interface_to_ffi (void)
138 ret
= (ffi_type
*) __go_alloc (sizeof (ffi_type
));
139 ret
->type
= FFI_TYPE_STRUCT
;
140 ret
->elements
= (ffi_type
**) __go_alloc (3 * sizeof (ffi_type
*));
141 ret
->elements
[0] = &ffi_type_pointer
;
142 ret
->elements
[1] = &ffi_type_pointer
;
143 ret
->elements
[2] = NULL
;
147 /* Return an ffi_type for a Go complex type. */
150 go_complex_to_ffi (ffi_type
*float_type
)
154 ret
= (ffi_type
*) __go_alloc (sizeof (ffi_type
));
155 ret
->type
= FFI_TYPE_STRUCT
;
156 ret
->elements
= (ffi_type
**) __go_alloc (3 * sizeof (ffi_type
*));
157 ret
->elements
[0] = float_type
;
158 ret
->elements
[1] = float_type
;
159 ret
->elements
[2] = NULL
;
163 /* Return an ffi_type for a type described by a
164 __go_type_descriptor. */
167 go_type_to_ffi (const struct __go_type_descriptor
*descriptor
)
169 switch (descriptor
->__code
& GO_CODE_MASK
)
172 if (sizeof (_Bool
) == 1)
173 return &ffi_type_uint8
;
174 else if (sizeof (_Bool
) == sizeof (int))
175 return &ffi_type_uint
;
178 if (sizeof (float) == 4)
179 return &ffi_type_float
;
182 if (sizeof (double) == 8)
183 return &ffi_type_double
;
186 if (sizeof (float) == 4)
187 return go_complex_to_ffi (&ffi_type_float
);
190 if (sizeof (double) == 8)
191 return go_complex_to_ffi (&ffi_type_double
);
194 return &ffi_type_sint16
;
196 return &ffi_type_sint32
;
198 return &ffi_type_sint64
;
200 return &ffi_type_sint8
;
202 return &ffi_type_sint
;
204 return &ffi_type_uint16
;
206 return &ffi_type_uint32
;
208 return &ffi_type_uint64
;
210 return &ffi_type_uint8
;
212 return &ffi_type_uint
;
214 if (sizeof (void *) == 2)
215 return &ffi_type_uint16
;
216 else if (sizeof (void *) == 4)
217 return &ffi_type_uint32
;
218 else if (sizeof (void *) == 8)
219 return &ffi_type_uint64
;
222 return go_array_to_ffi ((const struct __go_array_type
*) descriptor
);
224 return go_slice_to_ffi ((const struct __go_slice_type
*) descriptor
);
226 return go_struct_to_ffi ((const struct __go_struct_type
*) descriptor
);
228 return go_string_to_ffi ();
230 return go_interface_to_ffi ();
235 case GO_UNSAFE_POINTER
:
236 /* These types are always pointers, and for FFI purposes nothing
238 return &ffi_type_pointer
;
244 /* Return the return type for a function, given the number of out
245 parameters and their types. */
248 go_func_return_ffi (const struct __go_func_type
*func
)
251 const struct __go_type_descriptor
**types
;
255 count
= func
->__out
.__count
;
257 return &ffi_type_void
;
259 types
= (const struct __go_type_descriptor
**) func
->__out
.__values
;
262 return go_type_to_ffi (types
[0]);
264 ret
= (ffi_type
*) __go_alloc (sizeof (ffi_type
));
265 ret
->type
= FFI_TYPE_STRUCT
;
266 ret
->elements
= (ffi_type
**) __go_alloc ((count
+ 1) * sizeof (ffi_type
*));
267 for (i
= 0; i
< count
; ++i
)
268 ret
->elements
[i
] = go_type_to_ffi (types
[i
]);
269 ret
->elements
[count
] = NULL
;
273 /* Build an ffi_cif structure for a function described by a
274 __go_func_type structure. */
277 go_func_to_cif (const struct __go_func_type
*func
, _Bool is_interface
,
278 _Bool is_method
, ffi_cif
*cif
)
281 const struct __go_type_descriptor
**in_types
;
289 num_params
= func
->__in
.__count
;
290 in_types
= ((const struct __go_type_descriptor
**)
291 func
->__in
.__values
);
293 num_args
= num_params
+ (is_interface
? 1 : 0);
294 args
= (ffi_type
**) __go_alloc (num_args
* sizeof (ffi_type
*));
299 args
[0] = &ffi_type_pointer
;
304 args
[0] = &ffi_type_pointer
;
307 for (; i
< num_params
; ++i
)
308 args
[i
+ off
] = go_type_to_ffi (in_types
[i
]);
310 rettype
= go_func_return_ffi (func
);
312 status
= ffi_prep_cif (cif
, FFI_DEFAULT_ABI
, num_args
, rettype
, args
);
313 __go_assert (status
== FFI_OK
);
316 /* Get the total size required for the result parameters of a
320 go_results_size (const struct __go_func_type
*func
)
323 const struct __go_type_descriptor
**types
;
328 count
= func
->__out
.__count
;
332 types
= (const struct __go_type_descriptor
**) func
->__out
.__values
;
334 /* A single integer return value is always promoted to a full
338 switch (types
[0]->__code
& GO_CODE_MASK
)
349 return sizeof (ffi_arg
);
358 for (i
= 0; i
< count
; ++i
)
362 align
= types
[i
]->__field_align
;
363 if (align
> maxalign
)
365 off
= (off
+ align
- 1) & ~ (align
- 1);
366 off
+= types
[i
]->__size
;
369 off
= (off
+ maxalign
- 1) & ~ (maxalign
- 1);
374 /* Copy the results of calling a function via FFI from CALL_RESULT
375 into the addresses in RESULTS. */
378 go_set_results (const struct __go_func_type
*func
, unsigned char *call_result
,
382 const struct __go_type_descriptor
**types
;
386 count
= func
->__out
.__count
;
390 types
= (const struct __go_type_descriptor
**) func
->__out
.__values
;
392 /* A single integer return value is always promoted to a full
396 switch (types
[0]->__code
& GO_CODE_MASK
)
410 unsigned char buf
[sizeof (ffi_arg
)];
415 __builtin_memcpy (&u
.buf
, call_result
, sizeof (ffi_arg
));
418 switch (types
[0]->__size
)
425 __builtin_memcpy (results
[0], &b
, 1);
434 __builtin_memcpy (results
[0], &s
, 2);
443 __builtin_memcpy (results
[0], &w
, 4);
452 __builtin_memcpy (results
[0], &d
, 8);
468 for (i
= 0; i
< count
; ++i
)
473 align
= types
[i
]->__field_align
;
474 size
= types
[i
]->__size
;
475 off
= (off
+ align
- 1) & ~ (align
- 1);
476 __builtin_memcpy (results
[i
], call_result
+ off
, size
);
481 /* Call a function. The type of the function is FUNC_TYPE, and the
482 address is FUNC_ADDR. PARAMS is an array of parameter addresses.
483 RESULTS is an array of result addresses. */
486 reflect_call (const struct __go_func_type
*func_type
, const void *func_addr
,
487 _Bool is_interface
, _Bool is_method
, void **params
,
491 unsigned char *call_result
;
493 __go_assert ((func_type
->__common
.__code
& GO_CODE_MASK
) == GO_FUNC
);
494 go_func_to_cif (func_type
, is_interface
, is_method
, &cif
);
496 call_result
= (unsigned char *) malloc (go_results_size (func_type
));
498 ffi_call (&cif
, func_addr
, call_result
, params
);
500 /* Some day we may need to free result values if RESULTS is
503 go_set_results (func_type
, call_result
, results
);
508 #else /* !defined(USE_LIBFFI) */
511 reflect_call (const struct __go_func_type
*func_type
__attribute__ ((unused
)),
512 const void *func_addr
__attribute__ ((unused
)),
513 _Bool is_interface
__attribute__ ((unused
)),
514 _Bool is_method
__attribute__ ((unused
)),
515 void **params
__attribute__ ((unused
)),
516 void **results
__attribute__ ((unused
)))
518 /* Without FFI there is nothing we can do. */
519 runtime_throw("libgo built without FFI does not support "
520 "reflect.Call or runtime.SetFinalizer");
523 #endif /* !defined(USE_LIBFFI) */