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_complex_to_ffi (ffi_type
*)
34 __attribute__ ((no_split_stack
, unused
));
35 static ffi_type
*go_type_to_ffi (const struct __go_type_descriptor
*)
36 __attribute__ ((no_split_stack
));
37 static ffi_type
*go_func_return_ffi (const struct __go_func_type
*)
38 __attribute__ ((no_split_stack
));
40 /* Return an ffi_type for a Go array type. The libffi library does
41 not have any builtin support for passing arrays as values. We work
42 around this by pretending that the array is a struct. */
45 go_array_to_ffi (const struct __go_array_type
*descriptor
)
52 ret
= (ffi_type
*) __go_alloc (sizeof (ffi_type
));
53 ret
->type
= FFI_TYPE_STRUCT
;
54 len
= descriptor
->__len
;
55 ret
->elements
= (ffi_type
**) __go_alloc ((len
+ 1) * sizeof (ffi_type
*));
56 element
= go_type_to_ffi (descriptor
->__element_type
);
57 for (i
= 0; i
< len
; ++i
)
58 ret
->elements
[i
] = element
;
59 ret
->elements
[len
] = NULL
;
63 /* Return an ffi_type for a Go slice type. This describes the
64 __go_open_array type defines in array.h. */
68 const struct __go_slice_type
*descriptor
__attribute__ ((unused
)))
73 ret
= (ffi_type
*) __go_alloc (sizeof (ffi_type
));
74 ret
->type
= FFI_TYPE_STRUCT
;
75 ret
->elements
= (ffi_type
**) __go_alloc (4 * sizeof (ffi_type
*));
76 ret
->elements
[0] = &ffi_type_pointer
;
77 ffi_intgo
= sizeof (intgo
) == 4 ? &ffi_type_sint32
: &ffi_type_sint64
;
78 ret
->elements
[1] = ffi_intgo
;
79 ret
->elements
[2] = ffi_intgo
;
80 ret
->elements
[3] = NULL
;
84 /* Return an ffi_type for a Go struct type. */
87 go_struct_to_ffi (const struct __go_struct_type
*descriptor
)
91 const struct __go_struct_field
*fields
;
94 field_count
= descriptor
->__fields
.__count
;
95 if (field_count
== 0) {
96 return &ffi_type_void
;
98 ret
= (ffi_type
*) __go_alloc (sizeof (ffi_type
));
99 ret
->type
= FFI_TYPE_STRUCT
;
100 fields
= (const struct __go_struct_field
*) descriptor
->__fields
.__values
;
101 ret
->elements
= (ffi_type
**) __go_alloc ((field_count
+ 1)
102 * sizeof (ffi_type
*));
103 for (i
= 0; i
< field_count
; ++i
)
104 ret
->elements
[i
] = go_type_to_ffi (fields
[i
].__type
);
105 ret
->elements
[field_count
] = NULL
;
109 /* Return an ffi_type for a Go string type. This describes the String
113 go_string_to_ffi (void)
118 ret
= (ffi_type
*) __go_alloc (sizeof (ffi_type
));
119 ret
->type
= FFI_TYPE_STRUCT
;
120 ret
->elements
= (ffi_type
**) __go_alloc (3 * sizeof (ffi_type
*));
121 ret
->elements
[0] = &ffi_type_pointer
;
122 ffi_intgo
= sizeof (intgo
) == 4 ? &ffi_type_sint32
: &ffi_type_sint64
;
123 ret
->elements
[1] = ffi_intgo
;
124 ret
->elements
[2] = NULL
;
128 /* Return an ffi_type for a Go interface type. This describes the
129 __go_interface and __go_empty_interface structs. */
132 go_interface_to_ffi (void)
136 ret
= (ffi_type
*) __go_alloc (sizeof (ffi_type
));
137 ret
->type
= FFI_TYPE_STRUCT
;
138 ret
->elements
= (ffi_type
**) __go_alloc (3 * sizeof (ffi_type
*));
139 ret
->elements
[0] = &ffi_type_pointer
;
140 ret
->elements
[1] = &ffi_type_pointer
;
141 ret
->elements
[2] = NULL
;
145 /* Return an ffi_type for a Go complex type. */
148 go_complex_to_ffi (ffi_type
*float_type
)
152 ret
= (ffi_type
*) __go_alloc (sizeof (ffi_type
));
153 ret
->type
= FFI_TYPE_STRUCT
;
154 ret
->elements
= (ffi_type
**) __go_alloc (3 * sizeof (ffi_type
*));
155 ret
->elements
[0] = float_type
;
156 ret
->elements
[1] = float_type
;
157 ret
->elements
[2] = NULL
;
161 /* Return an ffi_type for a type described by a
162 __go_type_descriptor. */
165 go_type_to_ffi (const struct __go_type_descriptor
*descriptor
)
167 switch (descriptor
->__code
& GO_CODE_MASK
)
170 if (sizeof (_Bool
) == 1)
171 return &ffi_type_uint8
;
172 else if (sizeof (_Bool
) == sizeof (int))
173 return &ffi_type_uint
;
176 if (sizeof (float) == 4)
177 return &ffi_type_float
;
180 if (sizeof (double) == 8)
181 return &ffi_type_double
;
185 runtime_throw("the libffi library does not support Complex64 type with "
186 "reflect.Call or runtime.SetFinalizer");
188 if (sizeof (float) == 4)
189 return go_complex_to_ffi (&ffi_type_float
);
194 runtime_throw("the libffi library does not support Complex128 type with "
195 "reflect.Call or runtime.SetFinalizer");
197 if (sizeof (double) == 8)
198 return go_complex_to_ffi (&ffi_type_double
);
202 return &ffi_type_sint16
;
204 return &ffi_type_sint32
;
206 return &ffi_type_sint64
;
208 return &ffi_type_sint8
;
210 return sizeof (intgo
) == 4 ? &ffi_type_sint32
: &ffi_type_sint64
;
212 return &ffi_type_uint16
;
214 return &ffi_type_uint32
;
216 return &ffi_type_uint64
;
218 return &ffi_type_uint8
;
220 return sizeof (uintgo
) == 4 ? &ffi_type_uint32
: &ffi_type_uint64
;
222 if (sizeof (void *) == 2)
223 return &ffi_type_uint16
;
224 else if (sizeof (void *) == 4)
225 return &ffi_type_uint32
;
226 else if (sizeof (void *) == 8)
227 return &ffi_type_uint64
;
230 return go_array_to_ffi ((const struct __go_array_type
*) descriptor
);
232 return go_slice_to_ffi ((const struct __go_slice_type
*) descriptor
);
234 return go_struct_to_ffi ((const struct __go_struct_type
*) descriptor
);
236 return go_string_to_ffi ();
238 return go_interface_to_ffi ();
243 case GO_UNSAFE_POINTER
:
244 /* These types are always pointers, and for FFI purposes nothing
246 return &ffi_type_pointer
;
252 /* Return the return type for a function, given the number of out
253 parameters and their types. */
256 go_func_return_ffi (const struct __go_func_type
*func
)
259 const struct __go_type_descriptor
**types
;
263 count
= func
->__out
.__count
;
265 return &ffi_type_void
;
267 types
= (const struct __go_type_descriptor
**) func
->__out
.__values
;
272 #if defined (__i386__) && !defined (__x86_64__)
273 /* FFI does not support complex types. On 32-bit x86, a
274 complex64 will be returned in %eax/%edx. We normally tell
275 FFI that a complex64 is a struct of two floats. On 32-bit
276 x86 a struct of two floats is returned via a hidden first
277 pointer parameter. Fortunately we can make everything work
278 by pretending that complex64 is int64. */
279 if ((types
[0]->__code
& GO_CODE_MASK
) == GO_COMPLEX64
)
280 return &ffi_type_sint64
;
283 return go_type_to_ffi (types
[0]);
286 ret
= (ffi_type
*) __go_alloc (sizeof (ffi_type
));
287 ret
->type
= FFI_TYPE_STRUCT
;
288 ret
->elements
= (ffi_type
**) __go_alloc ((count
+ 1) * sizeof (ffi_type
*));
289 for (i
= 0; i
< count
; ++i
)
290 ret
->elements
[i
] = go_type_to_ffi (types
[i
]);
291 ret
->elements
[count
] = NULL
;
295 /* Build an ffi_cif structure for a function described by a
296 __go_func_type structure. */
299 __go_func_to_cif (const struct __go_func_type
*func
, _Bool is_interface
,
300 _Bool is_method
, ffi_cif
*cif
)
303 const struct __go_type_descriptor
**in_types
;
311 num_params
= func
->__in
.__count
;
312 in_types
= ((const struct __go_type_descriptor
**)
313 func
->__in
.__values
);
315 num_args
= num_params
+ (is_interface
? 1 : 0);
316 args
= (ffi_type
**) __go_alloc (num_args
* sizeof (ffi_type
*));
321 args
[0] = &ffi_type_pointer
;
326 args
[0] = &ffi_type_pointer
;
329 for (; i
< num_params
; ++i
)
330 args
[i
+ off
] = go_type_to_ffi (in_types
[i
]);
332 rettype
= go_func_return_ffi (func
);
334 status
= ffi_prep_cif (cif
, FFI_DEFAULT_ABI
, num_args
, rettype
, args
);
335 __go_assert (status
== FFI_OK
);
338 #endif /* defined(USE_LIBFFI) */