diff options
Diffstat (limited to 'libgo/runtime/go-reflect-map.c')
-rw-r--r-- | libgo/runtime/go-reflect-map.c | 140 |
1 files changed, 116 insertions, 24 deletions
diff --git a/libgo/runtime/go-reflect-map.c b/libgo/runtime/go-reflect-map.c index 67960dee41e..5559f6eadaf 100644 --- a/libgo/runtime/go-reflect-map.c +++ b/libgo/runtime/go-reflect-map.c @@ -8,69 +8,125 @@ #include <stdint.h> #include "go-alloc.h" +#include "go-panic.h" #include "go-type.h" #include "map.h" /* This file implements support for reflection on maps. These functions are called from reflect/value.go. */ -extern _Bool mapaccess (unsigned char *, unsigned char *, unsigned char *) +struct mapaccess_ret +{ + uintptr_t val; + _Bool pres; +}; + +extern struct mapaccess_ret mapaccess (uintptr_t, uintptr_t) asm ("libgo_reflect.reflect.mapaccess"); -_Bool -mapaccess (unsigned char *m, unsigned char *key, unsigned char *val) +struct mapaccess_ret +mapaccess (uintptr_t m, uintptr_t key_i) { struct __go_map *map = (struct __go_map *) m; + void *key; + const struct __go_type_descriptor *key_descriptor; void *p; const struct __go_type_descriptor *val_descriptor; + struct mapaccess_ret ret; + void *val; + void *pv; + + if (map == NULL) + __go_panic_msg ("lookup in nil map"); + + key_descriptor = map->__descriptor->__map_descriptor->__key_type; + if (__go_is_pointer_type (key_descriptor)) + key = &key_i; + else + key = (void *) key_i; p = __go_map_index (map, key, 0); + + val_descriptor = map->__descriptor->__map_descriptor->__val_type; + if (__go_is_pointer_type (val_descriptor)) + { + val = NULL; + pv = &val; + } + else + { + val = __go_alloc (val_descriptor->__size); + pv = val; + } + if (p == NULL) - return 0; + ret.pres = 0; else { - val_descriptor = map->__descriptor->__map_descriptor->__val_type; - __builtin_memcpy (val, p, val_descriptor->__size); - return 1; + __builtin_memcpy (pv, p, val_descriptor->__size); + ret.pres = 1; } + + ret.val = (uintptr_t) val; + return ret; } -extern void mapassign (unsigned char *, unsigned char *, unsigned char *) +extern void mapassign (uintptr_t, uintptr_t, uintptr_t, _Bool) asm ("libgo_reflect.reflect.mapassign"); void -mapassign (unsigned char *m, unsigned char *key, unsigned char *val) +mapassign (uintptr_t m, uintptr_t key_i, uintptr_t val_i, _Bool pres) { struct __go_map *map = (struct __go_map *) m; + const struct __go_type_descriptor *key_descriptor; + void *key; - if (val == NULL) + if (map == NULL) + __go_panic_msg ("lookup in nil map"); + + key_descriptor = map->__descriptor->__map_descriptor->__key_type; + if (__go_is_pointer_type (key_descriptor)) + key = &key_i; + else + key = (void *) key_i; + + if (!pres) __go_map_delete (map, key); else { void *p; const struct __go_type_descriptor *val_descriptor; + void *pv; p = __go_map_index (map, key, 1); + val_descriptor = map->__descriptor->__map_descriptor->__val_type; - __builtin_memcpy (p, val, val_descriptor->__size); + if (__go_is_pointer_type (val_descriptor)) + pv = &val_i; + else + pv = (void *) val_i; + __builtin_memcpy (p, pv, val_descriptor->__size); } } -extern int32_t maplen (unsigned char *) +extern int32_t maplen (uintptr_t) asm ("libgo_reflect.reflect.maplen"); int32_t -maplen (unsigned char *m __attribute__ ((unused))) +maplen (uintptr_t m) { struct __go_map *map = (struct __go_map *) m; + + if (map == NULL) + return 0; return (int32_t) map->__element_count; } -extern unsigned char *mapiterinit (unsigned char *) +extern unsigned char *mapiterinit (uintptr_t) asm ("libgo_reflect.reflect.mapiterinit"); unsigned char * -mapiterinit (unsigned char *m) +mapiterinit (uintptr_t m) { struct __go_hash_iter *it; @@ -88,35 +144,67 @@ mapiternext (unsigned char *it) __go_mapiternext ((struct __go_hash_iter *) it); } -extern _Bool mapiterkey (unsigned char *, unsigned char *) +struct mapiterkey_ret +{ + uintptr_t key; + _Bool ok; +}; + +extern struct mapiterkey_ret mapiterkey (unsigned char *) asm ("libgo_reflect.reflect.mapiterkey"); -_Bool -mapiterkey (unsigned char *ita, unsigned char *key) +struct mapiterkey_ret +mapiterkey (unsigned char *ita) { struct __go_hash_iter *it = (struct __go_hash_iter *) ita; + struct mapiterkey_ret ret; if (it->entry == NULL) - return 0; + { + ret.key = 0; + ret.ok = 0; + } else { - __go_mapiter1 (it, key); - return 1; + const struct __go_type_descriptor *key_descriptor; + void *key; + void *pk; + + key_descriptor = it->map->__descriptor->__map_descriptor->__key_type; + if (__go_is_pointer_type (key_descriptor)) + { + key = NULL; + pk = &key; + } + else + { + key = __go_alloc (key_descriptor->__size); + pk = key; + } + + __go_mapiter1 (it, pk); + + ret.key = (uintptr_t) key; + ret.ok = 1; } + + return ret; } /* Make a new map. We have to build our own map descriptor. */ -extern unsigned char *makemap (const struct __go_map_type *) +extern uintptr_t makemap (const struct __go_map_type *) asm ("libgo_reflect.reflect.makemap"); -unsigned char * +uintptr_t makemap (const struct __go_map_type *t) { struct __go_map_descriptor *md; unsigned int o; const struct __go_type_descriptor *kt; const struct __go_type_descriptor *vt; + struct __go_map* map; + void *ret; /* FIXME: Reference count. */ md = (struct __go_map_descriptor *) __go_alloc (sizeof (*md)); @@ -135,5 +223,9 @@ makemap (const struct __go_map_type *t) o = (o + vt->__field_align - 1) & ~ (vt->__field_align - 1); md->__entry_size = o; - return (unsigned char *) __go_new_map (md, 0); + map = __go_new_map (md, 0); + + ret = __go_alloc (sizeof (void *)); + __builtin_memcpy (ret, &map, sizeof (void *)); + return (uintptr_t) ret; } |