OSDN Git Service

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