compiler, runtime: drop size arguments to hash/equal functions
authorIan Lance Taylor <ian@gcc.gnu.org>
Tue, 10 Jan 2017 03:59:20 +0000 (03:59 +0000)
committerIan Lance Taylor <ian@gcc.gnu.org>
Tue, 10 Jan 2017 03:59:20 +0000 (03:59 +0000)
    Drop the size arguments for the hash/equal functions stored in type
    descriptors.  Types know what size they are.  To make this work,
    generate hash/equal functions for types that can use an identity
    comparison but are not a standard size and alignment.

    Drop the multiplications by 33 in the generated hash code and the
    reflect package hash code.  They are not necessary since we started
    passing a seed value around, as the seed includes the hash of the
    earlier values.

    Copy the algorithms for standard types from the Go 1.7 runtime,
    replacing the C functions.

    Reviewed-on: https://go-review.googlesource.com/34983

From-SVN: r244256

19 files changed:
gcc/go/gofrontend/MERGE
gcc/go/gofrontend/expressions.cc
gcc/go/gofrontend/gogo.cc
gcc/go/gofrontend/gogo.h
gcc/go/gofrontend/types.cc
gcc/go/gofrontend/types.h
libgo/Makefile.am
libgo/Makefile.in
libgo/go/reflect/type.go
libgo/go/runtime/alg.go
libgo/go/runtime/hashmap.go
libgo/go/runtime/hashmap_fast.go
libgo/go/runtime/type.go
libgo/runtime/go-type-complex.c [deleted file]
libgo/runtime/go-type-float.c [deleted file]
libgo/runtime/go-type-identity.c [deleted file]
libgo/runtime/go-type-string.c [deleted file]
libgo/runtime/go-type.h
libgo/runtime/go-unsafe-pointer.c

index 2bbbc0f..73c4d30 100644 (file)
@@ -1,4 +1,4 @@
-189ea81cc758e000325fd6cca7882c252d33f8f0
+f439989e483b7c2eada6ddcf6e730a791cce603f
 
 The first line of this file holds the git revision number of the last
 merge done from the gofrontend repository.
index 02c3320..da72103 100644 (file)
@@ -5335,7 +5335,6 @@ Binary_expression::lower_array_comparison(Gogo* gogo,
   Expression_list* args = new Expression_list();
   args->push_back(this->operand_address(inserter, this->left_));
   args->push_back(this->operand_address(inserter, this->right_));
-  args->push_back(Expression::make_type_info(at, TYPE_INFO_SIZE));
 
   Expression* ret = Expression::make_call(func, args, false, loc);
 
index ff82f11..4e2d6b4 100644 (file)
@@ -2343,7 +2343,7 @@ Gogo::clear_file_scope()
 // parse tree is lowered.
 
 void
-Gogo::queue_specific_type_function(Type* type, Named_type* name,
+Gogo::queue_specific_type_function(Type* type, Named_type* name, int64_t size,
                                   const std::string& hash_name,
                                   Function_type* hash_fntype,
                                   const std::string& equal_name,
@@ -2351,7 +2351,7 @@ Gogo::queue_specific_type_function(Type* type, Named_type* name,
 {
   go_assert(!this->specific_type_functions_are_written_);
   go_assert(!this->in_global_scope());
-  Specific_type_function* tsf = new Specific_type_function(type, name,
+  Specific_type_function* tsf = new Specific_type_function(type, name, size,
                                                           hash_name,
                                                           hash_fntype,
                                                           equal_name,
@@ -2386,7 +2386,7 @@ Specific_type_functions::type(Type* t)
     case Type::TYPE_NAMED:
       {
        Named_type* nt = t->named_type();
-       if (!t->compare_is_identity(this->gogo_) && t->is_comparable())
+       if (t->needs_specific_type_functions(this->gogo_))
          t->type_functions(this->gogo_, nt, NULL, NULL, &hash_fn, &equal_fn);
 
        // If this is a struct type, we don't want to make functions
@@ -2420,7 +2420,7 @@ Specific_type_functions::type(Type* t)
 
     case Type::TYPE_STRUCT:
     case Type::TYPE_ARRAY:
-      if (!t->compare_is_identity(this->gogo_) && t->is_comparable())
+      if (t->needs_specific_type_functions(this->gogo_))
        t->type_functions(this->gogo_, NULL, NULL, NULL, &hash_fn, &equal_fn);
       break;
 
@@ -2443,7 +2443,7 @@ Gogo::write_specific_type_functions()
     {
       Specific_type_function* tsf = this->specific_type_functions_.back();
       this->specific_type_functions_.pop_back();
-      tsf->type->write_specific_type_functions(this, tsf->name,
+      tsf->type->write_specific_type_functions(this, tsf->name, tsf->size,
                                               tsf->hash_name,
                                               tsf->hash_fntype,
                                               tsf->equal_name,
index 905f48d..7c29828 100644 (file)
@@ -563,7 +563,7 @@ class Gogo
   // used when a type-specific function is needed when not at the top
   // level.
   void
-  queue_specific_type_function(Type* type, Named_type* name,
+  queue_specific_type_function(Type* type, Named_type* name, int64_t size,
                               const std::string& hash_name,
                               Function_type* hash_fntype,
                               const std::string& equal_name,
@@ -824,17 +824,18 @@ class Gogo
   {
     Type* type;
     Named_type* name;
+    int64_t size;
     std::string hash_name;
     Function_type* hash_fntype;
     std::string equal_name;
     Function_type* equal_fntype;
 
-    Specific_type_function(Type* atype, Named_type* aname,
+    Specific_type_function(Type* atype, Named_type* aname, int64_t asize,
                           const std::string& ahash_name,
                           Function_type* ahash_fntype,
                           const std::string& aequal_name,
                           Function_type* aequal_fntype)
-      : type(atype), name(aname), hash_name(ahash_name),
+      : type(atype), name(aname), size(asize), hash_name(ahash_name),
        hash_fntype(ahash_fntype), equal_name(aequal_name),
        equal_fntype(aequal_fntype)
     { }
index e7fe326..0b394c9 100644 (file)
@@ -1425,7 +1425,9 @@ Type::make_builtin_struct_type(int nfields, ...)
 
   va_end(ap);
 
-  return Type::make_struct_type(sfl, bloc);
+  Struct_type* ret = Type::make_struct_type(sfl, bloc);
+  ret->set_is_struct_incomparable();
+  return ret;
 }
 
 // A list of builtin named types.
@@ -1488,7 +1490,6 @@ Type::make_type_descriptor_type()
       Typed_identifier_list *params = new Typed_identifier_list();
       params->push_back(Typed_identifier("key", unsafe_pointer_type, bloc));
       params->push_back(Typed_identifier("seed", uintptr_type, bloc));
-      params->push_back(Typed_identifier("key_size", uintptr_type, bloc));
 
       Typed_identifier_list* results = new Typed_identifier_list();
       results->push_back(Typed_identifier("", uintptr_type, bloc));
@@ -1499,7 +1500,6 @@ Type::make_type_descriptor_type()
       params = new Typed_identifier_list();
       params->push_back(Typed_identifier("key1", unsafe_pointer_type, bloc));
       params->push_back(Typed_identifier("key2", unsafe_pointer_type, bloc));
-      params->push_back(Typed_identifier("key_size", uintptr_type, bloc));
 
       results = new Typed_identifier_list();
       results->push_back(Typed_identifier("", Type::lookup_bool_type(), bloc));
@@ -1578,6 +1578,51 @@ Type::make_type_descriptor_ptr_type()
   return ret;
 }
 
+// Return whether this type needs specially built type functions.
+// This returns true for types that are comparable and either can not
+// use an identity comparison, or are a non-standard size.
+
+bool
+Type::needs_specific_type_functions(Gogo* gogo)
+{
+  if (!this->is_comparable())
+    return false;
+  if (!this->compare_is_identity(gogo))
+    return true;
+
+  // We create a few predeclared types for type descriptors; they are
+  // really just for the backend and don't need hash or equality
+  // functions.
+  Named_type* nt = this->named_type();
+  if (nt != NULL && Linemap::is_predeclared_location(nt->location()))
+    return false;
+
+  int64_t size, align;
+  if (!this->backend_type_size(gogo, &size)
+      || !this->backend_type_align(gogo, &align))
+    {
+      go_assert(saw_errors());
+      return false;
+    }
+  // This switch matches the one in Type::type_functions.
+  switch (size)
+    {
+    case 0:
+    case 1:
+    case 2:
+      return align < 2;
+    case 4:
+      return align < 4;
+    case 8:
+      return align < 8;
+    case 16:
+      // 8, not 16, because of how runtime.memequal128 is written.
+      return align < 8;
+    default:
+      return true;
+    }
+}
+
 // Set *HASH_FN and *EQUAL_FN to the runtime functions which compute a
 // hash code for this type and which compare whether two values of
 // this type are equal.  If NAME is not NULL it is the name of this
@@ -1610,7 +1655,6 @@ Type::type_functions(Gogo* gogo, Named_type* name, Function_type* hash_fntype,
          params->push_back(Typed_identifier("key", unsafe_pointer_type,
                                             bloc));
          params->push_back(Typed_identifier("seed", uintptr_type, bloc));
-         params->push_back(Typed_identifier("key_size", uintptr_type, bloc));
 
          Typed_identifier_list* results = new Typed_identifier_list();
          results->push_back(Typed_identifier("", uintptr_type, bloc));
@@ -1624,7 +1668,6 @@ Type::type_functions(Gogo* gogo, Named_type* name, Function_type* hash_fntype,
                                             bloc));
          params->push_back(Typed_identifier("key2", unsafe_pointer_type,
                                             bloc));
-         params->push_back(Typed_identifier("key_size", uintptr_type, bloc));
 
          Typed_identifier_list* results = new Typed_identifier_list();
          results->push_back(Typed_identifier("", Type::lookup_bool_type(),
@@ -1638,8 +1681,78 @@ Type::type_functions(Gogo* gogo, Named_type* name, Function_type* hash_fntype,
   const char* equal_fnname;
   if (this->compare_is_identity(gogo))
     {
-      hash_fnname = "runtime.memhash";
-      equal_fnname = "__go_type_equal_identity";
+      int64_t size, align;
+      if (!this->backend_type_size(gogo, &size)
+         || !this->backend_type_align(gogo, &align))
+       {
+         go_assert(saw_errors());
+         return;
+       }
+      bool build_functions = false;
+      // This switch matches the one in Type::needs_specific_type_functions.
+      // The alignment tests are because of the memequal functions,
+      // which assume that the values are aligned as required for an
+      // integer of that size.
+      switch (size)
+       {
+       case 0:
+         hash_fnname = "runtime.memhash0";
+         equal_fnname = "runtime.memequal0";
+         break;
+       case 1:
+         hash_fnname = "runtime.memhash8";
+         equal_fnname = "runtime.memequal8";
+         break;
+       case 2:
+         if (align < 2)
+           build_functions = true;
+         else
+           {
+             hash_fnname = "runtime.memhash16";
+             equal_fnname = "runtime.memequal16";
+           }
+         break;
+       case 4:
+         if (align < 4)
+           build_functions = true;
+         else
+           {
+             hash_fnname = "runtime.memhash32";
+             equal_fnname = "runtime.memequal32";
+           }
+         break;
+       case 8:
+         if (align < 8)
+           build_functions = true;
+         else
+           {
+             hash_fnname = "runtime.memhash64";
+             equal_fnname = "runtime.memequal64";
+           }
+         break;
+       case 16:
+         // 8, not 16, because of how runtime.memequal128 is written.
+         if (align < 8)
+           build_functions = true;
+         else
+           {
+             hash_fnname = "runtime.memhash128";
+             equal_fnname = "runtime.memequal128";
+           }
+         break;
+       default:
+         build_functions = true;
+         break;
+       }
+      if (build_functions)
+       {
+         // We don't have a built-in function for a type of this size
+         // and alignment.  Build a function to use that calls the
+         // generic hash/equality functions for identity, passing the size.
+         this->specific_type_functions(gogo, name, size, hash_fntype,
+                                       equal_fntype, hash_fn, equal_fn);
+         return;
+       }
     }
   else
     {
@@ -1661,18 +1774,40 @@ Type::type_functions(Gogo* gogo, Named_type* name, Function_type* hash_fntype,
          go_unreachable();
 
        case Type::TYPE_FLOAT:
-         hash_fnname = "__go_type_hash_float";
-         equal_fnname = "__go_type_equal_float";
+         switch (this->float_type()->bits())
+           {
+           case 32:
+             hash_fnname = "runtime.f32hash";
+             equal_fnname = "runtime.f32equal";
+             break;
+           case 64:
+             hash_fnname = "runtime.f64hash";
+             equal_fnname = "runtime.f64equal";
+             break;
+           default:
+             go_unreachable();
+           }
          break;
 
        case Type::TYPE_COMPLEX:
-         hash_fnname = "__go_type_hash_complex";
-         equal_fnname = "__go_type_equal_complex";
+         switch (this->complex_type()->bits())
+           {
+           case 64:
+             hash_fnname = "runtime.c64hash";
+             equal_fnname = "runtime.c64equal";
+             break;
+           case 128:
+             hash_fnname = "runtime.c128hash";
+             equal_fnname = "runtime.c128equal";
+             break;
+           default:
+             go_unreachable();
+           }
          break;
 
        case Type::TYPE_STRING:
-         hash_fnname = "__go_type_hash_string";
-         equal_fnname = "__go_type_equal_string";
+         hash_fnname = "runtime.strhash";
+         equal_fnname = "runtime.strequal";
          break;
 
        case Type::TYPE_STRUCT:
@@ -1680,7 +1815,7 @@ Type::type_functions(Gogo* gogo, Named_type* name, Function_type* hash_fntype,
            // This is a struct which can not be compared using a
            // simple identity function.  We need to build a function
            // for comparison.
-           this->specific_type_functions(gogo, name, hash_fntype,
+           this->specific_type_functions(gogo, name, -1, hash_fntype,
                                          equal_fntype, hash_fn, equal_fn);
            return;
          }
@@ -1697,7 +1832,7 @@ Type::type_functions(Gogo* gogo, Named_type* name, Function_type* hash_fntype,
              // This is an array which can not be compared using a
              // simple identity function.  We need to build a
              // function for comparison.
-             this->specific_type_functions(gogo, name, hash_fntype,
+             this->specific_type_functions(gogo, name, -1, hash_fntype,
                                            equal_fntype, hash_fn, equal_fn);
              return;
            }
@@ -1739,11 +1874,13 @@ Type::type_functions(Gogo* gogo, Named_type* name, Function_type* hash_fntype,
 
 Type::Type_functions Type::type_functions_table;
 
-// Handle a type function which is specific to a type: a struct or
-// array which can not use an identity comparison.
+// Handle a type function which is specific to a type: if SIZE == -1,
+// this is a struct or array that can not use an identity comparison.
+// Otherwise, it is a type that uses an identity comparison but is not
+// one of the standard supported sizes.
 
 void
-Type::specific_type_functions(Gogo* gogo, Named_type* name,
+Type::specific_type_functions(Gogo* gogo, Named_type* name, int64_t size,
                              Function_type* hash_fntype,
                              Function_type* equal_fntype,
                              Named_object** hash_fn,
@@ -1829,11 +1966,13 @@ Type::specific_type_functions(Gogo* gogo, Named_type* name,
   if (!is_defined_elsewhere)
     {
       if (gogo->in_global_scope())
-       this->write_specific_type_functions(gogo, name, hash_name, hash_fntype,
-                                           equal_name, equal_fntype);
+       this->write_specific_type_functions(gogo, name, size, hash_name,
+                                           hash_fntype, equal_name,
+                                           equal_fntype);
       else
-       gogo->queue_specific_type_function(this, name, hash_name, hash_fntype,
-                                          equal_name, equal_fntype);
+       gogo->queue_specific_type_function(this, name, size, hash_name,
+                                          hash_fntype, equal_name,
+                                          equal_fntype);
     }
 }
 
@@ -1841,7 +1980,7 @@ Type::specific_type_functions(Gogo* gogo, Named_type* name,
 // written specially.
 
 void
-Type::write_specific_type_functions(Gogo* gogo, Named_type* name,
+Type::write_specific_type_functions(Gogo* gogo, Named_type* name, int64_t size,
                                    const std::string& hash_name,
                                    Function_type* hash_fntype,
                                    const std::string& equal_name,
@@ -1862,7 +2001,9 @@ Type::write_specific_type_functions(Gogo* gogo, Named_type* name,
   hash_fn->func_value()->set_is_type_specific_function();
   gogo->start_block(bloc);
 
-  if (name != NULL && name->real_type()->named_type() != NULL)
+  if (size != -1)
+    this->write_identity_hash(gogo, size);
+  else if (name != NULL && name->real_type()->named_type() != NULL)
     this->write_named_hash(gogo, name, hash_fntype, equal_fntype);
   else if (this->struct_type() != NULL)
     this->struct_type()->write_hash_function(gogo, name, hash_fntype,
@@ -1883,7 +2024,9 @@ Type::write_specific_type_functions(Gogo* gogo, Named_type* name,
   equal_fn->func_value()->set_is_type_specific_function();
   gogo->start_block(bloc);
 
-  if (name != NULL && name->real_type()->named_type() != NULL)
+  if (size != -1)
+    this->write_identity_equal(gogo, size);
+  else if (name != NULL && name->real_type()->named_type() != NULL)
     this->write_named_equal(gogo, name);
   else if (this->struct_type() != NULL)
     this->struct_type()->write_equal_function(gogo, name);
@@ -1902,6 +2045,112 @@ Type::write_specific_type_functions(Gogo* gogo, Named_type* name,
   equal_fn->func_value()->descriptor(gogo, equal_fn);
 }
 
+// Write a hash function for a type that can use an identity hash but
+// is not one of the standard supported sizes.  For example, this
+// would be used for the type [3]byte.  This builds a return statement
+// that returns a call to the memhash function, passing the key and
+// seed from the function arguments (already constructed before this
+// is called), and the constant size.
+
+void
+Type::write_identity_hash(Gogo* gogo, int64_t size)
+{
+  Location bloc = Linemap::predeclared_location();
+
+  Type* unsafe_pointer_type = Type::make_pointer_type(Type::make_void_type());
+  Type* uintptr_type = Type::lookup_integer_type("uintptr");
+
+  Typed_identifier_list* params = new Typed_identifier_list();
+  params->push_back(Typed_identifier("key", unsafe_pointer_type, bloc));
+  params->push_back(Typed_identifier("seed", uintptr_type, bloc));
+  params->push_back(Typed_identifier("size", uintptr_type, bloc));
+
+  Typed_identifier_list* results = new Typed_identifier_list();
+  results->push_back(Typed_identifier("", uintptr_type, bloc));
+
+  Function_type* memhash_fntype = Type::make_function_type(NULL, params,
+                                                          results, bloc);
+
+  Named_object* memhash =
+    Named_object::make_function_declaration("runtime.memhash", NULL,
+                                           memhash_fntype, bloc);
+  memhash->func_declaration_value()->set_asm_name("runtime.memhash");
+
+  Named_object* key_arg = gogo->lookup("key", NULL);
+  go_assert(key_arg != NULL);
+  Named_object* seed_arg = gogo->lookup("seed", NULL);
+  go_assert(seed_arg != NULL);
+
+  Expression* key_ref = Expression::make_var_reference(key_arg, bloc);
+  Expression* seed_ref = Expression::make_var_reference(seed_arg, bloc);
+  Expression* size_arg = Expression::make_integer_int64(size, uintptr_type,
+                                                       bloc);
+  Expression_list* args = new Expression_list();
+  args->push_back(key_ref);
+  args->push_back(seed_ref);
+  args->push_back(size_arg);
+  Expression* func = Expression::make_func_reference(memhash, NULL, bloc);
+  Expression* call = Expression::make_call(func, args, false, bloc);
+
+  Expression_list* vals = new Expression_list();
+  vals->push_back(call);
+  Statement* s = Statement::make_return_statement(vals, bloc);
+  gogo->add_statement(s);
+}
+
+// Write an equality function for a type that can use an identity
+// equality comparison but is not one of the standard supported sizes.
+// For example, this would be used for the type [3]byte.  This builds
+// a return statement that returns a call to the memequal function,
+// passing the two keys from the function arguments (already
+// constructed before this is called), and the constant size.
+
+void
+Type::write_identity_equal(Gogo* gogo, int64_t size)
+{
+  Location bloc = Linemap::predeclared_location();
+
+  Type* unsafe_pointer_type = Type::make_pointer_type(Type::make_void_type());
+  Type* uintptr_type = Type::lookup_integer_type("uintptr");
+
+  Typed_identifier_list* params = new Typed_identifier_list();
+  params->push_back(Typed_identifier("key1", unsafe_pointer_type, bloc));
+  params->push_back(Typed_identifier("key2", unsafe_pointer_type, bloc));
+  params->push_back(Typed_identifier("size", uintptr_type, bloc));
+
+  Typed_identifier_list* results = new Typed_identifier_list();
+  results->push_back(Typed_identifier("", Type::lookup_bool_type(), bloc));
+
+  Function_type* memequal_fntype = Type::make_function_type(NULL, params,
+                                                           results, bloc);
+
+  Named_object* memequal =
+    Named_object::make_function_declaration("runtime.memequal", NULL,
+                                           memequal_fntype, bloc);
+  memequal->func_declaration_value()->set_asm_name("runtime.memequal");
+
+  Named_object* key1_arg = gogo->lookup("key1", NULL);
+  go_assert(key1_arg != NULL);
+  Named_object* key2_arg = gogo->lookup("key2", NULL);
+  go_assert(key2_arg != NULL);
+
+  Expression* key1_ref = Expression::make_var_reference(key1_arg, bloc);
+  Expression* key2_ref = Expression::make_var_reference(key2_arg, bloc);
+  Expression* size_arg = Expression::make_integer_int64(size, uintptr_type,
+                                                       bloc);
+  Expression_list* args = new Expression_list();
+  args->push_back(key1_ref);
+  args->push_back(key2_ref);
+  args->push_back(size_arg);
+  Expression* func = Expression::make_func_reference(memequal, NULL, bloc);
+  Expression* call = Expression::make_call(func, args, false, bloc);
+
+  Expression_list* vals = new Expression_list();
+  vals->push_back(call);
+  Statement* s = Statement::make_return_statement(vals, bloc);
+  gogo->add_statement(s);
+}
+
 // Write a hash function that simply calls the hash function for a
 // named type.  This is used when one named type is defined as
 // another.  This ensures that this case works when the other named
@@ -1926,10 +2175,6 @@ Type::write_named_hash(Gogo* gogo, Named_type* name,
   Named_object* seed_arg = gogo->lookup("seed", NULL);
   go_assert(seed_arg != NULL);
 
-  // The size of the type we are going to hash.
-  Named_object* keysz_arg = gogo->lookup("key_size", NULL);
-  go_assert(keysz_arg != NULL);
-
   Named_object* hash_fn;
   Named_object* equal_fn;
   name->real_type()->type_functions(gogo, base_type, hash_fntype, equal_fntype,
@@ -1938,11 +2183,9 @@ Type::write_named_hash(Gogo* gogo, Named_type* name,
   // Call the hash function for the base type.
   Expression* key_ref = Expression::make_var_reference(key_arg, bloc);
   Expression* seed_ref = Expression::make_var_reference(seed_arg, bloc);
-  Expression* keysz_ref = Expression::make_var_reference(keysz_arg, bloc);
   Expression_list* args = new Expression_list();
   args->push_back(key_ref);
   args->push_back(seed_ref);
-  args->push_back(keysz_ref);
   Expression* func = Expression::make_func_reference(hash_fn, NULL, bloc);
   Expression* call = Expression::make_call(func, args, false, bloc);
 
@@ -5410,7 +5653,6 @@ Struct_type::write_hash_function(Gogo* gogo, Named_type*,
   gogo->add_statement(key);
 
   // Loop over the struct fields.
-  bool first = true;
   const Struct_field_list* fields = this->fields_;
   for (Struct_field_list::const_iterator pf = fields->begin();
        pf != fields->end();
@@ -5419,19 +5661,6 @@ Struct_type::write_hash_function(Gogo* gogo, Named_type*,
       if (Gogo::is_sink_name(pf->field_name()))
        continue;
 
-      if (first)
-       first = false;
-      else
-       {
-         // Multiply retval by 33.
-         Expression* i33 = Expression::make_integer_ul(33, uintptr_type,
-                                                       bloc);
-         ref = Expression::make_temporary_reference(retval, bloc);
-         Statement* s = Statement::make_assignment_operation(OPERATOR_MULTEQ,
-                                                             ref, i33, bloc);
-         gogo->add_statement(s);
-       }
-
       // Get a pointer to the value of this field.
       Expression* offset = Expression::make_struct_field_offset(this, &*pf);
       ref = Expression::make_temporary_reference(key, bloc);
@@ -5439,10 +5668,6 @@ Struct_type::write_hash_function(Gogo* gogo, Named_type*,
                                                   bloc);
       subkey = Expression::make_cast(key_arg_type, subkey, bloc);
 
-      // Get the size of this field.
-      Expression* size = Expression::make_type_info(pf->type(),
-                                                   Expression::TYPE_INFO_SIZE);
-
       // Get the hash function to use for the type of this field.
       Named_object* hash_fn;
       Named_object* equal_fn;
@@ -5454,7 +5679,6 @@ Struct_type::write_hash_function(Gogo* gogo, Named_type*,
       Expression_list* args = new Expression_list();
       args->push_back(subkey);
       args->push_back(ref);
-      args->push_back(size);
       Expression* func = Expression::make_func_reference(hash_fn, NULL, bloc);
       Expression* call = Expression::make_call(func, args, false, bloc);
 
@@ -6295,14 +6519,6 @@ Array_type::write_hash_function(Gogo* gogo, Named_type* name,
 
   gogo->start_block(bloc);
 
-  // Multiply retval by 33.
-  Expression* i33 = Expression::make_integer_ul(33, uintptr_type, bloc);
-
-  ref = Expression::make_temporary_reference(retval, bloc);
-  Statement* s = Statement::make_assignment_operation(OPERATOR_MULTEQ, ref,
-                                                     i33, bloc);
-  gogo->add_statement(s);
-
   // Get the hash function for the element type.
   Named_object* hash_fn;
   Named_object* equal_fn;
@@ -6323,7 +6539,6 @@ Array_type::write_hash_function(Gogo* gogo, Named_type* name,
   Expression_list* args = new Expression_list();
   args->push_back(subkey);
   args->push_back(ref);
-  args->push_back(ele_size);
   Expression* func = Expression::make_func_reference(hash_fn, NULL, bloc);
   Expression* call = Expression::make_call(func, args, false, bloc);
 
@@ -6331,7 +6546,7 @@ Array_type::write_hash_function(Gogo* gogo, Named_type* name,
   Temporary_reference_expression* tref =
     Expression::make_temporary_reference(retval, bloc);
   tref->set_is_lvalue();
-  s = Statement::make_assignment(tref, call, bloc);
+  Statement* s = Statement::make_assignment(tref, call, bloc);
   gogo->add_statement(s);
 
   // Increase the element pointer.
index 58d60e5..e9c3162 100644 (file)
@@ -975,6 +975,10 @@ class Type
   bool
   is_backend_type_size_known(Gogo*);
 
+  // Return whether the type needs specially built type functions.
+  bool
+  needs_specific_type_functions(Gogo*);
+
   // Get the hash and equality functions for a type.
   void
   type_functions(Gogo*, Named_type* name, Function_type* hash_fntype,
@@ -983,7 +987,7 @@ class Type
 
   // Write the hash and equality type functions.
   void
-  write_specific_type_functions(Gogo*, Named_type*,
+  write_specific_type_functions(Gogo*, Named_type*, int64_t size,
                                const std::string& hash_name,
                                Function_type* hash_fntype,
                                const std::string& equal_name,
@@ -1206,11 +1210,18 @@ class Type
   // Build the hash and equality type functions for a type which needs
   // specific functions.
   void
-  specific_type_functions(Gogo*, Named_type*, Function_type* hash_fntype,
+  specific_type_functions(Gogo*, Named_type*, int64_t size,
+                         Function_type* hash_fntype,
                          Function_type* equal_fntype, Named_object** hash_fn,
                          Named_object** equal_fn);
 
   void
+  write_identity_hash(Gogo*, int64_t size);
+
+  void
+  write_identity_equal(Gogo*, int64_t size);
+
+  void
   write_named_hash(Gogo*, Named_type*, Function_type* hash_fntype,
                   Function_type* equal_fntype);
 
index 93eaa9f..fed4111 100644 (file)
@@ -446,10 +446,6 @@ runtime_files = \
        runtime/go-setenv.c \
        runtime/go-signal.c \
        runtime/go-strslice.c \
-       runtime/go-type-complex.c \
-       runtime/go-type-float.c \
-       runtime/go-type-identity.c \
-       runtime/go-type-string.c \
        runtime/go-typedesc-equal.c \
        runtime/go-unsafe-new.c \
        runtime/go-unsafe-newarray.c \
index 424e41b..581607a 100644 (file)
@@ -196,13 +196,12 @@ am__objects_5 = aeshash.lo go-assert.lo go-breakpoint.lo go-caller.lo \
        go-memcmp.lo go-memequal.lo go-memmove.lo go-nanotime.lo \
        go-now.lo go-new.lo go-nosys.lo go-reflect-call.lo \
        go-runtime-error.lo go-setenv.lo go-signal.lo go-strslice.lo \
-       go-type-complex.lo go-type-float.lo go-type-identity.lo \
-       go-type-string.lo go-typedesc-equal.lo go-unsafe-new.lo \
-       go-unsafe-newarray.lo go-unsafe-pointer.lo go-unsetenv.lo \
-       go-unwind.lo go-varargs.lo env_posix.lo heapdump.lo mcache.lo \
-       mcentral.lo $(am__objects_1) mfixalloc.lo mgc0.lo mheap.lo \
-       msize.lo panic.lo parfor.lo print.lo proc.lo runtime_c.lo \
-       thread.lo $(am__objects_2) yield.lo $(am__objects_3) malloc.lo \
+       go-typedesc-equal.lo go-unsafe-new.lo go-unsafe-newarray.lo \
+       go-unsafe-pointer.lo go-unsetenv.lo go-unwind.lo go-varargs.lo \
+       env_posix.lo heapdump.lo mcache.lo mcentral.lo \
+       $(am__objects_1) mfixalloc.lo mgc0.lo mheap.lo msize.lo \
+       panic.lo parfor.lo print.lo proc.lo runtime_c.lo thread.lo \
+       $(am__objects_2) yield.lo $(am__objects_3) malloc.lo \
        $(am__objects_4)
 am_libgo_llgo_la_OBJECTS = $(am__objects_5)
 libgo_llgo_la_OBJECTS = $(am_libgo_llgo_la_OBJECTS)
@@ -793,10 +792,6 @@ runtime_files = \
        runtime/go-setenv.c \
        runtime/go-signal.c \
        runtime/go-strslice.c \
-       runtime/go-type-complex.c \
-       runtime/go-type-float.c \
-       runtime/go-type-identity.c \
-       runtime/go-type-string.c \
        runtime/go-typedesc-equal.c \
        runtime/go-unsafe-new.c \
        runtime/go-unsafe-newarray.c \
@@ -1479,10 +1474,6 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-setenv.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-signal.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-strslice.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-type-complex.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-type-float.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-type-identity.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-type-string.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-typedesc-equal.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-unsafe-new.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-unsafe-newarray.Plo@am__quote@
@@ -1745,34 +1736,6 @@ go-strslice.lo: runtime/go-strslice.c
 @AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
 @am__fastdepCC_FALSE@  $(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o go-strslice.lo `test -f 'runtime/go-strslice.c' || echo '$(srcdir)/'`runtime/go-strslice.c
 
-go-type-complex.lo: runtime/go-type-complex.c
-@am__fastdepCC_TRUE@   $(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT go-type-complex.lo -MD -MP -MF $(DEPDIR)/go-type-complex.Tpo -c -o go-type-complex.lo `test -f 'runtime/go-type-complex.c' || echo '$(srcdir)/'`runtime/go-type-complex.c
-@am__fastdepCC_TRUE@   $(am__mv) $(DEPDIR)/go-type-complex.Tpo $(DEPDIR)/go-type-complex.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@      source='runtime/go-type-complex.c' object='go-type-complex.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@  $(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o go-type-complex.lo `test -f 'runtime/go-type-complex.c' || echo '$(srcdir)/'`runtime/go-type-complex.c
-
-go-type-float.lo: runtime/go-type-float.c
-@am__fastdepCC_TRUE@   $(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT go-type-float.lo -MD -MP -MF $(DEPDIR)/go-type-float.Tpo -c -o go-type-float.lo `test -f 'runtime/go-type-float.c' || echo '$(srcdir)/'`runtime/go-type-float.c
-@am__fastdepCC_TRUE@   $(am__mv) $(DEPDIR)/go-type-float.Tpo $(DEPDIR)/go-type-float.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@      source='runtime/go-type-float.c' object='go-type-float.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@  $(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o go-type-float.lo `test -f 'runtime/go-type-float.c' || echo '$(srcdir)/'`runtime/go-type-float.c
-
-go-type-identity.lo: runtime/go-type-identity.c
-@am__fastdepCC_TRUE@   $(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT go-type-identity.lo -MD -MP -MF $(DEPDIR)/go-type-identity.Tpo -c -o go-type-identity.lo `test -f 'runtime/go-type-identity.c' || echo '$(srcdir)/'`runtime/go-type-identity.c
-@am__fastdepCC_TRUE@   $(am__mv) $(DEPDIR)/go-type-identity.Tpo $(DEPDIR)/go-type-identity.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@      source='runtime/go-type-identity.c' object='go-type-identity.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@  $(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o go-type-identity.lo `test -f 'runtime/go-type-identity.c' || echo '$(srcdir)/'`runtime/go-type-identity.c
-
-go-type-string.lo: runtime/go-type-string.c
-@am__fastdepCC_TRUE@   $(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT go-type-string.lo -MD -MP -MF $(DEPDIR)/go-type-string.Tpo -c -o go-type-string.lo `test -f 'runtime/go-type-string.c' || echo '$(srcdir)/'`runtime/go-type-string.c
-@am__fastdepCC_TRUE@   $(am__mv) $(DEPDIR)/go-type-string.Tpo $(DEPDIR)/go-type-string.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@      source='runtime/go-type-string.c' object='go-type-string.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@  $(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o go-type-string.lo `test -f 'runtime/go-type-string.c' || echo '$(srcdir)/'`runtime/go-type-string.c
-
 go-typedesc-equal.lo: runtime/go-typedesc-equal.c
 @am__fastdepCC_TRUE@   $(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT go-typedesc-equal.lo -MD -MP -MF $(DEPDIR)/go-typedesc-equal.Tpo -c -o go-typedesc-equal.lo `test -f 'runtime/go-typedesc-equal.c' || echo '$(srcdir)/'`runtime/go-typedesc-equal.c
 @am__fastdepCC_TRUE@   $(am__mv) $(DEPDIR)/go-typedesc-equal.Tpo $(DEPDIR)/go-typedesc-equal.Plo
index 13b326f..4f13f14 100644 (file)
@@ -254,8 +254,8 @@ type rtype struct {
        size       uintptr
        hash       uint32 // hash of type; avoids computation in hash tables
 
-       hashfn  func(unsafe.Pointer, uintptr, uintptr) uintptr     // hash function
-       equalfn func(unsafe.Pointer, unsafe.Pointer, uintptr) bool // equality function
+       hashfn  func(unsafe.Pointer, uintptr) uintptr     // hash function
+       equalfn func(unsafe.Pointer, unsafe.Pointer) bool // equality function
 
        gc            unsafe.Pointer // garbage collection data
        string        *string        // string form; unnecessary  but undeniably useful
@@ -2203,23 +2203,20 @@ func StructOf(fields []StructField) Type {
                typ.gc = unsafe.Pointer(&gc[0])
        }
 
-       typ.hashfn = func(p unsafe.Pointer, seed, size uintptr) uintptr {
+       typ.hashfn = func(p unsafe.Pointer, seed uintptr) uintptr {
                ret := seed
-               for i, ft := range typ.fields {
-                       if i > 0 {
-                               ret *= 33
-                       }
+               for _, ft := range typ.fields {
                        o := unsafe.Pointer(uintptr(p) + ft.offset)
-                       ret = ft.typ.hashfn(o, ret, ft.typ.size)
+                       ret = ft.typ.hashfn(o, ret)
                }
                return ret
        }
 
-       typ.equalfn = func(p, q unsafe.Pointer, size uintptr) bool {
+       typ.equalfn = func(p, q unsafe.Pointer) bool {
                for _, ft := range typ.fields {
                        pi := unsafe.Pointer(uintptr(p) + ft.offset)
                        qi := unsafe.Pointer(uintptr(q) + ft.offset)
-                       if !ft.typ.equalfn(pi, qi, ft.typ.size) {
+                       if !ft.typ.equalfn(pi, qi) {
                                return false
                        }
                }
@@ -2348,19 +2345,18 @@ func ArrayOf(count int, elem Type) Type {
 
        array.kind &^= kindDirectIface
 
-       array.hashfn = func(p unsafe.Pointer, seed, size uintptr) uintptr {
+       array.hashfn = func(p unsafe.Pointer, seed uintptr) uintptr {
                ret := seed
                for i := 0; i < count; i++ {
-                       ret *= 33
-                       ret = typ.hashfn(p, ret, typ.size)
+                       ret = typ.hashfn(p, ret)
                        p = unsafe.Pointer(uintptr(p) + typ.size)
                }
                return ret
        }
 
-       array.equalfn = func(p1, p2 unsafe.Pointer, size uintptr) bool {
+       array.equalfn = func(p1, p2 unsafe.Pointer) bool {
                for i := 0; i < count; i++ {
-                       if !typ.equalfn(p1, p2, typ.size) {
+                       if !typ.equalfn(p1, p2) {
                                return false
                        }
                        p1 = unsafe.Pointer(uintptr(p1) + typ.size)
index 5331231..426b7f6 100644 (file)
@@ -12,8 +12,30 @@ import (
 // For gccgo, use go:linkname to rename compiler-called functions to
 // themselves, so that the compiler will export them.
 //
+//go:linkname memhash0 runtime.memhash0
+//go:linkname memhash8 runtime.memhash8
+//go:linkname memhash16 runtime.memhash16
+//go:linkname memhash32 runtime.memhash32
+//go:linkname memhash64 runtime.memhash64
+//go:linkname memhash128 runtime.memhash128
+//go:linkname strhash runtime.strhash
+//go:linkname f32hash runtime.f32hash
+//go:linkname f64hash runtime.f64hash
+//go:linkname c64hash runtime.c64hash
+//go:linkname c128hash runtime.c128hash
 //go:linkname interhash runtime.interhash
 //go:linkname nilinterhash runtime.nilinterhash
+//go:linkname memequal0 runtime.memequal0
+//go:linkname memequal8 runtime.memequal8
+//go:linkname memequal16 runtime.memequal16
+//go:linkname memequal32 runtime.memequal32
+//go:linkname memequal64 runtime.memequal64
+//go:linkname memequal128 runtime.memequal128
+//go:linkname strequal runtime.strequal
+//go:linkname f32equal runtime.f32equal
+//go:linkname f64equal runtime.f64equal
+//go:linkname c64equal runtime.c64equal
+//go:linkname c128equal runtime.c128equal
 //go:linkname interequal runtime.interequal
 //go:linkname nilinterequal runtime.nilinterequal
 //go:linkname efaceeq runtime.efaceeq
@@ -32,6 +54,25 @@ const (
        c1 = uintptr((8-sys.PtrSize)/4*3267000013 + (sys.PtrSize-4)/4*23344194077549503)
 )
 
+func memhash0(p unsafe.Pointer, h uintptr) uintptr {
+       return h
+}
+func memhash8(p unsafe.Pointer, h uintptr) uintptr {
+       return memhash(p, h, 1)
+}
+func memhash16(p unsafe.Pointer, h uintptr) uintptr {
+       return memhash(p, h, 2)
+}
+func memhash32(p unsafe.Pointer, h uintptr) uintptr {
+       return memhash(p, h, 4)
+}
+func memhash64(p unsafe.Pointer, h uintptr) uintptr {
+       return memhash(p, h, 8)
+}
+func memhash128(p unsafe.Pointer, h uintptr) uintptr {
+       return memhash(p, h, 16)
+}
+
 var useAeshash bool
 
 // in C code
@@ -46,6 +87,50 @@ func aeshashstr(p unsafe.Pointer, h uintptr) uintptr {
        return aeshashbody(unsafe.Pointer(ps.str), h, uintptr(ps.len), aeskeysched[:])
 }
 
+func strhash(a unsafe.Pointer, h uintptr) uintptr {
+       x := (*stringStruct)(a)
+       return memhash(x.str, h, uintptr(x.len))
+}
+
+// NOTE: Because NaN != NaN, a map can contain any
+// number of (mostly useless) entries keyed with NaNs.
+// To avoid long hash chains, we assign a random number
+// as the hash value for a NaN.
+
+func f32hash(p unsafe.Pointer, h uintptr) uintptr {
+       f := *(*float32)(p)
+       switch {
+       case f == 0:
+               return c1 * (c0 ^ h) // +0, -0
+       case f != f:
+               return c1 * (c0 ^ h ^ uintptr(fastrand1())) // any kind of NaN
+       default:
+               return memhash(p, h, 4)
+       }
+}
+
+func f64hash(p unsafe.Pointer, h uintptr) uintptr {
+       f := *(*float64)(p)
+       switch {
+       case f == 0:
+               return c1 * (c0 ^ h) // +0, -0
+       case f != f:
+               return c1 * (c0 ^ h ^ uintptr(fastrand1())) // any kind of NaN
+       default:
+               return memhash(p, h, 8)
+       }
+}
+
+func c64hash(p unsafe.Pointer, h uintptr) uintptr {
+       x := (*[2]float32)(p)
+       return f32hash(unsafe.Pointer(&x[1]), f32hash(unsafe.Pointer(&x[0]), h))
+}
+
+func c128hash(p unsafe.Pointer, h uintptr) uintptr {
+       x := (*[2]float64)(p)
+       return f64hash(unsafe.Pointer(&x[1]), f64hash(unsafe.Pointer(&x[0]), h))
+}
+
 func interhash(p unsafe.Pointer, h uintptr, size uintptr) uintptr {
        a := (*iface)(p)
        tab := a.tab
@@ -58,13 +143,13 @@ func interhash(p unsafe.Pointer, h uintptr, size uintptr) uintptr {
                panic(errorString("hash of unhashable type " + *t.string))
        }
        if isDirectIface(t) {
-               return c1 * fn(unsafe.Pointer(&a.data), h^c0, t.size)
+               return c1 * fn(unsafe.Pointer(&a.data), h^c0)
        } else {
-               return c1 * fn(a.data, h^c0, t.size)
+               return c1 * fn(a.data, h^c0)
        }
 }
 
-func nilinterhash(p unsafe.Pointer, h uintptr, size uintptr) uintptr {
+func nilinterhash(p unsafe.Pointer, h uintptr) uintptr {
        a := (*eface)(p)
        t := a._type
        if t == nil {
@@ -75,20 +160,51 @@ func nilinterhash(p unsafe.Pointer, h uintptr, size uintptr) uintptr {
                panic(errorString("hash of unhashable type " + *t.string))
        }
        if isDirectIface(t) {
-               return c1 * fn(unsafe.Pointer(&a.data), h^c0, t.size)
+               return c1 * fn(unsafe.Pointer(&a.data), h^c0)
        } else {
-               return c1 * fn(a.data, h^c0, t.size)
+               return c1 * fn(a.data, h^c0)
        }
 }
 
+func memequal0(p, q unsafe.Pointer) bool {
+       return true
+}
+func memequal8(p, q unsafe.Pointer) bool {
+       return *(*int8)(p) == *(*int8)(q)
+}
+func memequal16(p, q unsafe.Pointer) bool {
+       return *(*int16)(p) == *(*int16)(q)
+}
+func memequal32(p, q unsafe.Pointer) bool {
+       return *(*int32)(p) == *(*int32)(q)
+}
+func memequal64(p, q unsafe.Pointer) bool {
+       return *(*int64)(p) == *(*int64)(q)
+}
+func memequal128(p, q unsafe.Pointer) bool {
+       return *(*[2]int64)(p) == *(*[2]int64)(q)
+}
+func f32equal(p, q unsafe.Pointer) bool {
+       return *(*float32)(p) == *(*float32)(q)
+}
+func f64equal(p, q unsafe.Pointer) bool {
+       return *(*float64)(p) == *(*float64)(q)
+}
+func c64equal(p, q unsafe.Pointer) bool {
+       return *(*complex64)(p) == *(*complex64)(q)
+}
+func c128equal(p, q unsafe.Pointer) bool {
+       return *(*complex128)(p) == *(*complex128)(q)
+}
+func strequal(p, q unsafe.Pointer) bool {
+       return *(*string)(p) == *(*string)(q)
+}
 func interequal(p, q unsafe.Pointer, size uintptr) bool {
        return ifaceeq(*(*iface)(p), *(*iface)(q))
 }
-
 func nilinterequal(p, q unsafe.Pointer, size uintptr) bool {
        return efaceeq(*(*eface)(p), *(*eface)(q))
 }
-
 func efaceeq(x, y eface) bool {
        t := x._type
        if !eqtype(t, y._type) {
@@ -104,9 +220,8 @@ func efaceeq(x, y eface) bool {
        if isDirectIface(t) {
                return x.data == y.data
        }
-       return eq(x.data, y.data, t.size)
+       return eq(x.data, y.data)
 }
-
 func ifaceeq(x, y iface) bool {
        xtab := x.tab
        if xtab == nil && y.tab == nil {
@@ -126,7 +241,7 @@ func ifaceeq(x, y iface) bool {
        if isDirectIface(t) {
                return x.data == y.data
        }
-       return eq(x.data, y.data, t.size)
+       return eq(x.data, y.data)
 }
 
 func ifacevaleq(x iface, t *_type, p unsafe.Pointer) bool {
@@ -144,7 +259,7 @@ func ifacevaleq(x iface, t *_type, p unsafe.Pointer) bool {
        if isDirectIface(t) {
                return x.data == p
        }
-       return eq(x.data, p, t.size)
+       return eq(x.data, p)
 }
 
 func ifaceefaceeq(x iface, y eface) bool {
@@ -165,7 +280,7 @@ func ifaceefaceeq(x iface, y eface) bool {
        if isDirectIface(xt) {
                return x.data == y.data
        }
-       return eq(x.data, y.data, xt.size)
+       return eq(x.data, y.data)
 }
 
 func efacevaleq(x eface, t *_type, p unsafe.Pointer) bool {
@@ -182,7 +297,7 @@ func efacevaleq(x eface, t *_type, p unsafe.Pointer) bool {
        if isDirectIface(t) {
                return x.data == p
        }
-       return eq(x.data, p, t.size)
+       return eq(x.data, p)
 }
 
 func eqstring(x, y string) bool {
@@ -213,13 +328,47 @@ func cmpstring(x, y string) int {
        return 0
 }
 
+// For the unsafe.Pointer type descriptor in libgo/runtime/go-unsafe-pointer.c.
+
+func pointerhash(p unsafe.Pointer, h uintptr) uintptr {
+       return memhash(p, h, unsafe.Sizeof(unsafe.Pointer))
+}
+
+func pointerequal(p, q unsafe.Pointer) bool {
+       return *(*unsafe.Pointer)(p) == *(*unsafe.Pointer)(q)
+}
+
 // Force the creation of function descriptors for equality and hash
 // functions.  These will be referenced directly by the compiler.
 var _ = memhash
+var _ = memhash0
+var _ = memhash8
+var _ = memhash16
+var _ = memhash32
+var _ = memhash64
+var _ = memhash128
+var _ = strhash
+var _ = f32hash
+var _ = f64hash
+var _ = c64hash
+var _ = c128hash
 var _ = interhash
-var _ = interequal
 var _ = nilinterhash
+var _ = memequal0
+var _ = memequal8
+var _ = memequal16
+var _ = memequal32
+var _ = memequal64
+var _ = memequal128
+var _ = f32equal
+var _ = f64equal
+var _ = c64equal
+var _ = c128equal
+var _ = strequal
+var _ = interequal
 var _ = nilinterequal
+var _ = pointerhash
+var _ = pointerequal
 
 const hashRandomBytes = sys.PtrSize / 4 * 64
 
index aaf4fb4..77b33f3 100644 (file)
@@ -300,7 +300,7 @@ func mapaccess1(t *maptype, h *hmap, key unsafe.Pointer) unsafe.Pointer {
        }
        hashfn := t.key.hashfn
        equalfn := t.key.equalfn
-       hash := hashfn(key, uintptr(h.hash0), uintptr(t.keysize))
+       hash := hashfn(key, uintptr(h.hash0))
        m := uintptr(1)<<h.B - 1
        b := (*bmap)(add(h.buckets, (hash&m)*uintptr(t.bucketsize)))
        if c := h.oldbuckets; c != nil {
@@ -322,7 +322,7 @@ func mapaccess1(t *maptype, h *hmap, key unsafe.Pointer) unsafe.Pointer {
                        if t.indirectkey {
                                k = *((*unsafe.Pointer)(k))
                        }
-                       if equalfn(key, k, uintptr(t.keysize)) {
+                       if equalfn(key, k) {
                                v := add(unsafe.Pointer(b), dataOffset+bucketCnt*uintptr(t.keysize)+i*uintptr(t.valuesize))
                                if t.indirectvalue {
                                        v = *((*unsafe.Pointer)(v))
@@ -355,7 +355,7 @@ func mapaccess2(t *maptype, h *hmap, key unsafe.Pointer) (unsafe.Pointer, bool)
        }
        hashfn := t.key.hashfn
        equalfn := t.key.equalfn
-       hash := hashfn(key, uintptr(h.hash0), uintptr(t.keysize))
+       hash := hashfn(key, uintptr(h.hash0))
        m := uintptr(1)<<h.B - 1
        b := (*bmap)(unsafe.Pointer(uintptr(h.buckets) + (hash&m)*uintptr(t.bucketsize)))
        if c := h.oldbuckets; c != nil {
@@ -377,7 +377,7 @@ func mapaccess2(t *maptype, h *hmap, key unsafe.Pointer) (unsafe.Pointer, bool)
                        if t.indirectkey {
                                k = *((*unsafe.Pointer)(k))
                        }
-                       if equalfn(key, k, uintptr(t.keysize)) {
+                       if equalfn(key, k) {
                                v := add(unsafe.Pointer(b), dataOffset+bucketCnt*uintptr(t.keysize)+i*uintptr(t.valuesize))
                                if t.indirectvalue {
                                        v = *((*unsafe.Pointer)(v))
@@ -402,7 +402,7 @@ func mapaccessK(t *maptype, h *hmap, key unsafe.Pointer) (unsafe.Pointer, unsafe
        }
        hashfn := t.key.hashfn
        equalfn := t.key.equalfn
-       hash := hashfn(key, uintptr(h.hash0), uintptr(t.keysize))
+       hash := hashfn(key, uintptr(h.hash0))
        m := uintptr(1)<<h.B - 1
        b := (*bmap)(unsafe.Pointer(uintptr(h.buckets) + (hash&m)*uintptr(t.bucketsize)))
        if c := h.oldbuckets; c != nil {
@@ -424,7 +424,7 @@ func mapaccessK(t *maptype, h *hmap, key unsafe.Pointer) (unsafe.Pointer, unsafe
                        if t.indirectkey {
                                k = *((*unsafe.Pointer)(k))
                        }
-                       if equalfn(key, k, uintptr(t.keysize)) {
+                       if equalfn(key, k) {
                                v := add(unsafe.Pointer(b), dataOffset+bucketCnt*uintptr(t.keysize)+i*uintptr(t.valuesize))
                                if t.indirectvalue {
                                        v = *((*unsafe.Pointer)(v))
@@ -477,7 +477,7 @@ func mapassign1(t *maptype, h *hmap, key unsafe.Pointer, val unsafe.Pointer) {
 
        hashfn := t.key.hashfn
        equalfn := t.key.equalfn
-       hash := hashfn(key, uintptr(h.hash0), uintptr(t.keysize))
+       hash := hashfn(key, uintptr(h.hash0))
 
        if h.buckets == nil {
                h.buckets = newarray(t.bucket, 1)
@@ -512,7 +512,7 @@ again:
                        if t.indirectkey {
                                k2 = *((*unsafe.Pointer)(k2))
                        }
-                       if !equalfn(key, k2, uintptr(t.keysize)) {
+                       if !equalfn(key, k2) {
                                continue
                        }
                        // already have a mapping for key. Update it.
@@ -592,7 +592,7 @@ func mapdelete(t *maptype, h *hmap, key unsafe.Pointer) {
 
        hashfn := t.key.hashfn
        equalfn := t.key.equalfn
-       hash := hashfn(key, uintptr(h.hash0), uintptr(t.keysize))
+       hash := hashfn(key, uintptr(h.hash0))
        bucket := hash & (uintptr(1)<<h.B - 1)
        if h.oldbuckets != nil {
                growWork(t, h, bucket)
@@ -612,7 +612,7 @@ func mapdelete(t *maptype, h *hmap, key unsafe.Pointer) {
                        if t.indirectkey {
                                k2 = *((*unsafe.Pointer)(k2))
                        }
-                       if !equalfn(key, k2, uintptr(t.keysize)) {
+                       if !equalfn(key, k2) {
                                continue
                        }
                        memclr(k, uintptr(t.keysize))
@@ -760,10 +760,10 @@ next:
                                if t.indirectkey {
                                        k2 = *((*unsafe.Pointer)(k2))
                                }
-                               if t.reflexivekey || equalfn(k2, k2, uintptr(t.keysize)) {
+                               if t.reflexivekey || equalfn(k2, k2) {
                                        // If the item in the oldbucket is not destined for
                                        // the current new bucket in the iteration, skip it.
-                                       hash := hashfn(k2, uintptr(h.hash0), uintptr(t.keysize))
+                                       hash := hashfn(k2, uintptr(h.hash0))
                                        if hash&(uintptr(1)<<it.B-1) != checkBucket {
                                                continue
                                        }
@@ -797,7 +797,7 @@ next:
                                if t.indirectkey {
                                        k2 = *((*unsafe.Pointer)(k2))
                                }
-                               if t.reflexivekey || equalfn(k2, k2, uintptr(t.keysize)) {
+                               if t.reflexivekey || equalfn(k2, k2) {
                                        // Check the current hash table for the data.
                                        // This code handles the case where the key
                                        // has been deleted, updated, or deleted and reinserted.
@@ -913,9 +913,9 @@ func evacuate(t *maptype, h *hmap, oldbucket uintptr) {
                                }
                                // Compute hash to make our evacuation decision (whether we need
                                // to send this key/value to bucket x or bucket y).
-                               hash := hashfn(k2, uintptr(h.hash0), uintptr(t.keysize))
+                               hash := hashfn(k2, uintptr(h.hash0))
                                if h.flags&iterator != 0 {
-                                       if !t.reflexivekey && !equalfn(k2, k2, uintptr(t.keysize)) {
+                                       if !t.reflexivekey && !equalfn(k2, k2) {
                                                // If key != key (NaNs), then the hash could be (and probably
                                                // will be) entirely different from the old hash. Moreover,
                                                // it isn't reproducible. Reproducibility is required in the
index 4850b16..c6cad9d 100644 (file)
@@ -25,7 +25,7 @@ func mapaccess1_fast32(t *maptype, h *hmap, key uint32) unsafe.Pointer {
                // One-bucket table. No need to hash.
                b = (*bmap)(h.buckets)
        } else {
-               hash := t.key.hashfn(noescape(unsafe.Pointer(&key)), uintptr(h.hash0), uintptr(t.keysize))
+               hash := t.key.hashfn(noescape(unsafe.Pointer(&key)), uintptr(h.hash0))
                m := uintptr(1)<<h.B - 1
                b = (*bmap)(add(h.buckets, (hash&m)*uintptr(t.bucketsize)))
                if c := h.oldbuckets; c != nil {
@@ -70,7 +70,7 @@ func mapaccess2_fast32(t *maptype, h *hmap, key uint32) (unsafe.Pointer, bool) {
                // One-bucket table. No need to hash.
                b = (*bmap)(h.buckets)
        } else {
-               hash := t.key.hashfn(noescape(unsafe.Pointer(&key)), uintptr(h.hash0), uintptr(t.keysize))
+               hash := t.key.hashfn(noescape(unsafe.Pointer(&key)), uintptr(h.hash0))
                m := uintptr(1)<<h.B - 1
                b = (*bmap)(add(h.buckets, (hash&m)*uintptr(t.bucketsize)))
                if c := h.oldbuckets; c != nil {
@@ -115,7 +115,7 @@ func mapaccess1_fast64(t *maptype, h *hmap, key uint64) unsafe.Pointer {
                // One-bucket table. No need to hash.
                b = (*bmap)(h.buckets)
        } else {
-               hash := t.key.hashfn(noescape(unsafe.Pointer(&key)), uintptr(h.hash0), uintptr(t.keysize))
+               hash := t.key.hashfn(noescape(unsafe.Pointer(&key)), uintptr(h.hash0))
                m := uintptr(1)<<h.B - 1
                b = (*bmap)(add(h.buckets, (hash&m)*uintptr(t.bucketsize)))
                if c := h.oldbuckets; c != nil {
@@ -160,7 +160,7 @@ func mapaccess2_fast64(t *maptype, h *hmap, key uint64) (unsafe.Pointer, bool) {
                // One-bucket table. No need to hash.
                b = (*bmap)(h.buckets)
        } else {
-               hash := t.key.hashfn(noescape(unsafe.Pointer(&key)), uintptr(h.hash0), uintptr(t.keysize))
+               hash := t.key.hashfn(noescape(unsafe.Pointer(&key)), uintptr(h.hash0))
                m := uintptr(1)<<h.B - 1
                b = (*bmap)(add(h.buckets, (hash&m)*uintptr(t.bucketsize)))
                if c := h.oldbuckets; c != nil {
@@ -260,7 +260,7 @@ func mapaccess1_faststr(t *maptype, h *hmap, ky string) unsafe.Pointer {
                return unsafe.Pointer(&zeroVal[0])
        }
 dohash:
-       hash := t.key.hashfn(noescape(unsafe.Pointer(&ky)), uintptr(h.hash0), uintptr(t.keysize))
+       hash := t.key.hashfn(noescape(unsafe.Pointer(&ky)), uintptr(h.hash0))
        m := uintptr(1)<<h.B - 1
        b := (*bmap)(add(h.buckets, (hash&m)*uintptr(t.bucketsize)))
        if c := h.oldbuckets; c != nil {
@@ -363,7 +363,7 @@ func mapaccess2_faststr(t *maptype, h *hmap, ky string) (unsafe.Pointer, bool) {
                return unsafe.Pointer(&zeroVal[0]), false
        }
 dohash:
-       hash := t.key.hashfn(noescape(unsafe.Pointer(&ky)), uintptr(h.hash0), uintptr(t.keysize))
+       hash := t.key.hashfn(noescape(unsafe.Pointer(&ky)), uintptr(h.hash0))
        m := uintptr(1)<<h.B - 1
        b := (*bmap)(add(h.buckets, (hash&m)*uintptr(t.bucketsize)))
        if c := h.oldbuckets; c != nil {
index 4751a59..cfee35a 100644 (file)
@@ -16,8 +16,8 @@ type _type struct {
        size       uintptr
        hash       uint32
 
-       hashfn  func(unsafe.Pointer, uintptr, uintptr) uintptr
-       equalfn func(unsafe.Pointer, unsafe.Pointer, uintptr) bool
+       hashfn  func(unsafe.Pointer, uintptr) uintptr
+       equalfn func(unsafe.Pointer, unsafe.Pointer) bool
 
        gc     unsafe.Pointer
        string *string
diff --git a/libgo/runtime/go-type-complex.c b/libgo/runtime/go-type-complex.c
deleted file mode 100644 (file)
index 829572b..0000000
+++ /dev/null
@@ -1,120 +0,0 @@
-/* go-type-complex.c -- hash and equality complex functions.
-
-   Copyright 2012 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 <complex.h>
-#include <math.h>
-#include <stdint.h>
-#include <string.h>
-#include "runtime.h"
-#include "go-type.h"
-
-/* Hash function for float types.  */
-
-uintptr_t
-__go_type_hash_complex (const void *vkey, uintptr_t seed, uintptr_t key_size)
-{
-  if (key_size == 8)
-    {
-      const complex float *cfp;
-      complex float cf;
-      float cfr;
-      float cfi;
-      uint64_t fi;
-
-      cfp = (const complex float *) vkey;
-      cf = *cfp;
-
-      cfr = crealf (cf);
-      cfi = cimagf (cf);
-
-      if (isinf (cfr) || isinf (cfi))
-       return seed;
-
-      /* NaN != NaN, so the hash code of a NaN is irrelevant.  Make it
-        random so that not all NaNs wind up in the same place.  */
-      if (isnan (cfr) || isnan (cfi))
-       return runtime_fastrand1 ();
-
-      /* Avoid negative zero.  */
-      if (cfr == 0 && cfi == 0)
-       return seed;
-      else if (cfr == 0)
-       cf = cfi * I;
-      else if (cfi == 0)
-       cf = cfr;
-
-      memcpy (&fi, &cf, 8);
-      return (uintptr_t) cfi ^ seed;
-    }
-  else if (key_size == 16)
-    {
-      const complex double *cdp;
-      complex double cd;
-      double cdr;
-      double cdi;
-      uint64_t di[2];
-
-      cdp = (const complex double *) vkey;
-      cd = *cdp;
-
-      cdr = creal (cd);
-      cdi = cimag (cd);
-
-      if (isinf (cdr) || isinf (cdi))
-       return seed;
-
-      if (isnan (cdr) || isnan (cdi))
-       return runtime_fastrand1 ();
-
-      /* Avoid negative zero.  */
-      if (cdr == 0 && cdi == 0)
-       return seed;
-      else if (cdr == 0)
-       cd = cdi * I;
-      else if (cdi == 0)
-       cd = cdr;
-
-      memcpy (&di, &cd, 16);
-      return di[0] ^ di[1] ^ seed;
-    }
-  else
-    runtime_throw ("__go_type_hash_complex: invalid complex size");
-}
-
-const FuncVal __go_type_hash_complex_descriptor =
-  { (void *) __go_type_hash_complex };
-
-/* Equality function for complex types.  */
-
-_Bool
-__go_type_equal_complex (const void *vk1, const void *vk2, uintptr_t key_size)
-{
-  if (key_size == 8)
-    {
-      const complex float *cfp1;
-      const complex float *cfp2;
-      
-      cfp1 = (const complex float *) vk1;
-      cfp2 = (const complex float *) vk2;
-
-      return *cfp1 == *cfp2;
-    }
-  else if (key_size == 16)
-    {
-      const complex double *cdp1;
-      const complex double *cdp2;
-      
-      cdp1 = (const complex double *) vk1;
-      cdp2 = (const complex double *) vk2;
-
-      return *cdp1 == *cdp2;
-    }
-  else
-    runtime_throw ("__go_type_equal_complex: invalid complex size");
-}
-
-const FuncVal __go_type_equal_complex_descriptor =
-  { (void *) __go_type_equal_complex };
diff --git a/libgo/runtime/go-type-float.c b/libgo/runtime/go-type-float.c
deleted file mode 100644 (file)
index ae0e336..0000000
+++ /dev/null
@@ -1,92 +0,0 @@
-/* go-type-float.c -- hash and equality float functions.
-
-   Copyright 2012 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 <math.h>
-#include <stdint.h>
-#include "runtime.h"
-#include "go-type.h"
-
-/* Hash function for float types.  */
-
-uintptr_t
-__go_type_hash_float (const void *vkey, uintptr_t seed, uintptr_t key_size)
-{
-  if (key_size == 4)
-    {
-      const float *fp;
-      float f;
-      uint32_t si;
-
-      fp = (const float *) vkey;
-      f = *fp;
-
-      if (isinf (f) || f == 0)
-       return seed;
-
-      /* NaN != NaN, so the hash code of a NaN is irrelevant.  Make it
-        random so that not all NaNs wind up in the same place.  */
-      if (isnan (f))
-       return runtime_fastrand1 ();
-
-      memcpy (&si, vkey, 4);
-      return (uintptr_t) si ^ seed;
-    }
-  else if (key_size == 8)
-    {
-      const double *dp;
-      double d;
-      uint64_t di;
-
-      dp = (const double *) vkey;
-      d = *dp;
-
-      if (isinf (d) || d == 0)
-       return seed;
-
-      if (isnan (d))
-       return runtime_fastrand1 ();
-
-      memcpy (&di, vkey, 8);
-      return (uintptr_t) di ^ seed;
-    }
-  else
-    runtime_throw ("__go_type_hash_float: invalid float size");
-}
-
-const FuncVal __go_type_hash_float_descriptor =
-  { (void *) __go_type_hash_float };
-
-/* Equality function for float types.  */
-
-_Bool
-__go_type_equal_float (const void *vk1, const void *vk2, uintptr_t key_size)
-{
-  if (key_size == 4)
-    {
-      const float *fp1;
-      const float *fp2;
-
-      fp1 = (const float *) vk1;
-      fp2 = (const float *) vk2;
-
-      return *fp1 == *fp2;
-    }
-  else if (key_size == 8)
-    {
-      const double *dp1;
-      const double *dp2;
-
-      dp1 = (const double *) vk1;
-      dp2 = (const double *) vk2;
-
-      return *dp1 == *dp2;
-    }
-  else
-    runtime_throw ("__go_type_equal_float: invalid float size");
-}
-
-const FuncVal __go_type_equal_float_descriptor =
-  { (void *) __go_type_equal_float };
diff --git a/libgo/runtime/go-type-identity.c b/libgo/runtime/go-type-identity.c
deleted file mode 100644 (file)
index 842fa24..0000000
+++ /dev/null
@@ -1,32 +0,0 @@
-/* go-type-identity.c -- hash and equality identity functions.
-
-   Copyright 2009 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 <stddef.h>
-
-#include "runtime.h"
-#include "go-type.h"
-
-/* The hash functions for types that can compare as identity is
-   written in Go.  */
-
-extern uintptr runtime_memhash(void *, uintptr, uintptr)
-  __asm__ (GOSYM_PREFIX "runtime.memhash");
-
-const FuncVal __go_type_hash_identity_descriptor =
-  { (void *) runtime_memhash };
-
-/* An identity equality function for a type.  This is used for types
-   where we can check for equality by checking that the values have
-   the same bits.  */
-
-_Bool
-__go_type_equal_identity (const void *k1, const void *k2, uintptr_t key_size)
-{
-  return __builtin_memcmp (k1, k2, key_size) == 0;
-}
-
-const FuncVal __go_type_equal_identity_descriptor =
-  { (void *) __go_type_equal_identity };
diff --git a/libgo/runtime/go-type-string.c b/libgo/runtime/go-type-string.c
deleted file mode 100644 (file)
index c7277dd..0000000
+++ /dev/null
@@ -1,49 +0,0 @@
-/* go-type-string.c -- hash and equality string functions.
-
-   Copyright 2009 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 "runtime.h"
-#include "go-type.h"
-#include "go-string.h"
-
-/* A string hash function for a map.  */
-
-uintptr_t
-__go_type_hash_string (const void *vkey, uintptr_t seed,
-                      uintptr_t key_size __attribute__ ((unused)))
-{
-  uintptr_t ret;
-  const String *key;
-  intgo len;
-  intgo i;
-  const byte *p;
-
-  ret = seed;
-  key = (const String *) vkey;
-  len = key->len;
-  for (i = 0, p = key->str; i < len; i++, p++)
-    ret = ret * 33 + *p;
-  return ret;
-}
-
-const FuncVal __go_type_hash_string_descriptor =
-  { (void *) __go_type_hash_string };
-
-/* A string equality function for a map.  */
-
-_Bool
-__go_type_equal_string (const void *vk1, const void *vk2,
-                       uintptr_t key_size __attribute__ ((unused)))
-{
-  const String *k1;
-  const String *k2;
-
-  k1 = (const String *) vk1;
-  k2 = (const String *) vk2;
-  return __go_ptr_strings_equal (k1, k2);
-}
-
-const FuncVal __go_type_equal_string_descriptor =
-  { (void *) __go_type_equal_string };
index 2d5965c..e155254 100644 (file)
@@ -362,24 +362,4 @@ extern _Bool
 __go_type_descriptors_equal(const struct __go_type_descriptor*,
                            const struct __go_type_descriptor*);
 
-extern const FuncVal __go_type_hash_identity_descriptor;
-extern _Bool __go_type_equal_identity (const void *, const void *, uintptr_t);
-extern const FuncVal __go_type_equal_identity_descriptor;
-extern uintptr_t __go_type_hash_string (const void *, uintptr_t, uintptr_t);
-extern const FuncVal __go_type_hash_string_descriptor;
-extern _Bool __go_type_equal_string (const void *, const void *, uintptr_t);
-extern const FuncVal __go_type_equal_string_descriptor;
-extern uintptr_t __go_type_hash_float (const void *, uintptr_t, uintptr_t);
-extern const FuncVal __go_type_hash_float_descriptor;
-extern _Bool __go_type_equal_float (const void *, const void *, uintptr_t);
-extern const FuncVal __go_type_equal_float_descriptor;
-extern uintptr_t __go_type_hash_complex (const void *, uintptr_t, uintptr_t);
-extern const FuncVal __go_type_hash_complex_descriptor;
-extern _Bool __go_type_equal_complex (const void *, const void *, uintptr_t);
-extern const FuncVal __go_type_equal_complex_descriptor;
-extern uintptr_t __go_type_hash_interface (const void *, uintptr_t, uintptr_t);
-extern const FuncVal __go_type_hash_interface_descriptor;
-extern _Bool __go_type_equal_interface (const void *, const void *, uintptr_t);
-extern const FuncVal __go_type_equal_interface_descriptor;
-
 #endif /* !defined(LIBGO_GO_TYPE_H) */
index ce82fcd..b980683 100644 (file)
@@ -38,6 +38,11 @@ static const String reflection_string =
 
 const uintptr unsafe_Pointer_gc[] = {sizeof(void*), GC_APTR, 0, GC_END};
 
+extern const FuncVal runtime_pointerhash_descriptor
+  __asm__ (GOSYM_PREFIX "runtime.pointerhash$descriptor");
+extern const FuncVal runtime_pointerequal_descriptor
+  __asm__ (GOSYM_PREFIX "runtime.pointerequal$descriptor");
+
 const struct __go_type_descriptor unsafe_Pointer =
 {
   /* __code */
@@ -51,9 +56,9 @@ const struct __go_type_descriptor unsafe_Pointer =
   /* __hash */
   78501163U,
   /* __hashfn */
-  &__go_type_hash_identity_descriptor,
+  &runtime_pointerhash_descriptor,
   /* __equalfn */
-  &__go_type_equal_identity_descriptor,
+  &runtime_pointerequal_descriptor,
   /* __gc */
   unsafe_Pointer_gc,
   /* __reflection */
@@ -94,9 +99,9 @@ const struct __go_ptr_type pointer_unsafe_Pointer =
     /* __hash */
     1256018616U,
     /* __hashfn */
-    &__go_type_hash_identity_descriptor,
+    &runtime_pointerhash_descriptor,
     /* __equalfn */
-    &__go_type_equal_identity_descriptor,
+    &runtime_pointerequal_descriptor,
     /* __gc */
     unsafe_Pointer_gc,
     /* __reflection */