compiler: Fix bug converting unnamed types with placeholders.

From-SVN: r194011
This commit is contained in:
Ian Lance Taylor 2012-12-01 00:15:16 +00:00
parent 55ad8d77ab
commit 8ccaff35d4
2 changed files with 98 additions and 57 deletions

View File

@ -45,8 +45,7 @@ get_backend_interface_fields(Gogo* gogo, Interface_type* type,
// Class Type. // Class Type.
Type::Type(Type_classification classification) Type::Type(Type_classification classification)
: classification_(classification), btype_is_placeholder_(false), : classification_(classification), btype_(NULL), type_descriptor_var_(NULL)
btype_(NULL), type_descriptor_var_(NULL)
{ {
} }
@ -910,11 +909,7 @@ Btype*
Type::get_backend(Gogo* gogo) Type::get_backend(Gogo* gogo)
{ {
if (this->btype_ != NULL) if (this->btype_ != NULL)
{ return this->btype_;
if (this->btype_is_placeholder_ && gogo->named_types_are_converted())
this->finish_backend(gogo);
return this->btype_;
}
if (this->forward_declaration_type() != NULL if (this->forward_declaration_type() != NULL
|| this->named_type() != NULL) || this->named_type() != NULL)
@ -928,20 +923,36 @@ Type::get_backend(Gogo* gogo)
// that. There is no need to use the hash table for named types, as // that. There is no need to use the hash table for named types, as
// named types are only identical to themselves. // named types are only identical to themselves.
std::pair<Type*, Btype*> val(this, NULL); std::pair<Type*, Type_btype_entry> val;
val.first = this;
val.second.btype = NULL;
val.second.is_placeholder = false;
std::pair<Type_btypes::iterator, bool> ins = std::pair<Type_btypes::iterator, bool> ins =
Type::type_btypes.insert(val); Type::type_btypes.insert(val);
if (!ins.second && ins.first->second != NULL) if (!ins.second && ins.first->second.btype != NULL)
{ {
if (gogo != NULL && gogo->named_types_are_converted()) // Note that GOGO can be NULL here, but only when the GCC
this->btype_ = ins.first->second; // middle-end is asking for a frontend type. That will only
return ins.first->second; // happen for simple types, which should never require
// placeholders.
if (!ins.first->second.is_placeholder)
this->btype_ = ins.first->second.btype;
else if (gogo->named_types_are_converted())
{
this->finish_backend(gogo, ins.first->second.btype);
ins.first->second.is_placeholder = false;
}
return ins.first->second.btype;
} }
Btype* bt = this->get_btype_without_hash(gogo); Btype* bt = this->get_btype_without_hash(gogo);
if (ins.first->second == NULL) if (ins.first->second.btype == NULL)
ins.first->second = bt; {
ins.first->second.btype = bt;
ins.first->second.is_placeholder = false;
}
else else
{ {
// We have already created a backend representation for this // We have already created a backend representation for this
@ -949,10 +960,9 @@ Type::get_backend(Gogo* gogo)
// a named type which in turns uses an identical unnamed type. // a named type which in turns uses an identical unnamed type.
// Use the tree we created earlier and ignore the one we just // Use the tree we created earlier and ignore the one we just
// built. // built.
bt = ins.first->second; if (this->btype_ == bt)
if (gogo == NULL || !gogo->named_types_are_converted()) this->btype_ = ins.first->second.btype;
return bt; bt = ins.first->second.btype;
this->btype_ = bt;
} }
return bt; return bt;
@ -1019,6 +1029,37 @@ Type::get_backend_placeholder(Gogo* gogo)
// These are simple types that can just be created directly. // These are simple types that can just be created directly.
return this->get_backend(gogo); return this->get_backend(gogo);
case TYPE_MAP:
case TYPE_CHANNEL:
// All maps and channels have the same backend representation.
return this->get_backend(gogo);
case TYPE_NAMED:
case TYPE_FORWARD:
// Named types keep track of their own dependencies and manage
// their own placeholders.
return this->get_backend(gogo);
case TYPE_INTERFACE:
if (this->interface_type()->is_empty())
return Interface_type::get_backend_empty_interface_type(gogo);
break;
default:
break;
}
std::pair<Type*, Type_btype_entry> val;
val.first = this;
val.second.btype = NULL;
val.second.is_placeholder = false;
std::pair<Type_btypes::iterator, bool> ins =
Type::type_btypes.insert(val);
if (!ins.second && ins.first->second.btype != NULL)
return ins.first->second.btype;
switch (this->classification_)
{
case TYPE_FUNCTION: case TYPE_FUNCTION:
{ {
Location loc = this->function_type()->location(); Location loc = this->function_type()->location();
@ -1061,37 +1102,36 @@ Type::get_backend_placeholder(Gogo* gogo)
} }
break; break;
case TYPE_MAP:
case TYPE_CHANNEL:
// All maps and channels have the same backend representation.
return this->get_backend(gogo);
case TYPE_INTERFACE: case TYPE_INTERFACE:
if (this->interface_type()->is_empty()) {
return Interface_type::get_backend_empty_interface_type(gogo); go_assert(!this->interface_type()->is_empty());
else std::vector<Backend::Btyped_identifier> bfields;
{ get_backend_interface_fields(gogo, this->interface_type(), true,
std::vector<Backend::Btyped_identifier> bfields; &bfields);
get_backend_interface_fields(gogo, this->interface_type(), true, bt = gogo->backend()->struct_type(bfields);
&bfields); }
bt = gogo->backend()->struct_type(bfields);
}
break; break;
case TYPE_NAMED:
case TYPE_FORWARD:
// Named types keep track of their own dependencies and manage
// their own placeholders.
return this->get_backend(gogo);
case TYPE_SINK: case TYPE_SINK:
case TYPE_CALL_MULTIPLE_RESULT: case TYPE_CALL_MULTIPLE_RESULT:
/* Note that various classifications were handled in the earlier
switch. */
default: default:
go_unreachable(); go_unreachable();
} }
this->btype_ = bt; if (ins.first->second.btype == NULL)
this->btype_is_placeholder_ = true; {
ins.first->second.btype = bt;
ins.first->second.is_placeholder = true;
}
else
{
// A placeholder for this type got created along the way. Use
// that one and ignore the one we just built.
bt = ins.first->second.btype;
}
return bt; return bt;
} }
@ -1099,12 +1139,8 @@ Type::get_backend_placeholder(Gogo* gogo)
// using a placeholder type. // using a placeholder type.
void void
Type::finish_backend(Gogo* gogo) Type::finish_backend(Gogo* gogo, Btype *placeholder)
{ {
go_assert(this->btype_ != NULL);
if (!this->btype_is_placeholder_)
return;
switch (this->classification_) switch (this->classification_)
{ {
case TYPE_ERROR: case TYPE_ERROR:
@ -1120,7 +1156,7 @@ Type::finish_backend(Gogo* gogo)
case TYPE_FUNCTION: case TYPE_FUNCTION:
{ {
Btype* bt = this->do_get_backend(gogo); Btype* bt = this->do_get_backend(gogo);
if (!gogo->backend()->set_placeholder_function_type(this->btype_, bt)) if (!gogo->backend()->set_placeholder_function_type(placeholder, bt))
go_assert(saw_errors()); go_assert(saw_errors());
} }
break; break;
@ -1128,7 +1164,7 @@ Type::finish_backend(Gogo* gogo)
case TYPE_POINTER: case TYPE_POINTER:
{ {
Btype* bt = this->do_get_backend(gogo); Btype* bt = this->do_get_backend(gogo);
if (!gogo->backend()->set_placeholder_pointer_type(this->btype_, bt)) if (!gogo->backend()->set_placeholder_pointer_type(placeholder, bt))
go_assert(saw_errors()); go_assert(saw_errors());
} }
break; break;
@ -1165,7 +1201,7 @@ Type::finish_backend(Gogo* gogo)
go_unreachable(); go_unreachable();
} }
this->btype_is_placeholder_ = false; this->btype_ = placeholder;
} }
// Return a pointer to the type descriptor for this type. // Return a pointer to the type descriptor for this type.
@ -2968,8 +3004,8 @@ String_type::do_get_backend(Gogo* gogo)
// backend representation, so force it to be finished now. // backend representation, so force it to be finished now.
if (!gogo->named_types_are_converted()) if (!gogo->named_types_are_converted())
{ {
pb->get_backend_placeholder(gogo); Btype* bt = pb->get_backend_placeholder(gogo);
pb->finish_backend(gogo); pb->finish_backend(gogo, bt);
} }
fields[0].name = "__data"; fields[0].name = "__data";

View File

@ -888,7 +888,7 @@ class Type
// Finish the backend representation of a placeholder. // Finish the backend representation of a placeholder.
void void
finish_backend(Gogo*); finish_backend(Gogo*, Btype*);
// Build a type descriptor entry for this type. Return a pointer to // Build a type descriptor entry for this type. Return a pointer to
// it. The location is the location which causes us to need the // it. The location is the location which causes us to need the
@ -1210,10 +1210,18 @@ class Type
Btype* Btype*
get_btype_without_hash(Gogo*); get_btype_without_hash(Gogo*);
// A backend type that may be a placeholder.
struct Type_btype_entry
{
Btype *btype;
bool is_placeholder;
};
// A mapping from Type to Btype*, used to ensure that the backend // A mapping from Type to Btype*, used to ensure that the backend
// representation of identical types is identical. // representation of identical types is identical. This is only
typedef Unordered_map_hash(const Type*, Btype*, Type_hash_identical, // used for unnamed types.
Type_identical) Type_btypes; typedef Unordered_map_hash(const Type*, Type_btype_entry,
Type_hash_identical, Type_identical) Type_btypes;
static Type_btypes type_btypes; static Type_btypes type_btypes;
@ -1230,9 +1238,6 @@ class Type
// The type classification. // The type classification.
Type_classification classification_; Type_classification classification_;
// Whether btype_ is a placeholder type used while named types are
// being converted.
bool btype_is_placeholder_;
// The backend representation of the type, once it has been // The backend representation of the type, once it has been
// determined. // determined.
Btype* btype_; Btype* btype_;