Daily bump.
[official-gcc.git] / gcc / go / gofrontend / runtime.cc
blobe4dbd26ed5208b65f4ad300ed94e9a30af7bf76b
1 // runtime.cc -- runtime functions called by generated code
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.
7 #include "go-system.h"
9 #include "gogo.h"
10 #include "types.h"
11 #include "expressions.h"
12 #include "runtime.h"
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.
21 // Parameter and result types used by runtime functions.
23 enum Runtime_function_type
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 uint, C type uintgo.
34 RFT_UINT,
35 // Go type uint8, C type uint8_t.
36 RFT_UINT8,
37 // Go type uint16, C type uint16_t.
38 RFT_UINT16,
39 // Go type int32, C type int32_t.
40 RFT_INT32,
41 // Go type uint32, C type uint32_t.
42 RFT_UINT32,
43 // Go type int64, C type int64_t.
44 RFT_INT64,
45 // Go type uint64, C type uint64_t.
46 RFT_UINT64,
47 // Go type uintptr, C type uintptr_t.
48 RFT_UINTPTR,
49 // Go type rune, C type int32_t.
50 RFT_RUNE,
51 // Go type float64, C type double.
52 RFT_FLOAT64,
53 // Go type complex64, C type __complex float.
54 RFT_COMPLEX64,
55 // Go type complex128, C type __complex double.
56 RFT_COMPLEX128,
57 // Go type string, C type struct __go_string.
58 RFT_STRING,
59 // Go type unsafe.Pointer, C type "void *".
60 RFT_POINTER,
61 // Go type []any, C type struct __go_open_array.
62 RFT_SLICE,
63 // Go type map[any]any, C type struct __go_map *.
64 RFT_MAP,
65 // Go type chan any, C type struct __go_channel *.
66 RFT_CHAN,
67 // Go type non-empty interface, C type struct __go_interface.
68 RFT_IFACE,
69 // Go type interface{}, C type struct __go_empty_interface.
70 RFT_EFACE,
71 // Pointer to Go type descriptor.
72 RFT_TYPE,
73 // [2]string.
74 RFT_ARRAY2STRING,
75 // [3]string.
76 RFT_ARRAY3STRING,
77 // [4]string.
78 RFT_ARRAY4STRING,
79 // [5]string.
80 RFT_ARRAY5STRING,
82 NUMBER_OF_RUNTIME_FUNCTION_TYPES
85 // The Type structures for the runtime function types.
87 static Type* runtime_function_types[NUMBER_OF_RUNTIME_FUNCTION_TYPES];
89 // Get the Type for a Runtime_function_type code.
91 static Type*
92 runtime_function_type(Runtime_function_type bft)
94 go_assert(bft < NUMBER_OF_RUNTIME_FUNCTION_TYPES);
95 Type* any = Type::make_pointer_type(Type::make_void_type());
96 if (runtime_function_types[bft] == NULL)
98 const Location bloc = Linemap::predeclared_location();
99 Type* t;
100 switch (bft)
102 default:
103 case RFT_VOID:
104 go_unreachable();
106 case RFT_BOOL:
107 t = Type::make_boolean_type();
108 break;
110 case RFT_BOOLPTR:
111 t = Type::make_pointer_type(Type::lookup_bool_type());
112 break;
114 case RFT_INT:
115 t = Type::lookup_integer_type("int");
116 break;
118 case RFT_UINT:
119 t = Type::lookup_integer_type("uint");
120 break;
122 case RFT_UINT8:
123 t = Type::lookup_integer_type("uint8");
124 break;
126 case RFT_UINT16:
127 t = Type::lookup_integer_type("uint16");
128 break;
130 case RFT_INT32:
131 t = Type::lookup_integer_type("int32");
132 break;
134 case RFT_UINT32:
135 t = Type::lookup_integer_type("uint32");
136 break;
138 case RFT_INT64:
139 t = Type::lookup_integer_type("int64");
140 break;
142 case RFT_UINT64:
143 t = Type::lookup_integer_type("uint64");
144 break;
146 case RFT_RUNE:
147 t = Type::lookup_integer_type("int32");
148 break;
150 case RFT_UINTPTR:
151 t = Type::lookup_integer_type("uintptr");
152 break;
154 case RFT_FLOAT64:
155 t = Type::lookup_float_type("float64");
156 break;
158 case RFT_COMPLEX64:
159 t = Type::lookup_complex_type("complex64");
160 break;
162 case RFT_COMPLEX128:
163 t = Type::lookup_complex_type("complex128");
164 break;
166 case RFT_STRING:
167 t = Type::lookup_string_type();
168 break;
170 case RFT_POINTER:
171 t = Type::make_pointer_type(Type::make_void_type());
172 break;
174 case RFT_SLICE:
175 t = Type::make_array_type(any, NULL);
176 break;
178 case RFT_MAP:
179 t = Type::make_map_type(any, any, bloc);
180 break;
182 case RFT_CHAN:
183 t = Type::make_channel_type(true, true, any);
184 break;
186 case RFT_IFACE:
188 Typed_identifier_list* methods = new Typed_identifier_list();
189 Type* mtype = Type::make_function_type(NULL, NULL, NULL, bloc);
190 methods->push_back(Typed_identifier("x", mtype, bloc));
191 Interface_type* it = Type::make_interface_type(methods, bloc);
192 it->finalize_methods();
193 t = it;
195 break;
197 case RFT_EFACE:
198 t = Type::make_empty_interface_type(bloc);
199 break;
201 case RFT_TYPE:
202 t = Type::make_type_descriptor_ptr_type();
203 break;
205 case RFT_ARRAY2STRING:
207 Array_type* at =
208 Type::make_array_type(Type::make_string_type(),
209 Expression::make_integer_ul(2, NULL,
210 bloc));
211 at->set_is_array_incomparable();
212 t = at;
214 break;
216 case RFT_ARRAY3STRING:
218 Array_type* at =
219 Type::make_array_type(Type::make_string_type(),
220 Expression::make_integer_ul(3, NULL,
221 bloc));
222 at->set_is_array_incomparable();
223 t = at;
225 break;
227 case RFT_ARRAY4STRING:
229 Array_type* at =
230 Type::make_array_type(Type::make_string_type(),
231 Expression::make_integer_ul(4, NULL,
232 bloc));
233 at->set_is_array_incomparable();
234 t = at;
236 break;
238 case RFT_ARRAY5STRING:
240 Array_type* at =
241 Type::make_array_type(Type::make_string_type(),
242 Expression::make_integer_ul(5, NULL,
243 bloc));
244 at->set_is_array_incomparable();
245 t = at;
247 break;
250 runtime_function_types[bft] = t;
253 return runtime_function_types[bft];
256 // Convert an expression to the type to pass to a runtime function.
258 static Expression*
259 convert_to_runtime_function_type(Gogo* gogo, Runtime_function_type bft,
260 Expression* e, Location loc)
262 switch (bft)
264 default:
265 case RFT_VOID:
266 go_unreachable();
268 case RFT_BOOL:
269 case RFT_BOOLPTR:
270 case RFT_INT:
271 case RFT_UINT:
272 case RFT_UINT8:
273 case RFT_UINT16:
274 case RFT_INT32:
275 case RFT_UINT32:
276 case RFT_INT64:
277 case RFT_UINT64:
278 case RFT_UINTPTR:
279 case RFT_RUNE:
280 case RFT_FLOAT64:
281 case RFT_COMPLEX64:
282 case RFT_COMPLEX128:
283 case RFT_STRING:
284 case RFT_POINTER:
286 Type* t = runtime_function_type(bft);
287 Type_context context(t, false);
288 e->determine_type(gogo, &context);
289 if (!Type::are_identical(t, e->type(), true, NULL))
290 e = Expression::make_cast(t, e, loc);
291 return e;
294 case RFT_SLICE:
295 case RFT_MAP:
296 case RFT_CHAN:
297 case RFT_IFACE:
298 case RFT_EFACE:
299 case RFT_ARRAY2STRING:
300 case RFT_ARRAY3STRING:
301 case RFT_ARRAY4STRING:
302 case RFT_ARRAY5STRING:
303 return Expression::make_unsafe_cast(runtime_function_type(bft), e, loc);
305 case RFT_TYPE:
306 go_assert(e->type() == Type::make_type_descriptor_ptr_type());
307 return e;
311 // Convert all the types used for runtime functions to the backend
312 // representation.
314 void
315 Runtime::convert_types(Gogo* gogo)
317 for (int i = 0; i < static_cast<int>(NUMBER_OF_RUNTIME_FUNCTION_TYPES); ++i)
319 Type* t = runtime_function_types[i];
320 if (t != NULL && t->named_type() != NULL)
322 bool r = t->verify(gogo);
323 go_assert(r);
324 t->named_type()->convert(gogo);
329 // The type used to define a runtime function.
331 struct Runtime_function
333 // Function name.
334 const char* name;
335 // Parameter types. Never more than 6, as it happens. RFT_VOID if
336 // not used.
337 Runtime_function_type parameter_types[6];
338 // Result types. Never more than 2, as it happens. RFT_VOID if not
339 // used.
340 Runtime_function_type result_types[2];
343 static const Runtime_function runtime_functions[] =
346 #define DEF_GO_RUNTIME(CODE, NAME, PARAMS, RESULTS) { NAME, PARAMS, RESULTS } ,
348 #include "runtime.def"
350 #undef DEF_GO_RUNTIME
354 static Named_object*
355 runtime_function_declarations[Runtime::NUMBER_OF_FUNCTIONS];
357 // Get the declaration of a runtime function.
359 Named_object*
360 Runtime::runtime_declaration(Function code)
362 go_assert(code < Runtime::NUMBER_OF_FUNCTIONS);
363 if (runtime_function_declarations[code] == NULL)
365 const Runtime_function* pb = &runtime_functions[code];
367 Location bloc = Linemap::predeclared_location();
369 Typed_identifier_list* param_types = NULL;
370 if (pb->parameter_types[0] != RFT_VOID)
372 param_types = new Typed_identifier_list();
373 for (unsigned int i = 0;
374 i < (sizeof(pb->parameter_types)
375 / sizeof (pb->parameter_types[0]));
376 i++)
378 if (pb->parameter_types[i] == RFT_VOID)
379 break;
380 Type* t = runtime_function_type(pb->parameter_types[i]);
381 param_types->push_back(Typed_identifier("", t, bloc));
385 Typed_identifier_list* result_types = NULL;
386 if (pb->result_types[0] != RFT_VOID)
388 result_types = new Typed_identifier_list();
389 for (unsigned int i = 0;
390 i < sizeof(pb->result_types) / sizeof(pb->result_types[0]);
391 i++)
393 if (pb->result_types[i] == RFT_VOID)
394 break;
395 Type* t = runtime_function_type(pb->result_types[i]);
396 result_types->push_back(Typed_identifier("", t, bloc));
400 Function_type* fntype = Type::make_function_type(NULL, param_types,
401 result_types, bloc);
402 const char* n = pb->name;
403 const char* n1 = strchr(n, '.');
404 if (n1 != NULL)
405 n = n1 + 1;
406 Named_object* no = Named_object::make_function_declaration(n, NULL,
407 fntype, bloc);
408 no->func_declaration_value()->set_asm_name(pb->name);
410 runtime_function_declarations[code] = no;
413 return runtime_function_declarations[code];
416 // Make a call to a runtime function.
418 Call_expression*
419 Runtime::make_call(Gogo* gogo, Runtime::Function code, Location loc,
420 int param_count, ...)
422 go_assert(code < Runtime::NUMBER_OF_FUNCTIONS);
424 const Runtime_function* pb = &runtime_functions[code];
426 go_assert(static_cast<size_t>(param_count)
427 <= sizeof(pb->parameter_types) / sizeof(pb->parameter_types[0]));
429 Named_object* no = runtime_declaration(code);
430 Expression* func = Expression::make_func_reference(no, NULL, loc);
432 Expression_list* args = new Expression_list();
433 args->reserve(param_count);
435 va_list ap;
436 va_start(ap, param_count);
437 for (int i = 0; i < param_count; ++i)
439 Expression* e = va_arg(ap, Expression*);
440 Runtime_function_type rft = pb->parameter_types[i];
441 args->push_back(convert_to_runtime_function_type(gogo, rft, e, loc));
443 va_end(ap);
445 return Expression::make_call(func, args, false, loc);
448 // Get the runtime code for a named builtin function. This is used as a helper
449 // when creating function references for call expressions. Every reference to
450 // a builtin runtime function should have the associated runtime code. If the
451 // name is ambiguous and can refer to many runtime codes, return
452 // NUMBER_OF_FUNCTIONS.
454 Runtime::Function
455 Runtime::name_to_code(const std::string& name)
457 Function code = Runtime::NUMBER_OF_FUNCTIONS;
459 // Look through the known names for a match.
460 for (size_t i = 0; i < Runtime::NUMBER_OF_FUNCTIONS; i++)
462 const char* runtime_function_name = runtime_functions[i].name;
463 if (strcmp(runtime_function_name, name.c_str()) == 0)
464 code = static_cast<Runtime::Function>(i);
465 // The names in the table have "runtime." prefix. We may be
466 // called with a name without the prefix. Try matching
467 // without the prefix as well.
468 if (strncmp(runtime_function_name, "runtime.", 8) == 0
469 && strcmp(runtime_function_name + 8, name.c_str()) == 0)
470 code = static_cast<Runtime::Function>(i);
472 return code;