Use backend interface for map descriptors.
authorIan Lance Taylor <ian@gcc.gnu.org>
Sat, 11 Jun 2011 06:21:55 +0000 (06:21 +0000)
committerIan Lance Taylor <ian@gcc.gnu.org>
Sat, 11 Jun 2011 06:21:55 +0000 (06:21 +0000)
From-SVN: r174943

gcc/go/gofrontend/expressions.cc
gcc/go/gofrontend/gogo-tree.cc
gcc/go/gofrontend/gogo.cc
gcc/go/gofrontend/gogo.h
gcc/go/gofrontend/types.cc
gcc/go/gofrontend/types.h
libgo/runtime/go-map-delete.c
libgo/runtime/go-map-index.c
libgo/runtime/map.h

index 00af29620685bead9d769b687325a4c3109f3985..9c6af0b77626574c2a674d84d258bbbeb190d113 100644 (file)
@@ -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)
index 0c5cb671c05c28735e570a3b8520535b707be390..94d1c4dd1db8ecb002f0befe02402f6c5fc18ee1 100644 (file)
@@ -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<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
 // pointers, one for each interface method.  This is used for
 // interfaces.
index 484d1a11e8fbb44628a8a28e75ddd5e502e0aa82..194cacafcaf4ca05dd1803cece67c7049ff845fc 100644 (file)
@@ -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);
index 972369fe6fbdc6cf9739731a5e4d1d7d7c732160..cc349afd064d2ee2e9ce543279129878189bcf5d 100644 (file)
@@ -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<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.
   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<Named_object*> init_functions_;
   // Whether we need a magic initialization function.
index 15e35c2b29d851c5499581a3c58931fc0516d826..e19d4f2e7441bf96f8f2035b069a3499e5edd2ef 100644 (file)
@@ -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<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.
 
 void
index fc35431f6ad3fc2f896a372371d050c8ce7b6fa9..2ee80a4868b24d937f196bb10e2e0bce8f23fad2 100644 (file)
@@ -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.
index ec851e531d252c86d303b1fe796132bf17007c02..7a3a7b83d92cb46b6074cd3c798c222cc325688a 100644 (file)
@@ -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;
index 02a0f73f2247b7ca9807473c2ec4d929bffe6638..a387c4b98bc673b2ac2447533ac8d045dcadddf3 100644 (file)
@@ -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;
index 40c31f823151d23e6057c4007c029e96680e2656..0c587bb2afac96e2b12ee40bfb5a1cffae73c0de 100644 (file)
@@ -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