PR c/61077
[official-gcc.git] / libgo / runtime / go-ffi.c
blob21879b95b77ff505fdb5b318b7ad5fa4751a69b6
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. */
7 #include <stdio.h>
8 #include <stdint.h>
9 #include <stdlib.h>
11 #include "runtime.h"
12 #include "go-alloc.h"
13 #include "go-assert.h"
14 #include "go-type.h"
16 #ifdef USE_LIBFFI
18 #include "ffi.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
23 large stack. */
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. */
44 static ffi_type *
45 go_array_to_ffi (const struct __go_array_type *descriptor)
47 ffi_type *ret;
48 uintptr_t len;
49 ffi_type *element;
50 uintptr_t i;
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;
60 return ret;
63 /* Return an ffi_type for a Go slice type. This describes the
64 __go_open_array type defines in array.h. */
66 static ffi_type *
67 go_slice_to_ffi (
68 const struct __go_slice_type *descriptor __attribute__ ((unused)))
70 ffi_type *ret;
71 ffi_type *ffi_intgo;
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;
81 return ret;
84 /* Return an ffi_type for a Go struct type. */
86 static ffi_type *
87 go_struct_to_ffi (const struct __go_struct_type *descriptor)
89 ffi_type *ret;
90 int field_count;
91 const struct __go_struct_field *fields;
92 int i;
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;
106 return ret;
109 /* Return an ffi_type for a Go string type. This describes the String
110 struct. */
112 static ffi_type *
113 go_string_to_ffi (void)
115 ffi_type *ret;
116 ffi_type *ffi_intgo;
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;
125 return ret;
128 /* Return an ffi_type for a Go interface type. This describes the
129 __go_interface and __go_empty_interface structs. */
131 static ffi_type *
132 go_interface_to_ffi (void)
134 ffi_type *ret;
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;
142 return ret;
145 /* Return an ffi_type for a Go complex type. */
147 static ffi_type *
148 go_complex_to_ffi (ffi_type *float_type)
150 ffi_type *ret;
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;
158 return ret;
161 /* Return an ffi_type for a type described by a
162 __go_type_descriptor. */
164 static ffi_type *
165 go_type_to_ffi (const struct __go_type_descriptor *descriptor)
167 switch (descriptor->__code & GO_CODE_MASK)
169 case GO_BOOL:
170 if (sizeof (_Bool) == 1)
171 return &ffi_type_uint8;
172 else if (sizeof (_Bool) == sizeof (int))
173 return &ffi_type_uint;
174 abort ();
175 case GO_FLOAT32:
176 if (sizeof (float) == 4)
177 return &ffi_type_float;
178 abort ();
179 case GO_FLOAT64:
180 if (sizeof (double) == 8)
181 return &ffi_type_double;
182 abort ();
183 case GO_COMPLEX64:
184 #ifdef __alpha__
185 runtime_throw("the libffi library does not support Complex64 type with "
186 "reflect.Call or runtime.SetFinalizer");
187 #else
188 if (sizeof (float) == 4)
189 return go_complex_to_ffi (&ffi_type_float);
190 abort ();
191 #endif
192 case GO_COMPLEX128:
193 #ifdef __alpha__
194 runtime_throw("the libffi library does not support Complex128 type with "
195 "reflect.Call or runtime.SetFinalizer");
196 #else
197 if (sizeof (double) == 8)
198 return go_complex_to_ffi (&ffi_type_double);
199 abort ();
200 #endif
201 case GO_INT16:
202 return &ffi_type_sint16;
203 case GO_INT32:
204 return &ffi_type_sint32;
205 case GO_INT64:
206 return &ffi_type_sint64;
207 case GO_INT8:
208 return &ffi_type_sint8;
209 case GO_INT:
210 return sizeof (intgo) == 4 ? &ffi_type_sint32 : &ffi_type_sint64;
211 case GO_UINT16:
212 return &ffi_type_uint16;
213 case GO_UINT32:
214 return &ffi_type_uint32;
215 case GO_UINT64:
216 return &ffi_type_uint64;
217 case GO_UINT8:
218 return &ffi_type_uint8;
219 case GO_UINT:
220 return sizeof (uintgo) == 4 ? &ffi_type_uint32 : &ffi_type_uint64;
221 case GO_UINTPTR:
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;
228 abort ();
229 case GO_ARRAY:
230 return go_array_to_ffi ((const struct __go_array_type *) descriptor);
231 case GO_SLICE:
232 return go_slice_to_ffi ((const struct __go_slice_type *) descriptor);
233 case GO_STRUCT:
234 return go_struct_to_ffi ((const struct __go_struct_type *) descriptor);
235 case GO_STRING:
236 return go_string_to_ffi ();
237 case GO_INTERFACE:
238 return go_interface_to_ffi ();
239 case GO_CHAN:
240 case GO_FUNC:
241 case GO_MAP:
242 case GO_PTR:
243 case GO_UNSAFE_POINTER:
244 /* These types are always pointers, and for FFI purposes nothing
245 else matters. */
246 return &ffi_type_pointer;
247 default:
248 abort ();
252 /* Return the return type for a function, given the number of out
253 parameters and their types. */
255 static ffi_type *
256 go_func_return_ffi (const struct __go_func_type *func)
258 int count;
259 const struct __go_type_descriptor **types;
260 ffi_type *ret;
261 int i;
263 count = func->__out.__count;
264 if (count == 0)
265 return &ffi_type_void;
267 types = (const struct __go_type_descriptor **) func->__out.__values;
269 if (count == 1)
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;
281 #endif
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;
292 return ret;
295 /* Build an ffi_cif structure for a function described by a
296 __go_func_type structure. */
298 void
299 __go_func_to_cif (const struct __go_func_type *func, _Bool is_interface,
300 _Bool is_method, ffi_cif *cif)
302 int num_params;
303 const struct __go_type_descriptor **in_types;
304 size_t num_args;
305 ffi_type **args;
306 int off;
307 int i;
308 ffi_type *rettype;
309 ffi_status status;
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 *));
317 i = 0;
318 off = 0;
319 if (is_interface)
321 args[0] = &ffi_type_pointer;
322 off = 1;
324 else if (is_method)
326 args[0] = &ffi_type_pointer;
327 i = 1;
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) */