Commit da9e0b98 by Ian Lance Taylor

Use backend interface for interface types.

From-SVN: r173469
parent 3d528853
...@@ -6003,124 +6003,99 @@ Interface_type::implements_interface(const Type* t, std::string* reason) const ...@@ -6003,124 +6003,99 @@ Interface_type::implements_interface(const Type* t, std::string* reason) const
return true; return true;
} }
// Return a tree for an interface type. An interface is a pointer to // Return the backend representation of the empty interface type. We
// a struct. The struct has three fields. The first field is a // use the same struct for all empty interfaces.
// pointer to the type descriptor for the dynamic type of the object.
// The second field is a pointer to a table of methods for the
// interface to be used with the object. The third field is the value
// of the object itself.
tree Btype*
Interface_type::do_get_tree(Gogo* gogo) Interface_type::get_backend_empty_interface_type(Gogo* gogo)
{ {
if (this->methods_ == NULL) static Btype* empty_interface_type;
return Interface_type::empty_type_tree(gogo); if (empty_interface_type == NULL)
else
{ {
tree t = Interface_type::non_empty_type_tree(this->location_); std::vector<Backend::Btyped_identifier> bfields(2);
return this->fill_in_tree(gogo, t);
}
}
// Return a singleton struct for an empty interface type. We use the Type* pdt = Type::make_type_descriptor_ptr_type();
// same type for all empty interfaces. This lets us assign them to bfields[0].name = "__type_descriptor";
// each other directly without triggering GIMPLE type errors. bfields[0].btype = tree_to_type(pdt->get_tree(gogo));
bfields[0].location = UNKNOWN_LOCATION;
tree Type* vt = Type::make_pointer_type(Type::make_void_type());
Interface_type::empty_type_tree(Gogo* gogo) bfields[1].name = "__object";
{ bfields[1].btype = tree_to_type(vt->get_tree(gogo));
static tree empty_interface; bfields[1].location = UNKNOWN_LOCATION;
if (empty_interface != NULL_TREE)
return empty_interface;
tree dtype = Type::make_type_descriptor_type()->get_tree(gogo); empty_interface_type = gogo->backend()->struct_type(bfields);
dtype = build_pointer_type(build_qualified_type(dtype, TYPE_QUAL_CONST)); }
return Gogo::builtin_struct(&empty_interface, "__go_empty_interface", return empty_interface_type;
NULL_TREE, 2,
"__type_descriptor",
dtype,
"__object",
ptr_type_node);
} }
// Return a new struct for a non-empty interface type. The correct // Return the fields of a non-empty interface type. This is not
// values are filled in by fill_in_tree. // declared in types.h so that types.h doesn't have to #include
// backend.h.
tree static void
Interface_type::non_empty_type_tree(source_location location) get_backend_interface_fields(Gogo* gogo, Interface_type* type,
std::vector<Backend::Btyped_identifier>* bfields)
{ {
tree ret = make_node(RECORD_TYPE); source_location loc = type->location();
std::vector<Backend::Btyped_identifier> mfields(type->methods()->size() + 1);
tree field_trees = NULL_TREE; Type* pdt = Type::make_type_descriptor_ptr_type();
tree* pp = &field_trees; mfields[0].name = "__type_descriptor";
mfields[0].btype = tree_to_type(pdt->get_tree(gogo));
mfields[0].location = loc;
tree name_tree = get_identifier("__methods"); std::string last_name = "";
tree field = build_decl(location, FIELD_DECL, name_tree, ptr_type_node); size_t i = 1;
DECL_CONTEXT(field) = ret; for (Typed_identifier_list::const_iterator p = type->methods()->begin();
*pp = field; p != type->methods()->end();
pp = &DECL_CHAIN(field); ++p, ++i)
{
mfields[i].name = Gogo::unpack_hidden_name(p->name());
mfields[i].btype = tree_to_type(p->type()->get_tree(gogo));
mfields[i].location = loc;
// Sanity check: the names should be sorted.
go_assert(p->name() > last_name);
last_name = p->name();
}
name_tree = get_identifier("__object"); Btype* methods = gogo->backend()->struct_type(mfields);
field = build_decl(location, FIELD_DECL, name_tree, ptr_type_node);
DECL_CONTEXT(field) = ret;
*pp = field;
TYPE_FIELDS(ret) = field_trees; bfields->resize(2);
layout_type(ret); (*bfields)[0].name = "__methods";
(*bfields)[0].btype = gogo->backend()->pointer_type(methods);
(*bfields)[0].location = loc;
return ret; Type* vt = Type::make_pointer_type(Type::make_void_type());
(*bfields)[1].name = "__object";
(*bfields)[1].btype = tree_to_type(vt->get_tree(gogo));
(*bfields)[1].location = UNKNOWN_LOCATION;
} }
// Fill in the tree for an interface type. This is used for named // Return a tree for an interface type. An interface is a pointer to
// interface types. // a struct. The struct has three fields. The first field is a
// pointer to the type descriptor for the dynamic type of the object.
// The second field is a pointer to a table of methods for the
// interface to be used with the object. The third field is the value
// of the object itself.
tree tree
Interface_type::fill_in_tree(Gogo* gogo, tree type) Interface_type::do_get_tree(Gogo* gogo)
{ {
go_assert(this->methods_ != NULL); if (this->methods_ == NULL)
// Build the type of the table of methods.
tree method_table = make_node(RECORD_TYPE);
// The first field is a pointer to the type descriptor.
tree name_tree = get_identifier("__type_descriptor");
tree dtype = Type::make_type_descriptor_type()->get_tree(gogo);
dtype = build_pointer_type(build_qualified_type(dtype, TYPE_QUAL_CONST));
tree field = build_decl(this->location_, FIELD_DECL, name_tree, dtype);
DECL_CONTEXT(field) = method_table;
TYPE_FIELDS(method_table) = field;
std::string last_name = "";
tree* pp = &DECL_CHAIN(field);
for (Typed_identifier_list::const_iterator p = this->methods_->begin();
p != this->methods_->end();
++p)
{ {
std::string name = Gogo::unpack_hidden_name(p->name()); Btype* bt = Interface_type::get_backend_empty_interface_type(gogo);
name_tree = get_identifier_with_length(name.data(), name.length()); return type_to_tree(bt);
tree field_type = p->type()->get_tree(gogo); }
if (field_type == error_mark_node) else
return error_mark_node; {
field = build_decl(this->location_, FIELD_DECL, name_tree, field_type); std::vector<Backend::Btyped_identifier> bfields;
DECL_CONTEXT(field) = method_table; get_backend_interface_fields(gogo, this, &bfields);
*pp = field; Btype* bt = gogo->backend()->struct_type(bfields);
pp = &DECL_CHAIN(field); return type_to_tree(bt);
// Sanity check: the names should be sorted.
go_assert(p->name() > last_name);
last_name = p->name();
} }
layout_type(method_table);
// Update the type of the __methods field from a generic pointer to
// a pointer to the method table.
field = TYPE_FIELDS(type);
go_assert(strcmp(IDENTIFIER_POINTER(DECL_NAME(field)), "__methods") == 0);
TREE_TYPE(field) = build_pointer_type(method_table);
return type;
} }
// Initialization value. // Initialization value.
...@@ -7089,6 +7064,7 @@ Named_type::convert(Gogo* gogo) ...@@ -7089,6 +7064,7 @@ Named_type::convert(Gogo* gogo)
break; break;
case TYPE_ARRAY: case TYPE_ARRAY:
// Slice types were completed in create_placeholder.
if (!base->is_open_array_type()) if (!base->is_open_array_type())
{ {
Btype* bet = base->array_type()->get_backend_element(gogo); Btype* bet = base->array_type()->get_backend_element(gogo);
...@@ -7099,11 +7075,7 @@ Named_type::convert(Gogo* gogo) ...@@ -7099,11 +7075,7 @@ Named_type::convert(Gogo* gogo)
break; break;
case TYPE_INTERFACE: case TYPE_INTERFACE:
if (!base->interface_type()->is_empty()) // Interface types were completed in create_placeholder.
{
tree t = type_to_tree(bt);
bt = tree_to_type(base->interface_type()->fill_in_tree(gogo, t));
}
break; break;
case TYPE_ERROR: case TYPE_ERROR:
...@@ -7194,11 +7166,12 @@ Named_type::create_placeholder(Gogo* gogo) ...@@ -7194,11 +7166,12 @@ Named_type::create_placeholder(Gogo* gogo)
case TYPE_INTERFACE: case TYPE_INTERFACE:
if (base->interface_type()->is_empty()) if (base->interface_type()->is_empty())
bt = tree_to_type(Interface_type::empty_type_tree(gogo)); bt = Interface_type::get_backend_empty_interface_type(gogo);
else else
{ {
source_location loc = base->interface_type()->location(); bt = gogo->backend()->placeholder_struct_type(this->name(),
bt = tree_to_type(Interface_type::non_empty_type_tree(loc)); this->location_);
set_name = false;
} }
break; break;
...@@ -7218,12 +7191,24 @@ Named_type::create_placeholder(Gogo* gogo) ...@@ -7218,12 +7191,24 @@ Named_type::create_placeholder(Gogo* gogo)
if (base->is_open_array_type()) if (base->is_open_array_type())
{ {
// We do not record slices as dependencies of other types, // We do not record slices as dependencies of other types,
// because we can fill them in completely here. // because we can fill them in completely here with the final
// size.
std::vector<Backend::Btyped_identifier> bfields; std::vector<Backend::Btyped_identifier> bfields;
get_backend_slice_fields(gogo, base->array_type(), &bfields); get_backend_slice_fields(gogo, base->array_type(), &bfields);
if (!gogo->backend()->set_placeholder_struct_type(bt, bfields)) if (!gogo->backend()->set_placeholder_struct_type(bt, bfields))
this->named_btype_ = gogo->backend()->error_type(); this->named_btype_ = gogo->backend()->error_type();
} }
else if (base->interface_type() != NULL
&& !base->interface_type()->is_empty())
{
// We do not record interfaces as dependencies of other types,
// because we can fill them in completely here with the final
// size.
std::vector<Backend::Btyped_identifier> bfields;
get_backend_interface_fields(gogo, base->interface_type(), &bfields);
if (!gogo->backend()->set_placeholder_struct_type(bt, bfields))
this->named_btype_ = gogo->backend()->error_type();
}
} }
// Get a tree for a named type. // Get a tree for a named type.
......
...@@ -2369,16 +2369,8 @@ class Interface_type : public Type ...@@ -2369,16 +2369,8 @@ class Interface_type : public Type
do_import(Import*); do_import(Import*);
// Make a struct for an empty interface type. // Make a struct for an empty interface type.
static tree static Btype*
empty_type_tree(Gogo*); get_backend_empty_interface_type(Gogo*);
// Make a struct for non-empty interface type.
static tree
non_empty_type_tree(source_location);
// Fill in the fields for a named interface type.
tree
fill_in_tree(Gogo*, tree);
static Type* static Type*
make_interface_type_descriptor_type(); make_interface_type_descriptor_type();
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment