OSDN Git Service

Avoid always splitting the stack when calling append and copy.
[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 "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)
61     {
62     case GO_BOOL:
63       return &ptr_bool_descriptor;
64     case GO_FLOAT32:
65     case GO_FLOAT64:
66     case GO_FLOAT:
67       return &ptr_float_descriptor;
68     case GO_COMPLEX64:
69     case GO_COMPLEX128:
70     case GO_COMPLEX:
71       return &ptr_complex_descriptor;
72     case GO_INT16:
73     case GO_INT32:
74     case GO_INT64:
75     case GO_INT8:
76     case GO_INT:
77       return &ptr_int_descriptor;
78     case GO_UINT16:
79     case GO_UINT32:
80     case GO_UINT64:
81     case GO_UINT8:
82     case GO_UINTPTR:
83     case GO_UINT:
84       return &ptr_uint_descriptor;
85     case GO_STRING:
86       return &ptr_string_descriptor;
87     case GO_UNSAFE_POINTER:
88       return &ptr_unsafe_pointer_decriptor;
89     case GO_ARRAY:
90       return &ptr_array_descriptor;
91     case GO_SLICE:
92       return &ptr_slice_descriptor;
93     case GO_CHAN:
94       return &ptr_chan_descriptor;
95     case GO_FUNC:
96       return &ptr_func_descriptor;
97     case GO_INTERFACE:
98       return &ptr_interface_descriptor;
99     case GO_MAP:
100       return &ptr_map_descriptor;
101     case GO_PTR:
102       return &ptr_ptr_descriptor;
103     case GO_STRUCT:
104       return &ptr_struct_descriptor;
105     default:
106       abort ();
107     }
108 }
109
110 /* Implement unsafe.Reflect.  */
111
112 struct reflect_ret
113 {
114   struct __go_empty_interface rettype;
115   void *addr;
116 };
117
118 struct reflect_ret Reflect (struct __go_empty_interface)
119   asm ("libgo_unsafe.unsafe.Reflect");
120
121 struct reflect_ret
122 Reflect (struct __go_empty_interface e)
123 {
124   struct reflect_ret ret;
125
126   if (e.__type_descriptor == NULL)
127     {
128       ret.rettype.__type_descriptor = NULL;
129       ret.rettype.__object = NULL;
130       ret.addr = NULL;
131     }
132   else
133     {
134       size_t size;
135
136       ret.rettype.__type_descriptor =
137         get_descriptor (e.__type_descriptor->__code);
138
139       /* This memcpy is really just an assignment of a const pointer
140          to a non-const pointer.  FIXME: We should canonicalize this
141          pointer, so that for a given type we always return the same
142          pointer.  */
143       __builtin_memcpy (&ret.rettype.__object, &e.__type_descriptor,
144                         sizeof (void *));
145
146       /* Make a copy of the value.  */
147       size = e.__type_descriptor->__size;
148       if (size <= sizeof (uint64_t))
149         ret.addr = __go_alloc (sizeof (uint64_t));
150       else
151         ret.addr = __go_alloc (size);
152       if (__go_is_pointer_type (e.__type_descriptor))
153         *(void **) ret.addr = e.__object;
154       else
155         __builtin_memcpy (ret.addr, e.__object, size);
156     }
157
158   return ret;
159 }
160
161 /* Implement unsafe.Typeof.  */
162
163 struct __go_empty_interface Typeof (struct __go_empty_interface)
164   asm ("libgo_unsafe.unsafe.Typeof");
165
166 struct __go_empty_interface
167 Typeof (const struct __go_empty_interface e)
168 {
169   struct __go_empty_interface ret;
170
171   if (e.__type_descriptor == NULL)
172     {
173       ret.__type_descriptor = NULL;
174       ret.__object = NULL;
175     }
176   else
177     {
178       ret.__type_descriptor = get_descriptor (e.__type_descriptor->__code);
179
180       /* This memcpy is really just an assignment of a const pointer
181          to a non-const pointer.  FIXME: We should canonicalize this
182          pointer, so that for a given type we always return the same
183          pointer.  */
184       __builtin_memcpy (&ret.__object, &e.__type_descriptor, sizeof (void *));
185     }
186
187   return ret;
188 }