compiler: Fix bug converting unnamed types with placeholders.
From-SVN: r194011
This commit is contained in:
parent
55ad8d77ab
commit
8ccaff35d4
|
@ -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";
|
||||||
|
|
|
@ -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_;
|
||||||
|
|
Loading…
Reference in New Issue