Commit f788537d by Ian Lance Taylor

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

From-SVN: r248934
parent bbf97416
e5870eac67d4d5b1f86bdbfb13dadf4d5723f71d 7e3904e4370ccfd9062c2661c612476288244e17
The first line of this file holds the git revision number of the last The first line of this file holds the git revision number of the last
merge done from the gofrontend repository. merge done from the gofrontend repository.
...@@ -10156,9 +10156,13 @@ Call_expression::do_must_eval_in_order() const ...@@ -10156,9 +10156,13 @@ Call_expression::do_must_eval_in_order() const
Expression* Expression*
Call_expression::interface_method_function( Call_expression::interface_method_function(
Interface_field_reference_expression* interface_method, 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(); return interface_method->get_function();
} }
...@@ -10267,7 +10271,8 @@ Call_expression::do_get_backend(Translate_context* context) ...@@ -10267,7 +10271,8 @@ Call_expression::do_get_backend(Translate_context* context)
else else
{ {
Expression* first_arg; 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); fn_args[0] = first_arg->get_backend(context);
} }
...@@ -15392,10 +15397,16 @@ Interface_mtable_expression::do_type() ...@@ -15392,10 +15397,16 @@ Interface_mtable_expression::do_type()
Typed_identifier tid("__type_descriptor", Type::make_type_descriptor_ptr_type(), Typed_identifier tid("__type_descriptor", Type::make_type_descriptor_ptr_type(),
this->location()); this->location());
sfl->push_back(Struct_field(tid)); 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(); for (Typed_identifier_list::const_iterator p = interface_methods->begin();
p != interface_methods->end(); p != interface_methods->end();
++p) ++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()); Struct_type* st = Type::make_struct_type(sfl, this->location());
st->set_is_struct_incomparable(); st->set_is_struct_incomparable();
this->method_table_type_ = st; this->method_table_type_ = st;
...@@ -15456,11 +15467,18 @@ Interface_mtable_expression::do_get_backend(Translate_context* context) ...@@ -15456,11 +15467,18 @@ Interface_mtable_expression::do_get_backend(Translate_context* context)
else else
td_type = Type::make_pointer_type(this->type_); 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 // 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 // list of function pointers, one for each interface method. This is used for
// interfaces. // interfaces.
Expression_list* svals = new Expression_list(); 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(); Named_type* nt = this->type_->named_type();
Struct_type* st = this->type_->struct_type(); Struct_type* st = this->type_->struct_type();
...@@ -15480,13 +15498,24 @@ Interface_mtable_expression::do_get_backend(Translate_context* context) ...@@ -15480,13 +15498,24 @@ Interface_mtable_expression::do_get_backend(Translate_context* context)
Named_object* no = m->named_object(); Named_object* no = m->named_object();
go_assert(no->is_function() || no->is_function_declaration()); 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)); svals->push_back(Expression::make_func_code_reference(no, loc));
} }
Btype* btype = this->type()->get_backend(gogo); Btype *btype = gogo->backend()->struct_type(bstructfields);
Expression* mtable = Expression::make_struct_composite_literal(this->type(), std::vector<Bexpression*> ctor_bexprs;
svals, loc); for (Expression_list::const_iterator pe = svals->begin();
Bexpression* ctor = mtable->get_backend(context); 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; bool is_public = has_hidden_methods && this->type_->named_type() != NULL;
std::string asm_name(go_selectively_encode_id(mangled_name)); std::string asm_name(go_selectively_encode_id(mangled_name));
......
...@@ -2287,7 +2287,7 @@ class Call_expression : public Expression ...@@ -2287,7 +2287,7 @@ class Call_expression : public Expression
Expression* Expression*
interface_method_function(Interface_field_reference_expression*, interface_method_function(Interface_field_reference_expression*,
Expression**); Expression**, Location);
Bexpression* Bexpression*
set_results(Translate_context*); set_results(Translate_context*);
......
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