compiler: If type defined as type, forward hash/equal functions.
Fixes http://golang.org/issue/6789 . From-SVN: r205404
This commit is contained in:
parent
08af82b017
commit
304cfd9a7b
@ -1833,7 +1833,9 @@ Type::write_specific_type_functions(Gogo* gogo, Named_type* name,
|
||||
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 @@ Type::write_specific_type_functions(Gogo* gogo, Named_type* name,
|
||||
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 @@ Type::write_specific_type_functions(Gogo* gogo, Named_type* name,
|
||||
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 @@ class Type
|
||||
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,
|
||||
|
Loading…
x
Reference in New Issue
Block a user