diff options
author | upstream source tree <ports@midipix.org> | 2015-03-15 20:14:05 -0400 |
---|---|---|
committer | upstream source tree <ports@midipix.org> | 2015-03-15 20:14:05 -0400 |
commit | 554fd8c5195424bdbcabf5de30fdc183aba391bd (patch) | |
tree | 976dc5ab7fddf506dadce60ae936f43f58787092 /libgo/runtime/go-reflect.c | |
download | cbb-gcc-4.6.4-15d2061ac0796199866debe9ac87130894b0cdd3.tar.bz2 cbb-gcc-4.6.4-15d2061ac0796199866debe9ac87130894b0cdd3.tar.xz |
obtained gcc-4.6.4.tar.bz2 from upstream website;upstream
verified gcc-4.6.4.tar.bz2.sig;
imported gcc-4.6.4 source tree from verified upstream tarball.
downloading a git-generated archive based on the 'upstream' tag
should provide you with a source tree that is binary identical
to the one extracted from the above tarball.
if you have obtained the source via the command 'git clone',
however, do note that line-endings of files in your working
directory might differ from line-endings of the respective
files in the upstream repository.
Diffstat (limited to 'libgo/runtime/go-reflect.c')
-rw-r--r-- | libgo/runtime/go-reflect.c | 186 |
1 files changed, 186 insertions, 0 deletions
diff --git a/libgo/runtime/go-reflect.c b/libgo/runtime/go-reflect.c new file mode 100644 index 000000000..9485c0979 --- /dev/null +++ b/libgo/runtime/go-reflect.c @@ -0,0 +1,186 @@ +/* go-reflect.c -- implement unsafe.Reflect and unsafe.Typeof 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 <stdlib.h> +#include <stdint.h> + +#include "interface.h" +#include "go-alloc.h" +#include "go-panic.h" +#include "go-string.h" +#include "go-type.h" + +/* For field alignment. */ + +struct field_align +{ + char c; + struct __go_type_descriptor *p; +}; + +/* The type descriptors in the runtime package. */ + +extern const struct __go_type_descriptor ptr_bool_descriptor + asm ("__go_td_pN30_libgo_runtime.runtime.BoolType"); +extern const struct __go_type_descriptor ptr_float_descriptor + asm ("__go_td_pN31_libgo_runtime.runtime.FloatType"); +extern const struct __go_type_descriptor ptr_complex_descriptor + asm ("__go_td_pN33_libgo_runtime.runtime.ComplexType"); +extern const struct __go_type_descriptor ptr_int_descriptor + asm ("__go_td_pN29_libgo_runtime.runtime.IntType"); +extern const struct __go_type_descriptor ptr_uint_descriptor + asm ("__go_td_pN30_libgo_runtime.runtime.UintType"); +extern const struct __go_type_descriptor ptr_string_descriptor + asm ("__go_td_pN32_libgo_runtime.runtime.StringType"); +extern const struct __go_type_descriptor ptr_unsafe_pointer_decriptor + asm ("__go_td_pN39_libgo_runtime.runtime.UnsafePointerType"); +extern const struct __go_type_descriptor ptr_array_descriptor + asm ("__go_td_pN31_libgo_runtime.runtime.ArrayType"); +extern const struct __go_type_descriptor ptr_slice_descriptor + asm ("__go_td_pN31_libgo_runtime.runtime.SliceType"); +extern const struct __go_type_descriptor ptr_chan_descriptor + asm ("__go_td_pN30_libgo_runtime.runtime.ChanType"); +extern const struct __go_type_descriptor ptr_func_descriptor + asm ("__go_td_pN30_libgo_runtime.runtime.FuncType"); +extern const struct __go_type_descriptor ptr_interface_descriptor + asm ("__go_td_pN35_libgo_runtime.runtime.InterfaceType"); +extern const struct __go_type_descriptor ptr_map_descriptor + asm ("__go_td_pN29_libgo_runtime.runtime.MapType"); +extern const struct __go_type_descriptor ptr_ptr_descriptor + asm ("__go_td_pN29_libgo_runtime.runtime.PtrType"); +extern const struct __go_type_descriptor ptr_struct_descriptor + asm ("__go_td_pN32_libgo_runtime.runtime.StructType"); + +const struct __go_type_descriptor * +get_descriptor (int code) +{ + switch (code) + { + case GO_BOOL: + return &ptr_bool_descriptor; + case GO_FLOAT32: + case GO_FLOAT64: + return &ptr_float_descriptor; + case GO_COMPLEX64: + case GO_COMPLEX128: + return &ptr_complex_descriptor; + case GO_INT16: + case GO_INT32: + case GO_INT64: + case GO_INT8: + case GO_INT: + return &ptr_int_descriptor; + case GO_UINT16: + case GO_UINT32: + case GO_UINT64: + case GO_UINT8: + case GO_UINTPTR: + case GO_UINT: + return &ptr_uint_descriptor; + case GO_STRING: + return &ptr_string_descriptor; + case GO_UNSAFE_POINTER: + return &ptr_unsafe_pointer_decriptor; + case GO_ARRAY: + return &ptr_array_descriptor; + case GO_SLICE: + return &ptr_slice_descriptor; + case GO_CHAN: + return &ptr_chan_descriptor; + case GO_FUNC: + return &ptr_func_descriptor; + case GO_INTERFACE: + return &ptr_interface_descriptor; + case GO_MAP: + return &ptr_map_descriptor; + case GO_PTR: + return &ptr_ptr_descriptor; + case GO_STRUCT: + return &ptr_struct_descriptor; + default: + abort (); + } +} + +/* Implement unsafe.Reflect. */ + +struct reflect_ret +{ + struct __go_empty_interface rettype; + void *addr; +}; + +struct reflect_ret Reflect (struct __go_empty_interface) + asm ("libgo_unsafe.unsafe.Reflect"); + +struct reflect_ret +Reflect (struct __go_empty_interface e) +{ + struct reflect_ret ret; + + if (e.__type_descriptor == NULL) + { + ret.rettype.__type_descriptor = NULL; + ret.rettype.__object = NULL; + ret.addr = NULL; + } + else + { + size_t size; + + ret.rettype.__type_descriptor = + get_descriptor (e.__type_descriptor->__code); + + /* This memcpy is really just an assignment of a const pointer + to a non-const pointer. FIXME: We should canonicalize this + pointer, so that for a given type we always return the same + pointer. */ + __builtin_memcpy (&ret.rettype.__object, &e.__type_descriptor, + sizeof (void *)); + + /* Make a copy of the value. */ + size = e.__type_descriptor->__size; + if (size <= sizeof (uint64_t)) + ret.addr = __go_alloc (sizeof (uint64_t)); + else + ret.addr = __go_alloc (size); + if (__go_is_pointer_type (e.__type_descriptor)) + *(void **) ret.addr = e.__object; + else + __builtin_memcpy (ret.addr, e.__object, size); + } + + return ret; +} + +/* Implement unsafe.Typeof. */ + +struct __go_empty_interface Typeof (struct __go_empty_interface) + asm ("libgo_unsafe.unsafe.Typeof"); + +struct __go_empty_interface +Typeof (const struct __go_empty_interface e) +{ + struct __go_empty_interface ret; + + if (e.__type_descriptor == NULL) + { + ret.__type_descriptor = NULL; + ret.__object = NULL; + } + else + { + ret.__type_descriptor = get_descriptor (e.__type_descriptor->__code); + + /* This memcpy is really just an assignment of a const pointer + to a non-const pointer. FIXME: We should canonicalize this + pointer, so that for a given type we always return the same + pointer. */ + __builtin_memcpy (&ret.__object, &e.__type_descriptor, sizeof (void *)); + } + + return ret; +} |