OSDN Git Service

syscall: Fill out GNU/Linux support.
[pf3gnuchains/gcc-fork.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 "runtime.h"
11 #include "interface.h"
12 #include "go-alloc.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     runtime_panicstring ("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     runtime_panicstring ("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 }