diff options
author | Ian Lance Taylor <ian@gcc.gnu.org> | 2017-12-22 15:55:10 +0000 |
---|---|---|
committer | Ian Lance Taylor <ian@gcc.gnu.org> | 2017-12-22 15:55:10 +0000 |
commit | bb14e19c2be54dd10f40d705364e08524ec8310c (patch) | |
tree | 7efb527f7a7ce27ccda83182efded7baed05aec5 /gcc/go/gofrontend/escape.h | |
parent | e2a29465e91c75b337aabd5886af982653faf00e (diff) | |
download | gcc-bb14e19c2be54dd10f40d705364e08524ec8310c.zip gcc-bb14e19c2be54dd10f40d705364e08524ec8310c.tar.gz gcc-bb14e19c2be54dd10f40d705364e08524ec8310c.tar.bz2 |
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
Diffstat (limited to 'gcc/go/gofrontend/escape.h')
-rw-r--r-- | gcc/go/gofrontend/escape.h | 60 |
1 files changed, 44 insertions, 16 deletions
diff --git a/gcc/go/gofrontend/escape.h b/gcc/go/gofrontend/escape.h index 04247fe..ac72b19 100644 --- a/gcc/go/gofrontend/escape.h +++ b/gcc/go/gofrontend/escape.h @@ -51,7 +51,7 @@ public: suffix_value() const { return this->suffix_value_; } - // Increase the level because a node is referenced. + // Increase the level because a node is dereferenced. Level increase() const { @@ -61,7 +61,7 @@ public: return Level(this->value_ + 1, this->suffix_value_ + 1); } - // Decrease the level because a node is dereferenced. + // Decrease the level because a node is referenced. Level decrease() const { @@ -104,9 +104,9 @@ public: } private: - // The sum of all indirects (-1) and references (+1) applied to a Node. + // The sum of all references (-1) and indirects (+1) applied to a Node. int value_; - // The sum of all indirects (-1) abd references (+1) applied to a copied Node. + // The sum of all references (-1) abd indirects (+1) applied to a copied Node. int suffix_value_; }; @@ -123,7 +123,10 @@ class Node { NODE_OBJECT, NODE_EXPRESSION, - NODE_STATEMENT + NODE_STATEMENT, + // A "fake" node that models the indirection of its child node. + // This node does not correspond to an AST node. + NODE_INDIRECT }; // The state necessary to keep track of how a node escapes. @@ -161,11 +164,6 @@ class Node ESCAPE_NONE, // Is returned or reachable from a return statement. ESCAPE_RETURN, - // Allocated in an inner loop, assigned to an outer loop, - // which allows construction of non-escaping but arbitrarily large linked - // data structures (i.e., not eligible for allocation in a fixed-size stack - // stack frame). - ESCAPE_SCOPE, // Reachable from the heap. ESCAPE_HEAP, // By construction will not escape. @@ -174,17 +172,25 @@ class Node // Multiple constructors for each classification. Node(Named_object* no) - : classification_(NODE_OBJECT), state_(NULL), encoding_(ESCAPE_UNKNOWN) + : classification_(NODE_OBJECT), state_(NULL), encoding_(ESCAPE_UNKNOWN), + child_(NULL) { this->u_.object_val = no; } Node(Expression* e) - : classification_(NODE_EXPRESSION), state_(NULL), encoding_(ESCAPE_UNKNOWN) + : classification_(NODE_EXPRESSION), state_(NULL), encoding_(ESCAPE_UNKNOWN), + child_(NULL) { this->u_.expression_val = e; } Node(Statement* s) - : classification_(NODE_STATEMENT), state_(NULL), encoding_(ESCAPE_UNKNOWN) + : classification_(NODE_STATEMENT), state_(NULL), encoding_(ESCAPE_UNKNOWN), + child_(NULL) { this->u_.statement_val = s; } + Node(Node *n) + : classification_(NODE_INDIRECT), state_(NULL), encoding_(ESCAPE_UNKNOWN), + child_(n) + {} + // Return this node's type. Type* type() const; @@ -203,7 +209,7 @@ class Node // Return this node's detailed format string. std::string - details() const; + details(); std::string op_format() const; @@ -214,8 +220,7 @@ class Node // Return this node's escape encoding. int - encoding() const - { return this->encoding_; } + encoding(); // Set the node's escape encoding. void @@ -252,6 +257,22 @@ class Node : NULL); } + bool + is_indirect() const + { return this->classification_ == NODE_INDIRECT; } + + // Return its child node. + // Child node is used only in indirect node, and in expression node + // representing slicing an array. + Node* + child() const + { return this->child_; } + + // Set the child node. + void + set_child(Node* n) + { this->child_ = n; } + // Static creation methods for each value supported in the union. static Node* make_node(Named_object*); @@ -262,6 +283,9 @@ class Node static Node* make_node(Statement*); + static Node* + make_indirect_node(Node*); + // Return the maximum of an existing escape encoding E and a new // escape type. static int @@ -294,6 +318,10 @@ class Node // | Escapement_encoding: ESCAPE_BITS | int encoding_; + // Child node, used only in indirect node, and expression node representing + // slicing an array. + Node* child_; + // Cache all the Nodes created via Node::make_node to make the API simpler. static std::map<Named_object*, Node*> objects; static std::map<Expression*, Node*> expressions; |