runtime: initialize variable to avoid compiler warning
[official-gcc.git] / libgo / runtime / go-ffi.c
blobaafc7b205e0fb579a0fde75526eea84cc48a4d15
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_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. */
42 static ffi_type *
43 go_array_to_ffi (const struct __go_array_type *descriptor)
45 ffi_type *ret;
46 uintptr_t len;
47 ffi_type *element;
48 uintptr_t i;
50 ret = (ffi_type *) __go_alloc (sizeof (ffi_type));
51 ret->type = FFI_TYPE_STRUCT;
52 len = descriptor->__len;
53 if (len == 0)
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;
59 return ret;
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;
66 return ret;
69 /* Return an ffi_type for a Go slice type. This describes the
70 __go_open_array type defines in array.h. */
72 static ffi_type *
73 go_slice_to_ffi (
74 const struct __go_slice_type *descriptor __attribute__ ((unused)))
76 ffi_type *ret;
77 ffi_type *ffi_intgo;
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;
87 return ret;
90 /* Return an ffi_type for a Go struct type. */
92 static ffi_type *
93 go_struct_to_ffi (const struct __go_struct_type *descriptor)
95 ffi_type *ret;
96 int field_count;
97 const struct __go_struct_field *fields;
98 int i;
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;
109 return ret;
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;
117 return ret;
120 /* Return an ffi_type for a Go string type. This describes the String
121 struct. */
123 static ffi_type *
124 go_string_to_ffi (void)
126 ffi_type *ret;
127 ffi_type *ffi_intgo;
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;
136 return ret;
139 /* Return an ffi_type for a Go interface type. This describes the
140 __go_interface and __go_empty_interface structs. */
142 static ffi_type *
143 go_interface_to_ffi (void)
145 ffi_type *ret;
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;
153 return ret;
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));
166 static ffi_type *
167 go_complex_to_ffi (ffi_type *float_type)
169 ffi_type *ret;
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;
177 return ret;
179 #endif
181 /* Return an ffi_type for a type described by a
182 __go_type_descriptor. */
184 static ffi_type *
185 go_type_to_ffi (const struct __go_type_descriptor *descriptor)
187 switch (descriptor->__code & GO_CODE_MASK)
189 case GO_BOOL:
190 if (sizeof (_Bool) == 1)
191 return &ffi_type_uint8;
192 else if (sizeof (_Bool) == sizeof (int))
193 return &ffi_type_uint;
194 abort ();
195 case GO_FLOAT32:
196 if (sizeof (float) == 4)
197 return &ffi_type_float;
198 abort ();
199 case GO_FLOAT64:
200 if (sizeof (double) == 8)
201 return &ffi_type_double;
202 abort ();
203 case GO_COMPLEX64:
204 if (sizeof (float) == 4)
206 #ifdef FFI_TARGET_HAS_COMPLEX_TYPE
207 return &ffi_type_complex_float;
208 #else
209 return go_complex_to_ffi (&ffi_type_float);
210 #endif
212 abort ();
213 case GO_COMPLEX128:
214 if (sizeof (double) == 8)
216 #ifdef FFI_TARGET_HAS_COMPLEX_TYPE
217 return &ffi_type_complex_double;
218 #else
219 return go_complex_to_ffi (&ffi_type_double);
220 #endif
222 abort ();
223 case GO_INT16:
224 return &ffi_type_sint16;
225 case GO_INT32:
226 return &ffi_type_sint32;
227 case GO_INT64:
228 return &ffi_type_sint64;
229 case GO_INT8:
230 return &ffi_type_sint8;
231 case GO_INT:
232 return sizeof (intgo) == 4 ? &ffi_type_sint32 : &ffi_type_sint64;
233 case GO_UINT16:
234 return &ffi_type_uint16;
235 case GO_UINT32:
236 return &ffi_type_uint32;
237 case GO_UINT64:
238 return &ffi_type_uint64;
239 case GO_UINT8:
240 return &ffi_type_uint8;
241 case GO_UINT:
242 return sizeof (uintgo) == 4 ? &ffi_type_uint32 : &ffi_type_uint64;
243 case GO_UINTPTR:
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;
250 abort ();
251 case GO_ARRAY:
252 return go_array_to_ffi ((const struct __go_array_type *) descriptor);
253 case GO_SLICE:
254 return go_slice_to_ffi ((const struct __go_slice_type *) descriptor);
255 case GO_STRUCT:
256 return go_struct_to_ffi ((const struct __go_struct_type *) descriptor);
257 case GO_STRING:
258 return go_string_to_ffi ();
259 case GO_INTERFACE:
260 return go_interface_to_ffi ();
261 case GO_CHAN:
262 case GO_FUNC:
263 case GO_MAP:
264 case GO_PTR:
265 case GO_UNSAFE_POINTER:
266 /* These types are always pointers, and for FFI purposes nothing
267 else matters. */
268 return &ffi_type_pointer;
269 default:
270 abort ();
274 /* Return the return type for a function, given the number of out
275 parameters and their types. */
277 static ffi_type *
278 go_func_return_ffi (const struct __go_func_type *func)
280 int count;
281 const struct __go_type_descriptor **types;
282 ffi_type *ret;
283 int i;
285 count = func->__out.__count;
286 if (count == 0)
287 return &ffi_type_void;
289 types = (const struct __go_type_descriptor **) func->__out.__values;
291 if (count == 1)
292 return go_type_to_ffi (types[0]);
294 ret = (ffi_type *) __go_alloc (sizeof (ffi_type));
295 ret->type = FFI_TYPE_STRUCT;
296 ret->elements = (ffi_type **) __go_alloc ((count + 1) * sizeof (ffi_type *));
297 for (i = 0; i < count; ++i)
298 ret->elements[i] = go_type_to_ffi (types[i]);
299 ret->elements[count] = NULL;
300 return ret;
303 /* Build an ffi_cif structure for a function described by a
304 __go_func_type structure. */
306 void
307 __go_func_to_cif (const struct __go_func_type *func, _Bool is_interface,
308 _Bool is_method, ffi_cif *cif)
310 int num_params;
311 const struct __go_type_descriptor **in_types;
312 size_t num_args;
313 ffi_type **args;
314 int off;
315 int i;
316 ffi_type *rettype;
317 ffi_status status;
319 num_params = func->__in.__count;
320 in_types = ((const struct __go_type_descriptor **)
321 func->__in.__values);
323 num_args = num_params + (is_interface ? 1 : 0);
324 args = (ffi_type **) __go_alloc (num_args * sizeof (ffi_type *));
325 i = 0;
326 off = 0;
327 if (is_interface)
329 args[0] = &ffi_type_pointer;
330 off = 1;
332 else if (is_method)
334 args[0] = &ffi_type_pointer;
335 i = 1;
337 for (; i < num_params; ++i)
338 args[i + off] = go_type_to_ffi (in_types[i]);
340 rettype = go_func_return_ffi (func);
342 status = ffi_prep_cif (cif, FFI_DEFAULT_ABI, num_args, rettype, args);
343 __go_assert (status == FFI_OK);
346 #endif /* defined(USE_LIBFFI) */