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.
11 #include "expressions.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
21 // Parameter and result types used by runtime functions.
23 enum Runtime_function_type
25 // General indicator that value is not used.
27 // Go type bool, C type _Bool.
29 // Go type *bool, C type _Bool*.
31 // Go type int, C type intgo.
33 // Go type int32, C type int32_t.
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 complex64, C type __complex float.
47 // Go type complex128, C type __complex double.
49 // Go type string, C type struct __go_string.
51 // Go type unsafe.Pointer, C type "void *".
53 // Go type []any, C type struct __go_open_array.
55 // Go type map[any]any, C type struct __go_map *.
57 // Pointer to map iteration type.
59 // Go type chan any, C type struct __go_channel *.
61 // Go type non-empty interface, C type struct __go_interface.
63 // Go type interface{}, C type struct __go_empty_interface.
65 // Go type func(unsafe.Pointer), C type void (*) (void *).
67 // Pointer to Go type descriptor.
69 // Pointer to map descriptor.
72 NUMBER_OF_RUNTIME_FUNCTION_TYPES
75 // The Type structures for the runtime function types.
77 static Type
* runtime_function_types
[NUMBER_OF_RUNTIME_FUNCTION_TYPES
];
79 // Get the Type for a Runtime_function_type code.
82 runtime_function_type(Runtime_function_type bft
)
84 go_assert(bft
< NUMBER_OF_RUNTIME_FUNCTION_TYPES
);
85 if (runtime_function_types
[bft
] == NULL
)
87 const Location bloc
= Linemap::predeclared_location();
96 t
= Type::lookup_bool_type();
100 t
= Type::make_pointer_type(Type::lookup_bool_type());
104 t
= Type::lookup_integer_type("int");
108 t
= Type::lookup_integer_type("int32");
112 t
= Type::lookup_integer_type("int64");
116 t
= Type::lookup_integer_type("uint64");
120 t
= Type::lookup_integer_type("int32");
124 t
= Type::lookup_integer_type("uintptr");
128 t
= Type::lookup_float_type("float64");
132 t
= Type::lookup_complex_type("complex64");
136 t
= Type::lookup_complex_type("complex128");
140 t
= Type::lookup_string_type();
144 t
= Type::make_pointer_type(Type::make_void_type());
148 t
= Type::make_array_type(Type::make_void_type(), NULL
);
152 t
= Type::make_map_type(Type::make_void_type(),
153 Type::make_void_type(),
158 t
= Type::make_pointer_type(Runtime::map_iteration_type());
162 t
= Type::make_channel_type(true, true, Type::make_void_type());
167 Typed_identifier_list
* methods
= new Typed_identifier_list();
168 Type
* mtype
= Type::make_function_type(NULL
, NULL
, NULL
, bloc
);
169 methods
->push_back(Typed_identifier("x", mtype
, bloc
));
170 Interface_type
* it
= Type::make_interface_type(methods
, bloc
);
171 it
->finalize_methods();
177 t
= Type::make_empty_interface_type(bloc
);
182 Typed_identifier_list
* param_types
= new Typed_identifier_list();
183 Type
* ptrtype
= runtime_function_type(RFT_POINTER
);
184 param_types
->push_back(Typed_identifier("", ptrtype
, bloc
));
185 t
= Type::make_function_type(NULL
, param_types
, NULL
, bloc
);
190 t
= Type::make_type_descriptor_ptr_type();
193 case RFT_MAPDESCRIPTOR
:
194 t
= Type::make_pointer_type(Map_type::make_map_descriptor_type());
198 runtime_function_types
[bft
] = t
;
201 return runtime_function_types
[bft
];
204 // Convert an expression to the type to pass to a runtime function.
207 convert_to_runtime_function_type(Runtime_function_type bft
, Expression
* e
,
232 Type
* t
= runtime_function_type(bft
);
233 if (!Type::are_identical(t
, e
->type(), true, NULL
))
234 e
= Expression::make_cast(t
, e
, loc
);
243 return Expression::make_unsafe_cast(runtime_function_type(bft
), e
, loc
);
246 go_assert(e
->type() == Type::make_type_descriptor_ptr_type());
249 case RFT_MAPDESCRIPTOR
:
250 go_assert(e
->type()->points_to()
251 == Map_type::make_map_descriptor_type());
256 // Convert all the types used for runtime functions to the backend
260 Runtime::convert_types(Gogo
* gogo
)
262 for (int i
= 0; i
< static_cast<int>(NUMBER_OF_RUNTIME_FUNCTION_TYPES
); ++i
)
264 Type
* t
= runtime_function_types
[i
];
265 if (t
!= NULL
&& t
->named_type() != NULL
)
267 bool r
= t
->verify();
269 t
->named_type()->convert(gogo
);
274 // The type used to define a runtime function.
276 struct Runtime_function
280 // Parameter types. Never more than 6, as it happens. RFT_VOID if
282 Runtime_function_type parameter_types
[6];
283 // Result types. Never more than 2, as it happens. RFT_VOID if not
285 Runtime_function_type result_types
[2];
288 static const Runtime_function runtime_functions
[] =
291 #define DEF_GO_RUNTIME(CODE, NAME, PARAMS, RESULTS) { NAME, PARAMS, RESULTS } ,
293 #include "runtime.def"
295 #undef DEF_GO_RUNTIME
300 runtime_function_declarations
[Runtime::NUMBER_OF_FUNCTIONS
];
302 // Get the declaration of a runtime function.
305 Runtime::runtime_declaration(Function code
)
307 go_assert(code
< Runtime::NUMBER_OF_FUNCTIONS
);
308 if (runtime_function_declarations
[code
] == NULL
)
310 const Runtime_function
* pb
= &runtime_functions
[code
];
312 Location bloc
= Linemap::predeclared_location();
314 Typed_identifier_list
* param_types
= NULL
;
315 if (pb
->parameter_types
[0] != RFT_VOID
)
317 param_types
= new Typed_identifier_list();
318 for (unsigned int i
= 0;
319 i
< (sizeof(pb
->parameter_types
)
320 / sizeof (pb
->parameter_types
[0]));
323 if (pb
->parameter_types
[i
] == RFT_VOID
)
325 Type
* t
= runtime_function_type(pb
->parameter_types
[i
]);
326 param_types
->push_back(Typed_identifier("", t
, bloc
));
330 Typed_identifier_list
* result_types
= NULL
;
331 if (pb
->result_types
[0] != RFT_VOID
)
333 result_types
= new Typed_identifier_list();
334 for (unsigned int i
= 0;
335 i
< sizeof(pb
->result_types
) / sizeof(pb
->result_types
[0]);
338 if (pb
->result_types
[i
] == RFT_VOID
)
340 Type
* t
= runtime_function_type(pb
->result_types
[i
]);
341 result_types
->push_back(Typed_identifier("", t
, bloc
));
345 Function_type
* fntype
= Type::make_function_type(NULL
, param_types
,
347 const char* n
= pb
->name
;
348 const char* n1
= strchr(n
, '.');
351 Named_object
* no
= Named_object::make_function_declaration(n
, NULL
,
353 no
->func_declaration_value()->set_asm_name(pb
->name
);
355 runtime_function_declarations
[code
] = no
;
358 return runtime_function_declarations
[code
];
361 // Make a call to a runtime function.
364 Runtime::make_call(Runtime::Function code
, Location loc
,
365 int param_count
, ...)
367 go_assert(code
< Runtime::NUMBER_OF_FUNCTIONS
);
369 const Runtime_function
* pb
= &runtime_functions
[code
];
371 go_assert(static_cast<size_t>(param_count
)
372 <= sizeof(pb
->parameter_types
) / sizeof(pb
->parameter_types
[0]));
374 Named_object
* no
= runtime_declaration(code
);
375 Expression
* func
= Expression::make_func_reference(no
, NULL
, loc
);
377 Expression_list
* args
= new Expression_list();
378 args
->reserve(param_count
);
381 va_start(ap
, param_count
);
382 for (int i
= 0; i
< param_count
; ++i
)
384 Expression
* e
= va_arg(ap
, Expression
*);
385 Runtime_function_type rft
= pb
->parameter_types
[i
];
386 args
->push_back(convert_to_runtime_function_type(rft
, e
, loc
));
390 return Expression::make_call(func
, args
, false, loc
);
393 // The type we use for a map iteration. This is really a struct which
394 // is four pointers long. This must match the runtime struct
398 Runtime::map_iteration_type()
400 const unsigned long map_iteration_size
= 4;
403 mpz_init_set_ui(ival
, map_iteration_size
);
404 Expression
* iexpr
= Expression::make_integer(&ival
, NULL
,
405 Linemap::predeclared_location());
408 return Type::make_array_type(runtime_function_type(RFT_POINTER
), iexpr
);