Merge from branches/gcc-4_8-branch up to rev 204657.
[official-gcc.git] / gcc-4_8-branch / gcc / go / gofrontend / runtime.cc
blob3b0f1880758cc165022575a346abd5a35e355f39
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 type 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 // Pointer to map iteration type.
58 RFT_MAPITER,
59 // Go type chan any, C type struct __go_channel *.
60 RFT_CHAN,
61 // Go type non-empty interface, C type struct __go_interface.
62 RFT_IFACE,
63 // Go type interface{}, C type struct __go_empty_interface.
64 RFT_EFACE,
65 // Go type func(unsafe.Pointer), C type void (*) (void *).
66 RFT_FUNC_PTR,
67 // Pointer to Go type descriptor.
68 RFT_TYPE,
69 // Pointer to map descriptor.
70 RFT_MAPDESCRIPTOR,
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.
81 static Type*
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();
88 Type* t;
89 switch (bft)
91 default:
92 case RFT_VOID:
93 go_unreachable();
95 case RFT_BOOL:
96 t = Type::lookup_bool_type();
97 break;
99 case RFT_BOOLPTR:
100 t = Type::make_pointer_type(Type::lookup_bool_type());
101 break;
103 case RFT_INT:
104 t = Type::lookup_integer_type("int");
105 break;
107 case RFT_INT32:
108 t = Type::lookup_integer_type("int32");
109 break;
111 case RFT_INT64:
112 t = Type::lookup_integer_type("int64");
113 break;
115 case RFT_UINT64:
116 t = Type::lookup_integer_type("uint64");
117 break;
119 case RFT_RUNE:
120 t = Type::lookup_integer_type("int32");
121 break;
123 case RFT_UINTPTR:
124 t = Type::lookup_integer_type("uintptr");
125 break;
127 case RFT_FLOAT64:
128 t = Type::lookup_float_type("float64");
129 break;
131 case RFT_COMPLEX64:
132 t = Type::lookup_complex_type("complex64");
133 break;
135 case RFT_COMPLEX128:
136 t = Type::lookup_complex_type("complex128");
137 break;
139 case RFT_STRING:
140 t = Type::lookup_string_type();
141 break;
143 case RFT_POINTER:
144 t = Type::make_pointer_type(Type::make_void_type());
145 break;
147 case RFT_SLICE:
148 t = Type::make_array_type(Type::make_void_type(), NULL);
149 break;
151 case RFT_MAP:
152 t = Type::make_map_type(Type::make_void_type(),
153 Type::make_void_type(),
154 bloc);
155 break;
157 case RFT_MAPITER:
158 t = Type::make_pointer_type(Runtime::map_iteration_type());
159 break;
161 case RFT_CHAN:
162 t = Type::make_channel_type(true, true, Type::make_void_type());
163 break;
165 case RFT_IFACE:
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();
172 t = it;
174 break;
176 case RFT_EFACE:
177 t = Type::make_empty_interface_type(bloc);
178 break;
180 case RFT_FUNC_PTR:
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);
187 break;
189 case RFT_TYPE:
190 t = Type::make_type_descriptor_ptr_type();
191 break;
193 case RFT_MAPDESCRIPTOR:
194 t = Type::make_pointer_type(Map_type::make_map_descriptor_type());
195 break;
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.
206 static Expression*
207 convert_to_runtime_function_type(Runtime_function_type bft, Expression* e,
208 Location loc)
210 switch (bft)
212 default:
213 case RFT_VOID:
214 go_unreachable();
216 case RFT_BOOL:
217 case RFT_BOOLPTR:
218 case RFT_INT:
219 case RFT_INT32:
220 case RFT_INT64:
221 case RFT_UINT64:
222 case RFT_UINTPTR:
223 case RFT_RUNE:
224 case RFT_FLOAT64:
225 case RFT_COMPLEX64:
226 case RFT_COMPLEX128:
227 case RFT_STRING:
228 case RFT_POINTER:
229 case RFT_MAPITER:
230 case RFT_FUNC_PTR:
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);
235 return e;
238 case RFT_SLICE:
239 case RFT_MAP:
240 case RFT_CHAN:
241 case RFT_IFACE:
242 case RFT_EFACE:
243 return Expression::make_unsafe_cast(runtime_function_type(bft), e, loc);
245 case RFT_TYPE:
246 go_assert(e->type() == Type::make_type_descriptor_ptr_type());
247 return e;
249 case RFT_MAPDESCRIPTOR:
250 go_assert(e->type()->points_to()
251 == Map_type::make_map_descriptor_type());
252 return e;
256 // Convert all the types used for runtime functions to the backend
257 // representation.
259 void
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();
268 go_assert(r);
269 t->named_type()->convert(gogo);
274 // The type used to define a runtime function.
276 struct Runtime_function
278 // Function name.
279 const char* name;
280 // Parameter types. Never more than 6, as it happens. RFT_VOID if
281 // not used.
282 Runtime_function_type parameter_types[6];
283 // Result types. Never more than 2, as it happens. RFT_VOID if not
284 // used.
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
299 static Named_object*
300 runtime_function_declarations[Runtime::NUMBER_OF_FUNCTIONS];
302 // Get the declaration of a runtime function.
304 Named_object*
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]));
321 i++)
323 if (pb->parameter_types[i] == RFT_VOID)
324 break;
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]);
336 i++)
338 if (pb->result_types[i] == RFT_VOID)
339 break;
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,
346 result_types, bloc);
347 const char* n = pb->name;
348 const char* n1 = strchr(n, '.');
349 if (n1 != NULL)
350 n = n1 + 1;
351 Named_object* no = Named_object::make_function_declaration(n, NULL,
352 fntype, bloc);
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.
363 Call_expression*
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);
380 va_list ap;
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));
388 va_end(ap);
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
395 // __go_hash_iter.
397 Type*
398 Runtime::map_iteration_type()
400 const unsigned long map_iteration_size = 4;
402 mpz_t ival;
403 mpz_init_set_ui(ival, map_iteration_size);
404 Expression* iexpr = Expression::make_integer(&ival, NULL,
405 Linemap::predeclared_location());
406 mpz_clear(ival);
408 return Type::make_array_type(runtime_function_type(RFT_POINTER), iexpr);