This patch by Chris Manghane allocates expressions that do not escape on the stack. This only happens when doing escape analysis, which is still not enabled by default. 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 239002) +++ gcc/go/gofrontend/MERGE (working copy) @@ -1,4 +1,4 @@ -89a0b3a04f80df388242166b8835f12e82ceb194 +7d6c53910e52b7db2a77c1c1c3bc2c170283a1fa 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 238653) +++ gcc/go/gofrontend/expressions.cc (working copy) @@ -252,7 +252,9 @@ Expression::convert_type_to_interface(Ty else { // We are assigning a non-pointer value to the interface; the - // interface gets a copy of the value in the heap. + // interface gets a copy of the value in the heap if it escapes. + // TODO(cmang): Associate escape state state of RHS with newly + // created OBJ. obj = Expression::make_heap_expression(rhs, location); } @@ -729,6 +731,13 @@ Var_expression::do_address_taken(bool es else go_unreachable(); } + + if (this->variable_->is_variable() + && this->variable_->var_value()->is_in_heap()) + { + Node::make_node(this)->set_encoding(Node::ESCAPE_HEAP); + Node::make_node(this->variable_)->set_encoding(Node::ESCAPE_HEAP); + } } // Get the backend representation for a reference to a variable. @@ -831,6 +840,10 @@ Enclosed_var_expression::do_address_take else go_unreachable(); } + + if (this->variable_->is_variable() + && this->variable_->var_value()->is_in_heap()) + Node::make_node(this->variable_)->set_encoding(Node::ESCAPE_HEAP); } // Ast dump for enclosed variable expression. @@ -3769,9 +3782,18 @@ Unary_expression::do_flatten(Gogo* gogo, // value does not escape. If this->escapes_ is true, we may be // able to set it to false if taking the address of a variable // that does not escape. - if (this->escapes_ && this->expr_->var_expression() != NULL) + Node* n = Node::make_node(this); + if ((n->encoding() & ESCAPE_MASK) == int(Node::ESCAPE_NONE)) + this->escapes_ = false; + + Named_object* var = NULL; + if (this->expr_->var_expression() != NULL) + var = this->expr_->var_expression()->named_object(); + else if (this->expr_->enclosed_var_expression() != NULL) + var = this->expr_->enclosed_var_expression()->variable(); + + if (this->escapes_ && var != NULL) { - Named_object* var = this->expr_->var_expression()->named_object(); if (var->is_variable()) this->escapes_ = var->var_value()->escapes(); if (var->is_result_variable()) @@ -11658,7 +11680,9 @@ Allocation_expression::do_get_backend(Tr Gogo* gogo = context->gogo(); Location loc = this->location(); - if (this->allocate_on_stack_) + Node* n = Node::make_node(this); + if (this->allocate_on_stack_ + || (n->encoding() & ESCAPE_MASK) == int(Node::ESCAPE_NONE)) { int64_t size; bool ok = this->type_->backend_type_size(gogo, &size); @@ -12344,7 +12368,15 @@ Slice_construction_expression::do_get_ba space->unary_expression()->set_is_slice_init(); } else - space = Expression::make_heap_expression(array_val, loc); + { + space = Expression::make_heap_expression(array_val, loc); + Node* n = Node::make_node(this); + if ((n->encoding() & ESCAPE_MASK) == int(Node::ESCAPE_NONE)) + { + n = Node::make_node(space); + n->set_encoding(Node::ESCAPE_NONE); + } + } // Build a constructor for the slice. @@ -13417,8 +13449,12 @@ Heap_expression::do_get_backend(Translat Location loc = this->location(); Gogo* gogo = context->gogo(); Btype* btype = this->type()->get_backend(gogo); - Bexpression* space = Expression::make_allocation(this->expr_->type(), - loc)->get_backend(context); + + Expression* alloc = Expression::make_allocation(this->expr_->type(), loc); + Node* n = Node::make_node(this); + if ((n->encoding() & ESCAPE_MASK) == int(Node::ESCAPE_NONE)) + alloc->allocation_expression()->set_allocate_on_stack(); + Bexpression* space = alloc->get_backend(context); Bstatement* decl; Named_object* fn = context->function();