compiler: bring escape analysis mostly in line with gc compiler
authorIan Lance Taylor <ian@gcc.gnu.org>
Fri, 22 Dec 2017 15:55:10 +0000 (15:55 +0000)
committerIan Lance Taylor <ian@gcc.gnu.org>
Fri, 22 Dec 2017 15:55:10 +0000 (15:55 +0000)
commitbb14e19c2be54dd10f40d705364e08524ec8310c
tree7efb527f7a7ce27ccda83182efded7baed05aec5
parente2a29465e91c75b337aabd5886af982653faf00e
compiler: bring escape analysis mostly in line with gc compiler

    This CL ports the latest (~Go 1.10) escape analysis code from
    the gc compiler. Changes include:

    - In the gc compiler, the variable expression is represented
      with the variable node itself (ONAME). It is the same node
      used in the AST for multiple var expressions for the same
      variable. In our case, the var expressions nodes are distinct
      nodes. We need to propagate the escape state from/to the
      underlying variable in getter and setter. We already do it in
      the setter. Do it in the getter as well.

    - At the point of escape analysis, some AST constructs have not
      been lowered to runtime calls, for example, map literal
      construction and some builtin calls. Change the analysis to
      work on the non-lowered AST constructs instead of call
      expressions for them. For this to work, the analysis needs to
      look into Builtin_call_expression. Move its class definition
      from expressions.cc to expressions.h, and add necessary
      accessors. Also fix bugs in other runtime call handlings
      (selectsend, ifaceX2Y2, etc.).

    - Handle closures properly. The analysis tracks the function
      reference expression, and the escape state is propagated to
      the underlying heap expression for get_backend to do stack
      allocation for non-escaping closures.

    - Fix add_dereference. Before, this was doing expr->deref(),
      which undoes an indirection instead of add one. In the gc
      compiler, it adds a level of indirection, which is modeled as
      an OIND node regardless of the type of the expression. We
      can't do this for non-pointer typed expression, otherwise it
      will result in a type error. Instead, we model it with a
      special flavor of Node, "indirect". The flood phase handles
      this by incrementing its level.

    - Slicing of an array was not handled correctly. The gc compiler
      has an implicit (compiler inserted) OADDR node for the array,
      so the analysis is actually performed on the address of the
      array. We don't have this implicit address-of expression in
      the AST. Instead, we model this by adding an implicit child to
      the Node of the Array_index_expression representing slicing of
      an array.

    - Array_index_expression may represent indexing or slicing. The
      code distinguishes them by looking at whether the type of the
      expression is a slice. This does not work if the slice element
      is a slice. Instead, check whether its end() is NULL.

    - Temporary references was handled only in a limited case, as
      part of address-of expression. This CL handles it in general.
      The analysis uses the Temporary_statement as the point of
      tracking, and forwards Temporary_reference_expression to the
      underlying statement when needed.

    - Handle call return value flows, escpecially multiple return
      values. This includes porting part of CL 8202, CL 20102, and
      other fixes.

    - Support go:noescape pragma.

    - Add special handling for self assignment like
      b.buf = b.buf[m:n]. (CL 3162)

    - Remove ESCAPE_SCOPE, which was treated essentially the same as
      ESCAPE_HEAP, and was removed from the gc compiler. (CL 32130)

    - Run flood phase until fix point. (CL 30693)

    - Unnamed parameters do not escape. (CL 38600)

    - Various small bug fixes and improvements.

    "make check-go" passes except the one test in math/big, when the
    escape analysis is on. The escape analysis is still not run by
    default.

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

From-SVN: r255976
gcc/go/gofrontend/MERGE
gcc/go/gofrontend/escape.cc
gcc/go/gofrontend/escape.h
gcc/go/gofrontend/expressions.cc
gcc/go/gofrontend/expressions.h
gcc/go/gofrontend/gogo.h
gcc/go/gofrontend/runtime.cc