OSDN Git Service

compiler: Fix order of initialization bug with global var a, b = f().
[pf3gnuchains/gcc-fork.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 <gmp.h>
10
11 #include "gogo.h"
12 #include "types.h"
13 #include "expressions.h"
14 #include "runtime.h"
15
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
21 // libgo/runtime.
22
23 // Parameter and result types used by runtime functions.
24
25 enum Runtime_function_type
26 {
27   // General indicator that value is not used.
28   RFT_VOID,
29   // Go type bool, C type _Bool.
30   RFT_BOOL,
31   // Go type *bool, C type _Bool*.
32   RFT_BOOLPTR,
33   // Go type int, C type int.
34   RFT_INT,
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 complex128, C type __complex double.
46   RFT_COMPLEX128,
47   // Go type string, C type struct __go_string.
48   RFT_STRING,
49   // Go type unsafe.Pointer, C type "void *".
50   RFT_POINTER,
51   // Go type []any, C type struct __go_open_array.
52   RFT_SLICE,
53   // Go type map[any]any, C type struct __go_map *.
54   RFT_MAP,
55   // Pointer to map iteration type.
56   RFT_MAPITER,
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   // Pointer to map descriptor.
68   RFT_MAPDESCRIPTOR,
69
70   NUMBER_OF_RUNTIME_FUNCTION_TYPES
71 };
72
73 // The Type structures for the runtime function types.
74
75 static Type* runtime_function_types[NUMBER_OF_RUNTIME_FUNCTION_TYPES];
76
77 // Get the Type for a Runtime_function_type code.
78
79 static Type*
80 runtime_function_type(Runtime_function_type bft)
81 {
82   go_assert(bft < NUMBER_OF_RUNTIME_FUNCTION_TYPES);
83   if (runtime_function_types[bft] == NULL)
84     {
85       const Location bloc = Linemap::predeclared_location();
86       Type* t;
87       switch (bft)
88         {
89         default:
90         case RFT_VOID:
91           go_unreachable();
92
93         case RFT_BOOL:
94           t = Type::lookup_bool_type();
95           break;
96
97         case RFT_BOOLPTR:
98           t = Type::make_pointer_type(Type::lookup_bool_type());
99           break;
100
101         case RFT_INT:
102           t = Type::lookup_integer_type("int");
103           break;
104
105         case RFT_INT64:
106           t = Type::lookup_integer_type("int64");
107           break;
108
109         case RFT_UINT64:
110           t = Type::lookup_integer_type("uint64");
111           break;
112
113         case RFT_RUNE:
114           t = Type::lookup_integer_type("int32");
115           break;
116
117         case RFT_UINTPTR:
118           t = Type::lookup_integer_type("uintptr");
119           break;
120
121         case RFT_FLOAT64:
122           t = Type::lookup_float_type("float64");
123           break;
124
125         case RFT_COMPLEX128:
126           t = Type::lookup_complex_type("complex128");
127           break;
128
129         case RFT_STRING:
130           t = Type::lookup_string_type();
131           break;
132
133         case RFT_POINTER:
134           t = Type::make_pointer_type(Type::make_void_type());
135           break;
136
137         case RFT_SLICE:
138           t = Type::make_array_type(Type::make_void_type(), NULL);
139           break;
140
141         case RFT_MAP:
142           t = Type::make_map_type(Type::make_void_type(),
143                                   Type::make_void_type(),
144                                   bloc);
145           break;
146
147         case RFT_MAPITER:
148           t = Type::make_pointer_type(Runtime::map_iteration_type());
149           break;
150
151         case RFT_CHAN:
152           t = Type::make_channel_type(true, true, Type::make_void_type());
153           break;
154
155         case RFT_IFACE:
156           {
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();
162             t = it;
163           }
164           break;
165
166         case RFT_EFACE:
167           t = Type::make_empty_interface_type(bloc);
168           break;
169
170         case RFT_FUNC_PTR:
171           {
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);
176           }
177           break;
178
179         case RFT_TYPE:
180           t = Type::make_type_descriptor_ptr_type();
181           break;
182
183         case RFT_MAPDESCRIPTOR:
184           t = Type::make_pointer_type(Map_type::make_map_descriptor_type());
185           break;
186         }
187
188       runtime_function_types[bft] = t;
189     }
190
191   return runtime_function_types[bft];
192 }
193
194 // Convert an expression to the type to pass to a runtime function.
195
196 static Expression*
197 convert_to_runtime_function_type(Runtime_function_type bft, Expression* e,
198                                  Location loc)
199 {
200   switch (bft)
201     {
202     default:
203     case RFT_VOID:
204       go_unreachable();
205
206     case RFT_BOOL:
207     case RFT_BOOLPTR:
208     case RFT_INT:
209     case RFT_INT64:
210     case RFT_UINT64:
211     case RFT_UINTPTR:
212     case RFT_RUNE:
213     case RFT_FLOAT64:
214     case RFT_COMPLEX128:
215     case RFT_STRING:
216     case RFT_POINTER:
217     case RFT_MAPITER:
218     case RFT_FUNC_PTR:
219       {
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);
223         return e;
224       }
225
226     case RFT_SLICE:
227     case RFT_MAP:
228     case RFT_CHAN:
229     case RFT_IFACE:
230     case RFT_EFACE:
231       return Expression::make_unsafe_cast(runtime_function_type(bft), e, loc);
232
233     case RFT_TYPE:
234       go_assert(e->type() == Type::make_type_descriptor_ptr_type());
235       return e;
236
237     case RFT_MAPDESCRIPTOR:
238       go_assert(e->type()->points_to()
239                 == Map_type::make_map_descriptor_type());
240       return e;
241     }
242 }
243
244 // Convert all the types used for runtime functions to the backend
245 // representation.
246
247 void
248 Runtime::convert_types(Gogo* gogo)
249 {
250   for (int i = 0; i < static_cast<int>(NUMBER_OF_RUNTIME_FUNCTION_TYPES); ++i)
251     {
252       Type* t = runtime_function_types[i];
253       if (t != NULL && t->named_type() != NULL)
254         {
255           bool r = t->verify();
256           go_assert(r);
257           t->named_type()->convert(gogo);
258         }
259     }
260 }
261
262 // The type used to define a runtime function.
263
264 struct Runtime_function
265 {
266   // Function name.
267   const char* name;
268   // Parameter types.  Never more than 6, as it happens.  RFT_VOID if
269   // not used.
270   Runtime_function_type parameter_types[6];
271   // Result types.  Never more than 2, as it happens.  RFT_VOID if not
272   // used.
273   Runtime_function_type result_types[2];
274 };
275
276 static const Runtime_function runtime_functions[] =
277 {
278
279 #define DEF_GO_RUNTIME(CODE, NAME, PARAMS, RESULTS) { NAME, PARAMS, RESULTS } ,
280
281 #include "runtime.def"
282
283 #undef DEF_GO_RUNTIME
284
285 };
286
287 static Named_object*
288 runtime_function_declarations[Runtime::NUMBER_OF_FUNCTIONS];
289
290 // Get the declaration of a runtime function.
291
292 Named_object*
293 Runtime::runtime_declaration(Function code)
294 {
295   go_assert(code < Runtime::NUMBER_OF_FUNCTIONS);
296   if (runtime_function_declarations[code] == NULL)
297     {
298       const Runtime_function* pb = &runtime_functions[code];
299
300       Location bloc = Linemap::predeclared_location();
301
302       Typed_identifier_list* param_types = NULL;
303       if (pb->parameter_types[0] != RFT_VOID)
304         {
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]));
309                i++)
310             {
311               if (pb->parameter_types[i] == RFT_VOID)
312                 break;
313               Type* t = runtime_function_type(pb->parameter_types[i]);
314               param_types->push_back(Typed_identifier("", t, bloc));
315             }
316         }
317
318       Typed_identifier_list* result_types = NULL;
319       if (pb->result_types[0] != RFT_VOID)
320         {
321           result_types = new Typed_identifier_list();
322           for (unsigned int i = 0;
323                i < sizeof(pb->result_types) / sizeof(pb->result_types[0]);
324                i++)
325             {
326               if (pb->result_types[i] == RFT_VOID)
327                 break;
328               Type* t = runtime_function_type(pb->result_types[i]);
329               result_types->push_back(Typed_identifier("", t, bloc));
330             }
331         }
332
333       Function_type* fntype = Type::make_function_type(NULL, param_types,
334                                                        result_types, bloc);
335       const char* n = pb->name;
336       const char* n1 = strchr(n, '.');
337       if (n1 != NULL)
338         n = n1 + 1;
339       Named_object* no = Named_object::make_function_declaration(n, NULL,
340                                                                  fntype, bloc);
341       no->func_declaration_value()->set_asm_name(pb->name);
342
343       runtime_function_declarations[code] = no;
344     }
345
346   return runtime_function_declarations[code];
347 }
348
349 // Make a call to a runtime function.
350
351 Call_expression*
352 Runtime::make_call(Runtime::Function code, Location loc,
353                    int param_count, ...)
354 {
355   go_assert(code < Runtime::NUMBER_OF_FUNCTIONS);
356
357   const Runtime_function* pb = &runtime_functions[code];
358
359   go_assert(static_cast<size_t>(param_count)
360              <= sizeof(pb->parameter_types) / sizeof(pb->parameter_types[0]));
361
362   Named_object* no = runtime_declaration(code);
363   Expression* func = Expression::make_func_reference(no, NULL, loc);
364
365   Expression_list* args = new Expression_list();
366   args->reserve(param_count);
367
368   va_list ap;
369   va_start(ap, param_count);
370   for (int i = 0; i < param_count; ++i)
371     {
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));
375     }
376   va_end(ap);
377
378   return Expression::make_call(func, args, false, loc);
379 }
380
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
383 // __go_hash_iter.
384
385 Type*
386 Runtime::map_iteration_type()
387 {
388   const unsigned long map_iteration_size = 4;
389
390   mpz_t ival;
391   mpz_init_set_ui(ival, map_iteration_size);
392   Expression* iexpr = Expression::make_integer(&ival, NULL,
393                                                Linemap::predeclared_location());
394   mpz_clear(ival);
395
396   return Type::make_array_type(runtime_function_type(RFT_POINTER), iexpr);
397 }