OSDN Git Service

libgo: Solaris and Irix compatibility patches.
[pf3gnuchains/gcc-fork.git] / libgo / runtime / go-reflect-call.c
1 /* go-reflect-call.c -- call reflection support for Go.
2
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.  */
6
7 #include <stdio.h>
8 #include <stdlib.h>
9
10 #include "ffi.h"
11
12 #include "go-alloc.h"
13 #include "go-assert.h"
14 #include "go-type.h"
15 #include "runtime.h"
16
17 /* The functions in this file are only called from reflect_call.  As
18    reflect_call calls a libffi function, which will be compiled
19    without -fsplit-stack, it will always run with a large stack.  */
20
21 static ffi_type *go_array_to_ffi (const struct __go_array_type *)
22   __attribute__ ((no_split_stack));
23 static ffi_type *go_slice_to_ffi (const struct __go_slice_type *)
24   __attribute__ ((no_split_stack));
25 static ffi_type *go_struct_to_ffi (const struct __go_struct_type *)
26   __attribute__ ((no_split_stack));
27 static ffi_type *go_string_to_ffi (void) __attribute__ ((no_split_stack));
28 static ffi_type *go_interface_to_ffi (void) __attribute__ ((no_split_stack));
29 static ffi_type *go_complex_to_ffi (ffi_type *)
30   __attribute__ ((no_split_stack));
31 static ffi_type *go_type_to_ffi (const struct __go_type_descriptor *)
32   __attribute__ ((no_split_stack));
33 static ffi_type *go_func_return_ffi (const struct __go_func_type *)
34   __attribute__ ((no_split_stack));
35 static void go_func_to_cif (const struct __go_func_type *, _Bool, _Bool,
36                             ffi_cif *)
37   __attribute__ ((no_split_stack));
38 static size_t go_results_size (const struct __go_func_type *)
39   __attribute__ ((no_split_stack));
40 static void go_set_results (const struct __go_func_type *, unsigned char *,
41                             void **)
42   __attribute__ ((no_split_stack));
43
44 /* Return an ffi_type for a Go array type.  The libffi library does
45    not have any builtin support for passing arrays as values.  We work
46    around this by pretending that the array is a struct.  */
47
48 static ffi_type *
49 go_array_to_ffi (const struct __go_array_type *descriptor)
50 {
51   ffi_type *ret;
52   uintptr_t len;
53   ffi_type *element;
54   uintptr_t i;
55
56   ret = (ffi_type *) __go_alloc (sizeof (ffi_type));
57   ret->type = FFI_TYPE_STRUCT;
58   len = descriptor->__len;
59   ret->elements = (ffi_type **) __go_alloc ((len + 1) * sizeof (ffi_type *));
60   element = go_type_to_ffi (descriptor->__element_type);
61   for (i = 0; i < len; ++i)
62     ret->elements[i] = element;
63   ret->elements[len] = NULL;
64   return ret;
65 }
66
67 /* Return an ffi_type for a Go slice type.  This describes the
68    __go_open_array type defines in array.h.  */
69
70 static ffi_type *
71 go_slice_to_ffi (
72     const struct __go_slice_type *descriptor __attribute__ ((unused)))
73 {
74   ffi_type *ret;
75
76   ret = (ffi_type *) __go_alloc (sizeof (ffi_type));
77   ret->type = FFI_TYPE_STRUCT;
78   ret->elements = (ffi_type **) __go_alloc (4 * sizeof (ffi_type *));
79   ret->elements[0] = &ffi_type_pointer;
80   ret->elements[1] = &ffi_type_sint;
81   ret->elements[2] = &ffi_type_sint;
82   ret->elements[3] = NULL;
83   return ret;
84 }
85
86 /* Return an ffi_type for a Go struct type.  */
87
88 static ffi_type *
89 go_struct_to_ffi (const struct __go_struct_type *descriptor)
90 {
91   ffi_type *ret;
92   int field_count;
93   const struct __go_struct_field *fields;
94   int i;
95
96   ret = (ffi_type *) __go_alloc (sizeof (ffi_type));
97   ret->type = FFI_TYPE_STRUCT;
98   field_count = descriptor->__fields.__count;
99   fields = (const struct __go_struct_field *) descriptor->__fields.__values;
100   ret->elements = (ffi_type **) __go_alloc ((field_count + 1)
101                                             * sizeof (ffi_type *));
102   for (i = 0; i < field_count; ++i)
103     ret->elements[i] = go_type_to_ffi (fields[i].__type);
104   ret->elements[field_count] = NULL;
105   return ret;
106 }
107
108 /* Return an ffi_type for a Go string type.  This describes the
109    __go_string struct.  */
110
111 static ffi_type *
112 go_string_to_ffi (void)
113 {
114   ffi_type *ret;
115
116   ret = (ffi_type *) __go_alloc (sizeof (ffi_type));
117   ret->type = FFI_TYPE_STRUCT;
118   ret->elements = (ffi_type **) __go_alloc (3 * sizeof (ffi_type *));
119   ret->elements[0] = &ffi_type_pointer;
120   ret->elements[1] = &ffi_type_sint;
121   ret->elements[2] = NULL;
122   return ret;
123 }
124
125 /* Return an ffi_type for a Go interface type.  This describes the
126    __go_interface and __go_empty_interface structs.  */
127
128 static ffi_type *
129 go_interface_to_ffi (void)
130 {
131   ffi_type *ret;
132
133   ret = (ffi_type *) __go_alloc (sizeof (ffi_type));
134   ret->type = FFI_TYPE_STRUCT;
135   ret->elements = (ffi_type **) __go_alloc (3 * sizeof (ffi_type *));
136   ret->elements[0] = &ffi_type_pointer;
137   ret->elements[1] = &ffi_type_pointer;
138   ret->elements[2] = NULL;
139   return ret;
140 }
141
142 /* Return an ffi_type for a Go complex type.  */
143
144 static ffi_type *
145 go_complex_to_ffi (ffi_type *float_type)
146 {
147   ffi_type *ret;
148
149   ret = (ffi_type *) __go_alloc (sizeof (ffi_type));
150   ret->type = FFI_TYPE_STRUCT;
151   ret->elements = (ffi_type **) __go_alloc (3 * sizeof (ffi_type *));
152   ret->elements[0] = float_type;
153   ret->elements[1] = float_type;
154   ret->elements[2] = NULL;
155   return ret;
156 }
157
158 /* Return an ffi_type for a type described by a
159    __go_type_descriptor.  */
160
161 static ffi_type *
162 go_type_to_ffi (const struct __go_type_descriptor *descriptor)
163 {
164   switch (descriptor->__code & GO_CODE_MASK)
165     {
166     case GO_BOOL:
167       if (sizeof (_Bool) == 1)
168         return &ffi_type_uint8;
169       else if (sizeof (_Bool) == sizeof (int))
170         return &ffi_type_uint;
171       abort ();
172     case GO_FLOAT32:
173       if (sizeof (float) == 4)
174         return &ffi_type_float;
175       abort ();
176     case GO_FLOAT64:
177       if (sizeof (double) == 8)
178         return &ffi_type_double;
179       abort ();
180     case GO_COMPLEX64:
181       if (sizeof (float) == 4)
182         return go_complex_to_ffi (&ffi_type_float);
183       abort ();
184     case GO_COMPLEX128:
185       if (sizeof (double) == 8)
186         return go_complex_to_ffi (&ffi_type_double);
187       abort ();
188     case GO_INT16:
189       return &ffi_type_sint16;
190     case GO_INT32:
191       return &ffi_type_sint32;
192     case GO_INT64:
193       return &ffi_type_sint64;
194     case GO_INT8:
195       return &ffi_type_sint8;
196     case GO_INT:
197       return &ffi_type_sint;
198     case GO_UINT16:
199       return &ffi_type_uint16;
200     case GO_UINT32:
201       return &ffi_type_uint32;
202     case GO_UINT64:
203       return &ffi_type_uint64;
204     case GO_UINT8:
205       return &ffi_type_uint8;
206     case GO_UINT:
207       return &ffi_type_uint;
208     case GO_UINTPTR:
209       if (sizeof (void *) == 2)
210         return &ffi_type_uint16;
211       else if (sizeof (void *) == 4)
212         return &ffi_type_uint32;
213       else if (sizeof (void *) == 8)
214         return &ffi_type_uint64;
215       abort ();
216     case GO_ARRAY:
217       return go_array_to_ffi ((const struct __go_array_type *) descriptor);
218     case GO_SLICE:
219       return go_slice_to_ffi ((const struct __go_slice_type *) descriptor);
220     case GO_STRUCT:
221       return go_struct_to_ffi ((const struct __go_struct_type *) descriptor);
222     case GO_STRING:
223       return go_string_to_ffi ();
224     case GO_INTERFACE:
225       return go_interface_to_ffi ();
226     case GO_CHAN:
227     case GO_FUNC:
228     case GO_MAP:
229     case GO_PTR:
230     case GO_UNSAFE_POINTER:
231       /* These types are always pointers, and for FFI purposes nothing
232          else matters.  */
233       return &ffi_type_pointer;
234     default:
235       abort ();
236     }
237 }
238
239 /* Return the return type for a function, given the number of out
240    parameters and their types.  */
241
242 static ffi_type *
243 go_func_return_ffi (const struct __go_func_type *func)
244 {
245   int count;
246   const struct __go_type_descriptor **types;
247   ffi_type *ret;
248   int i;
249
250   count = func->__out.__count;
251   if (count == 0)
252     return &ffi_type_void;
253
254   types = (const struct __go_type_descriptor **) func->__out.__values;
255
256   if (count == 1)
257     return go_type_to_ffi (types[0]);
258
259   ret = (ffi_type *) __go_alloc (sizeof (ffi_type));
260   ret->type = FFI_TYPE_STRUCT;
261   ret->elements = (ffi_type **) __go_alloc ((count + 1) * sizeof (ffi_type *));
262   for (i = 0; i < count; ++i)
263     ret->elements[i] = go_type_to_ffi (types[i]);
264   ret->elements[count] = NULL;
265   return ret;
266 }
267
268 /* Build an ffi_cif structure for a function described by a
269    __go_func_type structure.  */
270
271 static void
272 go_func_to_cif (const struct __go_func_type *func, _Bool is_interface,
273                 _Bool is_method, ffi_cif *cif)
274 {
275   int num_params;
276   const struct __go_type_descriptor **in_types;
277   size_t num_args;
278   ffi_type **args;
279   int off;
280   int i;
281   ffi_type *rettype;
282   ffi_status status;
283
284   num_params = func->__in.__count;
285   in_types = ((const struct __go_type_descriptor **)
286               func->__in.__values);
287
288   num_args = num_params + (is_interface ? 1 : 0);
289   args = (ffi_type **) __go_alloc (num_args * sizeof (ffi_type *));
290   i = 0;
291   off = 0;
292   if (is_interface)
293     {
294       args[0] = &ffi_type_pointer;
295       off = 1;
296     }
297   else if (is_method)
298     {
299       args[0] = &ffi_type_pointer;
300       i = 1;
301     }
302   for (; i < num_params; ++i)
303     args[i + off] = go_type_to_ffi (in_types[i]);
304
305   rettype = go_func_return_ffi (func);
306
307   status = ffi_prep_cif (cif, FFI_DEFAULT_ABI, num_args, rettype, args);
308   __go_assert (status == FFI_OK);
309 }
310
311 /* Get the total size required for the result parameters of a
312    function.  */
313
314 static size_t
315 go_results_size (const struct __go_func_type *func)
316 {
317   int count;
318   const struct __go_type_descriptor **types;
319   size_t off;
320   size_t maxalign;
321   int i;
322
323   count = func->__out.__count;
324   if (count == 0)
325     return 0;
326
327   types = (const struct __go_type_descriptor **) func->__out.__values;
328
329   off = 0;
330   maxalign = 0;
331   for (i = 0; i < count; ++i)
332     {
333       size_t align;
334
335       align = types[i]->__field_align;
336       if (align > maxalign)
337         maxalign = align;
338       off = (off + align - 1) & ~ (align - 1);
339       off += types[i]->__size;
340     }
341
342   off = (off + maxalign - 1) & ~ (maxalign - 1);
343
344   return off;
345 }
346
347 /* Copy the results of calling a function via FFI from CALL_RESULT
348    into the addresses in RESULTS.  */
349
350 static void
351 go_set_results (const struct __go_func_type *func, unsigned char *call_result,
352                 void **results)
353 {
354   int count;
355   const struct __go_type_descriptor **types;
356   size_t off;
357   int i;
358
359   count = func->__out.__count;
360   if (count == 0)
361     return;
362
363   types = (const struct __go_type_descriptor **) func->__out.__values;
364
365   off = 0;
366   for (i = 0; i < count; ++i)
367     {
368       size_t align;
369       size_t size;
370
371       align = types[i]->__field_align;
372       size = types[i]->__size;
373       off = (off + align - 1) & ~ (align - 1);
374       __builtin_memcpy (results[i], call_result + off, size);
375       off += size;
376     }
377 }
378
379 /* Call a function.  The type of the function is FUNC_TYPE, and the
380    address is FUNC_ADDR.  PARAMS is an array of parameter addresses.
381    RESULTS is an array of result addresses.  */
382
383 void
384 reflect_call (const struct __go_func_type *func_type, const void *func_addr,
385               _Bool is_interface, _Bool is_method, void **params,
386               void **results)
387 {
388   ffi_cif cif;
389   unsigned char *call_result;
390
391   __go_assert (func_type->__common.__code == GO_FUNC);
392   go_func_to_cif (func_type, is_interface, is_method, &cif);
393
394   call_result = (unsigned char *) malloc (go_results_size (func_type));
395
396   ffi_call (&cif, func_addr, call_result, params);
397
398   /* Some day we may need to free result values if RESULTS is
399      NULL.  */
400   if (results != NULL)
401     go_set_results (func_type, call_result, results);
402
403   free (call_result);
404 }