Fix "PR c++/92804 ICE trying to use concept as a nested-name-specifier"
[official-gcc.git] / libgo / runtime / go-reflect-call.c
blob4d887eb87181f137d8a7ee52d23d2ee09ff76021
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-assert.h"
14 #ifdef USE_LIBFFI
15 #include "ffi.h"
16 #endif
18 #if defined(USE_LIBFFI) && FFI_GO_CLOSURES
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 functype *)
25 __attribute__ ((no_split_stack));
26 static void go_set_results (const struct functype *, unsigned char *, 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 functype *func)
35 int count;
36 const struct _type **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 _type **) func->out.__values;
47 /* A single integer return value is always promoted to a full word.
48 There is similar code below and in libgo/go/reflect/makefunc_ffi.go.*/
49 if (count == 1)
51 switch (types[0]->kind & kindMask)
53 case kindBool:
54 case kindInt8:
55 case kindInt16:
56 case kindInt32:
57 case kindUint8:
58 case kindUint16:
59 case kindUint32:
60 return sizeof (ffi_arg);
62 default:
63 break;
67 off = 0;
68 maxalign = 0;
69 for (i = 0; i < count; ++i)
71 size_t align;
73 align = types[i]->fieldAlign;
74 if (align > maxalign)
75 maxalign = align;
76 off = (off + align - 1) & ~ (align - 1);
77 off += types[i]->size;
80 off = (off + maxalign - 1) & ~ (maxalign - 1);
82 // The libffi library doesn't understand a struct with no fields.
83 // We generate a struct with a single field of type void. When used
84 // as a return value, libffi will think that requires a byte.
85 if (off == 0)
86 off = 1;
88 return off;
91 /* Copy the results of calling a function via FFI from CALL_RESULT
92 into the addresses in RESULTS. */
94 static void
95 go_set_results (const struct functype *func, unsigned char *call_result,
96 void **results)
98 int count;
99 const struct _type **types;
100 size_t off;
101 int i;
103 count = func->out.__count;
104 if (count == 0)
105 return;
107 types = (const struct _type **) func->out.__values;
109 /* A single integer return value is always promoted to a full word.
110 There is similar code above and in libgo/go/reflect/makefunc_ffi.go.*/
111 if (count == 1)
113 switch (types[0]->kind & kindMask)
115 case kindBool:
116 case kindInt8:
117 case kindInt16:
118 case kindInt32:
119 case kindUint8:
120 case kindUint16:
121 case kindUint32:
123 union
125 unsigned char buf[sizeof (ffi_arg)];
126 ffi_arg v;
127 } u;
128 ffi_arg v;
130 __builtin_memcpy (&u.buf, call_result, sizeof (ffi_arg));
131 v = u.v;
133 switch (types[0]->size)
135 case 1:
137 uint8_t b;
139 b = (uint8_t) v;
140 __builtin_memcpy (results[0], &b, 1);
142 break;
144 case 2:
146 uint16_t s;
148 s = (uint16_t) v;
149 __builtin_memcpy (results[0], &s, 2);
151 break;
153 case 4:
155 uint32_t w;
157 w = (uint32_t) v;
158 __builtin_memcpy (results[0], &w, 4);
160 break;
162 case 8:
164 uint64_t d;
166 d = (uint64_t) v;
167 __builtin_memcpy (results[0], &d, 8);
169 break;
171 default:
172 abort ();
175 return;
177 default:
178 break;
182 off = 0;
183 for (i = 0; i < count; ++i)
185 size_t align;
186 size_t size;
188 align = types[i]->fieldAlign;
189 size = types[i]->size;
190 off = (off + align - 1) & ~ (align - 1);
191 __builtin_memcpy (results[i], call_result + off, size);
192 off += size;
196 /* The code that converts the Go type to an FFI type is written in Go,
197 so that it can allocate Go heap memory. */
198 extern void ffiFuncToCIF(const struct functype*, _Bool, _Bool, ffi_cif*)
199 __asm__ ("runtime.ffiFuncToCIF");
201 /* Call a function. The type of the function is FUNC_TYPE, and the
202 closure is FUNC_VAL. PARAMS is an array of parameter addresses.
203 RESULTS is an array of result addresses.
205 If IS_INTERFACE is true this is a call to an interface method and
206 the first argument is the receiver, which is always a pointer.
207 This argument, the receiver, is not described in FUNC_TYPE.
209 If IS_METHOD is true this is a call to a method expression. The
210 first argument is the receiver. It is described in FUNC_TYPE, but
211 regardless of FUNC_TYPE, it is passed as a pointer. */
213 void
214 reflect_call (const struct functype *func_type, FuncVal *func_val,
215 _Bool is_interface, _Bool is_method, void **params,
216 void **results)
218 ffi_cif cif;
219 unsigned char *call_result;
221 __go_assert ((func_type->typ.kind & kindMask) == kindFunc);
222 ffiFuncToCIF (func_type, is_interface, is_method, &cif);
224 call_result = (unsigned char *) malloc (go_results_size (func_type));
226 ffi_call_go (&cif, (void (*)(void)) func_val->fn, call_result, params,
227 func_val);
229 /* Some day we may need to free result values if RESULTS is
230 NULL. */
231 if (results != NULL)
232 go_set_results (func_type, call_result, results);
234 free (call_result);
237 #else /* !defined(USE_LIBFFI) */
239 void
240 reflect_call (const struct functype *func_type __attribute__ ((unused)),
241 FuncVal *func_val __attribute__ ((unused)),
242 _Bool is_interface __attribute__ ((unused)),
243 _Bool is_method __attribute__ ((unused)),
244 void **params __attribute__ ((unused)),
245 void **results __attribute__ ((unused)))
247 /* Without FFI there is nothing we can do. */
248 runtime_throw("libgo built without FFI does not support "
249 "reflect.Call or runtime.SetFinalizer");
252 #endif /* !defined(USE_LIBFFI) */