From: Ian Lance Taylor Date: Sat, 11 Jun 2011 06:21:55 +0000 (+0000) Subject: Use backend interface for map descriptors. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=891daafaf87384c823ff5186562e5132f246a9e4;p=gcc.git Use backend interface for map descriptors. From-SVN: r174943 --- diff --git a/gcc/go/gofrontend/expressions.cc b/gcc/go/gofrontend/expressions.cc index 00af2962068..9c6af0b7762 100644 --- a/gcc/go/gofrontend/expressions.cc +++ b/gcc/go/gofrontend/expressions.cc @@ -11747,7 +11747,7 @@ Map_construction_expression::do_get_tree(Translate_context* context) 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)); if (type_tree == error_mark_node) diff --git a/gcc/go/gofrontend/gogo-tree.cc b/gcc/go/gofrontend/gogo-tree.cc index 0c5cb671c05..94d1c4dd1db 100644 --- a/gcc/go/gofrontend/gogo-tree.cc +++ b/gcc/go/gofrontend/gogo-tree.cc @@ -1974,141 +1974,6 @@ Gogo::slice_constructor(tree slice_type_tree, tree values, tree count, 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 val(maptype, NULL); - std::pair 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 // pointers, one for each interface method. This is used for // interfaces. diff --git a/gcc/go/gofrontend/gogo.cc b/gcc/go/gofrontend/gogo.cc index 484d1a11e8f..194cacafcaf 100644 --- a/gcc/go/gofrontend/gogo.cc +++ b/gcc/go/gofrontend/gogo.cc @@ -29,7 +29,6 @@ Gogo::Gogo(Backend* backend, int int_type_size, int pointer_size) imports_(), imported_unsafe_(false), packages_(), - map_descriptors_(NULL), init_functions_(), need_init_fn_(false), init_fn_name_(), @@ -2596,6 +2595,7 @@ Gogo::convert_named_types() Array_type::make_array_type_descriptor_type(); Array_type::make_slice_type_descriptor_type(); Map_type::make_map_type_descriptor_type(); + Map_type::make_map_descriptor_type(); Channel_type::make_chan_type_descriptor_type(); Interface_type::make_interface_type_descriptor_type(); Type::convert_builtin_named_types(this); diff --git a/gcc/go/gofrontend/gogo.h b/gcc/go/gofrontend/gogo.h index 972369fe6fb..cc349afd064 100644 --- a/gcc/go/gofrontend/gogo.h +++ b/gcc/go/gofrontend/gogo.h @@ -473,16 +473,6 @@ class Gogo slice_constructor(tree slice_type_tree, tree values, tree count, 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. void build_interface_method_tables(); @@ -599,10 +589,6 @@ class Gogo // Type used to map special names in the sys package. typedef std::map 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. Backend* backend_; // The package we are compiling. @@ -619,8 +605,6 @@ class Gogo // Mapping from package names we have seen to packages. This does // not include the package we are compiling. Packages packages_; - // Mapping from map types to map descriptors. - Map_descriptors* map_descriptors_; // The functions named "init", if there are any. std::vector init_functions_; // Whether we need a magic initialization function. diff --git a/gcc/go/gofrontend/types.cc b/gcc/go/gofrontend/types.cc index 15e35c2b29d..e19d4f2e744 100644 --- a/gcc/go/gofrontend/types.cc +++ b/gcc/go/gofrontend/types.cc @@ -5049,7 +5049,8 @@ Map_type::do_make_expression_tree(Translate_context* context, 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; tree ret = Gogo::call_builtin(&new_map_fndecl, @@ -5058,7 +5059,7 @@ Map_type::do_make_expression_tree(Translate_context* context, 2, map_type, TREE_TYPE(TYPE_FIELDS(TREE_TYPE(map_type))), - context->gogo()->map_descriptor(this), + this->map_descriptor_pointer(gogo, location), sizetype, expr_tree); 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); } +// 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 val(this, NULL); + std::pair 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. void diff --git a/gcc/go/gofrontend/types.h b/gcc/go/gofrontend/types.h index fc35431f6ad..2ee80a4868b 100644 --- a/gcc/go/gofrontend/types.h +++ b/gcc/go/gofrontend/types.h @@ -2157,6 +2157,15 @@ class Map_type : public Type static 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: int do_traverse(Traverse*); @@ -2194,6 +2203,14 @@ class Map_type : public Type do_export(Export*) const; 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. Type* key_type_; // The value type. diff --git a/libgo/runtime/go-map-delete.c b/libgo/runtime/go-map-delete.c index ec851e531d2..7a3a7b83d92 100644 --- a/libgo/runtime/go-map-delete.c +++ b/libgo/runtime/go-map-delete.c @@ -18,7 +18,7 @@ __go_map_delete (struct __go_map *map, const void *key) { const struct __go_map_descriptor *descriptor; const struct __go_type_descriptor *key_descriptor; - size_t key_offset; + uintptr_t key_offset; _Bool (*equalfn) (const void*, const void*, size_t); size_t key_hash; size_t key_size; diff --git a/libgo/runtime/go-map-index.c b/libgo/runtime/go-map-index.c index 02a0f73f224..a387c4b98bc 100644 --- a/libgo/runtime/go-map-index.c +++ b/libgo/runtime/go-map-index.c @@ -18,7 +18,7 @@ __go_map_rehash (struct __go_map *map) { const struct __go_map_descriptor *descriptor; const struct __go_type_descriptor *key_descriptor; - size_t key_offset; + uintptr_t key_offset; size_t key_size; size_t (*hashfn) (const void *, size_t); 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_type_descriptor *key_descriptor; - size_t key_offset; + uintptr_t key_offset; _Bool (*equalfn) (const void*, const void*, size_t); size_t key_hash; size_t key_size; diff --git a/libgo/runtime/map.h b/libgo/runtime/map.h index 40c31f82315..0c587bb2afa 100644 --- a/libgo/runtime/map.h +++ b/libgo/runtime/map.h @@ -22,15 +22,15 @@ struct __go_map_descriptor key_type key; value_type value; 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. */ - size_t __key_offset; + uintptr_t __key_offset; /* The offset of the value field in a map entry struct (the value field immediately follows the key field, but there may be some bytes inserted for alignment). */ - size_t __val_offset; + uintptr_t __val_offset; }; struct __go_map