diff --git a/gcc/go/gofrontend/expressions.cc b/gcc/go/gofrontend/expressions.cc index adc4fb092c4..f7a3c57bcb3 100644 --- a/gcc/go/gofrontend/expressions.cc +++ b/gcc/go/gofrontend/expressions.cc @@ -9013,8 +9013,51 @@ Call_expression::lower_varargs(Gogo* gogo, Named_object* function, // Flatten a call with multiple results into a temporary. Expression* -Call_expression::do_flatten(Gogo*, Named_object*, Statement_inserter* inserter) +Call_expression::do_flatten(Gogo* gogo, Named_object*, + Statement_inserter* inserter) { + if (this->classification() == EXPRESSION_ERROR) + return this; + + // Add temporary variables for all arguments that require type + // conversion. + Function_type* fntype = this->get_function_type(); + go_assert(fntype != NULL); + if (this->args_ != NULL && !this->args_->empty() + && fntype->parameters() != NULL && !fntype->parameters()->empty()) + { + bool is_interface_method = + this->fn_->interface_field_reference_expression() != NULL; + + Expression_list *args = new Expression_list(); + Typed_identifier_list::const_iterator pp = fntype->parameters()->begin(); + Expression_list::const_iterator pa = this->args_->begin(); + if (!is_interface_method && fntype->is_method()) + { + // The receiver argument. + args->push_back(*pa); + ++pa; + } + for (; pa != this->args_->end(); ++pa, ++pp) + { + go_assert(pp != fntype->parameters()->end()); + if (Type::are_identical(pp->type(), (*pa)->type(), true, NULL)) + args->push_back(*pa); + else + { + Location loc = (*pa)->location(); + Expression* arg = + Expression::convert_for_assignment(gogo, pp->type(), *pa, loc); + Temporary_statement* temp = + Statement::make_temporary(pp->type(), arg, loc); + inserter->insert(temp); + args->push_back(Expression::make_temporary_reference(temp, loc)); + } + } + delete this->args_; + this->args_ = args; + } + size_t rc = this->result_count(); if (rc > 1 && this->call_temp_ == NULL) { diff --git a/gcc/go/gofrontend/go.cc b/gcc/go/gofrontend/go.cc index 222ea90ae01..1772623a9ce 100644 --- a/gcc/go/gofrontend/go.cc +++ b/gcc/go/gofrontend/go.cc @@ -124,15 +124,15 @@ go_parse_input_files(const char** filenames, unsigned int filename_count, // Convert named types to backend representation. ::gogo->convert_named_types(); - // Flatten the parse tree. - ::gogo->flatten(); - // Build thunks for functions which call recover. ::gogo->build_recover_thunks(); // Convert complicated go and defer statements into simpler ones. ::gogo->simplify_thunk_statements(); + // Flatten the parse tree. + ::gogo->flatten(); + // Dump ast, use filename[0] as the base name ::gogo->dump_ast(filenames[0]); } diff --git a/libgo/runtime/malloc.goc b/libgo/runtime/malloc.goc index 028872259d9..c5e64c893b8 100644 --- a/libgo/runtime/malloc.goc +++ b/libgo/runtime/malloc.goc @@ -84,6 +84,7 @@ runtime_mallocgc(uintptr size, uintptr typ, uint32 flag) MLink *v, *next; byte *tiny; bool incallback; + void *closure; if(size == 0) { // All 0-length allocations use this pointer. @@ -95,6 +96,10 @@ runtime_mallocgc(uintptr size, uintptr typ, uint32 flag) m = runtime_m(); g = runtime_g(); + // We should not be called in between __go_set_closure and the + // actual function call, but cope with it if we are. + closure = g->closure; + incallback = false; if(m->mcache == nil && g->ncgo > 0) { // For gccgo this case can occur when a cgo or SWIG function @@ -175,6 +180,7 @@ runtime_mallocgc(uintptr size, uintptr typ, uint32 flag) m->locks--; if(incallback) runtime_entersyscall(); + g->closure = closure; return v; } } @@ -264,6 +270,8 @@ runtime_mallocgc(uintptr size, uintptr typ, uint32 flag) if(incallback) runtime_entersyscall(); + g->closure = closure; + return v; }