diff --git a/gcc/go/gofrontend/MERGE b/gcc/go/gofrontend/MERGE index e7ff6705563..05e47ec3fa9 100644 --- a/gcc/go/gofrontend/MERGE +++ b/gcc/go/gofrontend/MERGE @@ -1,4 +1,4 @@ -128ea3dce9b8753167f33d0a96bd093a6cbd58b8 +3e9f4ee16683883ccfb8661d99318c74bb7a4bef 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 ddb1d91f3e5..79702821336 100644 --- a/gcc/go/gofrontend/expressions.cc +++ b/gcc/go/gofrontend/expressions.cc @@ -7981,7 +7981,7 @@ Bound_method_expression::do_check_types(Gogo*) Bound_method_expression::Method_value_thunks Bound_method_expression::method_value_thunks; -// Find or create the thunk for METHOD. +// Find or create the thunk for FN. Named_object* Bound_method_expression::create_thunk(Gogo* gogo, const Method* method, @@ -8078,14 +8078,28 @@ Bound_method_expression::create_thunk(Gogo* gogo, const Method* method, gogo->add_statement(s); Block* b = gogo->finish_block(loc); gogo->add_block(b, loc); + + // This is called after lowering but before determine_types. gogo->lower_block(new_no, b); - gogo->flatten_block(new_no, b); + gogo->finish_function(loc); ins.first->second = new_no; return new_no; } +// Look up a thunk for FN. + +Named_object* +Bound_method_expression::lookup_thunk(Named_object* fn) +{ + Method_value_thunks::const_iterator p = + Bound_method_expression::method_value_thunks.find(fn); + if (p == Bound_method_expression::method_value_thunks.end()) + return NULL; + return p->second; +} + // Return an expression to check *REF for nil while dereferencing // according to FIELD_INDEXES. Update *REF to build up the field // reference. This is a static function so that we don't have to @@ -8129,10 +8143,11 @@ Bound_method_expression::do_flatten(Gogo* gogo, Named_object*, { Location loc = this->location(); - Named_object* thunk = Bound_method_expression::create_thunk(gogo, - this->method_, - this->function_); - if (thunk->is_erroneous()) + Named_object* thunk = Bound_method_expression::lookup_thunk(this->function_); + + // The thunk should have been created during the + // create_function_descriptors pass. + if (thunk == NULL || thunk->is_erroneous()) { go_assert(saw_errors()); return Expression::make_error(loc); @@ -14757,14 +14772,34 @@ Interface_field_reference_expression::create_thunk(Gogo* gogo, gogo->add_statement(s); Block* b = gogo->finish_block(loc); gogo->add_block(b, loc); + + // This is called after lowering but before determine_types. gogo->lower_block(new_no, b); - gogo->flatten_block(new_no, b); + gogo->finish_function(loc); ins.first->second->push_back(std::make_pair(name, new_no)); return new_no; } +// Lookup a thunk to call method NAME on TYPE. + +Named_object* +Interface_field_reference_expression::lookup_thunk(Interface_type* type, + const std::string& name) +{ + Interface_method_thunks::const_iterator p = + Interface_field_reference_expression::interface_method_thunks.find(type); + if (p == Interface_field_reference_expression::interface_method_thunks.end()) + return NULL; + for (Method_thunks::const_iterator pm = p->second->begin(); + pm != p->second->end(); + ++pm) + if (pm->first == name) + return pm->second; + return NULL; +} + // Get the backend representation for a method value. Bexpression* @@ -14778,9 +14813,11 @@ Interface_field_reference_expression::do_get_backend(Translate_context* context) } Named_object* thunk = - Interface_field_reference_expression::create_thunk(context->gogo(), - type, this->name_); - if (thunk->is_erroneous()) + Interface_field_reference_expression::lookup_thunk(type, this->name_); + + // The thunk should have been created during the + // create_function_descriptors pass. + if (thunk == NULL || thunk->is_erroneous()) { go_assert(saw_errors()); return context->backend()->error_expression(); diff --git a/gcc/go/gofrontend/expressions.h b/gcc/go/gofrontend/expressions.h index 93483544e46..92e8d8d96b4 100644 --- a/gcc/go/gofrontend/expressions.h +++ b/gcc/go/gofrontend/expressions.h @@ -3405,6 +3405,10 @@ class Bound_method_expression : public Expression static Named_object* create_thunk(Gogo*, const Method* method, Named_object* function); + // Look up a thunk. + static Named_object* + lookup_thunk(Named_object* function); + protected: int do_traverse(Traverse*); @@ -3578,6 +3582,10 @@ class Interface_field_reference_expression : public Expression static Named_object* create_thunk(Gogo*, Interface_type* type, const std::string& name); + // Look up a thunk. + static Named_object* + lookup_thunk(Interface_type* type, const std::string& name); + // Return an expression for the pointer to the function to call. Expression* get_function(); diff --git a/gcc/go/gofrontend/gogo.cc b/gcc/go/gofrontend/gogo.cc index 95b76bd317c..290d294e83b 100644 --- a/gcc/go/gofrontend/gogo.cc +++ b/gcc/go/gofrontend/gogo.cc @@ -3430,6 +3430,11 @@ Create_function_descriptors::expression(Expression** pexpr) if (args->traverse(this) == TRAVERSE_EXIT) return TRAVERSE_EXIT; } + + // Traverse the subexpressions of the function, if any. + if (fn->traverse_subexpressions(this) == TRAVERSE_EXIT) + return TRAVERSE_EXIT; + return TRAVERSE_SKIP_COMPONENTS; } }