From da9e0b98ac9d41b41520b5e587621707d59ae0f6 Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Fri, 6 May 2011 06:34:27 +0000 Subject: [PATCH] Use backend interface for interface types. From-SVN: r173469 --- gcc/go/gofrontend/types.cc | 193 +++++++++++++++++-------------------- gcc/go/gofrontend/types.h | 12 +-- 2 files changed, 91 insertions(+), 114 deletions(-) diff --git a/gcc/go/gofrontend/types.cc b/gcc/go/gofrontend/types.cc index 667f3e59095..a03ab1fbe11 100644 --- a/gcc/go/gofrontend/types.cc +++ b/gcc/go/gofrontend/types.cc @@ -6003,124 +6003,99 @@ Interface_type::implements_interface(const Type* t, std::string* reason) const return true; } -// Return a tree for an interface type. An interface is a pointer to -// 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. +// Return the backend representation of the empty interface type. We +// use the same struct for all empty interfaces. -tree -Interface_type::do_get_tree(Gogo* gogo) +Btype* +Interface_type::get_backend_empty_interface_type(Gogo* gogo) { - if (this->methods_ == NULL) - return Interface_type::empty_type_tree(gogo); - else + static Btype* empty_interface_type; + if (empty_interface_type == NULL) { - tree t = Interface_type::non_empty_type_tree(this->location_); - return this->fill_in_tree(gogo, t); - } -} + std::vector bfields(2); -// Return a singleton struct for an empty interface type. We use the -// same type for all empty interfaces. This lets us assign them to -// each other directly without triggering GIMPLE type errors. + Type* pdt = Type::make_type_descriptor_ptr_type(); + bfields[0].name = "__type_descriptor"; + bfields[0].btype = tree_to_type(pdt->get_tree(gogo)); + bfields[0].location = UNKNOWN_LOCATION; -tree -Interface_type::empty_type_tree(Gogo* gogo) -{ - static tree empty_interface; - if (empty_interface != NULL_TREE) - return empty_interface; + 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; - tree dtype = Type::make_type_descriptor_type()->get_tree(gogo); - dtype = build_pointer_type(build_qualified_type(dtype, TYPE_QUAL_CONST)); - return Gogo::builtin_struct(&empty_interface, "__go_empty_interface", - NULL_TREE, 2, - "__type_descriptor", - dtype, - "__object", - ptr_type_node); + empty_interface_type = gogo->backend()->struct_type(bfields); + } + return empty_interface_type; } -// Return a new struct for a non-empty interface type. The correct -// values are filled in by fill_in_tree. +// Return the fields of a non-empty interface type. This is not +// declared in types.h so that types.h doesn't have to #include +// backend.h. -tree -Interface_type::non_empty_type_tree(source_location location) +static void +get_backend_interface_fields(Gogo* gogo, Interface_type* type, + std::vector* bfields) { - tree ret = make_node(RECORD_TYPE); + source_location loc = type->location(); + + std::vector mfields(type->methods()->size() + 1); - tree field_trees = NULL_TREE; - tree* pp = &field_trees; + Type* pdt = Type::make_type_descriptor_ptr_type(); + 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"); - tree field = build_decl(location, FIELD_DECL, name_tree, ptr_type_node); - DECL_CONTEXT(field) = ret; - *pp = field; - pp = &DECL_CHAIN(field); + std::string last_name = ""; + size_t i = 1; + for (Typed_identifier_list::const_iterator p = type->methods()->begin(); + p != type->methods()->end(); + ++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"); - field = build_decl(location, FIELD_DECL, name_tree, ptr_type_node); - DECL_CONTEXT(field) = ret; - *pp = field; + Btype* methods = gogo->backend()->struct_type(mfields); - 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 -// interface types. +// Return a tree for an interface type. An interface is a pointer to +// 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 -Interface_type::fill_in_tree(Gogo* gogo, tree type) +Interface_type::do_get_tree(Gogo* gogo) { - go_assert(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) + if (this->methods_ == NULL) { - std::string name = Gogo::unpack_hidden_name(p->name()); - name_tree = get_identifier_with_length(name.data(), name.length()); - tree field_type = p->type()->get_tree(gogo); - if (field_type == error_mark_node) - return error_mark_node; - field = build_decl(this->location_, FIELD_DECL, name_tree, field_type); - DECL_CONTEXT(field) = method_table; - *pp = field; - pp = &DECL_CHAIN(field); - // Sanity check: the names should be sorted. - go_assert(p->name() > last_name); - last_name = p->name(); + Btype* bt = Interface_type::get_backend_empty_interface_type(gogo); + return type_to_tree(bt); + } + else + { + std::vector bfields; + get_backend_interface_fields(gogo, this, &bfields); + Btype* bt = gogo->backend()->struct_type(bfields); + return type_to_tree(bt); } - 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. @@ -7089,6 +7064,7 @@ Named_type::convert(Gogo* gogo) break; case TYPE_ARRAY: + // Slice types were completed in create_placeholder. if (!base->is_open_array_type()) { Btype* bet = base->array_type()->get_backend_element(gogo); @@ -7099,11 +7075,7 @@ Named_type::convert(Gogo* gogo) break; case TYPE_INTERFACE: - if (!base->interface_type()->is_empty()) - { - tree t = type_to_tree(bt); - bt = tree_to_type(base->interface_type()->fill_in_tree(gogo, t)); - } + // Interface types were completed in create_placeholder. break; case TYPE_ERROR: @@ -7194,11 +7166,12 @@ Named_type::create_placeholder(Gogo* gogo) case TYPE_INTERFACE: 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 { - source_location loc = base->interface_type()->location(); - bt = tree_to_type(Interface_type::non_empty_type_tree(loc)); + bt = gogo->backend()->placeholder_struct_type(this->name(), + this->location_); + set_name = false; } break; @@ -7218,12 +7191,24 @@ Named_type::create_placeholder(Gogo* gogo) if (base->is_open_array_type()) { // 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 bfields; get_backend_slice_fields(gogo, base->array_type(), &bfields); if (!gogo->backend()->set_placeholder_struct_type(bt, bfields)) 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 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. diff --git a/gcc/go/gofrontend/types.h b/gcc/go/gofrontend/types.h index 37199de7808..d8a0f71a7b9 100644 --- a/gcc/go/gofrontend/types.h +++ b/gcc/go/gofrontend/types.h @@ -2369,16 +2369,8 @@ class Interface_type : public Type do_import(Import*); // Make a struct for an empty interface type. - static tree - empty_type_tree(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 Btype* + get_backend_empty_interface_type(Gogo*); static Type* make_interface_type_descriptor_type(); -- 2.30.2