aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIan Lance Taylor <ian@gcc.gnu.org>2016-07-06 17:34:03 +0000
committerIan Lance Taylor <ian@gcc.gnu.org>2016-07-06 17:34:03 +0000
commitf91f0e21733dae6f8d1393d6c8029b8d9cf073fa (patch)
tree0aa44a0547ac2ca5457a2740648a3ffd2307f05e
parent5e030517680b8e7660d323007e5aa843f87b835d (diff)
downloadgcc-f91f0e21733dae6f8d1393d6c8029b8d9cf073fa.zip
gcc-f91f0e21733dae6f8d1393d6c8029b8d9cf073fa.tar.gz
gcc-f91f0e21733dae6f8d1393d6c8029b8d9cf073fa.tar.bz2
escape: Implement tag phase.
Adds notes to function parameters which summarize the escape of that parameter with respect to the function's scope. Reviewed-on: https://go-review.googlesource.com/18443 From-SVN: r238057
-rw-r--r--gcc/go/gofrontend/MERGE2
-rw-r--r--gcc/go/gofrontend/escape.cc98
2 files changed, 94 insertions, 6 deletions
diff --git a/gcc/go/gofrontend/MERGE b/gcc/go/gofrontend/MERGE
index e2a7a8d..4997623 100644
--- a/gcc/go/gofrontend/MERGE
+++ b/gcc/go/gofrontend/MERGE
@@ -1,4 +1,4 @@
-1f2f2c77c7ec92efa254e07162a8fc0d22a550e7
+c8fdad389ce6f439a02fb654d231053b47ff4e02
The first line of this file holds the git revision number of the last
merge done from the gofrontend repository.
diff --git a/gcc/go/gofrontend/escape.cc b/gcc/go/gofrontend/escape.cc
index 7a55818..af8f1e2 100644
--- a/gcc/go/gofrontend/escape.cc
+++ b/gcc/go/gofrontend/escape.cc
@@ -2194,15 +2194,103 @@ Gogo::propagate_escape(Escape_context* context, Node* dst)
}
}
+class Escape_analysis_tag
+{
+ public:
+ Escape_analysis_tag(Escape_context* context)
+ : context_(context)
+ { }
+
+ // Add notes to the function's type about the escape information of its
+ // input parameters.
+ void
+ tag(Named_object* fn);
+
+ private:
+ Escape_context* context_;
+};
+
+void
+Escape_analysis_tag::tag(Named_object* fn)
+{
+ // External functions are assumed unsafe
+ // unless //go:noescape is given before the declaration.
+ if (fn->package() != NULL || !fn->is_function())
+ {
+ // TODO(cmang): Implement //go:noescape directive for external functions;
+ // mark input parameters as not escaping.
+ return;
+ }
+
+ Function_type* fntype = fn->func_value()->type();
+ Bindings* bindings = fn->func_value()->block()->bindings();
+
+ if (fntype->is_method()
+ && !fntype->receiver()->name().empty()
+ && !Gogo::is_sink_name(fntype->receiver()->name()))
+ {
+ Named_object* rcvr_no = bindings->lookup(fntype->receiver()->name());
+ go_assert(rcvr_no != NULL);
+ Node* rcvr_node = Node::make_node(rcvr_no);
+ switch ((rcvr_node->encoding() & ESCAPE_MASK))
+ {
+ case Node::ESCAPE_NONE: // not touched by flood
+ case Node::ESCAPE_RETURN:
+ if (fntype->receiver()->type()->has_pointer())
+ // Don't bother tagging for scalars.
+ fntype->add_receiver_note(rcvr_node->encoding());
+ break;
+
+ case Node::ESCAPE_HEAP: // flooded, moved to heap.
+ case Node::ESCAPE_SCOPE: // flooded, value leaves scope.
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ int i = 0;
+ if (fntype->parameters() != NULL)
+ {
+ const Typed_identifier_list* til = fntype->parameters();
+ for (Typed_identifier_list::const_iterator p = til->begin();
+ p != til->end();
+ ++p, ++i)
+ {
+ if (p->name().empty() || Gogo::is_sink_name(p->name()))
+ continue;
+
+ Named_object* param_no = bindings->lookup(p->name());
+ go_assert(param_no != NULL);
+ Node* param_node = Node::make_node(param_no);
+ switch ((param_node->encoding() & ESCAPE_MASK))
+ {
+ case Node::ESCAPE_NONE: // not touched by flood
+ case Node::ESCAPE_RETURN:
+ if (p->type()->has_pointer())
+ // Don't bother tagging for scalars.
+ fntype->add_parameter_note(i, param_node->encoding());
+ break;
+
+ case Node::ESCAPE_HEAP: // flooded, moved to heap.
+ case Node::ESCAPE_SCOPE: // flooded, value leaves scope.
+ break;
+
+ default:
+ break;
+ }
+ }
+ }
+ fntype->set_is_tagged();
+}
// Tag each top-level function with escape information that will be used to
// retain analysis results across imports.
void
-Gogo::tag_function(Escape_context*, Named_object*)
+Gogo::tag_function(Escape_context* context, Named_object* fn)
{
- // TODO(cmang): Create escape information notes for each input and output
- // parameter in a given function.
- // Escape_analysis_tag eat(context, fn);
- // this->traverse(&eat);
+ Escape_analysis_tag eat(context);
+ eat.tag(fn);
}