OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [gcc/] [go/] [gofrontend/] [runtime.cc] - Blame information for rev 720

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 714 jeremybenn
// 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
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.