OSDN Git Service

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