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. */
13 #include "go-assert.h"
17 /* Forward declaration. */
19 static ffi_type
*go_type_to_ffi (const struct __go_type_descriptor
*);
21 /* Return an ffi_type for a Go array type. The libffi library does
22 not have any builtin support for passing arrays as values. We work
23 around this by pretending that the array is a struct. */
26 go_array_to_ffi (const struct __go_array_type
*descriptor
)
33 ret
= (ffi_type
*) __go_alloc (sizeof (ffi_type
));
34 __builtin_memset (ret
, 0, sizeof (ffi_type
));
35 ret
->type
= FFI_TYPE_STRUCT
;
36 len
= descriptor
->__len
;
37 ret
->elements
= (ffi_type
**) __go_alloc ((len
+ 1) * sizeof (ffi_type
*));
38 element
= go_type_to_ffi (descriptor
->__element_type
);
39 for (i
= 0; i
< len
; ++i
)
40 ret
->elements
[i
] = element
;
41 ret
->elements
[len
] = NULL
;
45 /* Return an ffi_type for a Go slice type. This describes the
46 __go_open_array type defines in array.h. */
50 const struct __go_slice_type
*descriptor
__attribute__ ((unused
)))
54 ret
= (ffi_type
*) __go_alloc (sizeof (ffi_type
));
55 __builtin_memset (ret
, 0, sizeof (ffi_type
));
56 ret
->type
= FFI_TYPE_STRUCT
;
57 ret
->elements
= (ffi_type
**) __go_alloc (4 * sizeof (ffi_type
*));
58 ret
->elements
[0] = &ffi_type_pointer
;
59 ret
->elements
[1] = &ffi_type_sint
;
60 ret
->elements
[2] = &ffi_type_sint
;
61 ret
->elements
[3] = NULL
;
65 /* Return an ffi_type for a Go struct type. */
68 go_struct_to_ffi (const struct __go_struct_type
*descriptor
)
72 const struct __go_struct_field
*fields
;
75 ret
= (ffi_type
*) __go_alloc (sizeof (ffi_type
));
76 __builtin_memset (ret
, 0, sizeof (ffi_type
));
77 ret
->type
= FFI_TYPE_STRUCT
;
78 field_count
= descriptor
->__fields
.__count
;
79 fields
= (const struct __go_struct_field
*) descriptor
->__fields
.__values
;
80 ret
->elements
= (ffi_type
**) __go_alloc ((field_count
+ 1)
81 * sizeof (ffi_type
*));
82 for (i
= 0; i
< field_count
; ++i
)
83 ret
->elements
[i
] = go_type_to_ffi (fields
[i
].__type
);
84 ret
->elements
[field_count
] = NULL
;
88 /* Return an ffi_type for a Go string type. This describes the
89 __go_string struct. */
92 go_string_to_ffi (void)
96 ret
= (ffi_type
*) __go_alloc (sizeof (ffi_type
));
97 ret
->type
= FFI_TYPE_STRUCT
;
98 ret
->elements
= (ffi_type
**) __go_alloc (3 * sizeof (ffi_type
*));
99 ret
->elements
[0] = &ffi_type_pointer
;
100 ret
->elements
[1] = &ffi_type_sint
;
101 ret
->elements
[2] = NULL
;
105 /* Return an ffi_type for a Go interface type. This describes the
106 __go_interface and __go_empty_interface structs. */
109 go_interface_to_ffi (void)
113 ret
= (ffi_type
*) __go_alloc (sizeof (ffi_type
));
114 ret
->type
= FFI_TYPE_STRUCT
;
115 ret
->elements
= (ffi_type
**) __go_alloc (3 * sizeof (ffi_type
*));
116 ret
->elements
[0] = &ffi_type_pointer
;
117 ret
->elements
[1] = &ffi_type_pointer
;
118 ret
->elements
[2] = NULL
;
122 /* Return an ffi_type for a type described by a
123 __go_type_descriptor. */
126 go_type_to_ffi (const struct __go_type_descriptor
*descriptor
)
128 switch (descriptor
->__code
)
131 if (sizeof (_Bool
) == 1)
132 return &ffi_type_uint8
;
133 else if (sizeof (_Bool
) == sizeof (int))
134 return &ffi_type_uint
;
137 if (sizeof (float) == 4)
138 return &ffi_type_float
;
141 if (sizeof (double) == 8)
142 return &ffi_type_double
;
145 return &ffi_type_float
;
152 return &ffi_type_sint16
;
154 return &ffi_type_sint32
;
156 return &ffi_type_sint64
;
158 return &ffi_type_sint8
;
160 return &ffi_type_sint
;
162 return &ffi_type_uint16
;
164 return &ffi_type_uint32
;
166 return &ffi_type_uint64
;
168 return &ffi_type_uint8
;
170 return &ffi_type_uint
;
172 if (sizeof (void *) == 2)
173 return &ffi_type_uint16
;
174 else if (sizeof (void *) == 4)
175 return &ffi_type_uint32
;
176 else if (sizeof (void *) == 8)
177 return &ffi_type_uint64
;
180 return go_array_to_ffi ((const struct __go_array_type
*) descriptor
);
182 return go_slice_to_ffi ((const struct __go_slice_type
*) descriptor
);
184 return go_struct_to_ffi ((const struct __go_struct_type
*) descriptor
);
186 return go_string_to_ffi ();
188 return go_interface_to_ffi ();
193 case GO_UNSAFE_POINTER
:
194 /* These types are always pointers, and for FFI purposes nothing
196 return &ffi_type_pointer
;
202 /* Return the return type for a function, given the number of out
203 parameters and their types. */
206 go_func_return_ffi (const struct __go_func_type
*func
)
209 const struct __go_type_descriptor
**types
;
213 count
= func
->__out
.__count
;
215 return &ffi_type_void
;
217 types
= (const struct __go_type_descriptor
**) func
->__out
.__values
;
220 return go_type_to_ffi (types
[0]);
222 ret
= (ffi_type
*) __go_alloc (sizeof (ffi_type
));
223 __builtin_memset (ret
, 0, sizeof (ffi_type
));
224 ret
->type
= FFI_TYPE_STRUCT
;
225 ret
->elements
= (ffi_type
**) __go_alloc ((count
+ 1) * sizeof (ffi_type
*));
226 for (i
= 0; i
< count
; ++i
)
227 ret
->elements
[i
] = go_type_to_ffi (types
[i
]);
228 ret
->elements
[count
] = NULL
;
232 /* Build an ffi_cif structure for a function described by a
233 __go_func_type structure. */
236 go_func_to_cif (const struct __go_func_type
*func
, _Bool is_interface
,
240 const struct __go_type_descriptor
**in_types
;
248 num_params
= func
->__in
.__count
;
249 in_types
= ((const struct __go_type_descriptor
**)
250 func
->__in
.__values
);
252 num_args
= num_params
+ (is_interface
? 1 : 0);
253 args
= (ffi_type
**) __go_alloc (num_args
* sizeof (ffi_type
*));
255 args
[0] = &ffi_type_pointer
;
256 off
= is_interface
? 1 : 0;
257 for (i
= 0; i
< num_params
; ++i
)
258 args
[i
+ off
] = go_type_to_ffi (in_types
[i
]);
260 rettype
= go_func_return_ffi (func
);
262 status
= ffi_prep_cif (cif
, FFI_DEFAULT_ABI
, num_args
, rettype
, args
);
263 __go_assert (status
== FFI_OK
);
266 /* Get the total size required for the result parameters of a
270 go_results_size (const struct __go_func_type
*func
)
273 const struct __go_type_descriptor
**types
;
278 count
= func
->__out
.__count
;
282 types
= (const struct __go_type_descriptor
**) func
->__out
.__values
;
286 for (i
= 0; i
< count
; ++i
)
290 align
= types
[i
]->__field_align
;
291 if (align
> maxalign
)
293 off
= (off
+ align
- 1) & ~ (align
- 1);
294 off
+= types
[i
]->__size
;
297 off
= (off
+ maxalign
- 1) & ~ (maxalign
- 1);
302 /* Copy the results of calling a function via FFI from CALL_RESULT
303 into the addresses in RESULTS. */
306 go_set_results (const struct __go_func_type
*func
, unsigned char *call_result
,
310 const struct __go_type_descriptor
**types
;
314 count
= func
->__out
.__count
;
318 types
= (const struct __go_type_descriptor
**) func
->__out
.__values
;
321 for (i
= 0; i
< count
; ++i
)
326 align
= types
[i
]->__field_align
;
327 size
= types
[i
]->__size
;
328 off
= (off
+ align
- 1) & ~ (align
- 1);
329 __builtin_memcpy (results
[i
], call_result
+ off
, size
);
334 /* Call a function. The type of the function is FUNC_TYPE, and the
335 address is FUNC_ADDR. PARAMS is an array of parameter addresses.
336 RESULTS is an array of result addresses. */
339 reflect_call (const struct __go_func_type
*func_type
, const void *func_addr
,
340 _Bool is_interface
, void **params
, void **results
)
343 unsigned char *call_result
;
345 __go_assert (func_type
->__common
.__code
== GO_FUNC
);
346 go_func_to_cif (func_type
, is_interface
, &cif
);
348 call_result
= (unsigned char *) malloc (go_results_size (func_type
));
350 ffi_call (&cif
, func_addr
, call_result
, params
);
352 /* Some day we may need to free result values if RESULTS is
355 go_set_results (func_type
, call_result
, results
);