bb30cc15aad029d3e848e78cbbe0e129f3c74609
[gcc.git] / gcc / go / gofrontend / runtime.cc
1 // runtime.cc -- runtime functions called by generated code
2
3 // Copyright 2011 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 "go-system.h"
8
9 #include "gogo.h"
10 #include "types.h"
11 #include "expressions.h"
12 #include "runtime.h"
13
14 // The frontend generates calls to various runtime functions. They
15 // are implemented in libgo/runtime. This is how the runtime
16 // functions are represented in the frontend. Note that there is
17 // currently nothing which ensures that the compiler's understanding
18 // of the runtime function matches the actual implementation in
19 // libgo/runtime.
20
21 // Parameter and result types used by runtime functions.
22
23 enum Runtime_function_type
24 {
25 // General indicator that value is not used.
26 RFT_VOID,
27 // Go untyped bool, C type _Bool.
28 RFT_BOOL,
29 // Go type *bool, C type _Bool*.
30 RFT_BOOLPTR,
31 // Go type int, C type intgo.
32 RFT_INT,
33 // Go type int32, C type int32_t.
34 RFT_INT32,
35 // Go type int64, C type int64_t.
36 RFT_INT64,
37 // Go type uint64, C type uint64_t.
38 RFT_UINT64,
39 // Go type uintptr, C type uintptr_t.
40 RFT_UINTPTR,
41 // Go type rune, C type int32_t.
42 RFT_RUNE,
43 // Go type float64, C type double.
44 RFT_FLOAT64,
45 // Go type complex64, C type __complex float.
46 RFT_COMPLEX64,
47 // Go type complex128, C type __complex double.
48 RFT_COMPLEX128,
49 // Go type string, C type struct __go_string.
50 RFT_STRING,
51 // Go type unsafe.Pointer, C type "void *".
52 RFT_POINTER,
53 // Go type []any, C type struct __go_open_array.
54 RFT_SLICE,
55 // Go type map[any]any, C type struct __go_map *.
56 RFT_MAP,
57 // Go type chan any, C type struct __go_channel *.
58 RFT_CHAN,
59 // Go type non-empty interface, C type struct __go_interface.
60 RFT_IFACE,
61 // Go type interface{}, C type struct __go_empty_interface.
62 RFT_EFACE,
63 // Go type func(unsafe.Pointer), C type void (*) (void *).
64 RFT_FUNC_PTR,
65 // Pointer to Go type descriptor.
66 RFT_TYPE,
67 // [2]string.
68 RFT_ARRAY2STRING,
69 // [3]string.
70 RFT_ARRAY3STRING,
71 // [4]string.
72 RFT_ARRAY4STRING,
73 // [5]string.
74 RFT_ARRAY5STRING,
75
76 NUMBER_OF_RUNTIME_FUNCTION_TYPES
77 };
78
79 // The Type structures for the runtime function types.
80
81 static Type* runtime_function_types[NUMBER_OF_RUNTIME_FUNCTION_TYPES];
82
83 // Get the Type for a Runtime_function_type code.
84
85 static Type*
86 runtime_function_type(Runtime_function_type bft)
87 {
88 go_assert(bft < NUMBER_OF_RUNTIME_FUNCTION_TYPES);
89 Type* any = Type::make_pointer_type(Type::make_void_type());
90 if (runtime_function_types[bft] == NULL)
91 {
92 const Location bloc = Linemap::predeclared_location();
93 Type* t;
94 switch (bft)
95 {
96 default:
97 case RFT_VOID:
98 go_unreachable();
99
100 case RFT_BOOL:
101 t = Type::make_boolean_type();
102 break;
103
104 case RFT_BOOLPTR:
105 t = Type::make_pointer_type(Type::lookup_bool_type());
106 break;
107
108 case RFT_INT:
109 t = Type::lookup_integer_type("int");
110 break;
111
112 case RFT_INT32:
113 t = Type::lookup_integer_type("int32");
114 break;
115
116 case RFT_INT64:
117 t = Type::lookup_integer_type("int64");
118 break;
119
120 case RFT_UINT64:
121 t = Type::lookup_integer_type("uint64");
122 break;
123
124 case RFT_RUNE:
125 t = Type::lookup_integer_type("int32");
126 break;
127
128 case RFT_UINTPTR:
129 t = Type::lookup_integer_type("uintptr");
130 break;
131
132 case RFT_FLOAT64:
133 t = Type::lookup_float_type("float64");
134 break;
135
136 case RFT_COMPLEX64:
137 t = Type::lookup_complex_type("complex64");
138 break;
139
140 case RFT_COMPLEX128:
141 t = Type::lookup_complex_type("complex128");
142 break;
143
144 case RFT_STRING:
145 t = Type::lookup_string_type();
146 break;
147
148 case RFT_POINTER:
149 t = Type::make_pointer_type(Type::make_void_type());
150 break;
151
152 case RFT_SLICE:
153 t = Type::make_array_type(any, NULL);
154 break;
155
156 case RFT_MAP:
157 t = Type::make_map_type(any, any, bloc);
158 break;
159
160 case RFT_CHAN:
161 t = Type::make_channel_type(true, true, any);
162 break;
163
164 case RFT_IFACE:
165 {
166 Typed_identifier_list* methods = new Typed_identifier_list();
167 Type* mtype = Type::make_function_type(NULL, NULL, NULL, bloc);
168 methods->push_back(Typed_identifier("x", mtype, bloc));
169 Interface_type* it = Type::make_interface_type(methods, bloc);
170 it->finalize_methods();
171 t = it;
172 }
173 break;
174
175 case RFT_EFACE:
176 t = Type::make_empty_interface_type(bloc);
177 break;
178
179 case RFT_FUNC_PTR:
180 {
181 Typed_identifier_list* param_types = new Typed_identifier_list();
182 Type* ptrtype = runtime_function_type(RFT_POINTER);
183 param_types->push_back(Typed_identifier("", ptrtype, bloc));
184 t = Type::make_function_type(NULL, param_types, NULL, bloc);
185 }
186 break;
187
188 case RFT_TYPE:
189 t = Type::make_type_descriptor_ptr_type();
190 break;
191
192 case RFT_ARRAY2STRING:
193 {
194 Array_type* at =
195 Type::make_array_type(Type::make_string_type(),
196 Expression::make_integer_ul(2, NULL,
197 bloc));
198 at->set_is_array_incomparable();
199 t = at;
200 }
201 break;
202
203 case RFT_ARRAY3STRING:
204 {
205 Array_type* at =
206 Type::make_array_type(Type::make_string_type(),
207 Expression::make_integer_ul(3, NULL,
208 bloc));
209 at->set_is_array_incomparable();
210 t = at;
211 }
212 break;
213
214 case RFT_ARRAY4STRING:
215 {
216 Array_type* at =
217 Type::make_array_type(Type::make_string_type(),
218 Expression::make_integer_ul(4, NULL,
219 bloc));
220 at->set_is_array_incomparable();
221 t = at;
222 }
223 break;
224
225 case RFT_ARRAY5STRING:
226 {
227 Array_type* at =
228 Type::make_array_type(Type::make_string_type(),
229 Expression::make_integer_ul(5, NULL,
230 bloc));
231 at->set_is_array_incomparable();
232 t = at;
233 }
234 break;
235 }
236
237 runtime_function_types[bft] = t;
238 }
239
240 return runtime_function_types[bft];
241 }
242
243 // Convert an expression to the type to pass to a runtime function.
244
245 static Expression*
246 convert_to_runtime_function_type(Runtime_function_type bft, Expression* e,
247 Location loc)
248 {
249 switch (bft)
250 {
251 default:
252 case RFT_VOID:
253 go_unreachable();
254
255 case RFT_BOOL:
256 case RFT_BOOLPTR:
257 case RFT_INT:
258 case RFT_INT32:
259 case RFT_INT64:
260 case RFT_UINT64:
261 case RFT_UINTPTR:
262 case RFT_RUNE:
263 case RFT_FLOAT64:
264 case RFT_COMPLEX64:
265 case RFT_COMPLEX128:
266 case RFT_STRING:
267 case RFT_POINTER:
268 case RFT_FUNC_PTR:
269 {
270 Type* t = runtime_function_type(bft);
271 if (!Type::are_identical(t, e->type(), true, NULL))
272 e = Expression::make_cast(t, e, loc);
273 return e;
274 }
275
276 case RFT_SLICE:
277 case RFT_MAP:
278 case RFT_CHAN:
279 case RFT_IFACE:
280 case RFT_EFACE:
281 case RFT_ARRAY2STRING:
282 case RFT_ARRAY3STRING:
283 case RFT_ARRAY4STRING:
284 case RFT_ARRAY5STRING:
285 return Expression::make_unsafe_cast(runtime_function_type(bft), e, loc);
286
287 case RFT_TYPE:
288 go_assert(e->type() == Type::make_type_descriptor_ptr_type());
289 return e;
290 }
291 }
292
293 // Convert all the types used for runtime functions to the backend
294 // representation.
295
296 void
297 Runtime::convert_types(Gogo* gogo)
298 {
299 for (int i = 0; i < static_cast<int>(NUMBER_OF_RUNTIME_FUNCTION_TYPES); ++i)
300 {
301 Type* t = runtime_function_types[i];
302 if (t != NULL && t->named_type() != NULL)
303 {
304 bool r = t->verify();
305 go_assert(r);
306 t->named_type()->convert(gogo);
307 }
308 }
309 }
310
311 // The type used to define a runtime function.
312
313 struct Runtime_function
314 {
315 // Function name.
316 const char* name;
317 // Parameter types. Never more than 6, as it happens. RFT_VOID if
318 // not used.
319 Runtime_function_type parameter_types[6];
320 // Result types. Never more than 2, as it happens. RFT_VOID if not
321 // used.
322 Runtime_function_type result_types[2];
323 };
324
325 static const Runtime_function runtime_functions[] =
326 {
327
328 #define DEF_GO_RUNTIME(CODE, NAME, PARAMS, RESULTS) { NAME, PARAMS, RESULTS } ,
329
330 #include "runtime.def"
331
332 #undef DEF_GO_RUNTIME
333
334 };
335
336 static Named_object*
337 runtime_function_declarations[Runtime::NUMBER_OF_FUNCTIONS];
338
339 // Get the declaration of a runtime function.
340
341 Named_object*
342 Runtime::runtime_declaration(Function code)
343 {
344 go_assert(code < Runtime::NUMBER_OF_FUNCTIONS);
345 if (runtime_function_declarations[code] == NULL)
346 {
347 const Runtime_function* pb = &runtime_functions[code];
348
349 Location bloc = Linemap::predeclared_location();
350
351 Typed_identifier_list* param_types = NULL;
352 if (pb->parameter_types[0] != RFT_VOID)
353 {
354 param_types = new Typed_identifier_list();
355 for (unsigned int i = 0;
356 i < (sizeof(pb->parameter_types)
357 / sizeof (pb->parameter_types[0]));
358 i++)
359 {
360 if (pb->parameter_types[i] == RFT_VOID)
361 break;
362 Type* t = runtime_function_type(pb->parameter_types[i]);
363 param_types->push_back(Typed_identifier("", t, bloc));
364 }
365 }
366
367 Typed_identifier_list* result_types = NULL;
368 if (pb->result_types[0] != RFT_VOID)
369 {
370 result_types = new Typed_identifier_list();
371 for (unsigned int i = 0;
372 i < sizeof(pb->result_types) / sizeof(pb->result_types[0]);
373 i++)
374 {
375 if (pb->result_types[i] == RFT_VOID)
376 break;
377 Type* t = runtime_function_type(pb->result_types[i]);
378 result_types->push_back(Typed_identifier("", t, bloc));
379 }
380 }
381
382 Function_type* fntype = Type::make_function_type(NULL, param_types,
383 result_types, bloc);
384 const char* n = pb->name;
385 const char* n1 = strchr(n, '.');
386 if (n1 != NULL)
387 n = n1 + 1;
388 Named_object* no = Named_object::make_function_declaration(n, NULL,
389 fntype, bloc);
390 no->func_declaration_value()->set_asm_name(pb->name);
391
392 runtime_function_declarations[code] = no;
393 }
394
395 return runtime_function_declarations[code];
396 }
397
398 // Make a call to a runtime function.
399
400 Call_expression*
401 Runtime::make_call(Runtime::Function code, Location loc,
402 int param_count, ...)
403 {
404 go_assert(code < Runtime::NUMBER_OF_FUNCTIONS);
405
406 const Runtime_function* pb = &runtime_functions[code];
407
408 go_assert(static_cast<size_t>(param_count)
409 <= sizeof(pb->parameter_types) / sizeof(pb->parameter_types[0]));
410
411 Named_object* no = runtime_declaration(code);
412 Expression* func = Expression::make_func_reference(no, NULL, loc);
413
414 Expression_list* args = new Expression_list();
415 args->reserve(param_count);
416
417 va_list ap;
418 va_start(ap, param_count);
419 for (int i = 0; i < param_count; ++i)
420 {
421 Expression* e = va_arg(ap, Expression*);
422 Runtime_function_type rft = pb->parameter_types[i];
423 args->push_back(convert_to_runtime_function_type(rft, e, loc));
424 }
425 va_end(ap);
426
427 return Expression::make_call(func, args, false, loc);
428 }
429
430 // Get the runtime code for a named builtin function. This is used as a helper
431 // when creating function references for call expressions. Every reference to
432 // a builtin runtime function should have the associated runtime code. If the
433 // name is ambiguous and can refer to many runtime codes, return
434 // NUMBER_OF_FUNCTIONS.
435
436 Runtime::Function
437 Runtime::name_to_code(const std::string& name)
438 {
439 Function code = Runtime::NUMBER_OF_FUNCTIONS;
440
441 // Look through the known names for a match.
442 for (size_t i = 0; i < Runtime::NUMBER_OF_FUNCTIONS; i++)
443 {
444 const char* runtime_function_name = runtime_functions[i].name;
445 if (strcmp(runtime_function_name, name.c_str()) == 0)
446 code = static_cast<Runtime::Function>(i);
447 // The names in the table have "runtime." prefix. We may be
448 // called with a name without the prefix. Try matching
449 // without the prefix as well.
450 if (strncmp(runtime_function_name, "runtime.", 8) == 0
451 && strcmp(runtime_function_name + 8, name.c_str()) == 0)
452 code = static_cast<Runtime::Function>(i);
453 }
454 return code;
455 }