OSDN Git Service

runtime: Fix typo in go-nosys.c.
[pf3gnuchains/gcc-fork.git] / libgo / runtime / go-reflect-map.c
1 /* go-reflect-map.c -- map reflection support for Go.
2
3    Copyright 2009, 2010 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 "go-alloc.h"
12 #include "go-assert.h"
13 #include "go-type.h"
14 #include "map.h"
15
16 /* This file implements support for reflection on maps.  These
17    functions are called from reflect/value.go.  */
18
19 struct mapaccess_ret
20 {
21   uintptr_t val;
22   _Bool pres;
23 };
24
25 extern struct mapaccess_ret mapaccess (struct __go_map_type *, uintptr_t,
26                                        uintptr_t)
27   asm ("libgo_reflect.reflect.mapaccess");
28
29 struct mapaccess_ret
30 mapaccess (struct __go_map_type *mt, uintptr_t m, uintptr_t key_i)
31 {
32   struct __go_map *map = (struct __go_map *) m;
33   void *key;
34   const struct __go_type_descriptor *key_descriptor;
35   void *p;
36   const struct __go_type_descriptor *val_descriptor;
37   struct mapaccess_ret ret;
38   void *val;
39   void *pv;
40
41   __go_assert (mt->__common.__code == GO_MAP);
42
43   key_descriptor = mt->__key_type;
44   if (__go_is_pointer_type (key_descriptor))
45     key = &key_i;
46   else
47     key = (void *) key_i;
48
49   if (map == NULL)
50     p = NULL;
51   else
52     p = __go_map_index (map, key, 0);
53
54   val_descriptor = mt->__val_type;
55   if (__go_is_pointer_type (val_descriptor))
56     {
57       val = NULL;
58       pv = &val;
59     }
60   else
61     {
62       val = __go_alloc (val_descriptor->__size);
63       pv = val;
64     }
65
66   if (p == NULL)
67     ret.pres = 0;
68   else
69     {
70       __builtin_memcpy (pv, p, val_descriptor->__size);
71       ret.pres = 1;
72     }
73
74   ret.val = (uintptr_t) val;
75   return ret;
76 }
77
78 extern void mapassign (struct __go_map_type *, uintptr_t, uintptr_t,
79                        uintptr_t, _Bool)
80   asm ("libgo_reflect.reflect.mapassign");
81
82 void
83 mapassign (struct __go_map_type *mt, uintptr_t m, uintptr_t key_i,
84            uintptr_t val_i, _Bool pres)
85 {
86   struct __go_map *map = (struct __go_map *) m;
87   const struct __go_type_descriptor *key_descriptor;
88   void *key;
89
90   __go_assert (mt->__common.__code == GO_MAP);
91
92   if (map == NULL)
93     runtime_panicstring ("assignment to entry in nil map");
94
95   key_descriptor = mt->__key_type;
96   if (__go_is_pointer_type (key_descriptor))
97     key = &key_i;
98   else
99     key = (void *) key_i;
100
101   if (!pres)
102     __go_map_delete (map, key);
103   else
104     {
105       void *p;
106       const struct __go_type_descriptor *val_descriptor;
107       void *pv;
108
109       p = __go_map_index (map, key, 1);
110
111       val_descriptor = mt->__val_type;
112       if (__go_is_pointer_type (val_descriptor))
113         pv = &val_i;
114       else
115         pv = (void *) val_i;
116       __builtin_memcpy (p, pv, val_descriptor->__size);
117     }
118 }
119
120 extern int32_t maplen (uintptr_t)
121   asm ("libgo_reflect.reflect.maplen");
122
123 int32_t
124 maplen (uintptr_t m)
125 {
126   struct __go_map *map = (struct __go_map *) m;
127
128   if (map == NULL)
129     return 0;
130   return (int32_t) map->__element_count;
131 }
132
133 extern unsigned char *mapiterinit (struct __go_map_type *, uintptr_t)
134   asm ("libgo_reflect.reflect.mapiterinit");
135
136 unsigned char *
137 mapiterinit (struct __go_map_type *mt, uintptr_t m)
138 {
139   struct __go_hash_iter *it;
140
141   __go_assert (mt->__common.__code == GO_MAP);
142   it = __go_alloc (sizeof (struct __go_hash_iter));
143   __go_mapiterinit ((struct __go_map *) m, it);
144   return (unsigned char *) it;
145 }
146
147 extern void mapiternext (unsigned char *)
148   asm ("libgo_reflect.reflect.mapiternext");
149
150 void
151 mapiternext (unsigned char *it)
152 {
153   __go_mapiternext ((struct __go_hash_iter *) it);
154 }
155
156 struct mapiterkey_ret
157 {
158   uintptr_t key;
159   _Bool ok;
160 };
161
162 extern struct mapiterkey_ret mapiterkey (unsigned char *)
163   asm ("libgo_reflect.reflect.mapiterkey");
164
165 struct mapiterkey_ret
166 mapiterkey (unsigned char *ita)
167 {
168   struct __go_hash_iter *it = (struct __go_hash_iter *) ita;
169   struct mapiterkey_ret ret;
170
171   if (it->entry == NULL)
172     {
173       ret.key = 0;
174       ret.ok = 0;
175     }
176   else
177     {
178       const struct __go_type_descriptor *key_descriptor;
179       void *key;
180       void *pk;
181
182       key_descriptor = it->map->__descriptor->__map_descriptor->__key_type;
183       if (__go_is_pointer_type (key_descriptor))
184         {
185           key = NULL;
186           pk = &key;
187         }
188       else
189         {
190           key = __go_alloc (key_descriptor->__size);
191           pk = key;
192         }
193
194       __go_mapiter1 (it, pk);
195
196       ret.key = (uintptr_t) key;
197       ret.ok = 1;
198     }
199
200   return ret;
201 }
202
203 /* Make a new map.  We have to build our own map descriptor.  */
204
205 extern uintptr_t makemap (const struct __go_map_type *)
206   asm ("libgo_reflect.reflect.makemap");
207
208 uintptr_t
209 makemap (const struct __go_map_type *t)
210 {
211   struct __go_map_descriptor *md;
212   unsigned int o;
213   const struct __go_type_descriptor *kt;
214   const struct __go_type_descriptor *vt;
215   struct __go_map* map;
216   void *ret;
217
218   /* FIXME: Reference count.  */
219   md = (struct __go_map_descriptor *) __go_alloc (sizeof (*md));
220   md->__map_descriptor = t;
221   o = sizeof (void *);
222   kt = t->__key_type;
223   o = (o + kt->__field_align - 1) & ~ (kt->__field_align - 1);
224   md->__key_offset = o;
225   o += kt->__size;
226   vt = t->__val_type;
227   o = (o + vt->__field_align - 1) & ~ (vt->__field_align - 1);
228   md->__val_offset = o;
229   o += vt->__size;
230   o = (o + sizeof (void *) - 1) & ~ (sizeof (void *) - 1);
231   o = (o + kt->__field_align - 1) & ~ (kt->__field_align - 1);
232   o = (o + vt->__field_align - 1) & ~ (vt->__field_align - 1);
233   md->__entry_size = o;
234
235   map = __go_new_map (md, 0);
236
237   ret = __go_alloc (sizeof (void *));
238   __builtin_memcpy (ret, &map, sizeof (void *));
239   return (uintptr_t) ret;
240 }