Use backend interface for map descriptors.

From-SVN: r174943
This commit is contained in:
Ian Lance Taylor 2011-06-11 06:21:55 +00:00
parent 70f910247b
commit 891daafaf8
9 changed files with 151 additions and 161 deletions

View File

@ -11747,7 +11747,7 @@ Map_construction_expression::do_get_tree(Translate_context* context)
valaddr = build_fold_addr_expr(tmp); valaddr = build_fold_addr_expr(tmp);
} }
tree descriptor = gogo->map_descriptor(mt); tree descriptor = mt->map_descriptor_pointer(gogo, loc);
tree type_tree = type_to_tree(this->type_->get_backend(gogo)); tree type_tree = type_to_tree(this->type_->get_backend(gogo));
if (type_tree == error_mark_node) if (type_tree == error_mark_node)

View File

@ -1974,141 +1974,6 @@ Gogo::slice_constructor(tree slice_type_tree, tree values, tree count,
return build_constructor(slice_type_tree, init); return build_constructor(slice_type_tree, init);
} }
// Build a map descriptor for a map of type MAPTYPE.
tree
Gogo::map_descriptor(Map_type* maptype)
{
if (this->map_descriptors_ == NULL)
this->map_descriptors_ = new Map_descriptors(10);
std::pair<const Map_type*, tree> val(maptype, NULL);
std::pair<Map_descriptors::iterator, bool> ins =
this->map_descriptors_->insert(val);
Map_descriptors::iterator p = ins.first;
if (!ins.second)
{
if (p->second == error_mark_node)
return error_mark_node;
go_assert(p->second != NULL_TREE && DECL_P(p->second));
return build_fold_addr_expr(p->second);
}
Type* keytype = maptype->key_type();
Type* valtype = maptype->val_type();
std::string mangled_name = ("__go_map_" + maptype->mangled_name(this));
tree id = get_identifier_from_string(mangled_name);
// Get the type of the map descriptor. This is __go_map_descriptor
// in libgo/map.h.
tree struct_type = this->map_descriptor_type();
// The map entry type is a struct with three fields. This struct is
// specific to MAPTYPE. Build it.
tree map_entry_type = make_node(RECORD_TYPE);
Btype* bkey_type = keytype->get_backend(this);
Btype* bval_type = valtype->get_backend(this);
map_entry_type = Gogo::builtin_struct(NULL, "__map", map_entry_type, 3,
"__next",
build_pointer_type(map_entry_type),
"__key",
type_to_tree(bkey_type),
"__val",
type_to_tree(bval_type));
if (map_entry_type == error_mark_node)
{
p->second = error_mark_node;
return error_mark_node;
}
tree map_entry_key_field = DECL_CHAIN(TYPE_FIELDS(map_entry_type));
go_assert(strcmp(IDENTIFIER_POINTER(DECL_NAME(map_entry_key_field)),
"__key") == 0);
tree map_entry_val_field = DECL_CHAIN(map_entry_key_field);
go_assert(strcmp(IDENTIFIER_POINTER(DECL_NAME(map_entry_val_field)),
"__val") == 0);
// Initialize the entries.
tree map_descriptor_field = TYPE_FIELDS(struct_type);
go_assert(strcmp(IDENTIFIER_POINTER(DECL_NAME(map_descriptor_field)),
"__map_descriptor") == 0);
tree entry_size_field = DECL_CHAIN(map_descriptor_field);
go_assert(strcmp(IDENTIFIER_POINTER(DECL_NAME(entry_size_field)),
"__entry_size") == 0);
tree key_offset_field = DECL_CHAIN(entry_size_field);
go_assert(strcmp(IDENTIFIER_POINTER(DECL_NAME(key_offset_field)),
"__key_offset") == 0);
tree val_offset_field = DECL_CHAIN(key_offset_field);
go_assert(strcmp(IDENTIFIER_POINTER(DECL_NAME(val_offset_field)),
"__val_offset") == 0);
VEC(constructor_elt, gc)* descriptor = VEC_alloc(constructor_elt, gc, 6);
constructor_elt* elt = VEC_quick_push(constructor_elt, descriptor, NULL);
elt->index = map_descriptor_field;
elt->value = maptype->type_descriptor_pointer(this, BUILTINS_LOCATION);
elt = VEC_quick_push(constructor_elt, descriptor, NULL);
elt->index = entry_size_field;
elt->value = TYPE_SIZE_UNIT(map_entry_type);
elt = VEC_quick_push(constructor_elt, descriptor, NULL);
elt->index = key_offset_field;
elt->value = byte_position(map_entry_key_field);
elt = VEC_quick_push(constructor_elt, descriptor, NULL);
elt->index = val_offset_field;
elt->value = byte_position(map_entry_val_field);
tree constructor = build_constructor(struct_type, descriptor);
tree decl = build_decl(BUILTINS_LOCATION, VAR_DECL, id, struct_type);
TREE_STATIC(decl) = 1;
TREE_USED(decl) = 1;
TREE_READONLY(decl) = 1;
TREE_CONSTANT(decl) = 1;
DECL_INITIAL(decl) = constructor;
make_decl_one_only(decl, DECL_ASSEMBLER_NAME(decl));
resolve_unique_section(decl, 1, 0);
rest_of_decl_compilation(decl, 1, 0);
go_preserve_from_gc(decl);
p->second = decl;
return build_fold_addr_expr(decl);
}
// Return a tree for the type of a map descriptor. This is struct
// __go_map_descriptor in libgo/runtime/map.h. This is the same for
// all map types.
tree
Gogo::map_descriptor_type()
{
static tree struct_type;
Type* tdt = Type::make_type_descriptor_type();
tree dtype = type_to_tree(tdt->get_backend(this));
dtype = build_qualified_type(dtype, TYPE_QUAL_CONST);
return Gogo::builtin_struct(&struct_type, "__go_map_descriptor", NULL_TREE,
4,
"__map_descriptor",
build_pointer_type(dtype),
"__entry_size",
sizetype,
"__key_offset",
sizetype,
"__val_offset",
sizetype);
}
// Build an interface method table for a type: a list of function // Build an interface method table for a type: a list of function
// pointers, one for each interface method. This is used for // pointers, one for each interface method. This is used for
// interfaces. // interfaces.

View File

@ -29,7 +29,6 @@ Gogo::Gogo(Backend* backend, int int_type_size, int pointer_size)
imports_(), imports_(),
imported_unsafe_(false), imported_unsafe_(false),
packages_(), packages_(),
map_descriptors_(NULL),
init_functions_(), init_functions_(),
need_init_fn_(false), need_init_fn_(false),
init_fn_name_(), init_fn_name_(),
@ -2596,6 +2595,7 @@ Gogo::convert_named_types()
Array_type::make_array_type_descriptor_type(); Array_type::make_array_type_descriptor_type();
Array_type::make_slice_type_descriptor_type(); Array_type::make_slice_type_descriptor_type();
Map_type::make_map_type_descriptor_type(); Map_type::make_map_type_descriptor_type();
Map_type::make_map_descriptor_type();
Channel_type::make_chan_type_descriptor_type(); Channel_type::make_chan_type_descriptor_type();
Interface_type::make_interface_type_descriptor_type(); Interface_type::make_interface_type_descriptor_type();
Type::convert_builtin_named_types(this); Type::convert_builtin_named_types(this);

View File

@ -473,16 +473,6 @@ class Gogo
slice_constructor(tree slice_type_tree, tree values, tree count, slice_constructor(tree slice_type_tree, tree values, tree count,
tree capacity); tree capacity);
// Build a map descriptor.
tree
map_descriptor(Map_type*);
// Return a tree for the type of a map descriptor. This is struct
// __go_map_descriptor in libgo/runtime/map.h. This is the same for
// all map types.
tree
map_descriptor_type();
// Build required interface method tables. // Build required interface method tables.
void void
build_interface_method_tables(); build_interface_method_tables();
@ -599,10 +589,6 @@ class Gogo
// Type used to map special names in the sys package. // Type used to map special names in the sys package.
typedef std::map<std::string, std::string> Sys_names; typedef std::map<std::string, std::string> Sys_names;
// Hash table mapping map types to map descriptor decls.
typedef Unordered_map_hash(const Map_type*, tree, Type_hash_identical,
Type_identical) Map_descriptors;
// The backend generator. // The backend generator.
Backend* backend_; Backend* backend_;
// The package we are compiling. // The package we are compiling.
@ -619,8 +605,6 @@ class Gogo
// Mapping from package names we have seen to packages. This does // Mapping from package names we have seen to packages. This does
// not include the package we are compiling. // not include the package we are compiling.
Packages packages_; Packages packages_;
// Mapping from map types to map descriptors.
Map_descriptors* map_descriptors_;
// The functions named "init", if there are any. // The functions named "init", if there are any.
std::vector<Named_object*> init_functions_; std::vector<Named_object*> init_functions_;
// Whether we need a magic initialization function. // Whether we need a magic initialization function.

View File

@ -5049,7 +5049,8 @@ Map_type::do_make_expression_tree(Translate_context* context,
location); location);
} }
tree map_type = type_to_tree(this->get_backend(context->gogo())); Gogo* gogo = context->gogo();
tree map_type = type_to_tree(this->get_backend(gogo));
static tree new_map_fndecl; static tree new_map_fndecl;
tree ret = Gogo::call_builtin(&new_map_fndecl, tree ret = Gogo::call_builtin(&new_map_fndecl,
@ -5058,7 +5059,7 @@ Map_type::do_make_expression_tree(Translate_context* context,
2, 2,
map_type, map_type,
TREE_TYPE(TYPE_FIELDS(TREE_TYPE(map_type))), TREE_TYPE(TYPE_FIELDS(TREE_TYPE(map_type))),
context->gogo()->map_descriptor(this), this->map_descriptor_pointer(gogo, location),
sizetype, sizetype,
expr_tree); expr_tree);
if (ret == error_mark_node) if (ret == error_mark_node)
@ -5136,6 +5137,129 @@ Map_type::do_type_descriptor(Gogo* gogo, Named_type* name)
return Expression::make_struct_composite_literal(mtdt, vals, bloc); return Expression::make_struct_composite_literal(mtdt, vals, bloc);
} }
// A mapping from map types to map descriptors.
Map_type::Map_descriptors Map_type::map_descriptors;
// Build a map descriptor for this type. Return a pointer to it.
tree
Map_type::map_descriptor_pointer(Gogo* gogo, source_location location)
{
Bvariable* bvar = this->map_descriptor(gogo);
tree var_tree = var_to_tree(bvar);
if (var_tree == error_mark_node)
return error_mark_node;
return build_fold_addr_expr_loc(location, var_tree);
}
// Build a map descriptor for this type.
Bvariable*
Map_type::map_descriptor(Gogo* gogo)
{
std::pair<Map_type*, Bvariable*> val(this, NULL);
std::pair<Map_type::Map_descriptors::iterator, bool> ins =
Map_type::map_descriptors.insert(val);
if (!ins.second)
return ins.first->second;
Type* key_type = this->key_type_;
Type* val_type = this->val_type_;
// The map entry type is a struct with three fields. Build that
// struct so that we can get the offsets of the key and value within
// a map entry. The first field should technically be a pointer to
// this type itself, but since we only care about field offsets we
// just use pointer to bool.
Type* pbool = Type::make_pointer_type(Type::make_boolean_type());
Struct_type* map_entry_type =
Type::make_builtin_struct_type(3,
"__next", pbool,
"__key", key_type,
"__val", val_type);
Type* map_descriptor_type = Map_type::make_map_descriptor_type();
const Struct_field_list* fields =
map_descriptor_type->struct_type()->fields();
Expression_list* vals = new Expression_list();
vals->reserve(4);
source_location bloc = BUILTINS_LOCATION;
Struct_field_list::const_iterator p = fields->begin();
go_assert(p->field_name() == "__map_descriptor");
vals->push_back(Expression::make_type_descriptor(this, bloc));
++p;
go_assert(p->field_name() == "__entry_size");
Expression::Type_info type_info = Expression::TYPE_INFO_SIZE;
vals->push_back(Expression::make_type_info(map_entry_type, type_info));
Struct_field_list::const_iterator pf = map_entry_type->fields()->begin();
++pf;
go_assert(pf->field_name() == "__key");
++p;
go_assert(p->field_name() == "__key_offset");
vals->push_back(Expression::make_struct_field_offset(map_entry_type, &*pf));
++pf;
go_assert(pf->field_name() == "__val");
++p;
go_assert(p->field_name() == "__val_offset");
vals->push_back(Expression::make_struct_field_offset(map_entry_type, &*pf));
++p;
go_assert(p == fields->end());
Expression* initializer =
Expression::make_struct_composite_literal(map_descriptor_type, vals, bloc);
std::string mangled_name = "__go_map_" + this->mangled_name(gogo);
Btype* map_descriptor_btype = map_descriptor_type->get_backend(gogo);
Bvariable* bvar = gogo->backend()->immutable_struct(mangled_name, true,
map_descriptor_btype,
bloc);
Translate_context context(gogo, NULL, NULL, NULL);
context.set_is_const();
Bexpression* binitializer = tree_to_expr(initializer->get_tree(&context));
gogo->backend()->immutable_struct_set_init(bvar, mangled_name, true,
map_descriptor_btype, bloc,
binitializer);
ins.first->second = bvar;
return bvar;
}
// Build the type of a map descriptor. This must match the struct
// __go_map_descriptor in libgo/runtime/map.h.
Type*
Map_type::make_map_descriptor_type()
{
static Type* ret;
if (ret == NULL)
{
Type* ptdt = Type::make_type_descriptor_ptr_type();
Type* uintptr_type = Type::lookup_integer_type("uintptr");
Struct_type* sf =
Type::make_builtin_struct_type(4,
"__map_descriptor", ptdt,
"__entry_size", uintptr_type,
"__key_offset", uintptr_type,
"__val_offset", uintptr_type);
ret = Type::make_builtin_named_type("__go_map_descriptor", sf);
}
return ret;
}
// Reflection string for a map. // Reflection string for a map.
void void

View File

@ -2157,6 +2157,15 @@ class Map_type : public Type
static Type* static Type*
make_map_type_descriptor_type(); make_map_type_descriptor_type();
static Type*
make_map_descriptor_type();
// Build a map descriptor for this type. Return a pointer to it.
// The location is the location which causes us to need the
// descriptor.
tree
map_descriptor_pointer(Gogo* gogo, source_location);
protected: protected:
int int
do_traverse(Traverse*); do_traverse(Traverse*);
@ -2194,6 +2203,14 @@ class Map_type : public Type
do_export(Export*) const; do_export(Export*) const;
private: private:
// Mapping from map types to map descriptors.
typedef Unordered_map_hash(const Map_type*, Bvariable*, Type_hash_identical,
Type_identical) Map_descriptors;
static Map_descriptors map_descriptors;
Bvariable*
map_descriptor(Gogo*);
// The key type. // The key type.
Type* key_type_; Type* key_type_;
// The value type. // The value type.

View File

@ -18,7 +18,7 @@ __go_map_delete (struct __go_map *map, const void *key)
{ {
const struct __go_map_descriptor *descriptor; const struct __go_map_descriptor *descriptor;
const struct __go_type_descriptor *key_descriptor; const struct __go_type_descriptor *key_descriptor;
size_t key_offset; uintptr_t key_offset;
_Bool (*equalfn) (const void*, const void*, size_t); _Bool (*equalfn) (const void*, const void*, size_t);
size_t key_hash; size_t key_hash;
size_t key_size; size_t key_size;

View File

@ -18,7 +18,7 @@ __go_map_rehash (struct __go_map *map)
{ {
const struct __go_map_descriptor *descriptor; const struct __go_map_descriptor *descriptor;
const struct __go_type_descriptor *key_descriptor; const struct __go_type_descriptor *key_descriptor;
size_t key_offset; uintptr_t key_offset;
size_t key_size; size_t key_size;
size_t (*hashfn) (const void *, size_t); size_t (*hashfn) (const void *, size_t);
uintptr_t old_bucket_count; uintptr_t old_bucket_count;
@ -78,7 +78,7 @@ __go_map_index (struct __go_map *map, const void *key, _Bool insert)
{ {
const struct __go_map_descriptor *descriptor; const struct __go_map_descriptor *descriptor;
const struct __go_type_descriptor *key_descriptor; const struct __go_type_descriptor *key_descriptor;
size_t key_offset; uintptr_t key_offset;
_Bool (*equalfn) (const void*, const void*, size_t); _Bool (*equalfn) (const void*, const void*, size_t);
size_t key_hash; size_t key_hash;
size_t key_size; size_t key_size;

View File

@ -22,15 +22,15 @@ struct __go_map_descriptor
key_type key; key_type key;
value_type value; value_type value;
This is the size of that struct. */ This is the size of that struct. */
size_t __entry_size; uintptr_t __entry_size;
/* The offset of the key field in a map entry struct. */ /* The offset of the key field in a map entry struct. */
size_t __key_offset; uintptr_t __key_offset;
/* The offset of the value field in a map entry struct (the value /* The offset of the value field in a map entry struct (the value
field immediately follows the key field, but there may be some field immediately follows the key field, but there may be some
bytes inserted for alignment). */ bytes inserted for alignment). */
size_t __val_offset; uintptr_t __val_offset;
}; };
struct __go_map struct __go_map