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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [libgo/] [runtime/] [go-reflect-call.c] - Blame information for rev 761

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

Line No. Rev Author Line
1 747 jeremybenn
/* go-reflect-call.c -- call reflection support for Go.
2
 
3
   Copyright 2009 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 <stdio.h>
8
#include <stdint.h>
9
#include <stdlib.h>
10
 
11
#include "config.h"
12
 
13
#include "go-alloc.h"
14
#include "go-assert.h"
15
#include "go-type.h"
16
#include "runtime.h"
17
 
18
#ifdef USE_LIBFFI
19
 
20
#include "ffi.h"
21
 
22
/* The functions in this file are only called from reflect_call.  As
23
   reflect_call calls a libffi function, which will be compiled
24
   without -fsplit-stack, it will always run with a large stack.  */
25
 
26
static ffi_type *go_array_to_ffi (const struct __go_array_type *)
27
  __attribute__ ((no_split_stack));
28
static ffi_type *go_slice_to_ffi (const struct __go_slice_type *)
29
  __attribute__ ((no_split_stack));
30
static ffi_type *go_struct_to_ffi (const struct __go_struct_type *)
31
  __attribute__ ((no_split_stack));
32
static ffi_type *go_string_to_ffi (void) __attribute__ ((no_split_stack));
33
static ffi_type *go_interface_to_ffi (void) __attribute__ ((no_split_stack));
34
static ffi_type *go_complex_to_ffi (ffi_type *)
35
  __attribute__ ((no_split_stack));
36
static ffi_type *go_type_to_ffi (const struct __go_type_descriptor *)
37
  __attribute__ ((no_split_stack));
38
static ffi_type *go_func_return_ffi (const struct __go_func_type *)
39
  __attribute__ ((no_split_stack));
40
static void go_func_to_cif (const struct __go_func_type *, _Bool, _Bool,
41
                            ffi_cif *)
42
  __attribute__ ((no_split_stack));
43
static size_t go_results_size (const struct __go_func_type *)
44
  __attribute__ ((no_split_stack));
45
static void go_set_results (const struct __go_func_type *, unsigned char *,
46
                            void **)
47
  __attribute__ ((no_split_stack));
48
 
49
/* Return an ffi_type for a Go array type.  The libffi library does
50
   not have any builtin support for passing arrays as values.  We work
51
   around this by pretending that the array is a struct.  */
52
 
53
static ffi_type *
54
go_array_to_ffi (const struct __go_array_type *descriptor)
55
{
56
  ffi_type *ret;
57
  uintptr_t len;
58
  ffi_type *element;
59
  uintptr_t i;
60
 
61
  ret = (ffi_type *) __go_alloc (sizeof (ffi_type));
62
  ret->type = FFI_TYPE_STRUCT;
63
  len = descriptor->__len;
64
  ret->elements = (ffi_type **) __go_alloc ((len + 1) * sizeof (ffi_type *));
65
  element = go_type_to_ffi (descriptor->__element_type);
66
  for (i = 0; i < len; ++i)
67
    ret->elements[i] = element;
68
  ret->elements[len] = NULL;
69
  return ret;
70
}
71
 
72
/* Return an ffi_type for a Go slice type.  This describes the
73
   __go_open_array type defines in array.h.  */
74
 
75
static ffi_type *
76
go_slice_to_ffi (
77
    const struct __go_slice_type *descriptor __attribute__ ((unused)))
78
{
79
  ffi_type *ret;
80
 
81
  ret = (ffi_type *) __go_alloc (sizeof (ffi_type));
82
  ret->type = FFI_TYPE_STRUCT;
83
  ret->elements = (ffi_type **) __go_alloc (4 * sizeof (ffi_type *));
84
  ret->elements[0] = &ffi_type_pointer;
85
  ret->elements[1] = &ffi_type_sint;
86
  ret->elements[2] = &ffi_type_sint;
87
  ret->elements[3] = NULL;
88
  return ret;
89
}
90
 
91
/* Return an ffi_type for a Go struct type.  */
92
 
93
static ffi_type *
94
go_struct_to_ffi (const struct __go_struct_type *descriptor)
95
{
96
  ffi_type *ret;
97
  int field_count;
98
  const struct __go_struct_field *fields;
99
  int i;
100
 
101
  ret = (ffi_type *) __go_alloc (sizeof (ffi_type));
102
  ret->type = FFI_TYPE_STRUCT;
103
  field_count = descriptor->__fields.__count;
104
  fields = (const struct __go_struct_field *) descriptor->__fields.__values;
105
  ret->elements = (ffi_type **) __go_alloc ((field_count + 1)
106
                                            * sizeof (ffi_type *));
107
  for (i = 0; i < field_count; ++i)
108
    ret->elements[i] = go_type_to_ffi (fields[i].__type);
109
  ret->elements[field_count] = NULL;
110
  return ret;
111
}
112
 
113
/* Return an ffi_type for a Go string type.  This describes the
114
   __go_string struct.  */
115
 
116
static ffi_type *
117
go_string_to_ffi (void)
118
{
119
  ffi_type *ret;
120
 
121
  ret = (ffi_type *) __go_alloc (sizeof (ffi_type));
122
  ret->type = FFI_TYPE_STRUCT;
123
  ret->elements = (ffi_type **) __go_alloc (3 * sizeof (ffi_type *));
124
  ret->elements[0] = &ffi_type_pointer;
125
  ret->elements[1] = &ffi_type_sint;
126
  ret->elements[2] = NULL;
127
  return ret;
128
}
129
 
130
/* Return an ffi_type for a Go interface type.  This describes the
131
   __go_interface and __go_empty_interface structs.  */
132
 
133
static ffi_type *
134
go_interface_to_ffi (void)
135
{
136
  ffi_type *ret;
137
 
138
  ret = (ffi_type *) __go_alloc (sizeof (ffi_type));
139
  ret->type = FFI_TYPE_STRUCT;
140
  ret->elements = (ffi_type **) __go_alloc (3 * sizeof (ffi_type *));
141
  ret->elements[0] = &ffi_type_pointer;
142
  ret->elements[1] = &ffi_type_pointer;
143
  ret->elements[2] = NULL;
144
  return ret;
145
}
146
 
147
/* Return an ffi_type for a Go complex type.  */
148
 
149
static ffi_type *
150
go_complex_to_ffi (ffi_type *float_type)
151
{
152
  ffi_type *ret;
153
 
154
  ret = (ffi_type *) __go_alloc (sizeof (ffi_type));
155
  ret->type = FFI_TYPE_STRUCT;
156
  ret->elements = (ffi_type **) __go_alloc (3 * sizeof (ffi_type *));
157
  ret->elements[0] = float_type;
158
  ret->elements[1] = float_type;
159
  ret->elements[2] = NULL;
160
  return ret;
161
}
162
 
163
/* Return an ffi_type for a type described by a
164
   __go_type_descriptor.  */
165
 
166
static ffi_type *
167
go_type_to_ffi (const struct __go_type_descriptor *descriptor)
168
{
169
  switch (descriptor->__code & GO_CODE_MASK)
170
    {
171
    case GO_BOOL:
172
      if (sizeof (_Bool) == 1)
173
        return &ffi_type_uint8;
174
      else if (sizeof (_Bool) == sizeof (int))
175
        return &ffi_type_uint;
176
      abort ();
177
    case GO_FLOAT32:
178
      if (sizeof (float) == 4)
179
        return &ffi_type_float;
180
      abort ();
181
    case GO_FLOAT64:
182
      if (sizeof (double) == 8)
183
        return &ffi_type_double;
184
      abort ();
185
    case GO_COMPLEX64:
186
      if (sizeof (float) == 4)
187
        return go_complex_to_ffi (&ffi_type_float);
188
      abort ();
189
    case GO_COMPLEX128:
190
      if (sizeof (double) == 8)
191
        return go_complex_to_ffi (&ffi_type_double);
192
      abort ();
193
    case GO_INT16:
194
      return &ffi_type_sint16;
195
    case GO_INT32:
196
      return &ffi_type_sint32;
197
    case GO_INT64:
198
      return &ffi_type_sint64;
199
    case GO_INT8:
200
      return &ffi_type_sint8;
201
    case GO_INT:
202
      return &ffi_type_sint;
203
    case GO_UINT16:
204
      return &ffi_type_uint16;
205
    case GO_UINT32:
206
      return &ffi_type_uint32;
207
    case GO_UINT64:
208
      return &ffi_type_uint64;
209
    case GO_UINT8:
210
      return &ffi_type_uint8;
211
    case GO_UINT:
212
      return &ffi_type_uint;
213
    case GO_UINTPTR:
214
      if (sizeof (void *) == 2)
215
        return &ffi_type_uint16;
216
      else if (sizeof (void *) == 4)
217
        return &ffi_type_uint32;
218
      else if (sizeof (void *) == 8)
219
        return &ffi_type_uint64;
220
      abort ();
221
    case GO_ARRAY:
222
      return go_array_to_ffi ((const struct __go_array_type *) descriptor);
223
    case GO_SLICE:
224
      return go_slice_to_ffi ((const struct __go_slice_type *) descriptor);
225
    case GO_STRUCT:
226
      return go_struct_to_ffi ((const struct __go_struct_type *) descriptor);
227
    case GO_STRING:
228
      return go_string_to_ffi ();
229
    case GO_INTERFACE:
230
      return go_interface_to_ffi ();
231
    case GO_CHAN:
232
    case GO_FUNC:
233
    case GO_MAP:
234
    case GO_PTR:
235
    case GO_UNSAFE_POINTER:
236
      /* These types are always pointers, and for FFI purposes nothing
237
         else matters.  */
238
      return &ffi_type_pointer;
239
    default:
240
      abort ();
241
    }
242
}
243
 
244
/* Return the return type for a function, given the number of out
245
   parameters and their types.  */
246
 
247
static ffi_type *
248
go_func_return_ffi (const struct __go_func_type *func)
249
{
250
  int count;
251
  const struct __go_type_descriptor **types;
252
  ffi_type *ret;
253
  int i;
254
 
255
  count = func->__out.__count;
256
  if (count == 0)
257
    return &ffi_type_void;
258
 
259
  types = (const struct __go_type_descriptor **) func->__out.__values;
260
 
261
  if (count == 1)
262
    return go_type_to_ffi (types[0]);
263
 
264
  ret = (ffi_type *) __go_alloc (sizeof (ffi_type));
265
  ret->type = FFI_TYPE_STRUCT;
266
  ret->elements = (ffi_type **) __go_alloc ((count + 1) * sizeof (ffi_type *));
267
  for (i = 0; i < count; ++i)
268
    ret->elements[i] = go_type_to_ffi (types[i]);
269
  ret->elements[count] = NULL;
270
  return ret;
271
}
272
 
273
/* Build an ffi_cif structure for a function described by a
274
   __go_func_type structure.  */
275
 
276
static void
277
go_func_to_cif (const struct __go_func_type *func, _Bool is_interface,
278
                _Bool is_method, ffi_cif *cif)
279
{
280
  int num_params;
281
  const struct __go_type_descriptor **in_types;
282
  size_t num_args;
283
  ffi_type **args;
284
  int off;
285
  int i;
286
  ffi_type *rettype;
287
  ffi_status status;
288
 
289
  num_params = func->__in.__count;
290
  in_types = ((const struct __go_type_descriptor **)
291
              func->__in.__values);
292
 
293
  num_args = num_params + (is_interface ? 1 : 0);
294
  args = (ffi_type **) __go_alloc (num_args * sizeof (ffi_type *));
295
  i = 0;
296
  off = 0;
297
  if (is_interface)
298
    {
299
      args[0] = &ffi_type_pointer;
300
      off = 1;
301
    }
302
  else if (is_method)
303
    {
304
      args[0] = &ffi_type_pointer;
305
      i = 1;
306
    }
307
  for (; i < num_params; ++i)
308
    args[i + off] = go_type_to_ffi (in_types[i]);
309
 
310
  rettype = go_func_return_ffi (func);
311
 
312
  status = ffi_prep_cif (cif, FFI_DEFAULT_ABI, num_args, rettype, args);
313
  __go_assert (status == FFI_OK);
314
}
315
 
316
/* Get the total size required for the result parameters of a
317
   function.  */
318
 
319
static size_t
320
go_results_size (const struct __go_func_type *func)
321
{
322
  int count;
323
  const struct __go_type_descriptor **types;
324
  size_t off;
325
  size_t maxalign;
326
  int i;
327
 
328
  count = func->__out.__count;
329
  if (count == 0)
330
    return 0;
331
 
332
  types = (const struct __go_type_descriptor **) func->__out.__values;
333
 
334
  /* A single integer return value is always promoted to a full
335
     word.  */
336
  if (count == 1)
337
    {
338
      switch (types[0]->__code & GO_CODE_MASK)
339
        {
340
        case GO_BOOL:
341
        case GO_INT8:
342
        case GO_INT16:
343
        case GO_INT32:
344
        case GO_UINT8:
345
        case GO_UINT16:
346
        case GO_UINT32:
347
        case GO_INT:
348
        case GO_UINT:
349
          return sizeof (ffi_arg);
350
 
351
        default:
352
          break;
353
        }
354
    }
355
 
356
  off = 0;
357
  maxalign = 0;
358
  for (i = 0; i < count; ++i)
359
    {
360
      size_t align;
361
 
362
      align = types[i]->__field_align;
363
      if (align > maxalign)
364
        maxalign = align;
365
      off = (off + align - 1) & ~ (align - 1);
366
      off += types[i]->__size;
367
    }
368
 
369
  off = (off + maxalign - 1) & ~ (maxalign - 1);
370
 
371
  return off;
372
}
373
 
374
/* Copy the results of calling a function via FFI from CALL_RESULT
375
   into the addresses in RESULTS.  */
376
 
377
static void
378
go_set_results (const struct __go_func_type *func, unsigned char *call_result,
379
                void **results)
380
{
381
  int count;
382
  const struct __go_type_descriptor **types;
383
  size_t off;
384
  int i;
385
 
386
  count = func->__out.__count;
387
  if (count == 0)
388
    return;
389
 
390
  types = (const struct __go_type_descriptor **) func->__out.__values;
391
 
392
  /* A single integer return value is always promoted to a full
393
     word.  */
394
  if (count == 1)
395
    {
396
      switch (types[0]->__code & GO_CODE_MASK)
397
        {
398
        case GO_BOOL:
399
        case GO_INT8:
400
        case GO_INT16:
401
        case GO_INT32:
402
        case GO_UINT8:
403
        case GO_UINT16:
404
        case GO_UINT32:
405
        case GO_INT:
406
        case GO_UINT:
407
          {
408
            union
409
            {
410
              unsigned char buf[sizeof (ffi_arg)];
411
              ffi_arg v;
412
            } u;
413
            ffi_arg v;
414
 
415
            __builtin_memcpy (&u.buf, call_result, sizeof (ffi_arg));
416
            v = u.v;
417
 
418
            switch (types[0]->__size)
419
              {
420
              case 1:
421
                {
422
                  uint8_t b;
423
 
424
                  b = (uint8_t) v;
425
                  __builtin_memcpy (results[0], &b, 1);
426
                }
427
                break;
428
 
429
              case 2:
430
                {
431
                  uint16_t s;
432
 
433
                  s = (uint16_t) v;
434
                  __builtin_memcpy (results[0], &s, 2);
435
                }
436
                break;
437
 
438
              case 4:
439
                {
440
                  uint32_t w;
441
 
442
                  w = (uint32_t) v;
443
                  __builtin_memcpy (results[0], &w, 4);
444
                }
445
                break;
446
 
447
              case 8:
448
                {
449
                  uint64_t d;
450
 
451
                  d = (uint64_t) v;
452
                  __builtin_memcpy (results[0], &d, 8);
453
                }
454
                break;
455
 
456
              default:
457
                abort ();
458
              }
459
          }
460
          return;
461
 
462
        default:
463
          break;
464
        }
465
    }
466
 
467
  off = 0;
468
  for (i = 0; i < count; ++i)
469
    {
470
      size_t align;
471
      size_t size;
472
 
473
      align = types[i]->__field_align;
474
      size = types[i]->__size;
475
      off = (off + align - 1) & ~ (align - 1);
476
      __builtin_memcpy (results[i], call_result + off, size);
477
      off += size;
478
    }
479
}
480
 
481
/* Call a function.  The type of the function is FUNC_TYPE, and the
482
   address is FUNC_ADDR.  PARAMS is an array of parameter addresses.
483
   RESULTS is an array of result addresses.  */
484
 
485
void
486
reflect_call (const struct __go_func_type *func_type, const void *func_addr,
487
              _Bool is_interface, _Bool is_method, void **params,
488
              void **results)
489
{
490
  ffi_cif cif;
491
  unsigned char *call_result;
492
 
493
  __go_assert ((func_type->__common.__code & GO_CODE_MASK) == GO_FUNC);
494
  go_func_to_cif (func_type, is_interface, is_method, &cif);
495
 
496
  call_result = (unsigned char *) malloc (go_results_size (func_type));
497
 
498
  ffi_call (&cif, func_addr, call_result, params);
499
 
500
  /* Some day we may need to free result values if RESULTS is
501
     NULL.  */
502
  if (results != NULL)
503
    go_set_results (func_type, call_result, results);
504
 
505
  free (call_result);
506
}
507
 
508
#else /* !defined(USE_LIBFFI) */
509
 
510
void
511
reflect_call (const struct __go_func_type *func_type __attribute__ ((unused)),
512
              const void *func_addr __attribute__ ((unused)),
513
              _Bool is_interface __attribute__ ((unused)),
514
              _Bool is_method __attribute__ ((unused)),
515
              void **params __attribute__ ((unused)),
516
              void **results __attribute__ ((unused)))
517
{
518
  /* Without FFI there is nothing we can do.  */
519
  runtime_throw("libgo built without FFI does not support "
520
                "reflect.Call or runtime.SetFinalizer");
521
}
522
 
523
#endif /* !defined(USE_LIBFFI) */

powered by: WebSVN 2.1.0

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