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.
13 #include "expressions.h"
16 // The frontend generates calls to various runtime functions. They
17 // are implemented in libgo/runtime. This is how the runtime
18 // functions are represented in the frontend. Note that there is
19 // currently nothing which ensures that the compiler's understanding
20 // of the runtime function matches the actual implementation in
23 // Parameter and result types used by runtime functions.
25 enum Runtime_function_type
27 // General indicator that value is not used.
29 // Go type bool, C type _Bool.
31 // Go type *bool, C type _Bool*.
33 // Go type int, C type int.
35 // Go type int64, C type int64_t.
37 // Go type uint64, C type uint64_t.
39 // Go type uintptr, C type uintptr_t.
41 // Go type rune, C type int32_t.
43 // Go type float64, C type double.
45 // Go type complex128, C type __complex double.
47 // Go type string, C type struct __go_string.
49 // Go type unsafe.Pointer, C type "void *".
51 // Go type []any, C type struct __go_open_array.
53 // Go type map[any]any, C type struct __go_map *.
55 // Pointer to map iteration type.
57 // Go type chan any, C type struct __go_channel *.
59 // Go type non-empty interface, C type struct __go_interface.
61 // Go type interface{}, C type struct __go_empty_interface.
63 // Go type func(unsafe.Pointer), C type void (*) (void *).
65 // Pointer to Go type descriptor.
67 // Pointer to map descriptor.
70 NUMBER_OF_RUNTIME_FUNCTION_TYPES
73 // The Type structures for the runtime function types.
75 static Type* runtime_function_types[NUMBER_OF_RUNTIME_FUNCTION_TYPES];
77 // Get the Type for a Runtime_function_type code.
80 runtime_function_type(Runtime_function_type bft)
82 go_assert(bft < NUMBER_OF_RUNTIME_FUNCTION_TYPES);
83 if (runtime_function_types[bft] == NULL)
85 const Location bloc = Linemap::predeclared_location();
94 t = Type::lookup_bool_type();
98 t = Type::make_pointer_type(Type::lookup_bool_type());
102 t = Type::lookup_integer_type("int");
106 t = Type::lookup_integer_type("int64");
110 t = Type::lookup_integer_type("uint64");
114 t = Type::lookup_integer_type("int32");
118 t = Type::lookup_integer_type("uintptr");
122 t = Type::lookup_float_type("float64");
126 t = Type::lookup_complex_type("complex128");
130 t = Type::lookup_string_type();
134 t = Type::make_pointer_type(Type::make_void_type());
138 t = Type::make_array_type(Type::make_void_type(), NULL);
142 t = Type::make_map_type(Type::make_void_type(),
143 Type::make_void_type(),
148 t = Type::make_pointer_type(Runtime::map_iteration_type());
152 t = Type::make_channel_type(true, true, Type::make_void_type());
157 Typed_identifier_list* methods = new Typed_identifier_list();
158 Type* mtype = Type::make_function_type(NULL, NULL, NULL, bloc);
159 methods->push_back(Typed_identifier("x", mtype, bloc));
160 Interface_type* it = Type::make_interface_type(methods, bloc);
161 it->finalize_methods();
167 t = Type::make_empty_interface_type(bloc);
172 Typed_identifier_list* param_types = new Typed_identifier_list();
173 Type* ptrtype = runtime_function_type(RFT_POINTER);
174 param_types->push_back(Typed_identifier("", ptrtype, bloc));
175 t = Type::make_function_type(NULL, param_types, NULL, bloc);
180 t = Type::make_type_descriptor_ptr_type();
183 case RFT_MAPDESCRIPTOR:
184 t = Type::make_pointer_type(Map_type::make_map_descriptor_type());
188 runtime_function_types[bft] = t;
191 return runtime_function_types[bft];
194 // Convert an expression to the type to pass to a runtime function.
197 convert_to_runtime_function_type(Runtime_function_type bft, Expression* e,
220 Type* t = runtime_function_type(bft);
221 if (!Type::are_identical(t, e->type(), true, NULL))
222 e = Expression::make_cast(t, e, loc);
231 return Expression::make_unsafe_cast(runtime_function_type(bft), e, loc);
234 go_assert(e->type() == Type::make_type_descriptor_ptr_type());
237 case RFT_MAPDESCRIPTOR:
238 go_assert(e->type()->points_to()
239 == Map_type::make_map_descriptor_type());
244 // Convert all the types used for runtime functions to the backend
248 Runtime::convert_types(Gogo* gogo)
250 for (int i = 0; i < static_cast<int>(NUMBER_OF_RUNTIME_FUNCTION_TYPES); ++i)
252 Type* t = runtime_function_types[i];
253 if (t != NULL && t->named_type() != NULL)
255 bool r = t->verify();
257 t->named_type()->convert(gogo);
262 // The type used to define a runtime function.
264 struct Runtime_function
268 // Parameter types. Never more than 6, as it happens. RFT_VOID if
270 Runtime_function_type parameter_types[6];
271 // Result types. Never more than 2, as it happens. RFT_VOID if not
273 Runtime_function_type result_types[2];
276 static const Runtime_function runtime_functions[] =
279 #define DEF_GO_RUNTIME(CODE, NAME, PARAMS, RESULTS) { NAME, PARAMS, RESULTS } ,
281 #include "runtime.def"
283 #undef DEF_GO_RUNTIME
288 runtime_function_declarations[Runtime::NUMBER_OF_FUNCTIONS];
290 // Get the declaration of a runtime function.
293 Runtime::runtime_declaration(Function code)
295 go_assert(code < Runtime::NUMBER_OF_FUNCTIONS);
296 if (runtime_function_declarations[code] == NULL)
298 const Runtime_function* pb = &runtime_functions[code];
300 Location bloc = Linemap::predeclared_location();
302 Typed_identifier_list* param_types = NULL;
303 if (pb->parameter_types[0] != RFT_VOID)
305 param_types = new Typed_identifier_list();
306 for (unsigned int i = 0;
307 i < (sizeof(pb->parameter_types)
308 / sizeof (pb->parameter_types[0]));
311 if (pb->parameter_types[i] == RFT_VOID)
313 Type* t = runtime_function_type(pb->parameter_types[i]);
314 param_types->push_back(Typed_identifier("", t, bloc));
318 Typed_identifier_list* result_types = NULL;
319 if (pb->result_types[0] != RFT_VOID)
321 result_types = new Typed_identifier_list();
322 for (unsigned int i = 0;
323 i < sizeof(pb->result_types) / sizeof(pb->result_types[0]);
326 if (pb->result_types[i] == RFT_VOID)
328 Type* t = runtime_function_type(pb->result_types[i]);
329 result_types->push_back(Typed_identifier("", t, bloc));
333 Function_type* fntype = Type::make_function_type(NULL, param_types,
335 const char* n = pb->name;
336 const char* n1 = strchr(n, '.');
339 Named_object* no = Named_object::make_function_declaration(n, NULL,
341 no->func_declaration_value()->set_asm_name(pb->name);
343 runtime_function_declarations[code] = no;
346 return runtime_function_declarations[code];
349 // Make a call to a runtime function.
352 Runtime::make_call(Runtime::Function code, Location loc,
353 int param_count, ...)
355 go_assert(code < Runtime::NUMBER_OF_FUNCTIONS);
357 const Runtime_function* pb = &runtime_functions[code];
359 go_assert(static_cast<size_t>(param_count)
360 <= sizeof(pb->parameter_types) / sizeof(pb->parameter_types[0]));
362 Named_object* no = runtime_declaration(code);
363 Expression* func = Expression::make_func_reference(no, NULL, loc);
365 Expression_list* args = new Expression_list();
366 args->reserve(param_count);
369 va_start(ap, param_count);
370 for (int i = 0; i < param_count; ++i)
372 Expression* e = va_arg(ap, Expression*);
373 Runtime_function_type rft = pb->parameter_types[i];
374 args->push_back(convert_to_runtime_function_type(rft, e, loc));
378 return Expression::make_call(func, args, false, loc);
381 // The type we use for a map iteration. This is really a struct which
382 // is four pointers long. This must match the runtime struct
386 Runtime::map_iteration_type()
388 const unsigned long map_iteration_size = 4;
391 mpz_init_set_ui(ival, map_iteration_size);
392 Expression* iexpr = Expression::make_integer(&ival, NULL,
393 Linemap::predeclared_location());
396 return Type::make_array_type(runtime_function_type(RFT_POINTER), iexpr);