aboutsummaryrefslogtreecommitdiffstats
path: root/gcc-4.8.1/libgo/runtime/go-reflect-call.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc-4.8.1/libgo/runtime/go-reflect-call.c')
-rw-r--r--gcc-4.8.1/libgo/runtime/go-reflect-call.c535
1 files changed, 0 insertions, 535 deletions
diff --git a/gcc-4.8.1/libgo/runtime/go-reflect-call.c b/gcc-4.8.1/libgo/runtime/go-reflect-call.c
deleted file mode 100644
index a66f92868..000000000
--- a/gcc-4.8.1/libgo/runtime/go-reflect-call.c
+++ /dev/null
@@ -1,535 +0,0 @@
-/* go-reflect-call.c -- call reflection support for Go.
-
- Copyright 2009 The Go Authors. All rights reserved.
- Use of this source code is governed by a BSD-style
- license that can be found in the LICENSE file. */
-
-#include <stdio.h>
-#include <stdint.h>
-#include <stdlib.h>
-
-#include "runtime.h"
-#include "go-alloc.h"
-#include "go-assert.h"
-#include "go-type.h"
-
-#ifdef USE_LIBFFI
-
-#include "ffi.h"
-
-/* The functions in this file are only called from reflect_call. As
- reflect_call calls a libffi function, which will be compiled
- without -fsplit-stack, it will always run with a large stack. */
-
-static ffi_type *go_array_to_ffi (const struct __go_array_type *)
- __attribute__ ((no_split_stack));
-static ffi_type *go_slice_to_ffi (const struct __go_slice_type *)
- __attribute__ ((no_split_stack));
-static ffi_type *go_struct_to_ffi (const struct __go_struct_type *)
- __attribute__ ((no_split_stack));
-static ffi_type *go_string_to_ffi (void) __attribute__ ((no_split_stack));
-static ffi_type *go_interface_to_ffi (void) __attribute__ ((no_split_stack));
-static ffi_type *go_complex_to_ffi (ffi_type *)
- __attribute__ ((no_split_stack, unused));
-static ffi_type *go_type_to_ffi (const struct __go_type_descriptor *)
- __attribute__ ((no_split_stack));
-static ffi_type *go_func_return_ffi (const struct __go_func_type *)
- __attribute__ ((no_split_stack));
-static void go_func_to_cif (const struct __go_func_type *, _Bool, _Bool,
- ffi_cif *)
- __attribute__ ((no_split_stack));
-static size_t go_results_size (const struct __go_func_type *)
- __attribute__ ((no_split_stack));
-static void go_set_results (const struct __go_func_type *, unsigned char *,
- void **)
- __attribute__ ((no_split_stack));
-
-/* Return an ffi_type for a Go array type. The libffi library does
- not have any builtin support for passing arrays as values. We work
- around this by pretending that the array is a struct. */
-
-static ffi_type *
-go_array_to_ffi (const struct __go_array_type *descriptor)
-{
- ffi_type *ret;
- uintptr_t len;
- ffi_type *element;
- uintptr_t i;
-
- ret = (ffi_type *) __go_alloc (sizeof (ffi_type));
- ret->type = FFI_TYPE_STRUCT;
- len = descriptor->__len;
- ret->elements = (ffi_type **) __go_alloc ((len + 1) * sizeof (ffi_type *));
- element = go_type_to_ffi (descriptor->__element_type);
- for (i = 0; i < len; ++i)
- ret->elements[i] = element;
- ret->elements[len] = NULL;
- return ret;
-}
-
-/* Return an ffi_type for a Go slice type. This describes the
- __go_open_array type defines in array.h. */
-
-static ffi_type *
-go_slice_to_ffi (
- const struct __go_slice_type *descriptor __attribute__ ((unused)))
-{
- ffi_type *ret;
- ffi_type *ffi_intgo;
-
- ret = (ffi_type *) __go_alloc (sizeof (ffi_type));
- ret->type = FFI_TYPE_STRUCT;
- ret->elements = (ffi_type **) __go_alloc (4 * sizeof (ffi_type *));
- ret->elements[0] = &ffi_type_pointer;
- ffi_intgo = sizeof (intgo) == 4 ? &ffi_type_sint32 : &ffi_type_sint64;
- ret->elements[1] = ffi_intgo;
- ret->elements[2] = ffi_intgo;
- ret->elements[3] = NULL;
- return ret;
-}
-
-/* Return an ffi_type for a Go struct type. */
-
-static ffi_type *
-go_struct_to_ffi (const struct __go_struct_type *descriptor)
-{
- ffi_type *ret;
- int field_count;
- const struct __go_struct_field *fields;
- int i;
-
- ret = (ffi_type *) __go_alloc (sizeof (ffi_type));
- ret->type = FFI_TYPE_STRUCT;
- field_count = descriptor->__fields.__count;
- fields = (const struct __go_struct_field *) descriptor->__fields.__values;
- ret->elements = (ffi_type **) __go_alloc ((field_count + 1)
- * sizeof (ffi_type *));
- for (i = 0; i < field_count; ++i)
- ret->elements[i] = go_type_to_ffi (fields[i].__type);
- ret->elements[field_count] = NULL;
- return ret;
-}
-
-/* Return an ffi_type for a Go string type. This describes the String
- struct. */
-
-static ffi_type *
-go_string_to_ffi (void)
-{
- ffi_type *ret;
- ffi_type *ffi_intgo;
-
- ret = (ffi_type *) __go_alloc (sizeof (ffi_type));
- ret->type = FFI_TYPE_STRUCT;
- ret->elements = (ffi_type **) __go_alloc (3 * sizeof (ffi_type *));
- ret->elements[0] = &ffi_type_pointer;
- ffi_intgo = sizeof (intgo) == 4 ? &ffi_type_sint32 : &ffi_type_sint64;
- ret->elements[1] = ffi_intgo;
- ret->elements[2] = NULL;
- return ret;
-}
-
-/* Return an ffi_type for a Go interface type. This describes the
- __go_interface and __go_empty_interface structs. */
-
-static ffi_type *
-go_interface_to_ffi (void)
-{
- ffi_type *ret;
-
- ret = (ffi_type *) __go_alloc (sizeof (ffi_type));
- ret->type = FFI_TYPE_STRUCT;
- ret->elements = (ffi_type **) __go_alloc (3 * sizeof (ffi_type *));
- ret->elements[0] = &ffi_type_pointer;
- ret->elements[1] = &ffi_type_pointer;
- ret->elements[2] = NULL;
- return ret;
-}
-
-/* Return an ffi_type for a Go complex type. */
-
-static ffi_type *
-go_complex_to_ffi (ffi_type *float_type)
-{
- ffi_type *ret;
-
- ret = (ffi_type *) __go_alloc (sizeof (ffi_type));
- ret->type = FFI_TYPE_STRUCT;
- ret->elements = (ffi_type **) __go_alloc (3 * sizeof (ffi_type *));
- ret->elements[0] = float_type;
- ret->elements[1] = float_type;
- ret->elements[2] = NULL;
- return ret;
-}
-
-/* Return an ffi_type for a type described by a
- __go_type_descriptor. */
-
-static ffi_type *
-go_type_to_ffi (const struct __go_type_descriptor *descriptor)
-{
- switch (descriptor->__code & GO_CODE_MASK)
- {
- case GO_BOOL:
- if (sizeof (_Bool) == 1)
- return &ffi_type_uint8;
- else if (sizeof (_Bool) == sizeof (int))
- return &ffi_type_uint;
- abort ();
- case GO_FLOAT32:
- if (sizeof (float) == 4)
- return &ffi_type_float;
- abort ();
- case GO_FLOAT64:
- if (sizeof (double) == 8)
- return &ffi_type_double;
- abort ();
- case GO_COMPLEX64:
-#ifdef __alpha__
- runtime_throw("the libffi library does not support Complex64 type with "
- "reflect.Call or runtime.SetFinalizer");
-#else
- if (sizeof (float) == 4)
- return go_complex_to_ffi (&ffi_type_float);
- abort ();
-#endif
- case GO_COMPLEX128:
-#ifdef __alpha__
- runtime_throw("the libffi library does not support Complex128 type with "
- "reflect.Call or runtime.SetFinalizer");
-#else
- if (sizeof (double) == 8)
- return go_complex_to_ffi (&ffi_type_double);
- abort ();
-#endif
- case GO_INT16:
- return &ffi_type_sint16;
- case GO_INT32:
- return &ffi_type_sint32;
- case GO_INT64:
- return &ffi_type_sint64;
- case GO_INT8:
- return &ffi_type_sint8;
- case GO_INT:
- return sizeof (intgo) == 4 ? &ffi_type_sint32 : &ffi_type_sint64;
- case GO_UINT16:
- return &ffi_type_uint16;
- case GO_UINT32:
- return &ffi_type_uint32;
- case GO_UINT64:
- return &ffi_type_uint64;
- case GO_UINT8:
- return &ffi_type_uint8;
- case GO_UINT:
- return sizeof (uintgo) == 4 ? &ffi_type_uint32 : &ffi_type_uint64;
- case GO_UINTPTR:
- if (sizeof (void *) == 2)
- return &ffi_type_uint16;
- else if (sizeof (void *) == 4)
- return &ffi_type_uint32;
- else if (sizeof (void *) == 8)
- return &ffi_type_uint64;
- abort ();
- case GO_ARRAY:
- return go_array_to_ffi ((const struct __go_array_type *) descriptor);
- case GO_SLICE:
- return go_slice_to_ffi ((const struct __go_slice_type *) descriptor);
- case GO_STRUCT:
- return go_struct_to_ffi ((const struct __go_struct_type *) descriptor);
- case GO_STRING:
- return go_string_to_ffi ();
- case GO_INTERFACE:
- return go_interface_to_ffi ();
- case GO_CHAN:
- case GO_FUNC:
- case GO_MAP:
- case GO_PTR:
- case GO_UNSAFE_POINTER:
- /* These types are always pointers, and for FFI purposes nothing
- else matters. */
- return &ffi_type_pointer;
- default:
- abort ();
- }
-}
-
-/* Return the return type for a function, given the number of out
- parameters and their types. */
-
-static ffi_type *
-go_func_return_ffi (const struct __go_func_type *func)
-{
- int count;
- const struct __go_type_descriptor **types;
- ffi_type *ret;
- int i;
-
- count = func->__out.__count;
- if (count == 0)
- return &ffi_type_void;
-
- types = (const struct __go_type_descriptor **) func->__out.__values;
-
- if (count == 1)
- return go_type_to_ffi (types[0]);
-
- ret = (ffi_type *) __go_alloc (sizeof (ffi_type));
- ret->type = FFI_TYPE_STRUCT;
- ret->elements = (ffi_type **) __go_alloc ((count + 1) * sizeof (ffi_type *));
- for (i = 0; i < count; ++i)
- ret->elements[i] = go_type_to_ffi (types[i]);
- ret->elements[count] = NULL;
- return ret;
-}
-
-/* Build an ffi_cif structure for a function described by a
- __go_func_type structure. */
-
-static void
-go_func_to_cif (const struct __go_func_type *func, _Bool is_interface,
- _Bool is_method, ffi_cif *cif)
-{
- int num_params;
- const struct __go_type_descriptor **in_types;
- size_t num_args;
- ffi_type **args;
- int off;
- int i;
- ffi_type *rettype;
- ffi_status status;
-
- num_params = func->__in.__count;
- in_types = ((const struct __go_type_descriptor **)
- func->__in.__values);
-
- num_args = num_params + (is_interface ? 1 : 0);
- args = (ffi_type **) __go_alloc (num_args * sizeof (ffi_type *));
- i = 0;
- off = 0;
- if (is_interface)
- {
- args[0] = &ffi_type_pointer;
- off = 1;
- }
- else if (is_method)
- {
- args[0] = &ffi_type_pointer;
- i = 1;
- }
- for (; i < num_params; ++i)
- args[i + off] = go_type_to_ffi (in_types[i]);
-
- rettype = go_func_return_ffi (func);
-
- status = ffi_prep_cif (cif, FFI_DEFAULT_ABI, num_args, rettype, args);
- __go_assert (status == FFI_OK);
-}
-
-/* Get the total size required for the result parameters of a
- function. */
-
-static size_t
-go_results_size (const struct __go_func_type *func)
-{
- int count;
- const struct __go_type_descriptor **types;
- size_t off;
- size_t maxalign;
- int i;
-
- count = func->__out.__count;
- if (count == 0)
- return 0;
-
- types = (const struct __go_type_descriptor **) func->__out.__values;
-
- /* A single integer return value is always promoted to a full
- word. */
- if (count == 1)
- {
- switch (types[0]->__code & GO_CODE_MASK)
- {
- case GO_BOOL:
- case GO_INT8:
- case GO_INT16:
- case GO_INT32:
- case GO_UINT8:
- case GO_UINT16:
- case GO_UINT32:
- case GO_INT:
- case GO_UINT:
- return sizeof (ffi_arg);
-
- default:
- break;
- }
- }
-
- off = 0;
- maxalign = 0;
- for (i = 0; i < count; ++i)
- {
- size_t align;
-
- align = types[i]->__field_align;
- if (align > maxalign)
- maxalign = align;
- off = (off + align - 1) & ~ (align - 1);
- off += types[i]->__size;
- }
-
- off = (off + maxalign - 1) & ~ (maxalign - 1);
-
- return off;
-}
-
-/* Copy the results of calling a function via FFI from CALL_RESULT
- into the addresses in RESULTS. */
-
-static void
-go_set_results (const struct __go_func_type *func, unsigned char *call_result,
- void **results)
-{
- int count;
- const struct __go_type_descriptor **types;
- size_t off;
- int i;
-
- count = func->__out.__count;
- if (count == 0)
- return;
-
- types = (const struct __go_type_descriptor **) func->__out.__values;
-
- /* A single integer return value is always promoted to a full
- word. */
- if (count == 1)
- {
- switch (types[0]->__code & GO_CODE_MASK)
- {
- case GO_BOOL:
- case GO_INT8:
- case GO_INT16:
- case GO_INT32:
- case GO_UINT8:
- case GO_UINT16:
- case GO_UINT32:
- case GO_INT:
- case GO_UINT:
- {
- union
- {
- unsigned char buf[sizeof (ffi_arg)];
- ffi_arg v;
- } u;
- ffi_arg v;
-
- __builtin_memcpy (&u.buf, call_result, sizeof (ffi_arg));
- v = u.v;
-
- switch (types[0]->__size)
- {
- case 1:
- {
- uint8_t b;
-
- b = (uint8_t) v;
- __builtin_memcpy (results[0], &b, 1);
- }
- break;
-
- case 2:
- {
- uint16_t s;
-
- s = (uint16_t) v;
- __builtin_memcpy (results[0], &s, 2);
- }
- break;
-
- case 4:
- {
- uint32_t w;
-
- w = (uint32_t) v;
- __builtin_memcpy (results[0], &w, 4);
- }
- break;
-
- case 8:
- {
- uint64_t d;
-
- d = (uint64_t) v;
- __builtin_memcpy (results[0], &d, 8);
- }
- break;
-
- default:
- abort ();
- }
- }
- return;
-
- default:
- break;
- }
- }
-
- off = 0;
- for (i = 0; i < count; ++i)
- {
- size_t align;
- size_t size;
-
- align = types[i]->__field_align;
- size = types[i]->__size;
- off = (off + align - 1) & ~ (align - 1);
- __builtin_memcpy (results[i], call_result + off, size);
- off += size;
- }
-}
-
-/* Call a function. The type of the function is FUNC_TYPE, and the
- address is FUNC_ADDR. PARAMS is an array of parameter addresses.
- RESULTS is an array of result addresses. */
-
-void
-reflect_call (const struct __go_func_type *func_type, const void *func_addr,
- _Bool is_interface, _Bool is_method, void **params,
- void **results)
-{
- ffi_cif cif;
- unsigned char *call_result;
-
- __go_assert ((func_type->__common.__code & GO_CODE_MASK) == GO_FUNC);
- go_func_to_cif (func_type, is_interface, is_method, &cif);
-
- call_result = (unsigned char *) malloc (go_results_size (func_type));
-
- ffi_call (&cif, func_addr, call_result, params);
-
- /* Some day we may need to free result values if RESULTS is
- NULL. */
- if (results != NULL)
- go_set_results (func_type, call_result, results);
-
- free (call_result);
-}
-
-#else /* !defined(USE_LIBFFI) */
-
-void
-reflect_call (const struct __go_func_type *func_type __attribute__ ((unused)),
- const void *func_addr __attribute__ ((unused)),
- _Bool is_interface __attribute__ ((unused)),
- _Bool is_method __attribute__ ((unused)),
- void **params __attribute__ ((unused)),
- void **results __attribute__ ((unused)))
-{
- /* Without FFI there is nothing we can do. */
- runtime_throw("libgo built without FFI does not support "
- "reflect.Call or runtime.SetFinalizer");
-}
-
-#endif /* !defined(USE_LIBFFI) */