gcc/libgo/runtime/go-reflect-map.c
Ian Lance Taylor f8d9fa9e80 libgo, compiler: Upgrade libgo to Go 1.4, except for runtime.
This upgrades all of libgo other than the runtime package to
the Go 1.4 release.  In Go 1.4 much of the runtime was
rewritten into Go.  Merging that code will take more time and
will not change the API, so I'm putting it off for now.

There are a few runtime changes anyhow, to accomodate other
packages that rely on minor modifications to the runtime
support.

The compiler changes slightly to add a one-bit flag to each
type descriptor kind that is stored directly in an interface,
which for gccgo is currently only pointer types.  Another
one-bit flag (gcprog) is reserved because it is used by the gc
compiler, but gccgo does not currently use it.

There is another error check in the compiler since I ran
across it during testing.

gotools/:
	* Makefile.am (go_cmd_go_files): Sort entries.  Add generate.go.
	* Makefile.in: Rebuild.

From-SVN: r219627
2015-01-15 00:27:56 +00:00

156 lines
4.1 KiB
C

/* go-reflect-map.c -- map reflection support for Go.
Copyright 2009, 2010 The Go Authors. All rights reserved.
Use of this source code is governed by a BSD-style
license that can be found in the LICENSE file. */
#include <stdlib.h>
#include <stdint.h>
#include "runtime.h"
#include "go-alloc.h"
#include "go-assert.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 void *mapaccess (struct __go_map_type *, void *, void *)
__asm__ (GOSYM_PREFIX "reflect.mapaccess");
void *
mapaccess (struct __go_map_type *mt, void *m, void *key)
{
struct __go_map *map = (struct __go_map *) m;
__go_assert ((mt->__common.__code & GO_CODE_MASK) == GO_MAP);
if (map == NULL)
return NULL;
else
return __go_map_index (map, key, 0);
}
extern void mapassign (struct __go_map_type *, void *, void *, void *)
__asm__ (GOSYM_PREFIX "reflect.mapassign");
void
mapassign (struct __go_map_type *mt, void *m, void *key, void *val)
{
struct __go_map *map = (struct __go_map *) m;
void *p;
__go_assert ((mt->__common.__code & GO_CODE_MASK) == GO_MAP);
if (map == NULL)
runtime_panicstring ("assignment to entry in nil map");
p = __go_map_index (map, key, 1);
__builtin_memcpy (p, val, mt->__val_type->__size);
}
extern void mapdelete (struct __go_map_type *, void *, void *)
__asm__ (GOSYM_PREFIX "reflect.mapdelete");
void
mapdelete (struct __go_map_type *mt, void *m, void *key)
{
struct __go_map *map = (struct __go_map *) m;
__go_assert ((mt->__common.__code & GO_CODE_MASK) == GO_MAP);
if (map == NULL)
return;
__go_map_delete (map, key);
}
extern int32_t maplen (void *) __asm__ (GOSYM_PREFIX "reflect.maplen");
int32_t
maplen (void *m)
{
struct __go_map *map = (struct __go_map *) m;
if (map == NULL)
return 0;
return (int32_t) map->__element_count;
}
extern unsigned char *mapiterinit (struct __go_map_type *, void *)
__asm__ (GOSYM_PREFIX "reflect.mapiterinit");
unsigned char *
mapiterinit (struct __go_map_type *mt, void *m)
{
struct __go_hash_iter *it;
__go_assert ((mt->__common.__code & GO_CODE_MASK) == GO_MAP);
it = __go_alloc (sizeof (struct __go_hash_iter));
__go_mapiterinit ((struct __go_map *) m, it);
return (unsigned char *) it;
}
extern void mapiternext (void *) __asm__ (GOSYM_PREFIX "reflect.mapiternext");
void
mapiternext (void *it)
{
__go_mapiternext ((struct __go_hash_iter *) it);
}
extern void *mapiterkey (void *) __asm__ (GOSYM_PREFIX "reflect.mapiterkey");
void *
mapiterkey (void *ita)
{
struct __go_hash_iter *it = (struct __go_hash_iter *) ita;
const struct __go_type_descriptor *key_descriptor;
void *key;
if (it->entry == NULL)
return NULL;
key_descriptor = it->map->__descriptor->__map_descriptor->__key_type;
key = __go_alloc (key_descriptor->__size);
__go_mapiter1 (it, key);
return key;
}
/* Make a new map. We have to build our own map descriptor. */
extern struct __go_map *makemap (const struct __go_map_type *)
__asm__ (GOSYM_PREFIX "reflect.makemap");
struct __go_map *
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;
md = (struct __go_map_descriptor *) __go_alloc (sizeof (*md));
md->__map_descriptor = t;
o = sizeof (void *);
kt = t->__key_type;
o = (o + kt->__field_align - 1) & ~ (kt->__field_align - 1);
md->__key_offset = o;
o += kt->__size;
vt = t->__val_type;
o = (o + vt->__field_align - 1) & ~ (vt->__field_align - 1);
md->__val_offset = o;
o += vt->__size;
o = (o + sizeof (void *) - 1) & ~ (sizeof (void *) - 1);
o = (o + kt->__field_align - 1) & ~ (kt->__field_align - 1);
o = (o + vt->__field_align - 1) & ~ (vt->__field_align - 1);
md->__entry_size = o;
return __go_new_map (md, 0);
}
extern _Bool ismapkey (const struct __go_type_descriptor *)
__asm__ (GOSYM_PREFIX "reflect.ismapkey");
_Bool
ismapkey (const struct __go_type_descriptor *typ)
{
return typ != NULL && typ->__hashfn != __go_type_hash_error;
}