1 /* go-ffi.c -- convert Go type description to libffi.
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"
20 /* The functions in this file are only called from reflect_call and
21 reflect.ffi. As these functions call libffi functions, which will
22 be compiled without -fsplit-stack, they will always run with a
25 static ffi_type
*go_array_to_ffi (const struct __go_array_type
*)
26 __attribute__ ((no_split_stack
));
27 static ffi_type
*go_slice_to_ffi (const struct __go_slice_type
*)
28 __attribute__ ((no_split_stack
));
29 static ffi_type
*go_struct_to_ffi (const struct __go_struct_type
*)
30 __attribute__ ((no_split_stack
));
31 static ffi_type
*go_string_to_ffi (void) __attribute__ ((no_split_stack
));
32 static ffi_type
*go_interface_to_ffi (void) __attribute__ ((no_split_stack
));
33 static ffi_type
*go_type_to_ffi (const struct __go_type_descriptor
*)
34 __attribute__ ((no_split_stack
));
35 static ffi_type
*go_func_return_ffi (const struct __go_func_type
*)
36 __attribute__ ((no_split_stack
));
38 /* Return an ffi_type for a Go array type. The libffi library does
39 not have any builtin support for passing arrays as values. We work
40 around this by pretending that the array is a struct. */
43 go_array_to_ffi (const struct __go_array_type
*descriptor
)
50 ret
= (ffi_type
*) __go_alloc (sizeof (ffi_type
));
51 ret
->type
= FFI_TYPE_STRUCT
;
52 len
= descriptor
->__len
;
55 /* The libffi library won't accept an empty struct. */
56 ret
->elements
= (ffi_type
**) __go_alloc (2 * sizeof (ffi_type
*));
57 ret
->elements
[0] = &ffi_type_void
;
58 ret
->elements
[1] = NULL
;
61 ret
->elements
= (ffi_type
**) __go_alloc ((len
+ 1) * sizeof (ffi_type
*));
62 element
= go_type_to_ffi (descriptor
->__element_type
);
63 for (i
= 0; i
< len
; ++i
)
64 ret
->elements
[i
] = element
;
65 ret
->elements
[len
] = NULL
;
69 /* Return an ffi_type for a Go slice type. This describes the
70 __go_open_array type defines in array.h. */
74 const struct __go_slice_type
*descriptor
__attribute__ ((unused
)))
79 ret
= (ffi_type
*) __go_alloc (sizeof (ffi_type
));
80 ret
->type
= FFI_TYPE_STRUCT
;
81 ret
->elements
= (ffi_type
**) __go_alloc (4 * sizeof (ffi_type
*));
82 ret
->elements
[0] = &ffi_type_pointer
;
83 ffi_intgo
= sizeof (intgo
) == 4 ? &ffi_type_sint32
: &ffi_type_sint64
;
84 ret
->elements
[1] = ffi_intgo
;
85 ret
->elements
[2] = ffi_intgo
;
86 ret
->elements
[3] = NULL
;
90 /* Return an ffi_type for a Go struct type. */
93 go_struct_to_ffi (const struct __go_struct_type
*descriptor
)
97 const struct __go_struct_field
*fields
;
100 field_count
= descriptor
->__fields
.__count
;
101 ret
= (ffi_type
*) __go_alloc (sizeof (ffi_type
));
102 ret
->type
= FFI_TYPE_STRUCT
;
103 if (field_count
== 0)
105 /* The libffi library won't accept an empty struct. */
106 ret
->elements
= (ffi_type
**) __go_alloc (2 * sizeof (ffi_type
*));
107 ret
->elements
[0] = &ffi_type_void
;
108 ret
->elements
[1] = NULL
;
111 fields
= (const struct __go_struct_field
*) descriptor
->__fields
.__values
;
112 ret
->elements
= (ffi_type
**) __go_alloc ((field_count
+ 1)
113 * sizeof (ffi_type
*));
114 for (i
= 0; i
< field_count
; ++i
)
115 ret
->elements
[i
] = go_type_to_ffi (fields
[i
].__type
);
116 ret
->elements
[field_count
] = NULL
;
120 /* Return an ffi_type for a Go string type. This describes the String
124 go_string_to_ffi (void)
129 ret
= (ffi_type
*) __go_alloc (sizeof (ffi_type
));
130 ret
->type
= FFI_TYPE_STRUCT
;
131 ret
->elements
= (ffi_type
**) __go_alloc (3 * sizeof (ffi_type
*));
132 ret
->elements
[0] = &ffi_type_pointer
;
133 ffi_intgo
= sizeof (intgo
) == 4 ? &ffi_type_sint32
: &ffi_type_sint64
;
134 ret
->elements
[1] = ffi_intgo
;
135 ret
->elements
[2] = NULL
;
139 /* Return an ffi_type for a Go interface type. This describes the
140 __go_interface and __go_empty_interface structs. */
143 go_interface_to_ffi (void)
147 ret
= (ffi_type
*) __go_alloc (sizeof (ffi_type
));
148 ret
->type
= FFI_TYPE_STRUCT
;
149 ret
->elements
= (ffi_type
**) __go_alloc (3 * sizeof (ffi_type
*));
150 ret
->elements
[0] = &ffi_type_pointer
;
151 ret
->elements
[1] = &ffi_type_pointer
;
152 ret
->elements
[2] = NULL
;
157 #ifndef FFI_TARGET_HAS_COMPLEX_TYPE
158 /* If libffi hasn't been updated for this target to support complex,
159 pretend complex is a structure. Warning: This does not work for
160 all ABIs. Eventually libffi should be updated for all targets
161 and this should go away. */
163 static ffi_type
*go_complex_to_ffi (ffi_type
*)
164 __attribute__ ((no_split_stack
));
167 go_complex_to_ffi (ffi_type
*float_type
)
171 ret
= (ffi_type
*) __go_alloc (sizeof (ffi_type
));
172 ret
->type
= FFI_TYPE_STRUCT
;
173 ret
->elements
= (ffi_type
**) __go_alloc (3 * sizeof (ffi_type
*));
174 ret
->elements
[0] = float_type
;
175 ret
->elements
[1] = float_type
;
176 ret
->elements
[2] = NULL
;
181 /* Return an ffi_type for a type described by a
182 __go_type_descriptor. */
185 go_type_to_ffi (const struct __go_type_descriptor
*descriptor
)
187 switch (descriptor
->__code
& GO_CODE_MASK
)
190 if (sizeof (_Bool
) == 1)
191 return &ffi_type_uint8
;
192 else if (sizeof (_Bool
) == sizeof (int))
193 return &ffi_type_uint
;
196 if (sizeof (float) == 4)
197 return &ffi_type_float
;
200 if (sizeof (double) == 8)
201 return &ffi_type_double
;
204 if (sizeof (float) == 4)
206 #ifdef FFI_TARGET_HAS_COMPLEX_TYPE
207 return &ffi_type_complex_float
;
209 return go_complex_to_ffi (&ffi_type_float
);
214 if (sizeof (double) == 8)
216 #ifdef FFI_TARGET_HAS_COMPLEX_TYPE
217 return &ffi_type_complex_double
;
219 return go_complex_to_ffi (&ffi_type_double
);
224 return &ffi_type_sint16
;
226 return &ffi_type_sint32
;
228 return &ffi_type_sint64
;
230 return &ffi_type_sint8
;
232 return sizeof (intgo
) == 4 ? &ffi_type_sint32
: &ffi_type_sint64
;
234 return &ffi_type_uint16
;
236 return &ffi_type_uint32
;
238 return &ffi_type_uint64
;
240 return &ffi_type_uint8
;
242 return sizeof (uintgo
) == 4 ? &ffi_type_uint32
: &ffi_type_uint64
;
244 if (sizeof (void *) == 2)
245 return &ffi_type_uint16
;
246 else if (sizeof (void *) == 4)
247 return &ffi_type_uint32
;
248 else if (sizeof (void *) == 8)
249 return &ffi_type_uint64
;
252 return go_array_to_ffi ((const struct __go_array_type
*) descriptor
);
254 return go_slice_to_ffi ((const struct __go_slice_type
*) descriptor
);
256 return go_struct_to_ffi ((const struct __go_struct_type
*) descriptor
);
258 return go_string_to_ffi ();
260 return go_interface_to_ffi ();
265 case GO_UNSAFE_POINTER
:
266 /* These types are always pointers, and for FFI purposes nothing
268 return &ffi_type_pointer
;
274 /* Return the return type for a function, given the number of out
275 parameters and their types. */
278 go_func_return_ffi (const struct __go_func_type
*func
)
281 const struct __go_type_descriptor
**types
;
285 count
= func
->__out
.__count
;
287 return &ffi_type_void
;
289 types
= (const struct __go_type_descriptor
**) func
->__out
.__values
;
291 // We compile a function that returns a zero-sized value as though
292 // it returns void. This works around a problem in libffi: it can't
293 // represent a zero-sized value.
294 for (i
= 0; i
< count
; ++i
)
296 if (types
[i
]->__size
> 0)
300 return &ffi_type_void
;
303 return go_type_to_ffi (types
[0]);
305 ret
= (ffi_type
*) __go_alloc (sizeof (ffi_type
));
306 ret
->type
= FFI_TYPE_STRUCT
;
307 ret
->elements
= (ffi_type
**) __go_alloc ((count
+ 1) * sizeof (ffi_type
*));
308 for (i
= 0; i
< count
; ++i
)
309 ret
->elements
[i
] = go_type_to_ffi (types
[i
]);
310 ret
->elements
[count
] = NULL
;
314 /* Build an ffi_cif structure for a function described by a
315 __go_func_type structure. */
318 __go_func_to_cif (const struct __go_func_type
*func
, _Bool is_interface
,
319 _Bool is_method
, ffi_cif
*cif
)
322 const struct __go_type_descriptor
**in_types
;
330 num_params
= func
->__in
.__count
;
331 in_types
= ((const struct __go_type_descriptor
**)
332 func
->__in
.__values
);
334 num_args
= num_params
+ (is_interface
? 1 : 0);
335 args
= (ffi_type
**) __go_alloc (num_args
* sizeof (ffi_type
*));
340 args
[0] = &ffi_type_pointer
;
345 args
[0] = &ffi_type_pointer
;
348 for (; i
< num_params
; ++i
)
349 args
[i
+ off
] = go_type_to_ffi (in_types
[i
]);
351 rettype
= go_func_return_ffi (func
);
353 status
= ffi_prep_cif (cif
, FFI_DEFAULT_ABI
, num_args
, rettype
, args
);
354 __go_assert (status
== FFI_OK
);
357 #endif /* defined(USE_LIBFFI) */