@@ -9013,8 +9013,51 @@
// 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)
{
@@ -124,15 +124,15 @@
// 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]);
}
@@ -84,6 +84,7 @@
MLink *v, *next;
byte *tiny;
bool incallback;
+ void *closure;
if(size == 0) {
// All 0-length allocations use this pointer.
@@ -95,6 +96,10 @@
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 @@
m->locks--;
if(incallback)
runtime_entersyscall();
+ g->closure = closure;
return v;
}
}
@@ -264,6 +270,8 @@
if(incallback)
runtime_entersyscall();
+ g->closure = closure;
+
return v;
}