1 // escape.cc -- Go escape analysis (based on Go compiler algorithm).
3 // Copyright 2016 The Go Authors. All rights reserved.
4 // Use of this source code is governed by a BSD-style
5 // license that can be found in the LICENSE file.
15 #include "expressions.h"
16 #include "statements.h"
20 #include "go-optimize.h"
21 #include "go-diagnostics.h"
26 // Return the node's type, if it makes sense for it to have one.
31 if (this->object() != NULL
32 && this->object()->is_variable())
33 return this->object()->var_value()->type();
34 else if (this->object() != NULL
35 && this->object()->is_function())
36 return this->object()->func_value()->type();
37 else if (this->expr() != NULL
)
38 return this->expr()->type();
39 else if (this->is_indirect())
41 if (this->child()->type()->deref()->is_void_type())
42 // This is a void*. The referred type can be actually any type,
43 // which may also be pointer. We model it as another void*, so
44 // we don't lose pointer-ness.
45 return this->child()->type();
47 return this->child()->type()->deref();
49 else if (this->statement() != NULL
50 && this->statement()->temporary_statement() != NULL
)
51 return this->statement()->temporary_statement()->type();
56 // A helper for reporting; return this node's location.
59 Node::location() const
61 if (this->object() != NULL
&& !this->object()->is_sink())
62 return this->object()->location();
63 else if (this->expr() != NULL
)
64 return this->expr()->location();
65 else if (this->statement() != NULL
)
66 return this->statement()->location();
67 else if (this->is_indirect())
68 return this->child()->location();
70 return Linemap::unknown_location();
73 // A helper for reporting; return the location where the underlying
77 Node::definition_location() const
79 if (this->object() != NULL
&& !this->object()->is_sink())
81 Named_object
* no
= this->object();
82 if (no
->is_variable() || no
->is_result_variable())
83 return no
->location();
85 else if (this->expr() != NULL
)
87 Var_expression
* ve
= this->expr()->var_expression();
90 Named_object
* no
= ve
->named_object();
91 if (no
->is_variable() || no
->is_result_variable())
92 return no
->location();
94 Enclosed_var_expression
* eve
= this->expr()->enclosed_var_expression();
97 Named_object
* no
= eve
->variable();
98 if (no
->is_variable() || no
->is_result_variable())
99 return no
->location();
102 return this->location();
105 // To match the cmd/gc debug output, strip away the packed prefixes on functions
106 // and variable/expressions.
109 strip_packed_prefix(Gogo
* gogo
, const std::string
& s
)
111 std::string packed_prefix
= "." + gogo
->pkgpath() + ".";
113 for (size_t pos
= fmt
.find(packed_prefix
);
114 pos
!= std::string::npos
;
115 pos
= fmt
.find(packed_prefix
))
116 fmt
.erase(pos
, packed_prefix
.length());
120 // A helper for debugging; return this node's AST formatted string.
121 // This is an implementation of gc's Nconv with obj.FmtShort.
124 Node::ast_format(Gogo
* gogo
) const
126 std::ostringstream ss
;
129 else if (this->object() != NULL
)
131 Named_object
* no
= this->object();
132 if (no
->is_function() && no
->func_value()->enclosing() != NULL
)
133 return "func literal";
136 else if (this->expr() != NULL
)
138 Expression
* e
= this->expr();
139 bool is_call
= e
->call_expression() != NULL
;
141 e
->call_expression()->fn();
142 Func_expression
* fe
= e
->func_expression();;
144 bool is_closure
= fe
!= NULL
&& fe
->closure() != NULL
;
148 return "(func literal)()";
149 return "func literal";
151 Ast_dump_context::dump_to_stream(this->expr(), &ss
);
153 else if (this->statement() != NULL
)
155 Statement
* s
= this->statement();
156 Goto_unnamed_statement
* unnamed
= s
->goto_unnamed_statement();
159 Statement
* derived
= unnamed
->unnamed_label()->derived_from();
162 switch (derived
->classification())
164 case Statement::STATEMENT_FOR
:
165 case Statement::STATEMENT_FOR_RANGE
:
169 case Statement::STATEMENT_SWITCH
:
173 case Statement::STATEMENT_TYPE_SWITCH
:
174 return "type switch";
182 Temporary_statement
* tmp
= s
->temporary_statement();
185 // Temporary's format can never match gc's output, and
186 // temporaries are inserted differently anyway. We just
187 // print something convenient.
188 ss
<< "tmp." << (uintptr_t) tmp
;
189 if (tmp
->init() != NULL
)
192 Ast_dump_context::dump_to_stream(tmp
->init(), &ss
);
197 Ast_dump_context::dump_to_stream(s
, &ss
);
199 else if (this->is_indirect())
200 return "*(" + this->child()->ast_format(gogo
) + ")";
202 std::string s
= strip_packed_prefix(gogo
, ss
.str());
204 // trim trailing space
205 return s
.substr(0, s
.find_last_not_of(' ') + 1);
208 // A helper for debugging; return this node's detailed format string.
209 // This is an implementation of gc's Jconv with obj.FmtShort.
214 std::stringstream details
;
216 if (!this->is_sink())
217 details
<< " l(" << Linemap::location_to_line(this->location()) << ")";
219 bool is_varargs
= false;
220 bool is_address_taken
= false;
221 bool is_in_heap
= false;
222 bool is_assigned
= false;
223 std::string class_name
;
225 Expression
* e
= this->expr();
226 Named_object
* node_object
= NULL
;
227 if (this->object() != NULL
)
228 node_object
= this->object();
229 else if (e
!= NULL
&& e
->var_expression() != NULL
)
230 node_object
= e
->var_expression()->named_object();
234 // TODO(cmang): For named variables and functions, we want to output
235 // the function depth.
236 if (node_object
->is_variable())
238 Variable
* var
= node_object
->var_value();
239 is_varargs
= var
->is_varargs_parameter();
240 is_address_taken
= (var
->is_address_taken()
241 || var
->is_non_escaping_address_taken());
242 is_in_heap
= var
->is_in_heap();
243 is_assigned
= var
->init() != NULL
;
245 if (var
->is_global())
246 class_name
= "PEXTERN";
247 else if (var
->is_parameter())
248 class_name
= "PPARAM";
249 else if (var
->is_closure())
250 class_name
= "PPARAMREF";
252 class_name
= "PAUTO";
254 else if (node_object
->is_result_variable())
255 class_name
= "PPARAMOUT";
256 else if (node_object
->is_function()
257 || node_object
->is_function_declaration())
258 class_name
= "PFUNC";
260 else if (e
!= NULL
&& e
->enclosed_var_expression() != NULL
)
262 Named_object
* enclosed
= e
->enclosed_var_expression()->variable();
263 if (enclosed
->is_variable())
265 Variable
* var
= enclosed
->var_value();
266 is_address_taken
= (var
->is_address_taken()
267 || var
->is_non_escaping_address_taken());
271 Result_variable
* var
= enclosed
->result_var_value();
272 is_address_taken
= (var
->is_address_taken()
273 || var
->is_non_escaping_address_taken());
275 class_name
= "PPARAMREF";
278 if (!class_name
.empty())
280 details
<< " class(" << class_name
;
286 switch ((this->encoding() & ESCAPE_MASK
))
288 case Node::ESCAPE_UNKNOWN
:
291 case Node::ESCAPE_HEAP
:
292 details
<< " esc(h)";
295 case Node::ESCAPE_NONE
:
296 details
<< " esc(no)";
299 case Node::ESCAPE_NEVER
:
300 details
<< " esc(N)";
304 details
<< " esc(" << this->encoding() << ")";
308 if (this->state_
!= NULL
&& this->state_
->loop_depth
!= 0)
309 details
<< " ld(" << this->state_
->loop_depth
<< ")";
312 details
<< " isddd(1)";
313 if (is_address_taken
)
314 details
<< " addrtaken";
316 details
<< " assigned";
318 return details
.str();
322 Node::op_format() const
324 std::stringstream op
;
325 Ast_dump_context
adc(&op
, false);
326 if (this->expr() != NULL
)
328 Expression
* e
= this->expr();
329 switch (e
->classification())
331 case Expression::EXPRESSION_UNARY
:
332 adc
.dump_operator(e
->unary_expression()->op());
335 case Expression::EXPRESSION_BINARY
:
336 adc
.dump_operator(e
->binary_expression()->op());
339 case Expression::EXPRESSION_CALL
:
340 op
<< "function call";
343 case Expression::EXPRESSION_FUNC_REFERENCE
:
344 if (e
->func_expression()->is_runtime_function())
346 switch (e
->func_expression()->runtime_code())
348 case Runtime::GOPANIC
:
352 case Runtime::GROWSLICE
:
356 case Runtime::SLICECOPY
:
357 case Runtime::SLICESTRINGCOPY
:
358 case Runtime::TYPEDSLICECOPY
:
362 case Runtime::MAKECHAN
:
363 case Runtime::MAKEMAP
:
364 case Runtime::MAKESLICE
:
365 case Runtime::MAKESLICE64
:
369 case Runtime::DEFERPROC
:
373 case Runtime::GORECOVER
:
387 case Expression::EXPRESSION_ALLOCATION
:
391 case Expression::EXPRESSION_RECEIVE
:
400 if (this->statement() != NULL
)
402 switch (this->statement()->classification())
404 case Statement::STATEMENT_DEFER
:
408 case Statement::STATEMENT_RETURN
:
416 if (this->is_indirect())
421 // Return this node's state, creating it if has not been initialized.
424 Node::state(Escape_context
* context
, Named_object
* fn
)
426 if (this->state_
== NULL
)
428 if (this->expr() != NULL
&& this->expr()->var_expression() != NULL
)
430 // Tie state of variable references to underlying variables.
431 Named_object
* var_no
= this->expr()->var_expression()->named_object();
432 Node
* var_node
= Node::make_node(var_no
);
433 this->state_
= var_node
->state(context
, fn
);
437 this->state_
= new Node::Escape_state
;
439 fn
= context
->current_function();
441 this->state_
->fn
= fn
;
444 go_assert(this->state_
!= NULL
);
451 if (this->expr() != NULL
452 && this->expr()->var_expression() != NULL
)
454 // Get the underlying object's encoding.
455 Named_object
* no
= this->expr()->var_expression()->named_object();
456 int enc
= Node::make_node(no
)->encoding();
457 this->encoding_
= enc
;
459 return this->encoding_
;
463 Node::set_encoding(int enc
)
465 this->encoding_
= enc
;
466 if (this->expr() != NULL
)
468 if (this->expr()->var_expression() != NULL
)
470 // Set underlying object as well.
471 Named_object
* no
= this->expr()->var_expression()->named_object();
472 Node::make_node(no
)->set_encoding(enc
);
474 else if (this->expr()->func_expression() != NULL
)
476 // Propagate the escape state to the underlying
477 // closure (heap expression).
478 Expression
* closure
= this->expr()->func_expression()->closure();
480 Node::make_node(closure
)->set_encoding(enc
);
486 Node::is_big(Escape_context
* context
) const
488 Type
* t
= this->type();
490 || t
->is_call_multiple_result_type()
497 bool ok
= t
->backend_type_size(context
->gogo(), &size
);
498 bool big
= ok
&& (size
< 0 || size
> 10 * 1024 * 1024);
500 if (this->expr() != NULL
)
502 if (this->expr()->allocation_expression() != NULL
)
504 ok
= t
->deref()->backend_type_size(context
->gogo(), &size
);
505 big
= big
|| size
<= 0 || size
>= (1 << 16);
507 else if (this->expr()->call_expression() != NULL
)
509 Call_expression
* call
= this->expr()->call_expression();
510 Func_expression
* fn
= call
->fn()->func_expression();
512 && fn
->is_runtime_function()
513 && (fn
->runtime_code() == Runtime::MAKESLICE
514 || fn
->runtime_code() == Runtime::MAKESLICE64
))
516 // Second argument is length.
517 Expression_list::iterator p
= call
->args()->begin();
521 if (e
->temporary_reference_expression() != NULL
)
523 Temporary_reference_expression
* tre
= e
->temporary_reference_expression();
524 if (tre
->statement() != NULL
&& tre
->statement()->init() != NULL
)
525 e
= tre
->statement()->init();
530 if (e
->numeric_constant_value(&nc
)
531 && nc
.to_unsigned_long(&v
) == Numeric_constant::NC_UL_VALID
)
532 big
= big
|| v
>= (1 << 16);
541 Node::is_sink() const
543 if (this->object() != NULL
544 && this->object()->is_sink())
546 else if (this->expr() != NULL
547 && this->expr()->is_sink_expression())
552 std::map
<Named_object
*, Node
*> Node::objects
;
553 std::map
<Expression
*, Node
*> Node::expressions
;
554 std::map
<Statement
*, Node
*> Node::statements
;
556 // Make a object node or return a cached node for this object.
559 Node::make_node(Named_object
* no
)
561 if (Node::objects
.find(no
) != Node::objects
.end())
562 return Node::objects
[no
];
564 Node
* n
= new Node(no
);
565 std::pair
<Named_object
*, Node
*> val(no
, n
);
566 Node::objects
.insert(val
);
570 // Make an expression node or return a cached node for this expression.
573 Node::make_node(Expression
* e
)
575 if (Node::expressions
.find(e
) != Node::expressions
.end())
576 return Node::expressions
[e
];
578 Node
* n
= new Node(e
);
579 std::pair
<Expression
*, Node
*> val(e
, n
);
580 Node::expressions
.insert(val
);
584 // Make a statement node or return a cached node for this statement.
587 Node::make_node(Statement
* s
)
589 if (Node::statements
.find(s
) != Node::statements
.end())
590 return Node::statements
[s
];
592 Node
* n
= new Node(s
);
593 std::pair
<Statement
*, Node
*> val(s
, n
);
594 Node::statements
.insert(val
);
598 // Make an indirect node with given child.
601 Node::make_indirect_node(Node
* child
)
603 Node
* n
= new Node(child
);
607 // Returns the maximum of an exisiting escape value
608 // (and its additional parameter flow flags) and a new escape type.
611 Node::max_encoding(int e
, int etype
)
613 if ((e
& ESCAPE_MASK
) > etype
)
615 if (etype
== Node::ESCAPE_NONE
|| etype
== Node::ESCAPE_RETURN
)
616 return (e
& ~ESCAPE_MASK
) | etype
;
620 // Return a modified encoding for an input parameter that flows into an
624 Node::note_inout_flows(int e
, int index
, Level level
)
626 // Flow+level is encoded in two bits.
627 // 00 = not flow, xx = level+1 for 0 <= level <= maxEncodedLevel.
628 // 16 bits for Esc allows 6x2bits or 4x3bits or 3x4bits if additional
629 // information would be useful.
630 if (level
.value() <= 0 && level
.suffix_value() > 0)
631 return Node::max_encoding(e
|ESCAPE_CONTENT_ESCAPES
, Node::ESCAPE_NONE
);
632 if (level
.value() < 0)
633 return Node::ESCAPE_HEAP
;
634 if (level
.value() > ESCAPE_MAX_ENCODED_LEVEL
)
635 level
= Level::From(ESCAPE_MAX_ENCODED_LEVEL
);
637 int encoded
= level
.value() + 1;
638 int shift
= ESCAPE_BITS_PER_OUTPUT_IN_TAG
* index
+ ESCAPE_RETURN_BITS
;
639 int old
= (e
>> shift
) & ESCAPE_BITS_MASK_FOR_TAG
;
641 || (encoded
!= 0 && encoded
< old
))
644 int encoded_flow
= old
<< shift
;
645 if (((encoded_flow
>> shift
) & ESCAPE_BITS_MASK_FOR_TAG
) != old
)
647 // Failed to encode. Put this on the heap.
648 return Node::ESCAPE_HEAP
;
651 return (e
& ~(ESCAPE_BITS_MASK_FOR_TAG
<< shift
)) | encoded_flow
;
654 // Class Escape_context.
656 Escape_context::Escape_context(Gogo
* gogo
, bool recursive
)
657 : gogo_(gogo
), current_function_(NULL
), recursive_(recursive
),
658 sink_(Node::make_node(Named_object::make_sink())), loop_depth_(0),
659 flood_id_(0), pdepth_(0)
661 // The sink always escapes to heap and strictly lives outside of the
662 // current function i.e. loop_depth == -1.
663 Node::Escape_state
* state
= this->sink_
->state(this, NULL
);
664 state
->loop_depth
= -1;
668 debug_function_name(Named_object
* fn
)
673 if (!fn
->is_function())
674 return Gogo::unpack_hidden_name(fn
->name());
675 if (fn
->func_value()->enclosing() == NULL
)
677 std::string fnname
= Gogo::unpack_hidden_name(fn
->name());
678 if (fn
->func_value()->is_method())
680 // Methods in gc compiler are named "T.m" or "(*T).m" where
681 // T is the receiver type. Add the receiver here.
682 Type
* rt
= fn
->func_value()->type()->receiver()->type();
683 switch (rt
->classification())
685 case Type::TYPE_NAMED
:
686 fnname
= rt
->named_type()->name() + "." + fnname
;
689 case Type::TYPE_POINTER
:
691 Named_type
* nt
= rt
->points_to()->named_type();
693 fnname
= "(*" + nt
->name() + ")." + fnname
;
704 // Closures are named ".$nested#" where # is a global counter. Add outer
705 // function name for better distinguishing. This is also closer to what
706 // gc compiler prints, "outer.func#".
707 Named_object
* enclosing
= fn
->func_value()->enclosing();
708 std::string name
= Gogo::unpack_hidden_name(fn
->name());
709 std::string outer_name
= Gogo::unpack_hidden_name(enclosing
->name());
710 return outer_name
+ "." + name
;
713 // Return the name of the current function.
716 Escape_context::current_function_name() const
718 return debug_function_name(this->current_function_
);
721 // Initialize the dummy return values for this Node N using the results
725 Escape_context::init_retvals(Node
* n
, Function_type
* fntype
)
727 if (fntype
== NULL
|| fntype
->results() == NULL
)
730 Node::Escape_state
* state
= n
->state(this, NULL
);
731 state
->retvals
.clear();
732 Location loc
= n
->location();
736 for (Typed_identifier_list::const_iterator p
= fntype
->results()->begin();
737 p
!= fntype
->results()->end();
740 snprintf(buf
, sizeof buf
, ".out%d", i
);
741 Variable
* dummy_var
= new Variable(p
->type(), NULL
, false, false,
743 dummy_var
->set_is_used();
744 Named_object
* dummy_no
=
745 Named_object::make_variable(buf
, NULL
, dummy_var
);
746 Node
* dummy_node
= Node::make_node(dummy_no
);
747 // Initialize the state of the dummy output node.
748 Node::Escape_state
* dummy_node_state
= dummy_node
->state(this, NULL
);
749 dummy_node_state
->loop_depth
= this->loop_depth_
;
751 // Add dummy node to the retvals of n.
752 state
->retvals
.push_back(dummy_node
);
757 // Apply an indirection to N and return the result.
760 Escape_context::add_dereference(Node
* n
)
762 Expression
* e
= n
->expr();
763 Location loc
= n
->location();
766 && e
->type()->points_to() != NULL
767 && !e
->type()->points_to()->is_void_type())
769 // We don't dereference void*, which can be actually any pointer type.
770 Expression
* deref_expr
= Expression::make_unary(OPERATOR_MULT
, e
, loc
);
771 ind
= Node::make_node(deref_expr
);
774 // The gc compiler simply makes an OIND node. We can't do it
775 // for non-pointer type because that will result in a type error.
776 // Instead, we model this by making a node with a special flavor.
777 ind
= Node::make_indirect_node(n
);
779 // Initialize the state.
780 Node::Escape_state
* state
= ind
->state(this, NULL
);
781 state
->loop_depth
= n
->state(this, NULL
)->loop_depth
;
786 Escape_context::track(Node
* n
)
788 n
->set_encoding(Node::ESCAPE_NONE
);
789 // Initialize this node's state if it hasn't been encountered
791 Node::Escape_state
* state
= n
->state(this, NULL
);
792 state
->loop_depth
= this->loop_depth_
;
794 this->noesc_
.push_back(n
);
797 // Return the string representation of an escapement encoding.
800 Escape_note::make_tag(int encoding
)
803 snprintf(buf
, sizeof buf
, "esc:0x%x", encoding
);
807 // Return the escapement encoding for a string tag.
810 Escape_note::parse_tag(std::string
* tag
)
812 if (tag
== NULL
|| tag
->substr(0, 4) != "esc:")
813 return Node::ESCAPE_UNKNOWN
;
814 int encoding
= (int)strtol(tag
->substr(4).c_str(), NULL
, 0);
816 return Node::ESCAPE_UNKNOWN
;
821 // The -fgo-optimize-alloc flag activates this escape analysis.
823 Go_optimize
optimize_allocation_flag("allocs");
825 // A helper function to compute whether a function name has a
826 // matching hash value.
829 escape_hash_match(std::string suffix
, std::string name
)
833 if (suffix
.at(0) == '-')
834 return !escape_hash_match(suffix
.substr(1), name
);
836 const char* p
= name
.c_str();
837 Go_sha1_helper
* sha1_helper
= go_create_sha1_helper();
838 sha1_helper
->process_bytes(p
, strlen(p
));
839 std::string s
= sha1_helper
->finish();
842 int j
= suffix
.size() - 1;
843 for (int i
= s
.size() - 1; i
>= 0; i
--)
846 for (int k
= 0; k
< 8; k
++, j
--, c
>>=1)
850 char bit
= suffix
.at(j
) - '0';
858 // Analyze the program flow for escape information.
861 Gogo::analyze_escape()
863 if (!optimize_allocation_flag
.is_enabled() || saw_errors())
866 // Currently runtime is hard-coded to non-escape in various places.
867 // Don't run escape analysis for runtime.
868 // TODO: remove this once it works for runtime.
869 if (this->compiling_runtime() && this->package_name() == "runtime")
872 // Discover strongly connected groups of functions to analyze for escape
873 // information in this package.
874 this->discover_analysis_sets();
876 if (!this->debug_escape_hash().empty())
877 std::cerr
<< "debug-escape-hash " << this->debug_escape_hash() << "\n";
879 for (std::vector
<Analysis_set
>::iterator p
= this->analysis_sets_
.begin();
880 p
!= this->analysis_sets_
.end();
883 std::vector
<Named_object
*> stack
= p
->first
;
885 if (!this->debug_escape_hash().empty())
888 for (std::vector
<Named_object
*>::const_iterator fn
= stack
.begin();
891 match
= match
|| escape_hash_match(this->debug_escape_hash(), (*fn
)->message_name());
894 // Escape analysis won't run on these functions, but still
895 // need to tag them, so the caller knows.
896 for (std::vector
<Named_object
*>::iterator fn
= stack
.begin();
899 if ((*fn
)->is_function())
901 Function_type
* fntype
= (*fn
)->func_value()->type();
902 fntype
->set_is_tagged();
904 std::cerr
<< "debug-escape-hash disables " << debug_function_name(*fn
) << "\n";
909 for (std::vector
<Named_object
*>::const_iterator fn
= stack
.begin();
912 if ((*fn
)->is_function())
913 std::cerr
<< "debug-escape-hash triggers " << debug_function_name(*fn
) << "\n";
916 Escape_context
* context
= new Escape_context(this, p
->second
);
918 // Analyze the flow of each function; build the connection graph.
919 // This is the assign phase.
920 for (std::vector
<Named_object
*>::reverse_iterator fn
= stack
.rbegin();
924 context
->set_current_function(*fn
);
925 this->assign_connectivity(context
, *fn
);
928 // Propagate levels across each dst. This is the flood phase.
929 std::set
<Node
*> dsts
= context
->dsts();
930 Unordered_map(Node
*, int) escapes
;
931 for (std::set
<Node
*>::iterator n
= dsts
.begin();
935 escapes
[*n
] = (*n
)->encoding();
936 this->propagate_escape(context
, *n
);
940 // Reflood if the roots' escape states increase. Run until fix point.
943 for (std::set
<Node
*>::iterator n
= dsts
.begin();
947 if ((*n
)->object() == NULL
948 && ((*n
)->expr() == NULL
949 || ((*n
)->expr()->var_expression() == NULL
950 && (*n
)->expr()->enclosed_var_expression() == NULL
951 && (*n
)->expr()->func_expression() == NULL
)))
953 if (escapes
[*n
] != (*n
)->encoding())
956 if (this->debug_escape_level() > 2)
957 go_inform((*n
)->location(), "Reflooding %s %s",
958 debug_function_name((*n
)->state(context
, NULL
)->fn
).c_str(),
959 (*n
)->ast_format(this).c_str());
960 escapes
[*n
] = (*n
)->encoding();
961 this->propagate_escape(context
, *n
);
968 // Tag each exported function's parameters with escape information.
969 for (std::vector
<Named_object
*>::iterator fn
= stack
.begin();
972 this->tag_function(context
, *fn
);
974 if (this->debug_escape_level() != 0)
976 std::vector
<Node
*> noesc
= context
->non_escaping_nodes();
977 for (std::vector
<Node
*>::const_iterator n
= noesc
.begin();
981 Node::Escape_state
* state
= (*n
)->state(context
, NULL
);
982 if ((*n
)->encoding() == Node::ESCAPE_NONE
)
983 go_inform((*n
)->location(), "%s %s does not escape",
984 strip_packed_prefix(this, debug_function_name(state
->fn
)).c_str(),
985 (*n
)->ast_format(this).c_str());
992 // Traverse the program, discovering the functions that are roots of strongly
993 // connected components. The goal of this phase to produce a set of functions
994 // that must be analyzed in order.
996 class Escape_analysis_discover
: public Traverse
999 Escape_analysis_discover(Gogo
* gogo
)
1000 : Traverse(traverse_functions
| traverse_func_declarations
),
1001 gogo_(gogo
), component_ids_()
1005 function(Named_object
*);
1008 function_declaration(Named_object
*);
1011 visit(Named_object
*);
1014 visit_code(Named_object
*, int);
1017 // A counter used to generate the ID for the function node in the graph.
1020 // Type used to map functions to an ID in a graph of connected components.
1021 typedef Unordered_map(Named_object
*, int) Component_ids
;
1025 // The list of functions encountered during connected component discovery.
1026 Component_ids component_ids_
;
1027 // The stack of functions that this component consists of.
1028 std::stack
<Named_object
*> stack_
;
1031 int Escape_analysis_discover::id
= 0;
1033 // Visit each function.
1036 Escape_analysis_discover::function(Named_object
* fn
)
1039 return TRAVERSE_CONTINUE
;
1043 Escape_analysis_discover::function_declaration(Named_object
* fn
)
1046 return TRAVERSE_CONTINUE
;
1049 // Visit a function FN, adding it to the current stack of functions
1050 // in this connected component. If this is the root of the component,
1051 // create a set of functions to be analyzed later.
1053 // Finding these sets is finding strongly connected components
1054 // in the static call graph. The algorithm for doing that is taken
1055 // from Sedgewick, Algorithms, Second Edition, p. 482, with two
1058 // First, a closure (fn->func_value()->enclosing() == NULL) cannot be the
1059 // root of a connected component. Refusing to use it as a root
1060 // forces it into the component of the function in which it appears.
1061 // This is more convenient for escape analysis.
1063 // Second, each function becomes two virtual nodes in the graph,
1064 // with numbers n and n+1. We record the function's node number as n
1065 // but search from node n+1. If the search tells us that the component
1066 // number (min) is n+1, we know that this is a trivial component: one function
1067 // plus its closures. If the search tells us that the component number is
1068 // n, then there was a path from node n+1 back to node n, meaning that
1069 // the function set is mutually recursive. The escape analysis can be
1070 // more precise when analyzing a single non-recursive function than
1071 // when analyzing a set of mutually recursive functions.
1074 Escape_analysis_discover::visit(Named_object
* fn
)
1076 Component_ids::const_iterator p
= this->component_ids_
.find(fn
);
1077 if (p
!= this->component_ids_
.end())
1083 this->component_ids_
[fn
] = id
;
1087 this->stack_
.push(fn
);
1088 min
= this->visit_code(fn
, min
);
1089 if ((min
== id
|| min
== id
+ 1)
1090 && ((fn
->is_function() && fn
->func_value()->enclosing() == NULL
)
1091 || fn
->is_function_declaration()))
1093 bool recursive
= min
== id
;
1094 std::vector
<Named_object
*> group
;
1096 for (; !this->stack_
.empty(); this->stack_
.pop())
1098 Named_object
* n
= this->stack_
.top();
1106 this->component_ids_
[n
] = std::numeric_limits
<int>::max();
1108 group
.push_back(fn
);
1109 this->component_ids_
[fn
] = std::numeric_limits
<int>::max();
1111 std::reverse(group
.begin(), group
.end());
1112 this->gogo_
->add_analysis_set(group
, recursive
);
1118 // Helper class for discovery step. Traverse expressions looking for
1119 // function calls and closures to visit during the discovery step.
1121 class Escape_discover_expr
: public Traverse
1124 Escape_discover_expr(Escape_analysis_discover
* ead
, int min
)
1125 : Traverse(traverse_expressions
),
1126 ead_(ead
), min_(min
)
1131 { return this->min_
; }
1134 expression(Expression
** pexpr
);
1137 // The original discovery analysis.
1138 Escape_analysis_discover
* ead_
;
1139 // The minimum component ID in this group.
1143 // Visit any calls or closures found when discovering expressions.
1146 Escape_discover_expr::expression(Expression
** pexpr
)
1148 Expression
* e
= *pexpr
;
1149 Named_object
* fn
= NULL
;
1150 if (e
->call_expression() != NULL
1151 && e
->call_expression()->fn()->func_expression() != NULL
)
1153 // Method call or function call.
1154 fn
= e
->call_expression()->fn()->func_expression()->named_object();
1156 else if (e
->func_expression() != NULL
1157 && e
->func_expression()->closure() != NULL
)
1160 fn
= e
->func_expression()->named_object();
1164 this->min_
= std::min(this->min_
, this->ead_
->visit(fn
));
1165 return TRAVERSE_CONTINUE
;
1168 // Visit the body of each function, returns ID of the minimum connected
1169 // component found in the body.
1172 Escape_analysis_discover::visit_code(Named_object
* fn
, int min
)
1174 if (!fn
->is_function())
1177 Escape_discover_expr
ede(this, min
);
1178 fn
->func_value()->traverse(&ede
);
1182 // Discover strongly connected groups of functions to analyze.
1185 Gogo::discover_analysis_sets()
1187 Escape_analysis_discover
ead(this);
1188 this->traverse(&ead
);
1191 // Traverse all label and goto statements and mark the underlying label
1192 // as looping or not looping.
1194 class Escape_analysis_loop
: public Traverse
1197 Escape_analysis_loop()
1198 : Traverse(traverse_statements
)
1202 statement(Block
*, size_t*, Statement
*);
1206 Escape_analysis_loop::statement(Block
*, size_t*, Statement
* s
)
1208 if (s
->label_statement() != NULL
)
1209 s
->label_statement()->label()->set_nonlooping();
1210 else if (s
->goto_statement() != NULL
)
1212 if (s
->goto_statement()->label()->nonlooping())
1213 s
->goto_statement()->label()->set_looping();
1215 return TRAVERSE_CONTINUE
;
1218 // Traversal class used to look at all interesting statements within a function
1219 // in order to build a connectivity graph between all nodes within a context's
1222 class Escape_analysis_assign
: public Traverse
1225 Escape_analysis_assign(Escape_context
* context
, Named_object
* fn
)
1226 : Traverse(traverse_statements
1227 | traverse_expressions
),
1228 context_(context
), fn_(fn
)
1231 // Model statements within a function as assignments and flows between nodes.
1233 statement(Block
*, size_t*, Statement
*);
1235 // Model expressions within a function as assignments and flows between nodes.
1237 expression(Expression
**);
1239 // Model calls within a function as assignments and flows between arguments
1242 call(Call_expression
* call
);
1244 // Model the assignment of DST to SRC.
1246 assign(Node
* dst
, Node
* src
);
1248 // Model the assignment of DST to dereference of SRC.
1250 assign_deref(Node
* dst
, Node
* src
);
1252 // Model the input-to-output assignment flow of one of a function call's
1253 // arguments, where the flow is encoding in NOTE.
1255 assign_from_note(std::string
* note
, const std::vector
<Node
*>& dsts
,
1258 // Record the flow of SRC to DST in DST.
1260 flows(Node
* dst
, Node
* src
);
1263 // The escape context for this set of functions.
1264 Escape_context
* context_
;
1265 // The current function being analyzed.
1269 // Helper function to detect self assignment like the following.
1271 // func (b *Buffer) Foo() {
1273 // b.buf = b.buf[n:m]
1277 is_self_assignment(Expression
* lhs
, Expression
* rhs
)
1279 Unary_expression
* lue
=
1280 (lhs
->field_reference_expression() != NULL
1281 ? lhs
->field_reference_expression()->expr()->unary_expression()
1282 : lhs
->unary_expression());
1283 Var_expression
* lve
=
1284 (lue
!= NULL
&& lue
->op() == OPERATOR_MULT
? lue
->operand()->var_expression() : NULL
);
1285 Array_index_expression
* raie
= rhs
->array_index_expression();
1286 String_index_expression
* rsie
= rhs
->string_index_expression();
1287 Expression
* rarray
=
1288 (raie
!= NULL
&& raie
->end() != NULL
&& raie
->array()->type()->is_slice_type()
1290 : (rsie
!= NULL
&& rsie
->type()->is_string_type() ? rsie
->string() : NULL
));
1291 Unary_expression
* rue
=
1292 (rarray
!= NULL
&& rarray
->field_reference_expression() != NULL
1293 ? rarray
->field_reference_expression()->expr()->unary_expression()
1294 : (rarray
!= NULL
? rarray
->unary_expression() : NULL
));
1295 Var_expression
* rve
=
1296 (rue
!= NULL
&& rue
->op() == OPERATOR_MULT
? rue
->operand()->var_expression() : NULL
);
1297 return lve
!= NULL
&& rve
!= NULL
1298 && lve
->named_object() == rve
->named_object();
1301 // Model statements within a function as assignments and flows between nodes.
1304 Escape_analysis_assign::statement(Block
*, size_t*, Statement
* s
)
1306 // Adjust the loop depth as we enter/exit blocks related to for statements.
1307 bool is_for_statement
= (s
->is_block_statement()
1308 && s
->block_statement()->is_lowered_for_statement());
1309 if (is_for_statement
)
1310 this->context_
->increase_loop_depth();
1312 s
->traverse_contents(this);
1314 if (is_for_statement
)
1315 this->context_
->decrease_loop_depth();
1317 Gogo
* gogo
= this->context_
->gogo();
1318 int debug_level
= gogo
->debug_escape_level();
1320 && s
->unnamed_label_statement() == NULL
1321 && s
->expression_statement() == NULL
1322 && !s
->is_block_statement())
1324 Node
* n
= Node::make_node(s
);
1325 std::string fn_name
= this->context_
->current_function_name();
1326 go_inform(s
->location(), "[%d] %s esc: %s",
1327 this->context_
->loop_depth(), fn_name
.c_str(),
1328 n
->ast_format(gogo
).c_str());
1331 switch (s
->classification())
1333 case Statement::STATEMENT_VARIABLE_DECLARATION
:
1335 Named_object
* var
= s
->variable_declaration_statement()->var();
1336 Node
* var_node
= Node::make_node(var
);
1337 Node::Escape_state
* state
= var_node
->state(this->context_
, NULL
);
1338 state
->loop_depth
= this->context_
->loop_depth();
1340 // Set the loop depth for this declaration.
1341 if (var
->is_variable()
1342 && var
->var_value()->init() != NULL
)
1344 Node
* init_node
= Node::make_node(var
->var_value()->init());
1345 this->assign(var_node
, init_node
);
1350 case Statement::STATEMENT_TEMPORARY
:
1352 Expression
* init
= s
->temporary_statement()->init();
1354 this->assign(Node::make_node(s
), Node::make_node(init
));
1358 case Statement::STATEMENT_LABEL
:
1360 Label_statement
* label_stmt
= s
->label_statement();
1361 if (label_stmt
->label()->looping())
1362 this->context_
->increase_loop_depth();
1364 if (debug_level
> 1)
1366 std::string label_type
= (label_stmt
->label()->looping()
1369 go_inform(s
->location(), "%s %s label",
1370 label_stmt
->label()->name().c_str(),
1371 label_type
.c_str());
1376 case Statement::STATEMENT_SWITCH
:
1377 case Statement::STATEMENT_TYPE_SWITCH
:
1378 // Want to model the assignment of each case variable to the switched upon
1379 // variable. This should be lowered into assignment statements; nothing
1380 // to here if that's the case.
1383 case Statement::STATEMENT_ASSIGNMENT
:
1385 Assignment_statement
* assn
= s
->assignment_statement();
1386 Expression
* lhs
= assn
->lhs();
1387 Expression
* rhs
= assn
->rhs();
1388 Node
* lhs_node
= Node::make_node(lhs
);
1389 Node
* rhs_node
= Node::make_node(rhs
);
1391 // Filter out the following special case.
1393 // func (b *Buffer) Foo() {
1395 // b.buf = b.buf[n:m]
1398 // This assignment is a no-op for escape analysis,
1399 // it does not store any new pointers into b that were not already there.
1400 // However, without this special case b will escape.
1401 if (is_self_assignment(lhs
, rhs
))
1403 if (debug_level
!= 0)
1404 go_inform(s
->location(), "%s ignoring self-assignment to %s",
1405 strip_packed_prefix(gogo
, this->context_
->current_function_name()).c_str(),
1406 lhs_node
->ast_format(gogo
).c_str());
1410 this->assign(lhs_node
, rhs_node
);
1414 case Statement::STATEMENT_SEND
:
1416 Node
* sent_node
= Node::make_node(s
->send_statement()->val());
1417 this->assign(this->context_
->sink(), sent_node
);
1421 case Statement::STATEMENT_DEFER
:
1422 if (this->context_
->loop_depth() == 1)
1424 // Defer statement may need to allocate a thunk. When it is
1425 // not inside a loop, this can be stack allocated, as it
1426 // runs before the function finishes.
1427 Node
* n
= Node::make_node(s
);
1428 n
->set_encoding(Node::ESCAPE_NONE
);
1433 case Statement::STATEMENT_GO
:
1435 // Defer f(x) or go f(x).
1436 // Both f and x escape to the heap.
1437 Thunk_statement
* thunk
= s
->thunk_statement();
1438 if (thunk
->call()->call_expression() == NULL
)
1441 Call_expression
* call
= thunk
->call()->call_expression();
1442 Node
* func_node
= Node::make_node(call
->fn());
1443 this->assign(this->context_
->sink(), func_node
);
1444 if (call
->args() != NULL
)
1446 for (Expression_list::const_iterator p
= call
->args()->begin();
1447 p
!= call
->args()->end();
1450 Node
* arg_node
= Node::make_node(*p
);
1451 this->assign(this->context_
->sink(), arg_node
);
1460 return TRAVERSE_SKIP_COMPONENTS
;
1463 // Model expressions within a function as assignments and flows between nodes.
1466 Escape_analysis_assign::expression(Expression
** pexpr
)
1468 Gogo
* gogo
= this->context_
->gogo();
1469 int debug_level
= gogo
->debug_escape_level();
1471 // Big stuff escapes unconditionally.
1472 Node
* n
= Node::make_node(*pexpr
);
1473 if ((n
->encoding() & ESCAPE_MASK
) != int(Node::ESCAPE_HEAP
)
1474 && n
->is_big(this->context_
))
1476 if (debug_level
> 1)
1477 go_inform((*pexpr
)->location(), "%s too large for stack",
1478 n
->ast_format(gogo
).c_str());
1479 if (debug_level
!= 0
1480 && ((*pexpr
)->var_expression() != NULL
1481 || (*pexpr
)->enclosed_var_expression() != NULL
))
1482 go_inform(n
->definition_location(),
1483 "moved to heap: %s",
1484 n
->ast_format(gogo
).c_str());
1486 n
->set_encoding(Node::ESCAPE_HEAP
);
1487 (*pexpr
)->address_taken(true);
1488 this->assign(this->context_
->sink(), n
);
1491 if ((*pexpr
)->func_expression() == NULL
)
1492 (*pexpr
)->traverse_subexpressions(this);
1494 if (debug_level
> 1)
1496 Node
* n
= Node::make_node(*pexpr
);
1497 std::string fn_name
= this->context_
->current_function_name();
1498 go_inform((*pexpr
)->location(), "[%d] %s esc: %s",
1499 this->context_
->loop_depth(), fn_name
.c_str(),
1500 n
->ast_format(gogo
).c_str());
1503 switch ((*pexpr
)->classification())
1505 case Expression::EXPRESSION_CALL
:
1507 Call_expression
* call
= (*pexpr
)->call_expression();
1508 if (call
->is_builtin())
1510 Builtin_call_expression
* bce
= call
->builtin_call_expression();
1511 switch (bce
->code())
1513 case Builtin_call_expression::BUILTIN_PANIC
:
1515 // Argument could leak through recover.
1516 Node
* panic_arg
= Node::make_node(call
->args()->front());
1517 this->assign(this->context_
->sink(), panic_arg
);
1521 case Builtin_call_expression::BUILTIN_APPEND
:
1523 // The contents being appended leak.
1524 if (call
->is_varargs())
1526 // append(slice1, slice2...) -- slice2 itself does not escape, but contents do
1527 Node
* appended
= Node::make_node(call
->args()->back());
1528 this->assign_deref(this->context_
->sink(), appended
);
1529 if (debug_level
> 2)
1530 go_inform((*pexpr
)->location(),
1531 "special treatment of append(slice1, slice2...)");
1535 for (Expression_list::const_iterator pa
=
1536 call
->args()->begin() + 1;
1537 pa
!= call
->args()->end();
1540 Node
* arg
= Node::make_node(*pa
);
1541 this->assign(this->context_
->sink(), arg
);
1545 // The content of the original slice leaks as well.
1546 Node
* appendee
= Node::make_node(call
->args()->front());
1547 this->assign_deref(this->context_
->sink(), appendee
);
1551 case Builtin_call_expression::BUILTIN_COPY
:
1553 // Lose track of the copied content.
1554 Node
* copied
= Node::make_node(call
->args()->back());
1555 this->assign_deref(this->context_
->sink(), copied
);
1564 Func_expression
* fe
= call
->fn()->func_expression();
1565 if (fe
!= NULL
&& fe
->is_runtime_function())
1567 switch (fe
->runtime_code())
1569 case Runtime::MAKECHAN
:
1570 case Runtime::MAKEMAP
:
1571 case Runtime::MAKESLICE
:
1572 case Runtime::MAKESLICE64
:
1573 this->context_
->track(n
);
1576 case Runtime::MAPASSIGN
:
1578 // Map key escapes. The last argument is the address
1580 Node
* key_node
= Node::make_node(call
->args()->back());
1581 this->assign_deref(this->context_
->sink(), key_node
);
1585 case Runtime::SELECTSEND
:
1587 // Send to a channel, lose track. The last argument is
1588 // the address of the value to send.
1589 Node
* arg_node
= Node::make_node(call
->args()->back());
1590 this->assign_deref(this->context_
->sink(), arg_node
);
1594 case Runtime::IFACEE2T2
:
1595 case Runtime::IFACEI2T2
:
1597 // x, ok = v.(T), where T is non-pointer non-interface,
1599 // ok = IFACEI2T2(type, v, (void*)&tmp_x)
1600 // Here v flows to tmp_x.
1601 // Note: other IFACEX2Y2 returns the conversion result.
1602 // Those are handled in ::assign.
1603 Node
* src_node
= Node::make_node(call
->args()->at(1));
1605 Expression
* arg2
= call
->args()->at(2);
1606 // Try to pull tmp_x out of the arg2 expression, and let v
1607 // flows into it, instead of simply dereference arg2,
1608 // which looks like dereference of an arbitrary pointer
1609 // and causes v immediately escape.
1610 // The expression form matches statement.cc,
1611 // Tuple_type_guard_assignment_statement::lower_to_object_type.
1612 Unary_expression
* ue
=
1613 (arg2
->conversion_expression() != NULL
1614 ? arg2
->conversion_expression()->expr()->unary_expression()
1615 : arg2
->unary_expression());
1616 if (ue
!= NULL
&& ue
->op() == OPERATOR_AND
)
1618 if (!ue
->operand()->type()->has_pointer())
1619 // Don't bother flowing non-pointer.
1621 dst_node
= Node::make_node(ue
->operand());
1624 dst_node
= this->context_
->add_dereference(Node::make_node(arg2
));
1625 this->assign(dst_node
, src_node
);
1638 case Expression::EXPRESSION_ALLOCATION
:
1639 // This is Runtime::NEW.
1640 this->context_
->track(n
);
1643 case Expression::EXPRESSION_STRING_CONCAT
:
1644 this->context_
->track(n
);
1647 case Expression::EXPRESSION_CONVERSION
:
1649 Type_conversion_expression
* tce
= (*pexpr
)->conversion_expression();
1650 Type
* ft
= tce
->expr()->type();
1651 Type
* tt
= tce
->type();
1652 if ((ft
->is_string_type() && tt
->is_slice_type())
1653 || (ft
->is_slice_type() && tt
->is_string_type())
1654 || (ft
->integer_type() != NULL
&& tt
->is_string_type()))
1656 // string([]byte), string([]rune), []byte(string), []rune(string), string(rune)
1657 this->context_
->track(n
);
1660 Node
* tce_node
= Node::make_node(tce
);
1661 Node
* converted
= Node::make_node(tce
->expr());
1662 this->context_
->track(tce_node
);
1664 this->assign(tce_node
, converted
);
1668 case Expression::EXPRESSION_FIXED_ARRAY_CONSTRUCTION
:
1669 case Expression::EXPRESSION_SLICE_CONSTRUCTION
:
1671 Node
* array_node
= Node::make_node(*pexpr
);
1672 if ((*pexpr
)->slice_literal() != NULL
)
1673 this->context_
->track(array_node
);
1675 Expression_list
* vals
= ((*pexpr
)->slice_literal() != NULL
1676 ? (*pexpr
)->slice_literal()->vals()
1677 : (*pexpr
)->array_literal()->vals());
1681 // Connect the array to its values.
1682 for (Expression_list::const_iterator p
= vals
->begin();
1686 this->assign(array_node
, Node::make_node(*p
));
1691 case Expression::EXPRESSION_STRUCT_CONSTRUCTION
:
1693 Node
* struct_node
= Node::make_node(*pexpr
);
1694 Expression_list
* vals
= (*pexpr
)->struct_literal()->vals();
1697 // Connect the struct to its values.
1698 for (Expression_list::const_iterator p
= vals
->begin();
1703 this->assign(struct_node
, Node::make_node(*p
));
1709 case Expression::EXPRESSION_HEAP
:
1711 Node
* pointer_node
= Node::make_node(*pexpr
);
1712 Node
* lit_node
= Node::make_node((*pexpr
)->heap_expression()->expr());
1713 this->context_
->track(pointer_node
);
1715 // Connect pointer node to literal node; if the pointer node escapes, so
1716 // does the literal node.
1717 this->assign(pointer_node
, lit_node
);
1721 case Expression::EXPRESSION_BOUND_METHOD
:
1723 Node
* bound_node
= Node::make_node(*pexpr
);
1724 this->context_
->track(bound_node
);
1726 Expression
* obj
= (*pexpr
)->bound_method_expression()->first_argument();
1727 Node
* obj_node
= Node::make_node(obj
);
1729 // A bound method implies the receiver will be used outside of the
1730 // lifetime of the method in some way. We lose track of the receiver.
1731 this->assign(this->context_
->sink(), obj_node
);
1735 case Expression::EXPRESSION_MAP_CONSTRUCTION
:
1737 Map_construction_expression
* mce
= (*pexpr
)->map_literal();
1738 Node
* map_node
= Node::make_node(mce
);
1739 this->context_
->track(map_node
);
1741 // All keys and values escape to memory.
1742 if (mce
->vals() != NULL
)
1744 for (Expression_list::const_iterator p
= mce
->vals()->begin();
1745 p
!= mce
->vals()->end();
1749 this->assign(this->context_
->sink(), Node::make_node(*p
));
1755 case Expression::EXPRESSION_FUNC_REFERENCE
:
1757 Func_expression
* fe
= (*pexpr
)->func_expression();
1758 if (fe
->closure() != NULL
)
1760 // Connect captured variables to the closure.
1761 Node
* closure_node
= Node::make_node(fe
);
1762 this->context_
->track(closure_node
);
1764 // A closure expression already exists as the heap expression:
1765 // &struct{f func_code, v []*Variable}{...}.
1766 // Link closure to the addresses of the variables enclosed.
1767 Heap_expression
* he
= fe
->closure()->heap_expression();
1768 Struct_construction_expression
* sce
= he
->expr()->struct_literal();
1770 // First field is function code, other fields are variable
1772 Expression_list::const_iterator p
= sce
->vals()->begin();
1774 for (; p
!= sce
->vals()->end(); ++p
)
1776 Node
* enclosed_node
= Node::make_node(*p
);
1777 Node::Escape_state
* state
=
1778 enclosed_node
->state(this->context_
, NULL
);
1779 state
->loop_depth
= this->context_
->loop_depth();
1780 this->assign(closure_node
, enclosed_node
);
1786 case Expression::EXPRESSION_UNARY
:
1788 if ((*pexpr
)->unary_expression()->op() != OPERATOR_AND
)
1791 Node
* addr_node
= Node::make_node(*pexpr
);
1792 this->context_
->track(addr_node
);
1794 Expression
* operand
= (*pexpr
)->unary_expression()->operand();
1795 Named_object
* var
= NULL
;
1796 if (operand
->var_expression() != NULL
)
1797 var
= operand
->var_expression()->named_object();
1798 else if (operand
->enclosed_var_expression() != NULL
)
1799 var
= operand
->enclosed_var_expression()->variable();
1804 if (var
->is_variable()
1805 && !var
->var_value()->is_parameter())
1807 // For &x, use the loop depth of x if known.
1808 Node::Escape_state
* addr_state
=
1809 addr_node
->state(this->context_
, NULL
);
1810 Node
* operand_node
= Node::make_node(operand
);
1811 Node::Escape_state
* operand_state
=
1812 operand_node
->state(this->context_
, NULL
);
1813 if (operand_state
->loop_depth
!= 0)
1814 addr_state
->loop_depth
= operand_state
->loop_depth
;
1816 else if ((var
->is_variable()
1817 && var
->var_value()->is_parameter())
1818 || var
->is_result_variable())
1820 Node::Escape_state
* addr_state
=
1821 addr_node
->state(this->context_
, NULL
);
1822 addr_state
->loop_depth
= 1;
1827 case Expression::EXPRESSION_ARRAY_INDEX
:
1829 Array_index_expression
* aie
= (*pexpr
)->array_index_expression();
1830 if (aie
->end() != NULL
&& !aie
->array()->type()->is_slice_type())
1832 // Slicing an array.
1833 Expression
* addr
= Expression::make_unary(OPERATOR_AND
, aie
->array(),
1835 Node
* addr_node
= Node::make_node(addr
);
1836 n
->set_child(addr_node
);
1837 this->context_
->track(addr_node
);
1845 return TRAVERSE_SKIP_COMPONENTS
;
1848 // Model calls within a function as assignments and flows between arguments
1852 Escape_analysis_assign::call(Call_expression
* call
)
1854 Gogo
* gogo
= this->context_
->gogo();
1855 int debug_level
= gogo
->debug_escape_level();
1857 Func_expression
* fn
= call
->fn()->func_expression();
1858 Function_type
* fntype
= call
->get_function_type();
1859 bool indirect
= false;
1861 // Interface method calls or closure calls are indirect calls.
1863 || (fntype
->is_method()
1864 && fntype
->receiver()->type()->interface_type() != NULL
)
1866 || (fn
->named_object()->is_function()
1867 && fn
->named_object()->func_value()->enclosing() != NULL
))
1870 Node
* call_node
= Node::make_node(call
);
1871 std::vector
<Node
*> arg_nodes
;
1872 if (call
->fn()->interface_field_reference_expression() != NULL
)
1874 Interface_field_reference_expression
* ifre
=
1875 call
->fn()->interface_field_reference_expression();
1876 Node
* field_node
= Node::make_node(ifre
->expr());
1877 arg_nodes
.push_back(field_node
);
1880 if (call
->args() != NULL
)
1882 for (Expression_list::const_iterator p
= call
->args()->begin();
1883 p
!= call
->args()->end();
1885 arg_nodes
.push_back(Node::make_node(*p
));
1890 // We don't know what happens to the parameters through indirect calls.
1891 // Be conservative and assume they all flow to theSink.
1892 for (std::vector
<Node
*>::iterator p
= arg_nodes
.begin();
1893 p
!= arg_nodes
.end();
1896 if (debug_level
> 2)
1897 go_inform(call
->location(),
1898 "esccall:: indirect call <- %s, untracked",
1899 (*p
)->ast_format(gogo
).c_str());
1900 this->assign(this->context_
->sink(), *p
);
1903 this->context_
->init_retvals(call_node
, fntype
);
1905 // It could be a closure call that returns captured variable.
1906 // Model this by flowing the func expression to result.
1907 // See issue #14409.
1908 Node
* fn_node
= Node::make_node(call
->fn());
1909 std::vector
<Node
*> retvals
= call_node
->state(this->context_
, NULL
)->retvals
;
1910 for (std::vector
<Node
*>::const_iterator p
= retvals
.begin();
1913 this->assign_deref(*p
, fn_node
);
1918 // If FN is an untagged function.
1920 && fn
->named_object()->is_function()
1921 && !fntype
->is_tagged())
1923 if (debug_level
> 2)
1924 go_inform(call
->location(), "esccall:: %s in recursive group",
1925 call_node
->ast_format(gogo
).c_str());
1927 Function
* f
= fn
->named_object()->func_value();
1928 const Bindings
* callee_bindings
= f
->block()->bindings();
1929 Function::Results
* results
= f
->result_variables();
1930 if (results
!= NULL
)
1932 // Setup output list on this call node.
1933 Node::Escape_state
* state
= call_node
->state(this->context_
, NULL
);
1934 for (Function::Results::const_iterator p1
= results
->begin();
1935 p1
!= results
->end();
1938 Node
* result_node
= Node::make_node(*p1
);
1939 state
->retvals
.push_back(result_node
);
1943 std::vector
<Node
*>::iterator p
= arg_nodes
.begin();
1944 if (fntype
->is_method())
1946 std::string rcvr_name
= fntype
->receiver()->name();
1947 if (rcvr_name
.empty() || Gogo::is_sink_name(rcvr_name
)
1948 || !fntype
->receiver()->type()->has_pointer())
1952 Named_object
* rcvr_no
=
1953 callee_bindings
->lookup_local(fntype
->receiver()->name());
1954 go_assert(rcvr_no
!= NULL
);
1955 Node
* rcvr_node
= Node::make_node(rcvr_no
);
1956 if (fntype
->receiver()->type()->points_to() == NULL
1957 && (*p
)->expr()->type()->points_to() != NULL
)
1958 // This is a call to a value method that has been lowered into a call
1959 // to a pointer method. Gccgo generates a pointer method for all
1960 // method calls and takes the address of the value passed as the
1961 // receiver then immediately dereferences it within the function.
1962 // In this case, the receiver address does not escape; its content
1963 // flows to the call.
1964 this->assign_deref(rcvr_node
, *p
);
1966 this->assign(rcvr_node
, *p
);
1971 const Typed_identifier_list
* til
= fntype
->parameters();
1974 for (Typed_identifier_list::const_iterator p1
= til
->begin();
1978 if (p1
->name().empty() || Gogo::is_sink_name(p1
->name()))
1981 Named_object
* param_no
=
1982 callee_bindings
->lookup_local(p1
->name());
1983 go_assert(param_no
!= NULL
);
1984 Expression
* arg
= (*p
)->expr();
1985 if (arg
->var_expression() != NULL
1986 && arg
->var_expression()->named_object() == param_no
)
1989 Node
* param_node
= Node::make_node(param_no
);
1990 this->assign(param_node
, *p
);
1993 for (; p
!= arg_nodes
.end(); ++p
)
1995 if (debug_level
> 2)
1996 go_inform(call
->location(), "esccall:: ... <- %s, untracked",
1997 (*p
)->ast_format(gogo
).c_str());
1998 this->assign(this->context_
->sink(), *p
);
2005 if (debug_level
> 2)
2006 go_inform(call
->location(), "esccall:: %s not recursive",
2007 call_node
->ast_format(gogo
).c_str());
2009 Node::Escape_state
* call_state
= call_node
->state(this->context_
, NULL
);
2010 if (!call_state
->retvals
.empty())
2011 go_error_at(Linemap::unknown_location(),
2012 "esc already decorated call %s",
2013 call_node
->ast_format(gogo
).c_str());
2014 this->context_
->init_retvals(call_node
, fntype
);
2017 std::vector
<Node
*>::iterator p
= arg_nodes
.begin();
2018 if (fntype
->is_method()
2019 && p
!= arg_nodes
.end())
2021 // First argument to call will be the receiver.
2022 std::string
* note
= fntype
->receiver()->note();
2023 if (fntype
->receiver()->type()->points_to() == NULL
2024 && (*p
)->expr()->type()->points_to() != NULL
)
2025 // This is a call to a value method that has been lowered into a call
2026 // to a pointer method. Gccgo generates a pointer method for all
2027 // method calls and takes the address of the value passed as the
2028 // receiver then immediately dereferences it within the function.
2029 // In this case, the receiver address does not escape; its content
2030 // flows to the call.
2031 this->assign_from_note(note
, call_state
->retvals
,
2032 this->context_
->add_dereference(*p
));
2035 if (!Type::are_identical(fntype
->receiver()->type(),
2036 (*p
)->expr()->type(), true, NULL
))
2038 // This will be converted later, preemptively track it instead
2039 // of its conversion expression which will show up in a later pass.
2040 this->context_
->track(*p
);
2042 this->assign_from_note(note
, call_state
->retvals
, *p
);
2047 const Typed_identifier_list
* til
= fntype
->parameters();
2050 for (Typed_identifier_list::const_iterator pn
= til
->begin();
2051 pn
!= til
->end() && p
!= arg_nodes
.end();
2054 if (!Type::are_identical(pn
->type(), (*p
)->expr()->type(),
2057 // This will be converted later, preemptively track it instead
2058 // of its conversion expression which will show up in a later pass.
2059 this->context_
->track(*p
);
2062 Type
* t
= pn
->type();
2064 && t
->has_pointer())
2066 std::string
* note
= pn
->note();
2067 int enc
= this->assign_from_note(note
, call_state
->retvals
, *p
);
2068 if (enc
== Node::ESCAPE_NONE
2069 && !call
->is_deferred()
2070 && !call
->is_concurrent())
2072 // TODO(cmang): Mark the argument as strictly non-escaping?
2073 // In the gc compiler this is for limiting the lifetime of
2074 // temporaries. We probably don't need this?
2079 for (; p
!= arg_nodes
.end(); ++p
)
2081 if (debug_level
> 2)
2082 go_inform(call
->location(), "esccall:: ... <- %s, untracked",
2083 (*p
)->ast_format(gogo
).c_str());
2084 this->assign(this->context_
->sink(), *p
);
2089 // Model the assignment of DST to SRC.
2090 // Assert that SRC somehow gets assigned to DST.
2091 // DST might need to be examined for evaluations that happen inside of it.
2092 // For example, in [DST]*f(x) = [SRC]y, we lose track of the indirection and
2093 // DST becomes the sink in our model.
2096 Escape_analysis_assign::assign(Node
* dst
, Node
* src
)
2098 Gogo
* gogo
= this->context_
->gogo();
2099 int debug_level
= gogo
->debug_escape_level();
2100 if (debug_level
> 1)
2101 go_inform(dst
->location(), "[%d] %s escassign: %s(%s)[%s] = %s(%s)[%s]",
2102 this->context_
->loop_depth(),
2103 strip_packed_prefix(gogo
, this->context_
->current_function_name()).c_str(),
2104 dst
->ast_format(gogo
).c_str(), dst
->details().c_str(),
2105 dst
->op_format().c_str(),
2106 src
->ast_format(gogo
).c_str(), src
->details().c_str(),
2107 src
->op_format().c_str());
2109 if (dst
->is_indirect())
2110 // Lose track of the dereference.
2111 dst
= this->context_
->sink();
2112 else if (dst
->expr() != NULL
)
2114 // Analyze the lhs of the assignment.
2115 // Replace DST with this->context_->sink() if we can't track it.
2116 Expression
* e
= dst
->expr();
2117 switch (e
->classification())
2119 case Expression::EXPRESSION_VAR_REFERENCE
:
2121 // If DST is a global variable, we have no way to track it.
2122 Named_object
* var
= e
->var_expression()->named_object();
2123 if (var
->is_variable() && var
->var_value()->is_global())
2124 dst
= this->context_
->sink();
2128 case Expression::EXPRESSION_FIELD_REFERENCE
:
2130 Expression
* strct
= e
->field_reference_expression()->expr();
2131 if (strct
->heap_expression() != NULL
)
2133 // When accessing the field of a struct reference, we lose
2134 // track of the indirection.
2135 dst
= this->context_
->sink();
2139 // Treat DST.x = SRC as if it were DST = SRC.
2140 Node
* struct_node
= Node::make_node(strct
);
2141 this->assign(struct_node
, src
);
2145 case Expression::EXPRESSION_ARRAY_INDEX
:
2147 Array_index_expression
* are
= e
->array_index_expression();
2148 if (!are
->array()->type()->is_slice_type())
2150 // Treat DST[i] = SRC as if it were DST = SRC if DST if a fixed
2152 Node
* array_node
= Node::make_node(are
->array());
2153 this->assign(array_node
, src
);
2157 // Lose track of the slice dereference.
2158 dst
= this->context_
->sink();
2162 case Expression::EXPRESSION_UNARY
:
2163 // Lose track of the dereference.
2164 if (e
->unary_expression()->op() == OPERATOR_MULT
)
2165 dst
= this->context_
->sink();
2168 case Expression::EXPRESSION_MAP_INDEX
:
2170 // Lose track of the map's key and value.
2171 Expression
* index
= e
->map_index_expression()->index();
2172 Node
* index_node
= Node::make_node(index
);
2173 this->assign(this->context_
->sink(), index_node
);
2175 dst
= this->context_
->sink();
2179 case Expression::EXPRESSION_TEMPORARY_REFERENCE
:
2181 // Temporary is tracked through the underlying Temporary_statement.
2182 Statement
* t
= dst
->expr()->temporary_reference_expression()->statement();
2183 dst
= Node::make_node(t
);
2188 // TODO(cmang): Add debugging info here: only a few expressions
2189 // should leave DST unmodified.
2194 if (src
->object() != NULL
)
2195 this->flows(dst
, src
);
2196 else if (src
->is_indirect())
2197 this->flows(dst
, src
);
2198 else if (src
->expr() != NULL
)
2200 Expression
* e
= src
->expr();
2201 switch (e
->classification())
2203 case Expression::EXPRESSION_VAR_REFERENCE
:
2204 case Expression::EXPRESSION_ENCLOSED_VAR_REFERENCE
:
2206 case Expression::EXPRESSION_HEAP
:
2208 case Expression::EXPRESSION_FIXED_ARRAY_CONSTRUCTION
:
2209 case Expression::EXPRESSION_SLICE_CONSTRUCTION
:
2210 // DST = [...]T{...}.
2211 case Expression::EXPRESSION_MAP_CONSTRUCTION
:
2212 // DST = map[T]V{...}.
2213 case Expression::EXPRESSION_STRUCT_CONSTRUCTION
:
2215 case Expression::EXPRESSION_ALLOCATION
:
2217 case Expression::EXPRESSION_BOUND_METHOD
:
2219 case Expression::EXPRESSION_STRING_CONCAT
:
2220 // DST = str1 + str2
2221 this->flows(dst
, src
);
2224 case Expression::EXPRESSION_UNSAFE_CONVERSION
:
2226 Expression
* underlying
= e
->unsafe_conversion_expression()->expr();
2227 Node
* underlying_node
= Node::make_node(underlying
);
2228 this->assign(dst
, underlying_node
);
2232 case Expression::EXPRESSION_CALL
:
2234 Call_expression
* call
= e
->call_expression();
2235 if (call
->is_builtin())
2237 Builtin_call_expression
* bce
= call
->builtin_call_expression();
2238 if (bce
->code() == Builtin_call_expression::BUILTIN_APPEND
)
2240 // Append returns the first argument.
2241 // The subsequent arguments are already leaked because
2242 // they are operands to append.
2243 Node
* appendee
= Node::make_node(call
->args()->front());
2244 this->assign(dst
, appendee
);
2248 Func_expression
* fe
= call
->fn()->func_expression();
2249 if (fe
!= NULL
&& fe
->is_runtime_function())
2251 switch (fe
->runtime_code())
2253 case Runtime::MAKECHAN
:
2254 case Runtime::MAKEMAP
:
2255 case Runtime::MAKESLICE
:
2256 case Runtime::MAKESLICE64
:
2258 this->flows(dst
, src
);
2267 && fe
->named_object()->is_function()
2268 && fe
->named_object()->func_value()->is_method()
2269 && (call
->is_deferred()
2270 || call
->is_concurrent()))
2272 // For a method call thunk, lose track of the call and treat it
2273 // as if DST = RECEIVER.
2274 Node
* rcvr_node
= Node::make_node(call
->args()->front());
2275 this->assign(dst
, rcvr_node
);
2279 // Result flows to dst.
2280 Node
* call_node
= Node::make_node(e
);
2281 Node::Escape_state
* call_state
= call_node
->state(this->context_
, NULL
);
2282 std::vector
<Node
*> retvals
= call_state
->retvals
;
2283 for (std::vector
<Node
*>::const_iterator p
= retvals
.begin();
2286 this->flows(dst
, *p
);
2290 case Expression::EXPRESSION_CALL_RESULT
:
2292 Call_result_expression
* cre
= e
->call_result_expression();
2293 Call_expression
* call
= cre
->call()->call_expression();
2294 if (call
->is_builtin())
2296 if (call
->fn()->func_expression() != NULL
2297 && call
->fn()->func_expression()->is_runtime_function())
2299 switch (call
->fn()->func_expression()->runtime_code())
2301 case Runtime::IFACEE2E2
:
2302 case Runtime::IFACEI2E2
:
2303 case Runtime::IFACEE2I2
:
2304 case Runtime::IFACEI2I2
:
2305 case Runtime::IFACEE2T2P
:
2306 case Runtime::IFACEI2T2P
:
2308 // x, ok = v.(T), where T is a pointer or interface,
2310 // x, ok = IFACEI2E2(v), or
2311 // x, ok = IFACEI2I2(type, v)
2312 // The last arg flows to the first result.
2313 // Note: IFACEX2T2 has different signature, handled by
2315 if (cre
->index() != 0)
2317 Node
* arg_node
= Node::make_node(call
->args()->back());
2318 this->assign(dst
, arg_node
);
2328 Node
* call_node
= Node::make_node(call
);
2329 Node
* ret_node
= call_node
->state(context_
, NULL
)->retvals
[cre
->index()];
2330 this->assign(dst
, ret_node
);
2334 case Expression::EXPRESSION_FUNC_REFERENCE
:
2335 if (e
->func_expression()->closure() != NULL
)
2336 this->flows(dst
, src
);
2339 case Expression::EXPRESSION_CONVERSION
:
2341 Type_conversion_expression
* tce
= e
->conversion_expression();
2342 Type
* ft
= tce
->expr()->type();
2343 Type
* tt
= tce
->type();
2344 if ((ft
->is_string_type() && tt
->is_slice_type())
2345 || (ft
->is_slice_type() && tt
->is_string_type())
2346 || (ft
->integer_type() != NULL
&& tt
->is_string_type()))
2348 // string([]byte), string([]rune), []byte(string), []rune(string), string(rune)
2349 this->flows(dst
, src
);
2352 // Conversion preserves input value.
2353 Expression
* underlying
= tce
->expr();
2354 this->assign(dst
, Node::make_node(underlying
));
2358 case Expression::EXPRESSION_FIELD_REFERENCE
:
2360 // A non-pointer can't escape from a struct.
2361 if (!e
->type()->has_pointer())
2366 case Expression::EXPRESSION_TYPE_GUARD
:
2367 case Expression::EXPRESSION_ARRAY_INDEX
:
2368 case Expression::EXPRESSION_STRING_INDEX
:
2370 Expression
* left
= NULL
;
2371 if (e
->field_reference_expression() != NULL
)
2373 left
= e
->field_reference_expression()->expr();
2374 if (left
->unary_expression() != NULL
2375 && left
->unary_expression()->op() == OPERATOR_MULT
)
2378 this->flows(dst
, src
);
2382 else if (e
->type_guard_expression() != NULL
)
2383 left
= e
->type_guard_expression()->expr();
2384 else if (e
->array_index_expression() != NULL
)
2386 Array_index_expression
* aie
= e
->array_index_expression();
2387 if (aie
->end() != NULL
)
2389 if (aie
->array()->type()->is_slice_type())
2390 left
= aie
->array();
2394 // The gc compiler has an implicit address operator.
2395 go_assert(src
->child() != NULL
);
2396 this->assign(dst
, src
->child());
2399 else if (!aie
->array()->type()->is_slice_type())
2401 // Indexing an array preserves the input value.
2402 Node
* array_node
= Node::make_node(aie
->array());
2403 this->assign(dst
, array_node
);
2408 this->flows(dst
, src
);
2412 else if (e
->string_index_expression() != NULL
)
2414 String_index_expression
* sie
= e
->string_index_expression();
2415 if (e
->type()->is_string_type())
2417 left
= sie
->string();
2420 this->flows(dst
, src
);
2424 go_assert(left
!= NULL
);
2426 // Conversions, field access, and slicing all preserve the input
2428 Node
* left_node
= Node::make_node(left
);
2429 this->assign(dst
, left_node
);
2433 case Expression::EXPRESSION_BINARY
:
2435 switch (e
->binary_expression()->op())
2438 case OPERATOR_MINUS
:
2444 case OPERATOR_LSHIFT
:
2445 case OPERATOR_RSHIFT
:
2447 case OPERATOR_BITCLEAR
:
2449 Node
* left
= Node::make_node(e
->binary_expression()->left());
2450 this->assign(dst
, left
);
2451 Node
* right
= Node::make_node(e
->binary_expression()->right());
2452 this->assign(dst
, right
);
2462 case Expression::EXPRESSION_UNARY
:
2464 switch (e
->unary_expression()->op())
2467 case OPERATOR_MINUS
:
2471 Node::make_node(e
->unary_expression()->operand());
2472 this->assign(dst
, op_node
);
2480 this->flows(dst
, src
);
2489 case Expression::EXPRESSION_TEMPORARY_REFERENCE
:
2491 Statement
* temp
= e
->temporary_reference_expression()->statement();
2492 this->assign(dst
, Node::make_node(temp
));
2497 // TODO(cmang): Add debug info here; this should not be reachable.
2498 // For now, just to be conservative, we'll just say dst flows to src.
2502 else if (src
->statement() != NULL
&& src
->statement()->temporary_statement() != NULL
)
2503 this->flows(dst
, src
);
2506 // Model the assignment of DST to an indirection of SRC.
2509 Escape_analysis_assign::assign_deref(Node
* dst
, Node
* src
)
2511 if (src
->expr() != NULL
)
2513 switch (src
->expr()->classification())
2515 case Expression::EXPRESSION_BOOLEAN
:
2516 case Expression::EXPRESSION_STRING
:
2517 case Expression::EXPRESSION_INTEGER
:
2518 case Expression::EXPRESSION_FLOAT
:
2519 case Expression::EXPRESSION_COMPLEX
:
2520 case Expression::EXPRESSION_NIL
:
2521 case Expression::EXPRESSION_IOTA
:
2522 // No need to try indirections on literal values
2523 // or numeric constants.
2531 this->assign(dst
, this->context_
->add_dereference(src
));
2534 // Model the input-to-output assignment flow of one of a function call's
2535 // arguments, where the flow is encoded in NOTE.
2538 Escape_analysis_assign::assign_from_note(std::string
* note
,
2539 const std::vector
<Node
*>& dsts
,
2542 int enc
= Escape_note::parse_tag(note
);
2543 if (src
->expr() != NULL
)
2545 switch (src
->expr()->classification())
2547 case Expression::EXPRESSION_BOOLEAN
:
2548 case Expression::EXPRESSION_STRING
:
2549 case Expression::EXPRESSION_INTEGER
:
2550 case Expression::EXPRESSION_FLOAT
:
2551 case Expression::EXPRESSION_COMPLEX
:
2552 case Expression::EXPRESSION_NIL
:
2553 case Expression::EXPRESSION_IOTA
:
2554 // There probably isn't a note for a literal value. Literal values
2555 // usually don't escape unless we lost track of the value some how.
2563 if (this->context_
->gogo()->debug_escape_level() > 2)
2564 go_inform(src
->location(), "assignfromtag:: src=%s em=%s",
2565 src
->ast_format(context_
->gogo()).c_str(),
2566 Escape_note::make_tag(enc
).c_str());
2568 if (enc
== Node::ESCAPE_UNKNOWN
)
2570 // Lost track of the value.
2571 this->assign(this->context_
->sink(), src
);
2574 else if (enc
== Node::ESCAPE_NONE
)
2577 // If the content inside a parameter (reached via indirection) escapes to
2578 // the heap, mark it.
2579 if ((enc
& ESCAPE_CONTENT_ESCAPES
) != 0)
2580 this->assign(this->context_
->sink(), this->context_
->add_dereference(src
));
2583 enc
>>= ESCAPE_RETURN_BITS
;
2584 for (std::vector
<Node
*>::const_iterator p
= dsts
.begin();
2585 enc
!= 0 && p
!= dsts
.end();
2588 // Prefer the lowest-level path to the reference (for escape purposes).
2589 // Two-bit encoding (for example. 1, 3, and 4 bits are other options)
2591 // 10 = 1-level, (content escapes),
2592 // 11 = 2-level, (content of content escapes).
2593 int bits
= enc
& ESCAPE_BITS_MASK_FOR_TAG
;
2597 for (int i
= 0; i
< bits
- 1; ++i
)
2599 // Encode level > 0 as indirections.
2600 n
= this->context_
->add_dereference(n
);
2602 this->assign(*p
, n
);
2604 enc
>>= ESCAPE_BITS_PER_OUTPUT_IN_TAG
;
2607 // If there are too many outputs to fit in the tag, that is handled on the
2608 // encoding end as ESCAPE_HEAP, so there is no need to check here.
2612 // Record the flow of SRC to DST in DST.
2615 Escape_analysis_assign::flows(Node
* dst
, Node
* src
)
2617 // Don't bother capturing the flow from scalars.
2618 if (src
->type() != NULL
&& !src
->type()->has_pointer())
2621 // Don't confuse a blank identifier with the sink.
2622 if (dst
->is_sink() && dst
!= this->context_
->sink())
2625 Node::Escape_state
* dst_state
= dst
->state(this->context_
, NULL
);
2626 Node::Escape_state
* src_state
= src
->state(this->context_
, NULL
);
2628 || dst_state
== src_state
2629 || dst_state
->flows
.find(src
) != dst_state
->flows
.end())
2632 Gogo
* gogo
= this->context_
->gogo();
2633 if (gogo
->debug_escape_level() > 2)
2634 go_inform(Linemap::unknown_location(), "flows:: %s <- %s",
2635 dst
->ast_format(gogo
).c_str(), src
->ast_format(gogo
).c_str());
2637 if (dst_state
->flows
.empty())
2638 this->context_
->add_dst(dst
);
2640 dst_state
->flows
.insert(src
);
2643 // Build a connectivity graph between nodes in the function being analyzed.
2646 Gogo::assign_connectivity(Escape_context
* context
, Named_object
* fn
)
2648 // Must be defined outside of this package.
2649 if (!fn
->is_function())
2652 int save_depth
= context
->loop_depth();
2653 context
->set_loop_depth(1);
2655 Escape_analysis_assign
ea(context
, fn
);
2656 Function::Results
* res
= fn
->func_value()->result_variables();
2659 for (Function::Results::const_iterator p
= res
->begin();
2663 Node
* res_node
= Node::make_node(*p
);
2664 Node::Escape_state
* res_state
= res_node
->state(context
, fn
);
2666 res_state
->loop_depth
= 0;
2668 // If this set of functions is recursive, we lose track of the return values.
2669 // Just say that the result flows to the sink.
2670 if (context
->recursive())
2671 ea
.flows(context
->sink(), res_node
);
2675 const Bindings
* callee_bindings
= fn
->func_value()->block()->bindings();
2676 Function_type
* fntype
= fn
->func_value()->type();
2677 Typed_identifier_list
* params
= (fntype
->parameters() != NULL
2678 ? fntype
->parameters()->copy()
2679 : new Typed_identifier_list
);
2680 if (fntype
->receiver() != NULL
)
2681 params
->push_back(*fntype
->receiver());
2683 for (Typed_identifier_list::const_iterator p
= params
->begin();
2687 if (p
->name().empty() || Gogo::is_sink_name(p
->name()))
2690 Named_object
* param_no
= callee_bindings
->lookup_local(p
->name());
2691 go_assert(param_no
!= NULL
);
2692 Node
* param_node
= Node::make_node(param_no
);
2693 Node::Escape_state
* param_state
= param_node
->state(context
, fn
);
2694 param_state
->fn
= fn
;
2695 param_state
->loop_depth
= 1;
2697 if (!p
->type()->has_pointer())
2700 // External function? Parameters must escape unless //go:noescape is set.
2701 // TODO(cmang): Implement //go:noescape directive.
2702 if (fn
->package() != NULL
)
2703 param_node
->set_encoding(Node::ESCAPE_HEAP
);
2706 param_node
->set_encoding(Node::ESCAPE_NONE
);
2707 context
->track(param_node
);
2711 Escape_analysis_loop el
;
2712 fn
->func_value()->traverse(&el
);
2714 fn
->func_value()->traverse(&ea
);
2715 context
->set_loop_depth(save_depth
);
2718 class Escape_analysis_flood
2721 Escape_analysis_flood(Escape_context
* context
)
2725 // Use the escape information in dst to update the escape information in src
2726 // and src's upstream.
2728 flood(Level
, Node
* dst
, Node
* src
, int);
2731 // The escape context for the group of functions being flooded.
2732 Escape_context
* context_
;
2735 // Whenever we hit a dereference node, the level goes up by one, and whenever
2736 // we hit an address-of, the level goes down by one. as long as we're on a
2737 // level > 0 finding an address-of just means we're following the upstream
2738 // of a dereference, so this address doesn't leak (yet).
2739 // If level == 0, it means the /value/ of this node can reach the root of this
2740 // flood so if this node is an address-of, its argument should be marked as
2741 // escaping iff its current function and loop depth are different from the
2743 // Once an object has been moved to the heap, all of its upstream should be
2744 // considered escaping to the global scope.
2745 // This is an implementation of gc/esc.go:escwalkBody.
2748 Escape_analysis_flood::flood(Level level
, Node
* dst
, Node
* src
,
2749 int extra_loop_depth
)
2751 // No need to flood src if it is a literal.
2752 if (src
->expr() != NULL
)
2754 switch (src
->expr()->classification())
2756 case Expression::EXPRESSION_BOOLEAN
:
2757 case Expression::EXPRESSION_STRING
:
2758 case Expression::EXPRESSION_INTEGER
:
2759 case Expression::EXPRESSION_FLOAT
:
2760 case Expression::EXPRESSION_COMPLEX
:
2761 case Expression::EXPRESSION_NIL
:
2762 case Expression::EXPRESSION_IOTA
:
2770 Node::Escape_state
* src_state
= src
->state(this->context_
, NULL
);
2771 if (src_state
->flood_id
== this->context_
->flood_id())
2773 // Esclevels are vectors, do not compare as integers,
2774 // and must use "min" of old and new to guarantee
2776 level
= level
.min(src_state
->level
);
2777 if (level
== src_state
->level
)
2779 // Have we been here already with an extraloopdepth,
2780 // or is the extraloopdepth provided no improvement on
2781 // what's already been seen?
2782 if (src_state
->max_extra_loop_depth
>= extra_loop_depth
2783 || src_state
->loop_depth
>= extra_loop_depth
)
2785 src_state
->max_extra_loop_depth
= extra_loop_depth
;
2789 src_state
->max_extra_loop_depth
= -1;
2791 src_state
->flood_id
= this->context_
->flood_id();
2792 src_state
->level
= level
;
2793 int mod_loop_depth
= std::max(extra_loop_depth
, src_state
->loop_depth
);
2795 Gogo
* gogo
= this->context_
->gogo();
2796 int debug_level
= gogo
->debug_escape_level();
2797 if (debug_level
> 1)
2798 go_inform(Linemap::unknown_location(),
2799 "escwalk: level:{%d %d} depth:%d "
2802 "extraloopdepth=%d",
2803 level
.value(), level
.suffix_value(), this->context_
->pdepth(),
2804 src
->op_format().c_str(),
2805 src
->ast_format(gogo
).c_str(),
2806 src
->details().c_str(),
2807 debug_function_name(src_state
->fn
).c_str(),
2808 src_state
->loop_depth
,
2811 this->context_
->increase_pdepth();
2813 // Input parameter flowing into output parameter?
2814 Named_object
* src_no
= NULL
;
2815 if (src
->expr() != NULL
&& src
->expr()->var_expression() != NULL
)
2816 src_no
= src
->expr()->var_expression()->named_object();
2818 src_no
= src
->object();
2819 bool src_is_param
= (src_no
!= NULL
2820 && src_no
->is_variable()
2821 && src_no
->var_value()->is_parameter());
2823 Named_object
* dst_no
= NULL
;
2824 if (dst
->expr() != NULL
&& dst
->expr()->var_expression() != NULL
)
2825 dst_no
= dst
->expr()->var_expression()->named_object();
2827 dst_no
= dst
->object();
2828 bool dst_is_result
= dst_no
!= NULL
&& dst_no
->is_result_variable();
2829 Node::Escape_state
* dst_state
= dst
->state(this->context_
, NULL
);
2833 && src_state
->fn
== dst_state
->fn
2834 && (src
->encoding() & ESCAPE_MASK
) < int(Node::ESCAPE_HEAP
)
2835 && dst
->encoding() != Node::ESCAPE_HEAP
)
2837 // This case handles:
2840 // 3. tmp := in; return &tmp
2842 if (debug_level
!= 0)
2844 if (debug_level
== 1)
2845 go_inform(src
->definition_location(),
2846 "leaking param: %s to result %s level=%d",
2847 src
->ast_format(gogo
).c_str(),
2848 dst
->ast_format(gogo
).c_str(),
2851 go_inform(src
->definition_location(),
2852 "leaking param: %s to result %s level={%d %d}",
2853 src
->ast_format(gogo
).c_str(),
2854 dst
->ast_format(gogo
).c_str(),
2855 level
.value(), level
.suffix_value());
2858 if ((src
->encoding() & ESCAPE_MASK
) != Node::ESCAPE_RETURN
)
2861 Node::ESCAPE_RETURN
| (src
->encoding() & ESCAPE_CONTENT_ESCAPES
);
2862 src
->set_encoding(enc
);
2865 int enc
= Node::note_inout_flows(src
->encoding(),
2866 dst_no
->result_var_value()->index(),
2868 src
->set_encoding(enc
);
2870 // In gc/esc.go:escwalkBody, this is a goto to the label for recursively
2871 // flooding the connection graph. Inlined here for convenience.
2872 level
= level
.copy();
2873 for (std::set
<Node
*>::const_iterator p
= src_state
->flows
.begin();
2874 p
!= src_state
->flows
.end();
2876 this->flood(level
, dst
, *p
, extra_loop_depth
);
2880 // If parameter content escape to heap, set ESCAPE_CONTENT_ESCAPES.
2881 // Note minor confusion around escape from pointer-to-struct vs
2882 // escape from struct.
2884 && dst
->encoding() == Node::ESCAPE_HEAP
2885 && (src
->encoding() & ESCAPE_MASK
) < int(Node::ESCAPE_HEAP
)
2886 && level
.value() > 0)
2889 Node::max_encoding((src
->encoding() | ESCAPE_CONTENT_ESCAPES
),
2891 src
->set_encoding(enc
);
2892 if (debug_level
!= 0)
2893 go_inform(src
->definition_location(), "mark escaped content: %s",
2894 src
->ast_format(gogo
).c_str());
2897 // A src object leaks if its value or address is assigned to a dst object
2898 // in a different scope (at a different loop depth).
2899 bool src_leaks
= (level
.value() <= 0
2900 && level
.suffix_value() <= 0
2901 && dst_state
->loop_depth
< mod_loop_depth
);
2902 src_leaks
= src_leaks
|| (level
.value() <= 0
2903 && (dst
->encoding() & ESCAPE_MASK
) == Node::ESCAPE_HEAP
);
2904 // old src encoding, used to prevent duplicate error messages
2905 int osrcesc
= src
->encoding();
2908 && (src_leaks
|| dst_state
->loop_depth
< 0)
2909 && (src
->encoding() & ESCAPE_MASK
) < int(Node::ESCAPE_HEAP
))
2911 if (level
.suffix_value() > 0)
2914 Node::max_encoding((src
->encoding() | ESCAPE_CONTENT_ESCAPES
),
2916 src
->set_encoding(enc
);
2917 if (debug_level
!= 0 && osrcesc
!= src
->encoding())
2918 go_inform(src
->definition_location(), "leaking param content: %s",
2919 src
->ast_format(gogo
).c_str());
2923 if (debug_level
!= 0)
2924 go_inform(src
->definition_location(), "leaking param: %s",
2925 src
->ast_format(gogo
).c_str());
2926 src
->set_encoding(Node::ESCAPE_HEAP
);
2929 else if (src
->expr() != NULL
)
2931 Expression
* e
= src
->expr();
2932 if (e
->enclosed_var_expression() != NULL
)
2934 if (src_leaks
&& debug_level
!= 0)
2935 go_inform(src
->location(), "leaking closure reference %s",
2936 src
->ast_format(gogo
).c_str());
2938 Node
* enclosed_node
=
2939 Node::make_node(e
->enclosed_var_expression()->variable());
2940 this->flood(level
, dst
, enclosed_node
, -1);
2942 else if (e
->heap_expression() != NULL
2943 || (e
->unary_expression() != NULL
2944 && e
->unary_expression()->op() == OPERATOR_AND
))
2946 // Pointer literals and address-of expressions.
2947 Expression
* underlying
;
2948 if (e
->heap_expression())
2949 underlying
= e
->heap_expression()->expr();
2951 underlying
= e
->unary_expression()->operand();
2952 Node
* underlying_node
= Node::make_node(underlying
);
2954 // If the address leaks, the underyling object must be moved
2956 underlying
->address_taken(src_leaks
);
2959 src
->set_encoding(Node::ESCAPE_HEAP
);
2960 if (debug_level
!= 0 && osrcesc
!= src
->encoding())
2962 if (underlying
->var_expression() != NULL
2963 || underlying
->enclosed_var_expression() != NULL
)
2964 go_inform(underlying_node
->definition_location(),
2965 "moved to heap: %s",
2966 underlying_node
->ast_format(gogo
).c_str());
2968 if (debug_level
> 1)
2969 go_inform(src
->location(),
2970 "%s escapes to heap, level={%d %d}, "
2971 "dst.eld=%d, src.eld=%d",
2972 src
->ast_format(gogo
).c_str(), level
.value(),
2973 level
.suffix_value(), dst_state
->loop_depth
,
2976 go_inform(src
->location(), "%s escapes to heap",
2977 src
->ast_format(gogo
).c_str());
2980 this->flood(level
.decrease(), dst
,
2981 underlying_node
, mod_loop_depth
);
2982 extra_loop_depth
= mod_loop_depth
;
2986 // Decrease the level each time we take the address of the object.
2987 this->flood(level
.decrease(), dst
, underlying_node
, -1);
2990 else if (e
->slice_literal() != NULL
)
2992 Slice_construction_expression
* slice
= e
->slice_literal();
2993 if (slice
->vals() != NULL
)
2995 for (Expression_list::const_iterator p
= slice
->vals()->begin();
2996 p
!= slice
->vals()->end();
3000 this->flood(level
.decrease(), dst
, Node::make_node(*p
), -1);
3005 src
->set_encoding(Node::ESCAPE_HEAP
);
3006 if (debug_level
!= 0 && osrcesc
!= src
->encoding())
3007 go_inform(src
->location(), "%s escapes to heap",
3008 src
->ast_format(gogo
).c_str());
3009 extra_loop_depth
= mod_loop_depth
;
3012 else if (e
->call_expression() != NULL
)
3014 Call_expression
* call
= e
->call_expression();
3015 if (call
->is_builtin())
3017 Builtin_call_expression
* bce
= call
->builtin_call_expression();
3018 if (bce
->code() == Builtin_call_expression::BUILTIN_APPEND
)
3020 // Propagate escape information to appendee.
3021 Expression
* appendee
= call
->args()->front();
3022 this->flood(level
, dst
, Node::make_node(appendee
), -1);
3025 else if (call
->fn()->func_expression() != NULL
3026 && call
->fn()->func_expression()->is_runtime_function())
3028 switch (call
->fn()->func_expression()->runtime_code())
3030 case Runtime::MAKECHAN
:
3031 case Runtime::MAKEMAP
:
3032 case Runtime::MAKESLICE
:
3033 case Runtime::MAKESLICE64
:
3036 src
->set_encoding(Node::ESCAPE_HEAP
);
3037 if (debug_level
!= 0 && osrcesc
!= src
->encoding())
3038 go_inform(src
->location(), "%s escapes to heap",
3039 src
->ast_format(gogo
).c_str());
3040 extra_loop_depth
= mod_loop_depth
;
3048 else if (src_state
->retvals
.size() > 0)
3050 // In this case a link went directly to a call, but should really go
3051 // to the dummy .outN outputs that were created for the call that
3052 // themselves link to the inputs with levels adjusted.
3054 // This can only happen with functions returning a single result.
3055 go_assert(src_state
->retvals
.size() == 1);
3056 if (debug_level
> 2)
3057 go_inform(src
->location(), "[%d] dst %s escwalk replace src: %s with %s",
3058 this->context_
->loop_depth(),
3059 dst
->ast_format(gogo
).c_str(),
3060 src
->ast_format(gogo
).c_str(),
3061 src_state
->retvals
[0]->ast_format(gogo
).c_str());
3062 src
= src_state
->retvals
[0];
3063 src_state
= src
->state(this->context_
, NULL
);
3066 else if (e
->allocation_expression() != NULL
&& src_leaks
)
3068 // Calls to Runtime::NEW get lowered into an allocation expression.
3069 src
->set_encoding(Node::ESCAPE_HEAP
);
3070 if (debug_level
!= 0 && osrcesc
!= src
->encoding())
3071 go_inform(src
->location(), "%s escapes to heap",
3072 src
->ast_format(gogo
).c_str());
3073 extra_loop_depth
= mod_loop_depth
;
3075 else if ((e
->map_literal() != NULL
3076 || e
->string_concat_expression() != NULL
3077 || (e
->func_expression() != NULL
&& e
->func_expression()->closure() != NULL
)
3078 || e
->bound_method_expression() != NULL
)
3081 src
->set_encoding(Node::ESCAPE_HEAP
);
3082 if (debug_level
!= 0 && osrcesc
!= src
->encoding())
3083 go_inform(src
->location(), "%s escapes to heap",
3084 src
->ast_format(gogo
).c_str());
3085 extra_loop_depth
= mod_loop_depth
;
3087 else if (e
->conversion_expression() != NULL
&& src_leaks
)
3089 Type_conversion_expression
* tce
= e
->conversion_expression();
3090 Type
* ft
= tce
->expr()->type();
3091 Type
* tt
= tce
->type();
3092 if ((ft
->is_string_type() && tt
->is_slice_type())
3093 || (ft
->is_slice_type() && tt
->is_string_type())
3094 || (ft
->integer_type() != NULL
&& tt
->is_string_type()))
3096 // string([]byte), string([]rune), []byte(string), []rune(string), string(rune)
3097 src
->set_encoding(Node::ESCAPE_HEAP
);
3098 if (debug_level
!= 0 && osrcesc
!= src
->encoding())
3099 go_inform(src
->location(), "%s escapes to heap",
3100 src
->ast_format(gogo
).c_str());
3101 extra_loop_depth
= mod_loop_depth
;
3104 else if (e
->array_index_expression() != NULL
3105 && !e
->array_index_expression()->array()->type()->is_slice_type())
3107 Array_index_expression
* aie
= e
->array_index_expression();
3108 if (aie
->end() != NULL
)
3110 // Slicing an array.
3111 // Flow its implicit address-of node to DST.
3112 this->flood(level
, dst
, src
->child(), -1);
3116 // Indexing an array.
3117 // An array element flowing to DST behaves like the array
3119 Expression
* underlying
= e
->array_index_expression()->array();
3120 Node
* underlying_node
= Node::make_node(underlying
);
3121 this->flood(level
, dst
, underlying_node
, -1);
3124 else if ((e
->field_reference_expression() != NULL
3125 && e
->field_reference_expression()->expr()->unary_expression() == NULL
)
3126 || e
->type_guard_expression() != NULL
3127 || (e
->array_index_expression() != NULL
3128 && e
->array_index_expression()->end() != NULL
)
3129 || (e
->string_index_expression() != NULL
3130 && e
->type()->is_string_type()))
3132 Expression
* underlying
;
3133 if (e
->field_reference_expression() != NULL
)
3134 underlying
= e
->field_reference_expression()->expr();
3135 else if (e
->type_guard_expression() != NULL
)
3136 underlying
= e
->type_guard_expression()->expr();
3137 else if (e
->array_index_expression() != NULL
)
3138 underlying
= e
->array_index_expression()->array();
3140 underlying
= e
->string_index_expression()->string();
3142 Node
* underlying_node
= Node::make_node(underlying
);
3143 this->flood(level
, dst
, underlying_node
, -1);
3145 else if ((e
->field_reference_expression() != NULL
3146 && e
->field_reference_expression()->expr()->unary_expression() != NULL
)
3147 || e
->array_index_expression() != NULL
3148 || e
->map_index_expression() != NULL
3149 || (e
->unary_expression() != NULL
3150 && e
->unary_expression()->op() == OPERATOR_MULT
))
3152 Expression
* underlying
;
3153 if (e
->field_reference_expression() != NULL
)
3155 underlying
= e
->field_reference_expression()->expr();
3156 underlying
= underlying
->unary_expression()->operand();
3158 else if (e
->array_index_expression() != NULL
)
3159 underlying
= e
->array_index_expression()->array();
3160 else if (e
->map_index_expression() != NULL
)
3161 underlying
= e
->map_index_expression()->map();
3163 underlying
= e
->unary_expression()->operand();
3165 // Increase the level for a dereference.
3166 Node
* underlying_node
= Node::make_node(underlying
);
3167 this->flood(level
.increase(), dst
, underlying_node
, -1);
3169 else if (e
->temporary_reference_expression() != NULL
)
3171 Statement
* t
= e
->temporary_reference_expression()->statement();
3172 this->flood(level
, dst
, Node::make_node(t
), -1);
3175 else if (src
->is_indirect())
3176 // Increase the level for a dereference.
3177 this->flood(level
.increase(), dst
, src
->child(), -1);
3179 level
= level
.copy();
3180 for (std::set
<Node
*>::const_iterator p
= src_state
->flows
.begin();
3181 p
!= src_state
->flows
.end();
3183 this->flood(level
, dst
, *p
, extra_loop_depth
);
3185 this->context_
->decrease_pdepth();
3188 // Propagate escape information across the nodes modeled in this Analysis_set.
3189 // This is an implementation of gc/esc.go:escflood.
3192 Gogo::propagate_escape(Escape_context
* context
, Node
* dst
)
3194 if (dst
->object() == NULL
3195 && (dst
->expr() == NULL
3196 || (dst
->expr()->var_expression() == NULL
3197 && dst
->expr()->enclosed_var_expression() == NULL
3198 && dst
->expr()->func_expression() == NULL
)))
3201 Node::Escape_state
* state
= dst
->state(context
, NULL
);
3202 Gogo
* gogo
= context
->gogo();
3203 if (gogo
->debug_escape_level() > 1)
3204 go_inform(Linemap::unknown_location(), "escflood:%d: dst %s scope:%s[%d]",
3205 context
->flood_id(), dst
->ast_format(gogo
).c_str(),
3206 debug_function_name(state
->fn
).c_str(),
3209 Escape_analysis_flood
eaf(context
);
3210 for (std::set
<Node
*>::const_iterator p
= state
->flows
.begin();
3211 p
!= state
->flows
.end();
3214 context
->increase_flood_id();
3215 eaf
.flood(Level::From(0), dst
, *p
, -1);
3219 class Escape_analysis_tag
3222 Escape_analysis_tag(Escape_context
* context
)
3226 // Add notes to the function's type about the escape information of its
3227 // input parameters.
3229 tag(Named_object
* fn
);
3232 Escape_context
* context_
;
3236 Escape_analysis_tag::tag(Named_object
* fn
)
3238 // External functions are assumed unsafe
3239 // unless //go:noescape is given before the declaration.
3240 if (fn
->package() != NULL
)
3243 if (fn
->is_function_declaration())
3245 Function_declaration
* fdcl
= fn
->func_declaration_value();
3246 if ((fdcl
->pragmas() & GOPRAGMA_NOESCAPE
) != 0)
3248 Function_type
* fntype
= fdcl
->type();
3249 if (fntype
->parameters() != NULL
)
3251 const Typed_identifier_list
* til
= fntype
->parameters();
3253 for (Typed_identifier_list::const_iterator p
= til
->begin();
3256 if (p
->type()->has_pointer())
3257 fntype
->add_parameter_note(i
, Node::ESCAPE_NONE
);
3262 if (!fn
->is_function())
3265 Function_type
* fntype
= fn
->func_value()->type();
3266 Bindings
* bindings
= fn
->func_value()->block()->bindings();
3268 if (fntype
->is_method()
3269 && !fntype
->receiver()->name().empty()
3270 && !Gogo::is_sink_name(fntype
->receiver()->name()))
3272 Named_object
* rcvr_no
= bindings
->lookup(fntype
->receiver()->name());
3273 go_assert(rcvr_no
!= NULL
);
3274 Node
* rcvr_node
= Node::make_node(rcvr_no
);
3275 switch ((rcvr_node
->encoding() & ESCAPE_MASK
))
3277 case Node::ESCAPE_NONE
: // not touched by flood
3278 case Node::ESCAPE_RETURN
:
3279 if (fntype
->receiver()->type()->has_pointer())
3280 // Don't bother tagging for scalars.
3281 fntype
->add_receiver_note(rcvr_node
->encoding());
3284 case Node::ESCAPE_HEAP
: // flooded, moved to heap.
3293 if (fntype
->parameters() != NULL
)
3295 const Typed_identifier_list
* til
= fntype
->parameters();
3296 for (Typed_identifier_list::const_iterator p
= til
->begin();
3300 if (p
->name().empty() || Gogo::is_sink_name(p
->name()))
3302 // Parameter not used in the function body, does not escape.
3303 if (p
->type()->has_pointer())
3304 fntype
->add_parameter_note(i
, Node::ESCAPE_NONE
);
3308 Named_object
* param_no
= bindings
->lookup(p
->name());
3309 go_assert(param_no
!= NULL
);
3310 Node
* param_node
= Node::make_node(param_no
);
3311 switch ((param_node
->encoding() & ESCAPE_MASK
))
3313 case Node::ESCAPE_NONE
: // not touched by flood
3314 case Node::ESCAPE_RETURN
:
3315 if (p
->type()->has_pointer())
3316 // Don't bother tagging for scalars.
3317 fntype
->add_parameter_note(i
, param_node
->encoding());
3320 case Node::ESCAPE_HEAP
: // flooded, moved to heap.
3328 fntype
->set_is_tagged();
3331 // Tag each top-level function with escape information that will be used to
3332 // retain analysis results across imports.
3335 Gogo::tag_function(Escape_context
* context
, Named_object
* fn
)
3337 Escape_analysis_tag
eat(context
);