From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 8246 invoked by alias); 11 Jun 2011 06:22:32 -0000 Received: (qmail 8227 invoked by uid 22791); 11 Jun 2011 06:22:29 -0000 X-SWARE-Spam-Status: No, hits=-0.8 required=5.0 tests=AWL,BAYES_50,DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,SPF_HELO_PASS,TW_FD,TW_TD,T_RP_MATCHES_RCVD,T_TVD_MIME_NO_HEADERS X-Spam-Check-By: sourceware.org Received: from smtp-out.google.com (HELO smtp-out.google.com) (74.125.121.67) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Sat, 11 Jun 2011 06:22:08 +0000 Received: from hpaq12.eem.corp.google.com (hpaq12.eem.corp.google.com [172.25.149.12]) by smtp-out.google.com with ESMTP id p5B6M7Lh021278 for ; Fri, 10 Jun 2011 23:22:07 -0700 Received: from pxi16 (pxi16.prod.google.com [10.243.27.16]) by hpaq12.eem.corp.google.com with ESMTP id p5B6M4mT004887 (version=TLSv1/SSLv3 cipher=RC4-SHA bits=128 verify=NOT) for ; Fri, 10 Jun 2011 23:22:05 -0700 Received: by pxi16 with SMTP id 16so1986342pxi.18 for ; Fri, 10 Jun 2011 23:22:03 -0700 (PDT) Received: by 10.68.15.129 with SMTP id x1mr1406091pbc.49.1307773323643; Fri, 10 Jun 2011 23:22:03 -0700 (PDT) Received: from coign.google.com ([216.239.45.130]) by mx.google.com with ESMTPS id k9sm2914477pbc.70.2011.06.10.23.22.01 (version=TLSv1/SSLv3 cipher=OTHER); Fri, 10 Jun 2011 23:22:02 -0700 (PDT) From: Ian Lance Taylor To: gcc-patches@gcc.gnu.org, gofrontend-dev@googlegroups.com Subject: Go patch committed: Use backend interface for map descriptors Date: Sat, 11 Jun 2011 07:24:00 -0000 Message-ID: User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/23.1 (gnu/linux) MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="=-=-=" X-System-Of-Record: true X-IsSubscribed: yes Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org X-SW-Source: 2011-06/txt/msg00893.txt.bz2 --=-=-= Content-length: 311 This patch to the Go frontend uses the backend interface for map descriptors. In order to do this I had to change the types of the map descriptor fields from size_t to uintptr_t, which led to a few changes in libgo. Bootstrapped and ran Go testsuite on x86_64-unknown-linux-gnu. Committed to mainline. Ian --=-=-= Content-Type: text/x-diff Content-Disposition: inline; filename=foo.patch Content-Description: patch Content-length: 14923 diff -r ca6a5fdb7c4b go/expressions.cc --- a/go/expressions.cc Fri Jun 10 22:09:54 2011 -0700 +++ b/go/expressions.cc Fri Jun 10 23:18:06 2011 -0700 @@ -11747,7 +11747,7 @@ 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 -r ca6a5fdb7c4b go/gogo-tree.cc --- a/go/gogo-tree.cc Fri Jun 10 22:09:54 2011 -0700 +++ b/go/gogo-tree.cc Fri Jun 10 23:18:06 2011 -0700 @@ -1974,141 +1974,6 @@ 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 -r ca6a5fdb7c4b go/gogo.cc --- a/go/gogo.cc Fri Jun 10 22:09:54 2011 -0700 +++ b/go/gogo.cc Fri Jun 10 23:18:06 2011 -0700 @@ -29,7 +29,6 @@ imports_(), imported_unsafe_(false), packages_(), - map_descriptors_(NULL), init_functions_(), need_init_fn_(false), init_fn_name_(), @@ -2596,6 +2595,7 @@ 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 -r ca6a5fdb7c4b go/gogo.h --- a/go/gogo.h Fri Jun 10 22:09:54 2011 -0700 +++ b/go/gogo.h Fri Jun 10 23:18:06 2011 -0700 @@ -473,16 +473,6 @@ 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 @@ // 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 @@ // 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 -r ca6a5fdb7c4b go/types.cc --- a/go/types.cc Fri Jun 10 22:09:54 2011 -0700 +++ b/go/types.cc Fri Jun 10 23:18:06 2011 -0700 @@ -5049,7 +5049,8 @@ 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 @@ 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 @@ 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 -r ca6a5fdb7c4b go/types.h --- a/go/types.h Fri Jun 10 22:09:54 2011 -0700 +++ b/go/types.h Fri Jun 10 23:18:06 2011 -0700 @@ -2157,6 +2157,15 @@ 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 @@ 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 -r ca6a5fdb7c4b libgo/runtime/go-map-delete.c --- a/libgo/runtime/go-map-delete.c Fri Jun 10 22:09:54 2011 -0700 +++ b/libgo/runtime/go-map-delete.c Fri Jun 10 23:18:06 2011 -0700 @@ -18,7 +18,7 @@ { 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 -r ca6a5fdb7c4b libgo/runtime/go-map-index.c --- a/libgo/runtime/go-map-index.c Fri Jun 10 22:09:54 2011 -0700 +++ b/libgo/runtime/go-map-index.c Fri Jun 10 23:18:06 2011 -0700 @@ -18,7 +18,7 @@ { 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 @@ { 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 -r ca6a5fdb7c4b libgo/runtime/map.h --- a/libgo/runtime/map.h Fri Jun 10 22:09:54 2011 -0700 +++ b/libgo/runtime/map.h Fri Jun 10 23:18:06 2011 -0700 @@ -22,15 +22,15 @@ 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 --=-=-=--