aboutsummaryrefslogtreecommitdiff
path: root/gcc/go/gofrontend/escape.h
diff options
context:
space:
mode:
authorIan Lance Taylor <ian@gcc.gnu.org>2017-12-22 15:55:10 +0000
committerIan Lance Taylor <ian@gcc.gnu.org>2017-12-22 15:55:10 +0000
commitbb14e19c2be54dd10f40d705364e08524ec8310c (patch)
tree7efb527f7a7ce27ccda83182efded7baed05aec5 /gcc/go/gofrontend/escape.h
parente2a29465e91c75b337aabd5886af982653faf00e (diff)
downloadgcc-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.h60
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;