@@ -1833,7 +1833,9 @@
bloc);
gogo->start_block(bloc);
- if (this->struct_type() != NULL)
+ 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,
equal_fntype);
else if (this->array_type() != NULL)
@@ -1851,7 +1853,9 @@
false, bloc);
gogo->start_block(bloc);
- if (this->struct_type() != NULL)
+ 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);
else if (this->array_type() != NULL)
this->array_type()->write_equal_function(gogo, name);
@@ -1864,6 +1868,100 @@
gogo->finish_function(bloc);
}
+// 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
+// type is defined in another package and relies on calling hash
+// functions defined only in that package.
+
+void
+Type::write_named_hash(Gogo* gogo, Named_type* name,
+ Function_type* hash_fntype, Function_type* equal_fntype)
+{
+ Location bloc = Linemap::predeclared_location();
+
+ Named_type* base_type = name->real_type()->named_type();
+ go_assert(base_type != NULL);
+
+ // The pointer to the type we are going to hash. This is an
+ // unsafe.Pointer.
+ Named_object* key_arg = gogo->lookup("key", NULL);
+ go_assert(key_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,
+ &hash_fn, &equal_fn);
+
+ // Call the hash function for the base type.
+ Expression* key_ref = Expression::make_var_reference(key_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(keysz_ref);
+ Expression* func = Expression::make_func_reference(hash_fn, NULL, bloc);
+ Expression* call = Expression::make_call(func, args, false, bloc);
+
+ // Return the hash of the base type.
+ 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 that simply calls the equality 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
+// type is defined in another package and relies on calling equality
+// functions defined only in that package.
+
+void
+Type::write_named_equal(Gogo* gogo, Named_type* name)
+{
+ Location bloc = Linemap::predeclared_location();
+
+ // The pointers to the types we are going to compare. These have
+ // type unsafe.Pointer.
+ Named_object* key1_arg = gogo->lookup("key1", NULL);
+ Named_object* key2_arg = gogo->lookup("key2", NULL);
+ go_assert(key1_arg != NULL && key2_arg != NULL);
+
+ Named_type* base_type = name->real_type()->named_type();
+ go_assert(base_type != NULL);
+
+ // Build temporaries with the base type.
+ Type* pt = Type::make_pointer_type(base_type);
+
+ Expression* ref = Expression::make_var_reference(key1_arg, bloc);
+ ref = Expression::make_cast(pt, ref, bloc);
+ Temporary_statement* p1 = Statement::make_temporary(pt, ref, bloc);
+ gogo->add_statement(p1);
+
+ ref = Expression::make_var_reference(key2_arg, bloc);
+ ref = Expression::make_cast(pt, ref, bloc);
+ Temporary_statement* p2 = Statement::make_temporary(pt, ref, bloc);
+ gogo->add_statement(p2);
+
+ // Compare the values for equality.
+ Expression* t1 = Expression::make_temporary_reference(p1, bloc);
+ t1 = Expression::make_unary(OPERATOR_MULT, t1, bloc);
+
+ Expression* t2 = Expression::make_temporary_reference(p2, bloc);
+ t2 = Expression::make_unary(OPERATOR_MULT, t2, bloc);
+
+ Expression* cond = Expression::make_binary(OPERATOR_EQEQ, t1, t2, bloc);
+
+ // Return the equality comparison.
+ Expression_list* vals = new Expression_list();
+ vals->push_back(cond);
+ Statement* s = Statement::make_return_statement(vals, bloc);
+ gogo->add_statement(s);
+}
+
// Return a composite literal for the type descriptor for a plain type
// of kind RUNTIME_TYPE_KIND named NAME.
@@ -1138,6 +1138,13 @@
Function_type* equal_fntype, Named_object** hash_fn,
Named_object** equal_fn);
+ void
+ write_named_hash(Gogo*, Named_type*, Function_type* hash_fntype,
+ Function_type* equal_fntype);
+
+ void
+ write_named_equal(Gogo*, Named_type*);
+
// Build a composite literal for the uncommon type information.
Expression*
uncommon_type_constructor(Gogo*, Type* uncommon_type,