From db122cb9f301a8659577c928622f113e4ae536e0 Mon Sep 17 00:00:00 2001 From: ian Date: Tue, 6 Jun 2017 20:57:03 +0000 Subject: [PATCH] compiler: typing fixes for Interface_mtable_expression Interface_mtable_expression::do_type computes a type that incorporates Go type descriptors for the interface methods, whereas in order to have strict type agreement with the mtable data, the interface method fields need to be C function ptrs. Change the type recipe accordingly, and then update Interface_mtable_expression::do_get_backend to compute a revised backend type that uses the correct fcn types. Reviewed-on: https://go-review.googlesource.com/44750 git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@248934 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/go/gofrontend/MERGE | 2 +- gcc/go/gofrontend/expressions.cc | 47 ++++++++++++++++++++++++++++++++-------- gcc/go/gofrontend/expressions.h | 2 +- 3 files changed, 40 insertions(+), 11 deletions(-) diff --git a/gcc/go/gofrontend/MERGE b/gcc/go/gofrontend/MERGE index 33259da299f..df16770883e 100644 --- a/gcc/go/gofrontend/MERGE +++ b/gcc/go/gofrontend/MERGE @@ -1,4 +1,4 @@ -e5870eac67d4d5b1f86bdbfb13dadf4d5723f71d +7e3904e4370ccfd9062c2661c612476288244e17 The first line of this file holds the git revision number of the last merge done from the gofrontend repository. diff --git a/gcc/go/gofrontend/expressions.cc b/gcc/go/gofrontend/expressions.cc index fec206d4462..a656b0681a1 100644 --- a/gcc/go/gofrontend/expressions.cc +++ b/gcc/go/gofrontend/expressions.cc @@ -10156,9 +10156,13 @@ Call_expression::do_must_eval_in_order() const Expression* Call_expression::interface_method_function( Interface_field_reference_expression* interface_method, - Expression** first_arg_ptr) + Expression** first_arg_ptr, + Location location) { - *first_arg_ptr = interface_method->get_underlying_object(); + Expression* object = interface_method->get_underlying_object(); + Type* unsafe_ptr_type = Type::make_pointer_type(Type::make_void_type()); + *first_arg_ptr = + Expression::make_unsafe_cast(unsafe_ptr_type, object, location); return interface_method->get_function(); } @@ -10267,7 +10271,8 @@ Call_expression::do_get_backend(Translate_context* context) else { Expression* first_arg; - fn = this->interface_method_function(interface_method, &first_arg); + fn = this->interface_method_function(interface_method, &first_arg, + location); fn_args[0] = first_arg->get_backend(context); } @@ -15392,10 +15397,16 @@ Interface_mtable_expression::do_type() Typed_identifier tid("__type_descriptor", Type::make_type_descriptor_ptr_type(), this->location()); sfl->push_back(Struct_field(tid)); + Type* unsafe_ptr_type = Type::make_pointer_type(Type::make_void_type()); for (Typed_identifier_list::const_iterator p = interface_methods->begin(); p != interface_methods->end(); ++p) - sfl->push_back(Struct_field(*p)); + { + // We want C function pointers here, not func descriptors; model + // using void* pointers. + Typed_identifier method(p->name(), unsafe_ptr_type, p->location()); + sfl->push_back(Struct_field(method)); + } Struct_type* st = Type::make_struct_type(sfl, this->location()); st->set_is_struct_incomparable(); this->method_table_type_ = st; @@ -15456,11 +15467,18 @@ Interface_mtable_expression::do_get_backend(Translate_context* context) else td_type = Type::make_pointer_type(this->type_); + std::vector bstructfields; + // Build an interface method table for a type: a type descriptor followed by a // list of function pointers, one for each interface method. This is used for // interfaces. Expression_list* svals = new Expression_list(); - svals->push_back(Expression::make_type_descriptor(td_type, loc)); + Expression* tdescriptor = Expression::make_type_descriptor(td_type, loc); + svals->push_back(tdescriptor); + + Btype* tdesc_btype = tdescriptor->type()->get_backend(gogo); + Backend::Btyped_identifier btd("_type", tdesc_btype, loc); + bstructfields.push_back(btd); Named_type* nt = this->type_->named_type(); Struct_type* st = this->type_->struct_type(); @@ -15480,13 +15498,24 @@ Interface_mtable_expression::do_get_backend(Translate_context* context) Named_object* no = m->named_object(); go_assert(no->is_function() || no->is_function_declaration()); + + Btype* fcn_btype = m->type()->get_backend_fntype(gogo); + Backend::Btyped_identifier bmtype(p->name(), fcn_btype, loc); + bstructfields.push_back(bmtype); + svals->push_back(Expression::make_func_code_reference(no, loc)); } - Btype* btype = this->type()->get_backend(gogo); - Expression* mtable = Expression::make_struct_composite_literal(this->type(), - svals, loc); - Bexpression* ctor = mtable->get_backend(context); + Btype *btype = gogo->backend()->struct_type(bstructfields); + std::vector ctor_bexprs; + for (Expression_list::const_iterator pe = svals->begin(); + pe != svals->end(); + ++pe) + { + ctor_bexprs.push_back((*pe)->get_backend(context)); + } + Bexpression* ctor = + gogo->backend()->constructor_expression(btype, ctor_bexprs, loc); bool is_public = has_hidden_methods && this->type_->named_type() != NULL; std::string asm_name(go_selectively_encode_id(mangled_name)); diff --git a/gcc/go/gofrontend/expressions.h b/gcc/go/gofrontend/expressions.h index 5567605b151..43fb854e8d1 100644 --- a/gcc/go/gofrontend/expressions.h +++ b/gcc/go/gofrontend/expressions.h @@ -2287,7 +2287,7 @@ class Call_expression : public Expression Expression* interface_method_function(Interface_field_reference_expression*, - Expression**); + Expression**, Location); Bexpression* set_results(Translate_context*); -- 2.11.4.GIT