diff options
author | Ian Lance Taylor <ian@gcc.gnu.org> | 2016-07-06 17:34:03 +0000 |
---|---|---|
committer | Ian Lance Taylor <ian@gcc.gnu.org> | 2016-07-06 17:34:03 +0000 |
commit | f91f0e21733dae6f8d1393d6c8029b8d9cf073fa (patch) | |
tree | 0aa44a0547ac2ca5457a2740648a3ffd2307f05e | |
parent | 5e030517680b8e7660d323007e5aa843f87b835d (diff) | |
download | gcc-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/MERGE | 2 | ||||
-rw-r--r-- | gcc/go/gofrontend/escape.cc | 98 |
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); } |