2014-07-29 Ed Smith-Rowland <3dw4rd@verizon.net>
[official-gcc.git] / libgo / runtime / go-reflect-call.c
blobdfc703eb2c827c92ba06511104228ff7a37dab03
1 /* go-reflect-call.c -- call reflection support for Go.
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 "go-ffi.h"
20 /* The functions in this file are only called from reflect_call. As
21 reflect_call calls a libffi function, which will be compiled
22 without -fsplit-stack, it will always run with a large stack. */
24 static size_t go_results_size (const struct __go_func_type *)
25 __attribute__ ((no_split_stack));
26 static void go_set_results (const struct __go_func_type *, unsigned char *,
27 void **)
28 __attribute__ ((no_split_stack));
30 /* Get the total size required for the result parameters of a
31 function. */
33 static size_t
34 go_results_size (const struct __go_func_type *func)
36 int count;
37 const struct __go_type_descriptor **types;
38 size_t off;
39 size_t maxalign;
40 int i;
42 count = func->__out.__count;
43 if (count == 0)
44 return 0;
46 types = (const struct __go_type_descriptor **) func->__out.__values;
48 /* A single integer return value is always promoted to a full
49 word. */
50 if (count == 1)
52 switch (types[0]->__code & GO_CODE_MASK)
54 case GO_BOOL:
55 case GO_INT8:
56 case GO_INT16:
57 case GO_INT32:
58 case GO_UINT8:
59 case GO_UINT16:
60 case GO_UINT32:
61 case GO_INT:
62 case GO_UINT:
63 return sizeof (ffi_arg);
65 default:
66 break;
70 off = 0;
71 maxalign = 0;
72 for (i = 0; i < count; ++i)
74 size_t align;
76 align = types[i]->__field_align;
77 if (align > maxalign)
78 maxalign = align;
79 off = (off + align - 1) & ~ (align - 1);
80 off += types[i]->__size;
83 off = (off + maxalign - 1) & ~ (maxalign - 1);
85 return off;
88 /* Copy the results of calling a function via FFI from CALL_RESULT
89 into the addresses in RESULTS. */
91 static void
92 go_set_results (const struct __go_func_type *func, unsigned char *call_result,
93 void **results)
95 int count;
96 const struct __go_type_descriptor **types;
97 size_t off;
98 int i;
100 count = func->__out.__count;
101 if (count == 0)
102 return;
104 types = (const struct __go_type_descriptor **) func->__out.__values;
106 /* A single integer return value is always promoted to a full
107 word. */
108 if (count == 1)
110 switch (types[0]->__code & GO_CODE_MASK)
112 case GO_BOOL:
113 case GO_INT8:
114 case GO_INT16:
115 case GO_INT32:
116 case GO_UINT8:
117 case GO_UINT16:
118 case GO_UINT32:
119 case GO_INT:
120 case GO_UINT:
122 union
124 unsigned char buf[sizeof (ffi_arg)];
125 ffi_arg v;
126 } u;
127 ffi_arg v;
129 __builtin_memcpy (&u.buf, call_result, sizeof (ffi_arg));
130 v = u.v;
132 switch (types[0]->__size)
134 case 1:
136 uint8_t b;
138 b = (uint8_t) v;
139 __builtin_memcpy (results[0], &b, 1);
141 break;
143 case 2:
145 uint16_t s;
147 s = (uint16_t) v;
148 __builtin_memcpy (results[0], &s, 2);
150 break;
152 case 4:
154 uint32_t w;
156 w = (uint32_t) v;
157 __builtin_memcpy (results[0], &w, 4);
159 break;
161 case 8:
163 uint64_t d;
165 d = (uint64_t) v;
166 __builtin_memcpy (results[0], &d, 8);
168 break;
170 default:
171 abort ();
174 return;
176 default:
177 break;
181 off = 0;
182 for (i = 0; i < count; ++i)
184 size_t align;
185 size_t size;
187 align = types[i]->__field_align;
188 size = types[i]->__size;
189 off = (off + align - 1) & ~ (align - 1);
190 __builtin_memcpy (results[i], call_result + off, size);
191 off += size;
195 /* Call a function. The type of the function is FUNC_TYPE, and the
196 closure is FUNC_VAL. PARAMS is an array of parameter addresses.
197 RESULTS is an array of result addresses.
199 If IS_INTERFACE is true this is a call to an interface method and
200 the first argument is the receiver, which is always a pointer.
201 This argument, the receiver, is not described in FUNC_TYPE.
203 If IS_METHOD is true this is a call to a method expression. The
204 first argument is the receiver. It is described in FUNC_TYPE, but
205 regardless of FUNC_TYPE, it is passed as a pointer.
207 If neither IS_INTERFACE nor IS_METHOD is true then we are calling a
208 function indirectly, and we must pass a closure pointer via
209 __go_set_closure. The pointer to pass is simply FUNC_VAL. */
211 void
212 reflect_call (const struct __go_func_type *func_type, FuncVal *func_val,
213 _Bool is_interface, _Bool is_method, void **params,
214 void **results)
216 ffi_cif cif;
217 unsigned char *call_result;
219 __go_assert ((func_type->__common.__code & GO_CODE_MASK) == GO_FUNC);
220 __go_func_to_cif (func_type, is_interface, is_method, &cif);
222 call_result = (unsigned char *) malloc (go_results_size (func_type));
224 if (!is_interface && !is_method)
225 __go_set_closure (func_val);
226 ffi_call (&cif, func_val->fn, call_result, params);
228 /* Some day we may need to free result values if RESULTS is
229 NULL. */
230 if (results != NULL)
231 go_set_results (func_type, call_result, results);
233 free (call_result);
236 #else /* !defined(USE_LIBFFI) */
238 void
239 reflect_call (const struct __go_func_type *func_type __attribute__ ((unused)),
240 FuncVal *func_val __attribute__ ((unused)),
241 _Bool is_interface __attribute__ ((unused)),
242 _Bool is_method __attribute__ ((unused)),
243 void **params __attribute__ ((unused)),
244 void **results __attribute__ ((unused)))
246 /* Without FFI there is nothing we can do. */
247 runtime_throw("libgo built without FFI does not support "
248 "reflect.Call or runtime.SetFinalizer");
251 #endif /* !defined(USE_LIBFFI) */