aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIan Lance Taylor <iant@google.com>2015-05-06 22:59:54 +0000
committerIan Lance Taylor <iant@google.com>2015-05-06 22:59:54 +0000
commitcdbd155a21876b7ab71d835e627f2dd7379f8aa6 (patch)
tree454bb15a23bb83b1772d0827e771fc506dd5efba
parentf5050f8ec0a3526c30cbe384508672260e3750de (diff)
compiler: Analyze escape information of interface parameters.
When analyzing function calls with interface parameters, all arguments related to an interface parameter were assumed to escape via the function arguments. Now, if an argument is related to a non-escaping parameter with an interface type, the argument may be stack-allocated. git-svn-id: https://gcc.gnu.org/svn/gcc/trunk@222865 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--gcc/go/gofrontend/escape.cc28
1 files changed, 16 insertions, 12 deletions
diff --git a/gcc/go/gofrontend/escape.cc b/gcc/go/gofrontend/escape.cc
index 0d8739818dd..883e69c41d0 100644
--- a/gcc/go/gofrontend/escape.cc
+++ b/gcc/go/gofrontend/escape.cc
@@ -586,8 +586,20 @@ Build_connection_graphs::handle_call(Named_object* object, Expression* e)
// Only call expression statements are interesting
// e.g. 'func(var)' for which we can show var does not escape.
Call_expression* ce = e->call_expression();
- if (ce == NULL || ce->args() == NULL)
+ if (ce == NULL)
return;
+ else if (ce->args() == NULL)
+ {
+ if (ce->fn()->interface_field_reference_expression() != NULL)
+ {
+ // This is a call to an interface method with no arguments. OBJECT
+ // must be the receiver and we assume it escapes.
+ Connection_node* rcvr_node =
+ this->gogo_->add_connection_node(object)->connection_node();
+ rcvr_node->set_escape_state(Node::ESCAPE_ARG);
+ }
+ return;
+ }
// If the function call that references OBJECT is unknown, we must be
// conservative and assume every argument escapes. A function call is unknown
@@ -606,6 +618,8 @@ Build_connection_graphs::handle_call(Named_object* object, Expression* e)
this->gogo_->add_connection_node(arg_no)->connection_node();
arg_node->set_escape_state(Node::ESCAPE_ARG);
}
+ else if ((*arg)->call_expression() != NULL)
+ this->handle_call(object, *arg);
}
return;
}
@@ -787,7 +801,6 @@ Build_connection_graphs::handle_call(Named_object* object, Expression* e)
++pos)
{
std::string param_name;
- bool param_is_interface = false;
if (*pos >= 0 && params->size() <= static_cast<size_t>(*pos))
{
// There were more arguments than there are parameters. This must be
@@ -804,11 +817,7 @@ Build_connection_graphs::handle_call(Named_object* object, Expression* e)
param_name = fntype->receiver()->name();
}
else
- {
- param_name = params->at(*pos).name();
- param_is_interface =
- (params->at(*pos).type()->interface_type() != NULL);
- }
+ param_name = params->at(*pos).name();
if (Gogo::is_sink_name(param_name) || param_name.empty())
continue;
@@ -832,11 +841,6 @@ Build_connection_graphs::handle_call(Named_object* object, Expression* e)
Node* arg_node = this->gogo_->add_connection_node(object);
Node* param_node = this->gogo_->add_connection_node(param_no);
-
- // Act conservatively when an argument is converted into an interface
- // value. FIXME.
- if (param_is_interface)
- param_node->connection_node()->set_escape_state(Node::ESCAPE_ARG);
param_node->add_edge(arg_node);
}