This patch by Than McIntosh fixes the types that the Go frontend passes to the middle-end for interface method tables. The Go frontend was using Go function types for values that are actually C function pointers. The value is a pointer either way, but clearly the type should be correct. Bootstrapped and ran Go testsuite on x86_64-pc-linux-gnu. Committed to mainline.
Ian
Index: gcc/go/gofrontend/MERGE =================================================================== --- gcc/go/gofrontend/MERGE (revision 248765) +++ gcc/go/gofrontend/MERGE (working copy) @@ -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. Index: gcc/go/gofrontend/expressions.cc =================================================================== --- gcc/go/gofrontend/expressions.cc (revision 248528) +++ gcc/go/gofrontend/expressions.cc (working copy) @@ -10156,9 +10156,13 @@ Call_expression::do_must_eval_in_order() 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(Translat 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_back else td_type = Type::make_pointer_type(this->type_); + std::vector<Backend::Btyped_identifier> 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_back 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<Bexpression*> 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)); Index: gcc/go/gofrontend/expressions.h =================================================================== --- gcc/go/gofrontend/expressions.h (revision 248528) +++ gcc/go/gofrontend/expressions.h (working copy) @@ -2287,7 +2287,7 @@ class Call_expression : public Expressio Expression* interface_method_function(Interface_field_reference_expression*, - Expression**); + Expression**, Location); Bexpression* set_results(Translate_context*);