2016-07-13 Thomas Preud'homme <thomas.preudhomme@arm.com>
[official-gcc.git] / libgo / runtime / go-reflect-call.c
blob2a14d6c6adddebdd79a80738abe417f2bc836b2a
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"
15 #include "go-ffi.h"
17 #if defined(USE_LIBFFI) && FFI_GO_CLOSURES
19 /* The functions in this file are only called from reflect_call. As
20 reflect_call calls a libffi function, which will be compiled
21 without -fsplit-stack, it will always run with a large stack. */
23 static size_t go_results_size (const struct __go_func_type *)
24 __attribute__ ((no_split_stack));
25 static void go_set_results (const struct __go_func_type *, unsigned char *,
26 void **)
27 __attribute__ ((no_split_stack));
29 /* Get the total size required for the result parameters of a
30 function. */
32 static size_t
33 go_results_size (const struct __go_func_type *func)
35 int count;
36 const struct __go_type_descriptor **types;
37 size_t off;
38 size_t maxalign;
39 int i;
41 count = func->__out.__count;
42 if (count == 0)
43 return 0;
45 types = (const struct __go_type_descriptor **) func->__out.__values;
47 /* A single integer return value is always promoted to a full
48 word. */
49 if (count == 1)
51 switch (types[0]->__code & GO_CODE_MASK)
53 case GO_BOOL:
54 case GO_INT8:
55 case GO_INT16:
56 case GO_INT32:
57 case GO_UINT8:
58 case GO_UINT16:
59 case GO_UINT32:
60 case GO_INT:
61 case GO_UINT:
62 return sizeof (ffi_arg);
64 default:
65 break;
69 off = 0;
70 maxalign = 0;
71 for (i = 0; i < count; ++i)
73 size_t align;
75 align = types[i]->__field_align;
76 if (align > maxalign)
77 maxalign = align;
78 off = (off + align - 1) & ~ (align - 1);
79 off += types[i]->__size;
82 off = (off + maxalign - 1) & ~ (maxalign - 1);
84 // The libffi library doesn't understand a struct with no fields.
85 // We generate a struct with a single field of type void. When used
86 // as a return value, libffi will think that requires a byte.
87 if (off == 0)
88 off = 1;
90 return off;
93 /* Copy the results of calling a function via FFI from CALL_RESULT
94 into the addresses in RESULTS. */
96 static void
97 go_set_results (const struct __go_func_type *func, unsigned char *call_result,
98 void **results)
100 int count;
101 const struct __go_type_descriptor **types;
102 size_t off;
103 int i;
105 count = func->__out.__count;
106 if (count == 0)
107 return;
109 types = (const struct __go_type_descriptor **) func->__out.__values;
111 /* A single integer return value is always promoted to a full
112 word. */
113 if (count == 1)
115 switch (types[0]->__code & GO_CODE_MASK)
117 case GO_BOOL:
118 case GO_INT8:
119 case GO_INT16:
120 case GO_INT32:
121 case GO_UINT8:
122 case GO_UINT16:
123 case GO_UINT32:
124 case GO_INT:
125 case GO_UINT:
127 union
129 unsigned char buf[sizeof (ffi_arg)];
130 ffi_arg v;
131 } u;
132 ffi_arg v;
134 __builtin_memcpy (&u.buf, call_result, sizeof (ffi_arg));
135 v = u.v;
137 switch (types[0]->__size)
139 case 1:
141 uint8_t b;
143 b = (uint8_t) v;
144 __builtin_memcpy (results[0], &b, 1);
146 break;
148 case 2:
150 uint16_t s;
152 s = (uint16_t) v;
153 __builtin_memcpy (results[0], &s, 2);
155 break;
157 case 4:
159 uint32_t w;
161 w = (uint32_t) v;
162 __builtin_memcpy (results[0], &w, 4);
164 break;
166 case 8:
168 uint64_t d;
170 d = (uint64_t) v;
171 __builtin_memcpy (results[0], &d, 8);
173 break;
175 default:
176 abort ();
179 return;
181 default:
182 break;
186 off = 0;
187 for (i = 0; i < count; ++i)
189 size_t align;
190 size_t size;
192 align = types[i]->__field_align;
193 size = types[i]->__size;
194 off = (off + align - 1) & ~ (align - 1);
195 __builtin_memcpy (results[i], call_result + off, size);
196 off += size;
200 /* Call a function. The type of the function is FUNC_TYPE, and the
201 closure is FUNC_VAL. PARAMS is an array of parameter addresses.
202 RESULTS is an array of result addresses.
204 If IS_INTERFACE is true this is a call to an interface method and
205 the first argument is the receiver, which is always a pointer.
206 This argument, the receiver, is not described in FUNC_TYPE.
208 If IS_METHOD is true this is a call to a method expression. The
209 first argument is the receiver. It is described in FUNC_TYPE, but
210 regardless of FUNC_TYPE, it is passed as a pointer. */
212 void
213 reflect_call (const struct __go_func_type *func_type, FuncVal *func_val,
214 _Bool is_interface, _Bool is_method, void **params,
215 void **results)
217 ffi_cif cif;
218 unsigned char *call_result;
220 __go_assert ((func_type->__common.__code & GO_CODE_MASK) == GO_FUNC);
221 __go_func_to_cif (func_type, is_interface, is_method, &cif);
223 call_result = (unsigned char *) malloc (go_results_size (func_type));
225 ffi_call_go (&cif, func_val->fn, call_result, params, func_val);
227 /* Some day we may need to free result values if RESULTS is
228 NULL. */
229 if (results != NULL)
230 go_set_results (func_type, call_result, results);
232 free (call_result);
235 #else /* !defined(USE_LIBFFI) */
237 void
238 reflect_call (const struct __go_func_type *func_type __attribute__ ((unused)),
239 FuncVal *func_val __attribute__ ((unused)),
240 _Bool is_interface __attribute__ ((unused)),
241 _Bool is_method __attribute__ ((unused)),
242 void **params __attribute__ ((unused)),
243 void **results __attribute__ ((unused)))
245 /* Without FFI there is nothing we can do. */
246 runtime_throw("libgo built without FFI does not support "
247 "reflect.Call or runtime.SetFinalizer");
250 #endif /* !defined(USE_LIBFFI) */