Commit f91f0e21 by Ian Lance Taylor

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
parent 5e030517
1f2f2c77c7ec92efa254e07162a8fc0d22a550e7
c8fdad389ce6f439a02fb654d231053b47ff4e02
The first line of this file holds the git revision number of the last
merge done from the gofrontend repository.
......@@ -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);
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment