Fix r180999.
[gcc.git] / libgo / runtime / go-reflect.c
1 /* go-reflect.c -- implement unsafe.Reflect and unsafe.Typeof 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 <stdlib.h>
8 #include <stdint.h>
9
10 #include "interface.h"
11 #include "go-alloc.h"
12 #include "go-panic.h"
13 #include "go-string.h"
14 #include "go-type.h"
15
16 /* For field alignment. */
17
18 struct field_align
19 {
20 char c;
21 struct __go_type_descriptor *p;
22 };
23
24 /* The type descriptors in the runtime package. */
25
26 extern const struct __go_type_descriptor ptr_bool_descriptor
27 asm ("__go_td_pN30_libgo_runtime.runtime.BoolType");
28 extern const struct __go_type_descriptor ptr_float_descriptor
29 asm ("__go_td_pN31_libgo_runtime.runtime.FloatType");
30 extern const struct __go_type_descriptor ptr_complex_descriptor
31 asm ("__go_td_pN33_libgo_runtime.runtime.ComplexType");
32 extern const struct __go_type_descriptor ptr_int_descriptor
33 asm ("__go_td_pN29_libgo_runtime.runtime.IntType");
34 extern const struct __go_type_descriptor ptr_uint_descriptor
35 asm ("__go_td_pN30_libgo_runtime.runtime.UintType");
36 extern const struct __go_type_descriptor ptr_string_descriptor
37 asm ("__go_td_pN32_libgo_runtime.runtime.StringType");
38 extern const struct __go_type_descriptor ptr_unsafe_pointer_decriptor
39 asm ("__go_td_pN39_libgo_runtime.runtime.UnsafePointerType");
40 extern const struct __go_type_descriptor ptr_array_descriptor
41 asm ("__go_td_pN31_libgo_runtime.runtime.ArrayType");
42 extern const struct __go_type_descriptor ptr_slice_descriptor
43 asm ("__go_td_pN31_libgo_runtime.runtime.SliceType");
44 extern const struct __go_type_descriptor ptr_chan_descriptor
45 asm ("__go_td_pN30_libgo_runtime.runtime.ChanType");
46 extern const struct __go_type_descriptor ptr_func_descriptor
47 asm ("__go_td_pN30_libgo_runtime.runtime.FuncType");
48 extern const struct __go_type_descriptor ptr_interface_descriptor
49 asm ("__go_td_pN35_libgo_runtime.runtime.InterfaceType");
50 extern const struct __go_type_descriptor ptr_map_descriptor
51 asm ("__go_td_pN29_libgo_runtime.runtime.MapType");
52 extern const struct __go_type_descriptor ptr_ptr_descriptor
53 asm ("__go_td_pN29_libgo_runtime.runtime.PtrType");
54 extern const struct __go_type_descriptor ptr_struct_descriptor
55 asm ("__go_td_pN32_libgo_runtime.runtime.StructType");
56
57 const struct __go_type_descriptor *
58 get_descriptor (int code)
59 {
60 switch (code & GO_CODE_MASK)
61 {
62 case GO_BOOL:
63 return &ptr_bool_descriptor;
64 case GO_FLOAT32:
65 case GO_FLOAT64:
66 return &ptr_float_descriptor;
67 case GO_COMPLEX64:
68 case GO_COMPLEX128:
69 return &ptr_complex_descriptor;
70 case GO_INT16:
71 case GO_INT32:
72 case GO_INT64:
73 case GO_INT8:
74 case GO_INT:
75 return &ptr_int_descriptor;
76 case GO_UINT16:
77 case GO_UINT32:
78 case GO_UINT64:
79 case GO_UINT8:
80 case GO_UINTPTR:
81 case GO_UINT:
82 return &ptr_uint_descriptor;
83 case GO_STRING:
84 return &ptr_string_descriptor;
85 case GO_UNSAFE_POINTER:
86 return &ptr_unsafe_pointer_decriptor;
87 case GO_ARRAY:
88 return &ptr_array_descriptor;
89 case GO_SLICE:
90 return &ptr_slice_descriptor;
91 case GO_CHAN:
92 return &ptr_chan_descriptor;
93 case GO_FUNC:
94 return &ptr_func_descriptor;
95 case GO_INTERFACE:
96 return &ptr_interface_descriptor;
97 case GO_MAP:
98 return &ptr_map_descriptor;
99 case GO_PTR:
100 return &ptr_ptr_descriptor;
101 case GO_STRUCT:
102 return &ptr_struct_descriptor;
103 default:
104 abort ();
105 }
106 }
107
108 /* Implement unsafe.Reflect. */
109
110 struct reflect_ret
111 {
112 struct __go_empty_interface rettype;
113 void *addr;
114 };
115
116 struct reflect_ret Reflect (struct __go_empty_interface)
117 asm ("libgo_unsafe.unsafe.Reflect");
118
119 struct reflect_ret
120 Reflect (struct __go_empty_interface e)
121 {
122 struct reflect_ret ret;
123
124 if (((uintptr_t) e.__type_descriptor & reflectFlags) != 0)
125 __go_panic_msg ("invalid interface value");
126
127 if (e.__type_descriptor == NULL)
128 {
129 ret.rettype.__type_descriptor = NULL;
130 ret.rettype.__object = NULL;
131 ret.addr = NULL;
132 }
133 else
134 {
135 size_t size;
136
137 ret.rettype.__type_descriptor =
138 get_descriptor (e.__type_descriptor->__code);
139
140 /* This memcpy is really just an assignment of a const pointer
141 to a non-const pointer. FIXME: We should canonicalize this
142 pointer, so that for a given type we always return the same
143 pointer. */
144 __builtin_memcpy (&ret.rettype.__object, &e.__type_descriptor,
145 sizeof (void *));
146
147 /* Make a copy of the value. */
148 size = e.__type_descriptor->__size;
149 if (size <= sizeof (uint64_t))
150 ret.addr = __go_alloc (sizeof (uint64_t));
151 else
152 ret.addr = __go_alloc (size);
153 if (__go_is_pointer_type (e.__type_descriptor))
154 *(void **) ret.addr = e.__object;
155 else
156 __builtin_memcpy (ret.addr, e.__object, size);
157 }
158
159 return ret;
160 }
161
162 /* Implement unsafe.Typeof. */
163
164 struct __go_empty_interface Typeof (struct __go_empty_interface)
165 asm ("libgo_unsafe.unsafe.Typeof");
166
167 struct __go_empty_interface
168 Typeof (const struct __go_empty_interface e)
169 {
170 struct __go_empty_interface ret;
171
172 if (((uintptr_t) e.__type_descriptor & reflectFlags) != 0)
173 __go_panic_msg ("invalid interface value");
174
175 if (e.__type_descriptor == NULL)
176 {
177 ret.__type_descriptor = NULL;
178 ret.__object = NULL;
179 }
180 else
181 {
182 ret.__type_descriptor = get_descriptor (e.__type_descriptor->__code);
183
184 /* This memcpy is really just an assignment of a const pointer
185 to a non-const pointer. FIXME: We should canonicalize this
186 pointer, so that for a given type we always return the same
187 pointer. */
188 __builtin_memcpy (&ret.__object, &e.__type_descriptor, sizeof (void *));
189 }
190
191 return ret;
192 }