[Patch Doc] Update documentation for __fp16 type
[official-gcc.git] / libgo / runtime / go-reflect-call.c
blobdc2f60575ecee148ffac0d5afa9b49199fcee3b8
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
17 #include "ffi.h"
18 #endif
20 #if defined(USE_LIBFFI) && FFI_GO_CLOSURES
22 /* The functions in this file are only called from reflect_call. As
23 reflect_call calls a libffi function, which will be compiled
24 without -fsplit-stack, it will always run with a large stack. */
26 static size_t go_results_size (const struct __go_func_type *)
27 __attribute__ ((no_split_stack));
28 static void go_set_results (const struct __go_func_type *, unsigned char *,
29 void **)
30 __attribute__ ((no_split_stack));
32 /* Get the total size required for the result parameters of a
33 function. */
35 static size_t
36 go_results_size (const struct __go_func_type *func)
38 int count;
39 const struct __go_type_descriptor **types;
40 size_t off;
41 size_t maxalign;
42 int i;
44 count = func->__out.__count;
45 if (count == 0)
46 return 0;
48 types = (const struct __go_type_descriptor **) func->__out.__values;
50 /* A single integer return value is always promoted to a full
51 word. */
52 if (count == 1)
54 switch (types[0]->__code & GO_CODE_MASK)
56 case GO_BOOL:
57 case GO_INT8:
58 case GO_INT16:
59 case GO_INT32:
60 case GO_UINT8:
61 case GO_UINT16:
62 case GO_UINT32:
63 case GO_INT:
64 case GO_UINT:
65 return sizeof (ffi_arg);
67 default:
68 break;
72 off = 0;
73 maxalign = 0;
74 for (i = 0; i < count; ++i)
76 size_t align;
78 align = types[i]->__field_align;
79 if (align > maxalign)
80 maxalign = align;
81 off = (off + align - 1) & ~ (align - 1);
82 off += types[i]->__size;
85 off = (off + maxalign - 1) & ~ (maxalign - 1);
87 // The libffi library doesn't understand a struct with no fields.
88 // We generate a struct with a single field of type void. When used
89 // as a return value, libffi will think that requires a byte.
90 if (off == 0)
91 off = 1;
93 return off;
96 /* Copy the results of calling a function via FFI from CALL_RESULT
97 into the addresses in RESULTS. */
99 static void
100 go_set_results (const struct __go_func_type *func, unsigned char *call_result,
101 void **results)
103 int count;
104 const struct __go_type_descriptor **types;
105 size_t off;
106 int i;
108 count = func->__out.__count;
109 if (count == 0)
110 return;
112 types = (const struct __go_type_descriptor **) func->__out.__values;
114 /* A single integer return value is always promoted to a full
115 word. */
116 if (count == 1)
118 switch (types[0]->__code & GO_CODE_MASK)
120 case GO_BOOL:
121 case GO_INT8:
122 case GO_INT16:
123 case GO_INT32:
124 case GO_UINT8:
125 case GO_UINT16:
126 case GO_UINT32:
127 case GO_INT:
128 case GO_UINT:
130 union
132 unsigned char buf[sizeof (ffi_arg)];
133 ffi_arg v;
134 } u;
135 ffi_arg v;
137 __builtin_memcpy (&u.buf, call_result, sizeof (ffi_arg));
138 v = u.v;
140 switch (types[0]->__size)
142 case 1:
144 uint8_t b;
146 b = (uint8_t) v;
147 __builtin_memcpy (results[0], &b, 1);
149 break;
151 case 2:
153 uint16_t s;
155 s = (uint16_t) v;
156 __builtin_memcpy (results[0], &s, 2);
158 break;
160 case 4:
162 uint32_t w;
164 w = (uint32_t) v;
165 __builtin_memcpy (results[0], &w, 4);
167 break;
169 case 8:
171 uint64_t d;
173 d = (uint64_t) v;
174 __builtin_memcpy (results[0], &d, 8);
176 break;
178 default:
179 abort ();
182 return;
184 default:
185 break;
189 off = 0;
190 for (i = 0; i < count; ++i)
192 size_t align;
193 size_t size;
195 align = types[i]->__field_align;
196 size = types[i]->__size;
197 off = (off + align - 1) & ~ (align - 1);
198 __builtin_memcpy (results[i], call_result + off, size);
199 off += size;
203 /* The code that converts the Go type to an FFI type is written in Go,
204 so that it can allocate Go heap memory. */
205 extern void ffiFuncToCIF(const struct __go_func_type*, _Bool, _Bool, ffi_cif*)
206 __asm__ ("runtime.ffiFuncToCIF");
208 /* Call a function. The type of the function is FUNC_TYPE, and the
209 closure is FUNC_VAL. PARAMS is an array of parameter addresses.
210 RESULTS is an array of result addresses.
212 If IS_INTERFACE is true this is a call to an interface method and
213 the first argument is the receiver, which is always a pointer.
214 This argument, the receiver, is not described in FUNC_TYPE.
216 If IS_METHOD is true this is a call to a method expression. The
217 first argument is the receiver. It is described in FUNC_TYPE, but
218 regardless of FUNC_TYPE, it is passed as a pointer. */
220 void
221 reflect_call (const struct __go_func_type *func_type, FuncVal *func_val,
222 _Bool is_interface, _Bool is_method, void **params,
223 void **results)
225 ffi_cif cif;
226 unsigned char *call_result;
228 __go_assert ((func_type->__common.__code & GO_CODE_MASK) == GO_FUNC);
229 ffiFuncToCIF (func_type, is_interface, is_method, &cif);
231 call_result = (unsigned char *) malloc (go_results_size (func_type));
233 ffi_call_go (&cif, func_val->fn, call_result, params, func_val);
235 /* Some day we may need to free result values if RESULTS is
236 NULL. */
237 if (results != NULL)
238 go_set_results (func_type, call_result, results);
240 free (call_result);
243 #else /* !defined(USE_LIBFFI) */
245 void
246 reflect_call (const struct __go_func_type *func_type __attribute__ ((unused)),
247 FuncVal *func_val __attribute__ ((unused)),
248 _Bool is_interface __attribute__ ((unused)),
249 _Bool is_method __attribute__ ((unused)),
250 void **params __attribute__ ((unused)),
251 void **results __attribute__ ((unused)))
253 /* Without FFI there is nothing we can do. */
254 runtime_throw("libgo built without FFI does not support "
255 "reflect.Call or runtime.SetFinalizer");
258 #endif /* !defined(USE_LIBFFI) */