compiler: stack allocate defer thunk
authorIan Lance Taylor <ian@gcc.gnu.org>
Tue, 9 Jan 2018 23:36:46 +0000 (23:36 +0000)
committerIan Lance Taylor <ian@gcc.gnu.org>
Tue, 9 Jan 2018 23:36:46 +0000 (23:36 +0000)
    Defer statement may need to allocate a thunk. When it is not
    inside a loop, this can be stack allocated, as it runs before
    the function finishes.

    Reviewed-on: https://go-review.googlesource.com/85639

From-SVN: r256410

gcc/go/gofrontend/MERGE
gcc/go/gofrontend/escape.cc
gcc/go/gofrontend/statements.cc

index fe3c16e2fe6cd0b48eb92596d28e22159ddeeb78..80ccaf3b3b98fa8084e7e2938656447d6d953d02 100644 (file)
@@ -1,4 +1,4 @@
-d5774539b17112d9ce709a1fe722daf68eb8594f
+7c5e4d67041e3529a055a923b2b9f5ef09aa72a3
 
 The first line of this file holds the git revision number of the last
 merge done from the gofrontend repository.
index 7a0545108bb73c3322055f0dd6ebc60592a305eb..65ccf9bd0db015b5d085564f89dd4dafbeef3655 100644 (file)
@@ -1420,7 +1420,14 @@ Escape_analysis_assign::statement(Block*, size_t*, Statement* s)
 
     case Statement::STATEMENT_DEFER:
       if (this->context_->loop_depth() == 1)
-       break;
+        {
+          // Defer statement may need to allocate a thunk. When it is
+          // not inside a loop, this can be stack allocated, as it
+          // runs before the function finishes.
+          Node* n = Node::make_node(s);
+          n->set_encoding(Node::ESCAPE_NONE);
+          break;
+        }
       // fallthrough
 
     case Statement::STATEMENT_GO:
index 93718ff8c2af8dbeafd48f126197ea3369871053..1c079bb40c7dae0144211270a06d2db9d7fef520 100644 (file)
@@ -2156,6 +2156,8 @@ Thunk_statement::simplify_statement(Gogo* gogo, Named_object* function,
 
   // Allocate the initialized struct on the heap.
   constructor = Expression::make_heap_expression(constructor, location);
+  if ((Node::make_node(this)->encoding() & ESCAPE_MASK) == Node::ESCAPE_NONE)
+    constructor->heap_expression()->set_allocate_on_stack();
 
   // Throw an error if the function is nil.  This is so that for `go
   // nil` we get a backtrace from the go statement, rather than a