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";
134 ss
<< no
->message_name();
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::MAKECHAN64
:
364 case Runtime::MAKEMAP
:
365 case Runtime::MAKESLICE
:
366 case Runtime::MAKESLICE64
:
370 case Runtime::DEFERPROC
:
374 case Runtime::GORECOVER
:
388 case Expression::EXPRESSION_ALLOCATION
:
392 case Expression::EXPRESSION_RECEIVE
:
401 if (this->statement() != NULL
)
403 switch (this->statement()->classification())
405 case Statement::STATEMENT_DEFER
:
409 case Statement::STATEMENT_RETURN
:
417 if (this->is_indirect())
422 // Return this node's state, creating it if has not been initialized.
425 Node::state(Escape_context
* context
, Named_object
* fn
)
427 if (this->state_
== NULL
)
429 if (this->expr() != NULL
&& this->expr()->var_expression() != NULL
)
431 // Tie state of variable references to underlying variables.
432 Named_object
* var_no
= this->expr()->var_expression()->named_object();
433 Node
* var_node
= Node::make_node(var_no
);
434 this->state_
= var_node
->state(context
, fn
);
438 this->state_
= new Node::Escape_state
;
440 fn
= context
->current_function();
442 this->state_
->fn
= fn
;
445 go_assert(this->state_
!= NULL
);
451 if (this->state_
!= NULL
)
453 if (this->expr() == NULL
|| this->expr()->var_expression() == NULL
)
454 // Var expression Node is excluded since it shares state with the
455 // underlying var Node.
463 if (this->expr() != NULL
464 && this->expr()->var_expression() != NULL
)
466 // Get the underlying object's encoding.
467 Named_object
* no
= this->expr()->var_expression()->named_object();
468 int enc
= Node::make_node(no
)->encoding();
469 this->encoding_
= enc
;
471 return this->encoding_
;
475 Node::set_encoding(int enc
)
477 this->encoding_
= enc
;
478 if (this->expr() != NULL
)
480 if (this->expr()->var_expression() != NULL
)
482 // Set underlying object as well.
483 Named_object
* no
= this->expr()->var_expression()->named_object();
484 Node::make_node(no
)->set_encoding(enc
);
486 else if (this->expr()->func_expression() != NULL
)
488 // Propagate the escape state to the underlying
489 // closure (heap expression).
490 Expression
* closure
= this->expr()->func_expression()->closure();
492 Node::make_node(closure
)->set_encoding(enc
);
498 Node::is_big(Escape_context
* context
) const
500 Type
* t
= this->type();
502 || t
->is_call_multiple_result_type()
509 bool ok
= t
->backend_type_size(context
->gogo(), &size
);
510 bool big
= ok
&& (size
< 0 || size
> 10 * 1024 * 1024);
512 if (this->expr() != NULL
)
514 if (this->expr()->allocation_expression() != NULL
)
516 ok
= t
->deref()->backend_type_size(context
->gogo(), &size
);
517 big
= big
|| size
<= 0 || size
>= (1 << 16);
519 else if (this->expr()->call_expression() != NULL
)
521 Call_expression
* call
= this->expr()->call_expression();
522 Func_expression
* fn
= call
->fn()->func_expression();
524 && fn
->is_runtime_function()
525 && (fn
->runtime_code() == Runtime::MAKESLICE
526 || fn
->runtime_code() == Runtime::MAKESLICE64
))
528 // Second argument is length.
529 Expression_list::iterator p
= call
->args()->begin();
533 if (e
->temporary_reference_expression() != NULL
)
535 Temporary_reference_expression
* tre
= e
->temporary_reference_expression();
536 if (tre
->statement() != NULL
&& tre
->statement()->init() != NULL
)
537 e
= tre
->statement()->init();
542 if (e
->numeric_constant_value(&nc
)
543 && nc
.to_unsigned_long(&v
) == Numeric_constant::NC_UL_VALID
)
544 big
= big
|| v
>= (1 << 16);
553 Node::is_sink() const
555 if (this->object() != NULL
556 && this->object()->is_sink())
558 else if (this->expr() != NULL
559 && this->expr()->is_sink_expression())
564 std::map
<Named_object
*, Node
*> Node::objects
;
565 std::map
<Expression
*, Node
*> Node::expressions
;
566 std::map
<Statement
*, Node
*> Node::statements
;
567 std::vector
<Node
*> Node::indirects
;
569 // Make a object node or return a cached node for this object.
572 Node::make_node(Named_object
* no
)
574 if (Node::objects
.find(no
) != Node::objects
.end())
575 return Node::objects
[no
];
577 Node
* n
= new Node(no
);
578 std::pair
<Named_object
*, Node
*> val(no
, n
);
579 Node::objects
.insert(val
);
583 // Make an expression node or return a cached node for this expression.
586 Node::make_node(Expression
* e
)
588 if (Node::expressions
.find(e
) != Node::expressions
.end())
589 return Node::expressions
[e
];
591 Node
* n
= new Node(e
);
592 std::pair
<Expression
*, Node
*> val(e
, n
);
593 Node::expressions
.insert(val
);
597 // Make a statement node or return a cached node for this statement.
600 Node::make_node(Statement
* s
)
602 if (Node::statements
.find(s
) != Node::statements
.end())
603 return Node::statements
[s
];
605 Node
* n
= new Node(s
);
606 std::pair
<Statement
*, Node
*> val(s
, n
);
607 Node::statements
.insert(val
);
611 // Make an indirect node with given child.
614 Node::make_indirect_node(Node
* child
)
616 Node
* n
= new Node(child
);
617 Node::indirects
.push_back(n
);
621 // Returns the maximum of an exisiting escape value
622 // (and its additional parameter flow flags) and a new escape type.
625 Node::max_encoding(int e
, int etype
)
627 if ((e
& ESCAPE_MASK
) > etype
)
629 if (etype
== Node::ESCAPE_NONE
|| etype
== Node::ESCAPE_RETURN
)
630 return (e
& ~ESCAPE_MASK
) | etype
;
634 // Return a modified encoding for an input parameter that flows into an
638 Node::note_inout_flows(int e
, int index
, Level level
)
640 // Flow+level is encoded in two bits.
641 // 00 = not flow, xx = level+1 for 0 <= level <= maxEncodedLevel.
642 // 16 bits for Esc allows 6x2bits or 4x3bits or 3x4bits if additional
643 // information would be useful.
644 if (level
.value() <= 0 && level
.suffix_value() > 0)
645 return Node::max_encoding(e
|ESCAPE_CONTENT_ESCAPES
, Node::ESCAPE_NONE
);
646 if (level
.value() < 0)
647 return Node::ESCAPE_HEAP
;
648 if (level
.value() > ESCAPE_MAX_ENCODED_LEVEL
)
649 level
= Level::From(ESCAPE_MAX_ENCODED_LEVEL
);
651 int encoded
= level
.value() + 1;
652 int shift
= ESCAPE_BITS_PER_OUTPUT_IN_TAG
* index
+ ESCAPE_RETURN_BITS
;
653 int old
= (e
>> shift
) & ESCAPE_BITS_MASK_FOR_TAG
;
655 || (encoded
!= 0 && encoded
< old
))
658 int encoded_flow
= old
<< shift
;
659 if (((encoded_flow
>> shift
) & ESCAPE_BITS_MASK_FOR_TAG
) != old
)
661 // Failed to encode. Put this on the heap.
662 return Node::ESCAPE_HEAP
;
665 return (e
& ~(ESCAPE_BITS_MASK_FOR_TAG
<< shift
)) | encoded_flow
;
668 // Class Escape_context.
670 Escape_context::Escape_context(Gogo
* gogo
, bool recursive
)
671 : gogo_(gogo
), current_function_(NULL
), recursive_(recursive
),
672 sink_(Node::make_node(Named_object::make_sink())), loop_depth_(0),
673 flood_id_(0), pdepth_(0)
675 // The sink always escapes to heap and strictly lives outside of the
676 // current function i.e. loop_depth == -1.
677 Node::Escape_state
* state
= this->sink_
->state(this, NULL
);
678 state
->loop_depth
= -1;
682 debug_function_name(Named_object
* fn
)
687 if (!fn
->is_function())
688 return Gogo::unpack_hidden_name(fn
->name());
690 std::string fnname
= Gogo::unpack_hidden_name(fn
->name());
691 if (fn
->func_value()->is_method())
693 // Methods in gc compiler are named "T.m" or "(*T).m" where
694 // T is the receiver type. Add the receiver here.
695 Type
* rt
= fn
->func_value()->type()->receiver()->type();
696 switch (rt
->classification())
698 case Type::TYPE_NAMED
:
699 fnname
= rt
->named_type()->name() + "." + fnname
;
702 case Type::TYPE_POINTER
:
704 Named_type
* nt
= rt
->points_to()->named_type();
706 fnname
= "(*" + nt
->name() + ")." + fnname
;
718 // Return the name of the current function.
721 Escape_context::current_function_name() const
723 return debug_function_name(this->current_function_
);
726 // Initialize the dummy return values for this Node N using the results
730 Escape_context::init_retvals(Node
* n
, Function_type
* fntype
)
732 if (fntype
== NULL
|| fntype
->results() == NULL
)
735 Node::Escape_state
* state
= n
->state(this, NULL
);
736 state
->retvals
.clear();
737 Location loc
= n
->location();
741 for (Typed_identifier_list::const_iterator p
= fntype
->results()->begin();
742 p
!= fntype
->results()->end();
745 snprintf(buf
, sizeof buf
, ".out%d", i
);
746 Variable
* dummy_var
= new Variable(p
->type(), NULL
, false, false,
748 dummy_var
->set_is_used();
749 Named_object
* dummy_no
=
750 Named_object::make_variable(buf
, NULL
, dummy_var
);
751 Node
* dummy_node
= Node::make_node(dummy_no
);
752 // Initialize the state of the dummy output node.
753 Node::Escape_state
* dummy_node_state
= dummy_node
->state(this, NULL
);
754 dummy_node_state
->loop_depth
= this->loop_depth_
;
756 // Add dummy node to the retvals of n.
757 state
->retvals
.push_back(dummy_node
);
762 // Apply an indirection to N and return the result.
765 Escape_context::add_dereference(Node
* n
)
767 Expression
* e
= n
->expr();
768 Location loc
= n
->location();
771 && e
->type()->points_to() != NULL
772 && !e
->type()->points_to()->is_void_type())
774 // We don't dereference void*, which can be actually any pointer type.
775 Expression
* deref_expr
= Expression::make_unary(OPERATOR_MULT
, e
, loc
);
776 ind
= Node::make_node(deref_expr
);
779 // The gc compiler simply makes an OIND node. We can't do it
780 // for non-pointer type because that will result in a type error.
781 // Instead, we model this by making a node with a special flavor.
782 ind
= Node::make_indirect_node(n
);
784 // Initialize the state.
785 Node::Escape_state
* state
= ind
->state(this, NULL
);
786 state
->loop_depth
= n
->state(this, NULL
)->loop_depth
;
791 Escape_context::track(Node
* n
)
793 n
->set_encoding(Node::ESCAPE_NONE
);
794 // Initialize this node's state if it hasn't been encountered
796 Node::Escape_state
* state
= n
->state(this, NULL
);
797 state
->loop_depth
= this->loop_depth_
;
799 this->noesc_
.push_back(n
);
802 // Return the string representation of an escapement encoding.
805 Escape_note::make_tag(int encoding
)
808 snprintf(buf
, sizeof buf
, "esc:0x%x", encoding
);
812 // Return the escapement encoding for a string tag.
815 Escape_note::parse_tag(std::string
* tag
)
817 if (tag
== NULL
|| tag
->substr(0, 4) != "esc:")
818 return Node::ESCAPE_UNKNOWN
;
819 int encoding
= (int)strtol(tag
->substr(4).c_str(), NULL
, 0);
821 return Node::ESCAPE_UNKNOWN
;
826 // The -fgo-optimize-alloc flag activates this escape analysis.
828 Go_optimize
optimize_allocation_flag("allocs", true);
830 // A helper function to compute whether a function name has a
831 // matching hash value.
834 escape_hash_match(std::string suffix
, std::string name
)
838 if (suffix
.at(0) == '-')
839 return !escape_hash_match(suffix
.substr(1), name
);
841 const char* p
= name
.c_str();
842 Go_sha1_helper
* sha1_helper
= go_create_sha1_helper();
843 sha1_helper
->process_bytes(p
, strlen(p
));
844 std::string s
= sha1_helper
->finish();
847 int j
= suffix
.size() - 1;
848 for (int i
= s
.size() - 1; i
>= 0; i
--)
851 for (int k
= 0; k
< 8; k
++, j
--, c
>>=1)
855 char bit
= suffix
.at(j
) - '0';
863 // Analyze the program flow for escape information.
866 Gogo::analyze_escape()
871 if (!optimize_allocation_flag
.is_enabled()
872 && !this->compiling_runtime())
873 // We always run escape analysis when compiling runtime.
876 // Discover strongly connected groups of functions to analyze for escape
877 // information in this package.
878 this->discover_analysis_sets();
880 if (!this->debug_escape_hash().empty())
881 std::cerr
<< "debug-escape-hash " << this->debug_escape_hash() << "\n";
883 for (std::vector
<Analysis_set
>::iterator p
= this->analysis_sets_
.begin();
884 p
!= this->analysis_sets_
.end();
887 std::vector
<Named_object
*> stack
= p
->first
;
889 if (!this->debug_escape_hash().empty())
892 for (std::vector
<Named_object
*>::const_iterator fn
= stack
.begin();
895 match
= match
|| escape_hash_match(this->debug_escape_hash(), (*fn
)->message_name());
898 // Escape analysis won't run on these functions, but still
899 // need to tag them, so the caller knows.
900 for (std::vector
<Named_object
*>::iterator fn
= stack
.begin();
903 if ((*fn
)->is_function())
905 Function_type
* fntype
= (*fn
)->func_value()->type();
906 fntype
->set_is_tagged();
908 std::cerr
<< "debug-escape-hash disables " << debug_function_name(*fn
) << "\n";
913 for (std::vector
<Named_object
*>::const_iterator fn
= stack
.begin();
916 if ((*fn
)->is_function())
917 std::cerr
<< "debug-escape-hash triggers " << debug_function_name(*fn
) << "\n";
920 Escape_context
* context
= new Escape_context(this, p
->second
);
922 // Analyze the flow of each function; build the connection graph.
923 // This is the assign phase.
924 for (std::vector
<Named_object
*>::reverse_iterator fn
= stack
.rbegin();
928 context
->set_current_function(*fn
);
929 this->assign_connectivity(context
, *fn
);
932 // Propagate levels across each dst. This is the flood phase.
933 std::set
<Node
*> dsts
= context
->dsts();
934 Unordered_map(Node
*, int) escapes
;
935 for (std::set
<Node
*>::iterator n
= dsts
.begin();
939 escapes
[*n
] = (*n
)->encoding();
940 this->propagate_escape(context
, *n
);
944 // Reflood if the roots' escape states increase. Run until fix point.
947 for (std::set
<Node
*>::iterator n
= dsts
.begin();
951 if ((*n
)->object() == NULL
952 && ((*n
)->expr() == NULL
953 || ((*n
)->expr()->var_expression() == NULL
954 && (*n
)->expr()->enclosed_var_expression() == NULL
955 && (*n
)->expr()->func_expression() == NULL
)))
957 if (escapes
[*n
] != (*n
)->encoding())
960 if (this->debug_escape_level() > 2)
961 go_inform((*n
)->location(), "Reflooding %s %s",
962 debug_function_name((*n
)->state(context
, NULL
)->fn
).c_str(),
963 (*n
)->ast_format(this).c_str());
964 escapes
[*n
] = (*n
)->encoding();
965 this->propagate_escape(context
, *n
);
972 // Tag each exported function's parameters with escape information.
973 for (std::vector
<Named_object
*>::iterator fn
= stack
.begin();
976 this->tag_function(context
, *fn
);
978 if (this->debug_escape_level() != 0)
980 std::vector
<Node
*> noesc
= context
->non_escaping_nodes();
981 for (std::vector
<Node
*>::const_iterator n
= noesc
.begin();
985 Node::Escape_state
* state
= (*n
)->state(context
, NULL
);
986 if ((*n
)->encoding() == Node::ESCAPE_NONE
)
987 go_inform((*n
)->location(), "%s %s does not escape",
988 strip_packed_prefix(this, debug_function_name(state
->fn
)).c_str(),
989 (*n
)->ast_format(this).c_str());
996 // Traverse the program, discovering the functions that are roots of strongly
997 // connected components. The goal of this phase to produce a set of functions
998 // that must be analyzed in order.
1000 class Escape_analysis_discover
: public Traverse
1003 Escape_analysis_discover(Gogo
* gogo
)
1004 : Traverse(traverse_functions
| traverse_func_declarations
),
1005 gogo_(gogo
), component_ids_()
1009 function(Named_object
*);
1012 function_declaration(Named_object
*);
1015 visit(Named_object
*);
1018 visit_code(Named_object
*, int);
1021 // A counter used to generate the ID for the function node in the graph.
1024 // Type used to map functions to an ID in a graph of connected components.
1025 typedef Unordered_map(Named_object
*, int) Component_ids
;
1029 // The list of functions encountered during connected component discovery.
1030 Component_ids component_ids_
;
1031 // The stack of functions that this component consists of.
1032 std::stack
<Named_object
*> stack_
;
1035 int Escape_analysis_discover::id
= 0;
1037 // Visit each function.
1040 Escape_analysis_discover::function(Named_object
* fn
)
1043 return TRAVERSE_CONTINUE
;
1047 Escape_analysis_discover::function_declaration(Named_object
* fn
)
1050 return TRAVERSE_CONTINUE
;
1053 // Visit a function FN, adding it to the current stack of functions
1054 // in this connected component. If this is the root of the component,
1055 // create a set of functions to be analyzed later.
1057 // Finding these sets is finding strongly connected components
1058 // in the static call graph. The algorithm for doing that is taken
1059 // from Sedgewick, Algorithms, Second Edition, p. 482, with two
1062 // First, a closure (fn->func_value()->enclosing() == NULL) cannot be the
1063 // root of a connected component. Refusing to use it as a root
1064 // forces it into the component of the function in which it appears.
1065 // This is more convenient for escape analysis.
1067 // Second, each function becomes two virtual nodes in the graph,
1068 // with numbers n and n+1. We record the function's node number as n
1069 // but search from node n+1. If the search tells us that the component
1070 // number (min) is n+1, we know that this is a trivial component: one function
1071 // plus its closures. If the search tells us that the component number is
1072 // n, then there was a path from node n+1 back to node n, meaning that
1073 // the function set is mutually recursive. The escape analysis can be
1074 // more precise when analyzing a single non-recursive function than
1075 // when analyzing a set of mutually recursive functions.
1078 Escape_analysis_discover::visit(Named_object
* fn
)
1080 Component_ids::const_iterator p
= this->component_ids_
.find(fn
);
1081 if (p
!= this->component_ids_
.end())
1087 this->component_ids_
[fn
] = id
;
1091 this->stack_
.push(fn
);
1092 min
= this->visit_code(fn
, min
);
1093 if ((min
== id
|| min
== id
+ 1)
1094 && ((fn
->is_function() && fn
->func_value()->enclosing() == NULL
)
1095 || fn
->is_function_declaration()))
1097 bool recursive
= min
== id
;
1098 std::vector
<Named_object
*> group
;
1100 for (; !this->stack_
.empty(); this->stack_
.pop())
1102 Named_object
* n
= this->stack_
.top();
1110 this->component_ids_
[n
] = std::numeric_limits
<int>::max();
1112 group
.push_back(fn
);
1113 this->component_ids_
[fn
] = std::numeric_limits
<int>::max();
1115 std::reverse(group
.begin(), group
.end());
1116 this->gogo_
->add_analysis_set(group
, recursive
);
1122 // Helper class for discovery step. Traverse expressions looking for
1123 // function calls and closures to visit during the discovery step.
1125 class Escape_discover_expr
: public Traverse
1128 Escape_discover_expr(Escape_analysis_discover
* ead
, int min
)
1129 : Traverse(traverse_expressions
),
1130 ead_(ead
), min_(min
)
1135 { return this->min_
; }
1138 expression(Expression
** pexpr
);
1141 // The original discovery analysis.
1142 Escape_analysis_discover
* ead_
;
1143 // The minimum component ID in this group.
1147 // Visit any calls or closures found when discovering expressions.
1150 Escape_discover_expr::expression(Expression
** pexpr
)
1152 Expression
* e
= *pexpr
;
1153 Named_object
* fn
= NULL
;
1154 if (e
->call_expression() != NULL
1155 && e
->call_expression()->fn()->func_expression() != NULL
)
1157 // Method call or function call.
1158 fn
= e
->call_expression()->fn()->func_expression()->named_object();
1160 else if (e
->func_expression() != NULL
1161 && e
->func_expression()->closure() != NULL
)
1164 fn
= e
->func_expression()->named_object();
1168 this->min_
= std::min(this->min_
, this->ead_
->visit(fn
));
1169 return TRAVERSE_CONTINUE
;
1172 // Visit the body of each function, returns ID of the minimum connected
1173 // component found in the body.
1176 Escape_analysis_discover::visit_code(Named_object
* fn
, int min
)
1178 if (!fn
->is_function())
1181 Escape_discover_expr
ede(this, min
);
1182 fn
->func_value()->traverse(&ede
);
1186 // Discover strongly connected groups of functions to analyze.
1189 Gogo::discover_analysis_sets()
1191 Escape_analysis_discover
ead(this);
1192 this->traverse(&ead
);
1195 // Traverse all label and goto statements and mark the underlying label
1196 // as looping or not looping.
1198 class Escape_analysis_loop
: public Traverse
1201 Escape_analysis_loop()
1202 : Traverse(traverse_statements
)
1206 statement(Block
*, size_t*, Statement
*);
1210 Escape_analysis_loop::statement(Block
*, size_t*, Statement
* s
)
1212 if (s
->label_statement() != NULL
)
1213 s
->label_statement()->label()->set_nonlooping();
1214 else if (s
->goto_statement() != NULL
)
1216 if (s
->goto_statement()->label()->nonlooping())
1217 s
->goto_statement()->label()->set_looping();
1219 return TRAVERSE_CONTINUE
;
1222 // Traversal class used to look at all interesting statements within a function
1223 // in order to build a connectivity graph between all nodes within a context's
1226 class Escape_analysis_assign
: public Traverse
1229 Escape_analysis_assign(Escape_context
* context
, Named_object
* fn
)
1230 : Traverse(traverse_statements
1231 | traverse_expressions
),
1232 context_(context
), fn_(fn
)
1235 // Model statements within a function as assignments and flows between nodes.
1237 statement(Block
*, size_t*, Statement
*);
1239 // Model expressions within a function as assignments and flows between nodes.
1241 expression(Expression
**);
1243 // Model calls within a function as assignments and flows between arguments
1246 call(Call_expression
* call
);
1248 // Model the assignment of DST to SRC.
1250 assign(Node
* dst
, Node
* src
);
1252 // Model the assignment of DST to dereference of SRC.
1254 assign_deref(Node
* dst
, Node
* src
);
1256 // Model the input-to-output assignment flow of one of a function call's
1257 // arguments, where the flow is encoding in NOTE.
1259 assign_from_note(std::string
* note
, const std::vector
<Node
*>& dsts
,
1262 // Record the flow of SRC to DST in DST.
1264 flows(Node
* dst
, Node
* src
);
1267 // The escape context for this set of functions.
1268 Escape_context
* context_
;
1269 // The current function being analyzed.
1273 // Helper function to detect self assignment like the following.
1275 // func (b *Buffer) Foo() {
1277 // b.buf = b.buf[n:m]
1281 is_self_assignment(Expression
* lhs
, Expression
* rhs
)
1283 Unary_expression
* lue
=
1284 (lhs
->field_reference_expression() != NULL
1285 ? lhs
->field_reference_expression()->expr()->unary_expression()
1286 : lhs
->unary_expression());
1287 Var_expression
* lve
=
1288 (lue
!= NULL
&& lue
->op() == OPERATOR_MULT
? lue
->operand()->var_expression() : NULL
);
1289 Array_index_expression
* raie
= rhs
->array_index_expression();
1290 String_index_expression
* rsie
= rhs
->string_index_expression();
1291 Expression
* rarray
=
1292 (raie
!= NULL
&& raie
->end() != NULL
&& raie
->array()->type()->is_slice_type()
1294 : (rsie
!= NULL
&& rsie
->type()->is_string_type() ? rsie
->string() : NULL
));
1295 Unary_expression
* rue
=
1296 (rarray
!= NULL
&& rarray
->field_reference_expression() != NULL
1297 ? rarray
->field_reference_expression()->expr()->unary_expression()
1298 : (rarray
!= NULL
? rarray
->unary_expression() : NULL
));
1299 Var_expression
* rve
=
1300 (rue
!= NULL
&& rue
->op() == OPERATOR_MULT
? rue
->operand()->var_expression() : NULL
);
1301 return lve
!= NULL
&& rve
!= NULL
1302 && lve
->named_object() == rve
->named_object();
1305 // Model statements within a function as assignments and flows between nodes.
1308 Escape_analysis_assign::statement(Block
*, size_t*, Statement
* s
)
1310 // Adjust the loop depth as we enter/exit blocks related to for statements.
1311 bool is_for_statement
= (s
->is_block_statement()
1312 && s
->block_statement()->is_lowered_for_statement());
1313 if (is_for_statement
)
1314 this->context_
->increase_loop_depth();
1316 s
->traverse_contents(this);
1318 if (is_for_statement
)
1319 this->context_
->decrease_loop_depth();
1321 Gogo
* gogo
= this->context_
->gogo();
1322 int debug_level
= gogo
->debug_escape_level();
1324 && s
->unnamed_label_statement() == NULL
1325 && s
->expression_statement() == NULL
1326 && !s
->is_block_statement())
1328 Node
* n
= Node::make_node(s
);
1329 std::string fn_name
= this->context_
->current_function_name();
1330 go_inform(s
->location(), "[%d] %s esc: %s",
1331 this->context_
->loop_depth(), fn_name
.c_str(),
1332 n
->ast_format(gogo
).c_str());
1335 switch (s
->classification())
1337 case Statement::STATEMENT_VARIABLE_DECLARATION
:
1339 Named_object
* var
= s
->variable_declaration_statement()->var();
1340 Node
* var_node
= Node::make_node(var
);
1341 Node::Escape_state
* state
= var_node
->state(this->context_
, NULL
);
1342 state
->loop_depth
= this->context_
->loop_depth();
1344 // Set the loop depth for this declaration.
1345 if (var
->is_variable()
1346 && var
->var_value()->init() != NULL
)
1348 Node
* init_node
= Node::make_node(var
->var_value()->init());
1349 this->assign(var_node
, init_node
);
1354 case Statement::STATEMENT_TEMPORARY
:
1356 Expression
* init
= s
->temporary_statement()->init();
1358 this->assign(Node::make_node(s
), Node::make_node(init
));
1362 case Statement::STATEMENT_LABEL
:
1364 Label_statement
* label_stmt
= s
->label_statement();
1365 if (label_stmt
->label()->looping())
1366 this->context_
->increase_loop_depth();
1368 if (debug_level
> 1)
1370 std::string label_type
= (label_stmt
->label()->looping()
1373 go_inform(s
->location(), "%s %s label",
1374 label_stmt
->label()->name().c_str(),
1375 label_type
.c_str());
1380 case Statement::STATEMENT_SWITCH
:
1381 case Statement::STATEMENT_TYPE_SWITCH
:
1382 // Want to model the assignment of each case variable to the switched upon
1383 // variable. This should be lowered into assignment statements; nothing
1384 // to here if that's the case.
1387 case Statement::STATEMENT_ASSIGNMENT
:
1389 Assignment_statement
* assn
= s
->assignment_statement();
1390 Expression
* lhs
= assn
->lhs();
1391 Expression
* rhs
= assn
->rhs();
1392 Node
* lhs_node
= Node::make_node(lhs
);
1393 Node
* rhs_node
= Node::make_node(rhs
);
1395 // Filter out the following special case.
1397 // func (b *Buffer) Foo() {
1399 // b.buf = b.buf[n:m]
1402 // This assignment is a no-op for escape analysis,
1403 // it does not store any new pointers into b that were not already there.
1404 // However, without this special case b will escape.
1405 if (is_self_assignment(lhs
, rhs
))
1407 if (debug_level
!= 0)
1408 go_inform(s
->location(), "%s ignoring self-assignment to %s",
1409 strip_packed_prefix(gogo
, this->context_
->current_function_name()).c_str(),
1410 lhs_node
->ast_format(gogo
).c_str());
1414 this->assign(lhs_node
, rhs_node
);
1418 case Statement::STATEMENT_SEND
:
1420 Node
* sent_node
= Node::make_node(s
->send_statement()->val());
1421 this->assign(this->context_
->sink(), sent_node
);
1425 case Statement::STATEMENT_DEFER
:
1426 if (this->context_
->loop_depth() == 1)
1428 // Defer statement may need to allocate a thunk. When it is
1429 // not inside a loop, this can be stack allocated, as it
1430 // runs before the function finishes.
1431 Node
* n
= Node::make_node(s
);
1432 n
->set_encoding(Node::ESCAPE_NONE
);
1437 case Statement::STATEMENT_GO
:
1439 // Defer f(x) or go f(x).
1440 // Both f and x escape to the heap.
1441 Thunk_statement
* thunk
= s
->thunk_statement();
1442 if (thunk
->call()->call_expression() == NULL
)
1445 Call_expression
* call
= thunk
->call()->call_expression();
1446 Node
* func_node
= Node::make_node(call
->fn());
1447 this->assign(this->context_
->sink(), func_node
);
1448 if (call
->args() != NULL
)
1450 for (Expression_list::const_iterator p
= call
->args()->begin();
1451 p
!= call
->args()->end();
1454 Node
* arg_node
= Node::make_node(*p
);
1455 this->assign(this->context_
->sink(), arg_node
);
1464 return TRAVERSE_SKIP_COMPONENTS
;
1467 // Helper function to emit moved-to-heap diagnostics.
1470 move_to_heap(Gogo
* gogo
, Expression
*expr
)
1473 if (expr
->var_expression() != NULL
)
1474 no
= expr
->var_expression()->named_object();
1475 else if (expr
->enclosed_var_expression() != NULL
)
1476 no
= expr
->enclosed_var_expression()->variable();
1480 if ((no
->is_variable()
1481 && !no
->var_value()->is_global())
1482 || no
->is_result_variable())
1484 Node
* n
= Node::make_node(expr
);
1485 if (gogo
->debug_escape_level() != 0)
1486 go_inform(n
->definition_location(),
1487 "moved to heap: %s",
1488 n
->ast_format(gogo
).c_str());
1489 if (gogo
->compiling_runtime() && gogo
->package_name() == "runtime")
1490 go_error_at(expr
->location(),
1491 "%s escapes to heap, not allowed in runtime",
1492 n
->ast_format(gogo
).c_str());
1496 // Model expressions within a function as assignments and flows between nodes.
1499 Escape_analysis_assign::expression(Expression
** pexpr
)
1501 Gogo
* gogo
= this->context_
->gogo();
1502 int debug_level
= gogo
->debug_escape_level();
1504 // Big stuff escapes unconditionally.
1505 Node
* n
= Node::make_node(*pexpr
);
1506 if ((n
->encoding() & ESCAPE_MASK
) != int(Node::ESCAPE_HEAP
)
1507 && n
->is_big(this->context_
))
1509 if (debug_level
> 1)
1510 go_inform((*pexpr
)->location(), "%s too large for stack",
1511 n
->ast_format(gogo
).c_str());
1512 move_to_heap(gogo
, *pexpr
);
1513 n
->set_encoding(Node::ESCAPE_HEAP
);
1514 (*pexpr
)->address_taken(true);
1515 this->assign(this->context_
->sink(), n
);
1518 if ((*pexpr
)->func_expression() == NULL
)
1519 (*pexpr
)->traverse_subexpressions(this);
1521 if (debug_level
> 1)
1523 Node
* n
= Node::make_node(*pexpr
);
1524 std::string fn_name
= this->context_
->current_function_name();
1525 go_inform((*pexpr
)->location(), "[%d] %s esc: %s",
1526 this->context_
->loop_depth(), fn_name
.c_str(),
1527 n
->ast_format(gogo
).c_str());
1530 switch ((*pexpr
)->classification())
1532 case Expression::EXPRESSION_CALL
:
1534 Call_expression
* call
= (*pexpr
)->call_expression();
1535 if (call
->is_builtin())
1537 Builtin_call_expression
* bce
= call
->builtin_call_expression();
1538 switch (bce
->code())
1540 case Builtin_call_expression::BUILTIN_PANIC
:
1542 // Argument could leak through recover.
1543 Node
* panic_arg
= Node::make_node(call
->args()->front());
1544 this->assign(this->context_
->sink(), panic_arg
);
1548 case Builtin_call_expression::BUILTIN_APPEND
:
1550 // The contents being appended leak.
1551 if (call
->is_varargs())
1553 // append(slice1, slice2...) -- slice2 itself does not escape, but contents do
1554 Node
* appended
= Node::make_node(call
->args()->back());
1555 this->assign_deref(this->context_
->sink(), appended
);
1556 if (debug_level
> 2)
1557 go_inform((*pexpr
)->location(),
1558 "special treatment of append(slice1, slice2...)");
1562 for (Expression_list::const_iterator pa
=
1563 call
->args()->begin() + 1;
1564 pa
!= call
->args()->end();
1567 Node
* arg
= Node::make_node(*pa
);
1568 this->assign(this->context_
->sink(), arg
);
1572 // The content of the original slice leaks as well.
1573 Node
* appendee
= Node::make_node(call
->args()->front());
1574 this->assign_deref(this->context_
->sink(), appendee
);
1578 case Builtin_call_expression::BUILTIN_COPY
:
1580 // Lose track of the copied content.
1581 Node
* copied
= Node::make_node(call
->args()->back());
1582 this->assign_deref(this->context_
->sink(), copied
);
1591 Func_expression
* fe
= call
->fn()->func_expression();
1592 if (fe
!= NULL
&& fe
->is_runtime_function())
1594 switch (fe
->runtime_code())
1596 case Runtime::MAKECHAN
:
1597 case Runtime::MAKECHAN64
:
1598 case Runtime::MAKEMAP
:
1599 case Runtime::MAKESLICE
:
1600 case Runtime::MAKESLICE64
:
1601 this->context_
->track(n
);
1604 case Runtime::MAPASSIGN
:
1606 // Map key escapes. The last argument is the address
1608 Node
* key_node
= Node::make_node(call
->args()->back());
1609 this->assign_deref(this->context_
->sink(), key_node
);
1613 case Runtime::SELECTSEND
:
1615 // Send to a channel, lose track. The last argument is
1616 // the address of the value to send.
1617 Node
* arg_node
= Node::make_node(call
->args()->back());
1618 this->assign_deref(this->context_
->sink(), arg_node
);
1622 case Runtime::IFACEE2T2
:
1623 case Runtime::IFACEI2T2
:
1625 // x, ok = v.(T), where T is non-pointer non-interface,
1627 // ok = IFACEI2T2(type, v, (void*)&tmp_x)
1628 // Here v flows to tmp_x.
1629 // Note: other IFACEX2Y2 returns the conversion result.
1630 // Those are handled in ::assign.
1631 Node
* src_node
= Node::make_node(call
->args()->at(1));
1633 Expression
* arg2
= call
->args()->at(2);
1634 // Try to pull tmp_x out of the arg2 expression, and let v
1635 // flows into it, instead of simply dereference arg2,
1636 // which looks like dereference of an arbitrary pointer
1637 // and causes v immediately escape.
1638 // The expression form matches statement.cc,
1639 // Tuple_type_guard_assignment_statement::lower_to_object_type.
1640 Unary_expression
* ue
=
1641 (arg2
->conversion_expression() != NULL
1642 ? arg2
->conversion_expression()->expr()->unary_expression()
1643 : arg2
->unary_expression());
1644 if (ue
!= NULL
&& ue
->op() == OPERATOR_AND
)
1646 if (!ue
->operand()->type()->has_pointer())
1647 // Don't bother flowing non-pointer.
1649 dst_node
= Node::make_node(ue
->operand());
1652 dst_node
= this->context_
->add_dereference(Node::make_node(arg2
));
1653 this->assign(dst_node
, src_node
);
1666 case Expression::EXPRESSION_ALLOCATION
:
1667 // This is Runtime::NEW.
1668 this->context_
->track(n
);
1671 case Expression::EXPRESSION_STRING_CONCAT
:
1672 this->context_
->track(n
);
1675 case Expression::EXPRESSION_CONVERSION
:
1677 Type_conversion_expression
* tce
= (*pexpr
)->conversion_expression();
1678 Type
* ft
= tce
->expr()->type();
1679 Type
* tt
= tce
->type();
1680 if ((ft
->is_string_type() && tt
->is_slice_type())
1681 || (ft
->is_slice_type() && tt
->is_string_type())
1682 || (ft
->integer_type() != NULL
&& tt
->is_string_type()))
1684 // string([]byte), string([]rune), []byte(string), []rune(string), string(rune)
1685 this->context_
->track(n
);
1688 Node
* tce_node
= Node::make_node(tce
);
1689 Node
* converted
= Node::make_node(tce
->expr());
1690 this->context_
->track(tce_node
);
1692 this->assign(tce_node
, converted
);
1696 case Expression::EXPRESSION_FIXED_ARRAY_CONSTRUCTION
:
1697 case Expression::EXPRESSION_SLICE_CONSTRUCTION
:
1699 Node
* array_node
= Node::make_node(*pexpr
);
1700 if ((*pexpr
)->slice_literal() != NULL
)
1701 this->context_
->track(array_node
);
1703 Expression_list
* vals
= ((*pexpr
)->slice_literal() != NULL
1704 ? (*pexpr
)->slice_literal()->vals()
1705 : (*pexpr
)->array_literal()->vals());
1709 // Connect the array to its values.
1710 for (Expression_list::const_iterator p
= vals
->begin();
1714 this->assign(array_node
, Node::make_node(*p
));
1719 case Expression::EXPRESSION_STRUCT_CONSTRUCTION
:
1721 Node
* struct_node
= Node::make_node(*pexpr
);
1722 Expression_list
* vals
= (*pexpr
)->struct_literal()->vals();
1725 // Connect the struct to its values.
1726 for (Expression_list::const_iterator p
= vals
->begin();
1731 this->assign(struct_node
, Node::make_node(*p
));
1737 case Expression::EXPRESSION_HEAP
:
1739 Node
* pointer_node
= Node::make_node(*pexpr
);
1740 Node
* lit_node
= Node::make_node((*pexpr
)->heap_expression()->expr());
1741 this->context_
->track(pointer_node
);
1743 // Connect pointer node to literal node; if the pointer node escapes, so
1744 // does the literal node.
1745 this->assign(pointer_node
, lit_node
);
1749 case Expression::EXPRESSION_BOUND_METHOD
:
1751 Node
* bound_node
= Node::make_node(*pexpr
);
1752 this->context_
->track(bound_node
);
1754 Expression
* obj
= (*pexpr
)->bound_method_expression()->first_argument();
1755 Node
* obj_node
= Node::make_node(obj
);
1757 // A bound method implies the receiver will be used outside of the
1758 // lifetime of the method in some way. We lose track of the receiver.
1759 this->assign(this->context_
->sink(), obj_node
);
1763 case Expression::EXPRESSION_MAP_CONSTRUCTION
:
1765 Map_construction_expression
* mce
= (*pexpr
)->map_literal();
1766 Node
* map_node
= Node::make_node(mce
);
1767 this->context_
->track(map_node
);
1769 // All keys and values escape to memory.
1770 if (mce
->vals() != NULL
)
1772 for (Expression_list::const_iterator p
= mce
->vals()->begin();
1773 p
!= mce
->vals()->end();
1777 this->assign(this->context_
->sink(), Node::make_node(*p
));
1783 case Expression::EXPRESSION_FUNC_REFERENCE
:
1785 Func_expression
* fe
= (*pexpr
)->func_expression();
1786 if (fe
->closure() != NULL
)
1788 // Connect captured variables to the closure.
1789 Node
* closure_node
= Node::make_node(fe
);
1790 this->context_
->track(closure_node
);
1792 // A closure expression already exists as the heap expression:
1793 // &struct{f func_code, v []*Variable}{...}.
1794 // Link closure to the addresses of the variables enclosed.
1795 Heap_expression
* he
= fe
->closure()->heap_expression();
1796 Struct_construction_expression
* sce
= he
->expr()->struct_literal();
1798 // First field is function code, other fields are variable
1800 Expression_list::const_iterator p
= sce
->vals()->begin();
1802 for (; p
!= sce
->vals()->end(); ++p
)
1804 Node
* enclosed_node
= Node::make_node(*p
);
1805 this->context_
->track(enclosed_node
);
1806 this->assign(closure_node
, enclosed_node
);
1812 case Expression::EXPRESSION_UNARY
:
1814 if ((*pexpr
)->unary_expression()->op() != OPERATOR_AND
)
1817 Node
* addr_node
= Node::make_node(*pexpr
);
1818 this->context_
->track(addr_node
);
1820 Expression
* operand
= (*pexpr
)->unary_expression()->operand();
1821 Named_object
* var
= NULL
;
1822 if (operand
->var_expression() != NULL
)
1823 var
= operand
->var_expression()->named_object();
1824 else if (operand
->enclosed_var_expression() != NULL
)
1825 var
= operand
->enclosed_var_expression()->variable();
1830 if (var
->is_variable()
1831 && !var
->var_value()->is_parameter())
1833 // For &x, use the loop depth of x if known.
1834 Node::Escape_state
* addr_state
=
1835 addr_node
->state(this->context_
, NULL
);
1836 Node
* operand_node
= Node::make_node(operand
);
1837 Node::Escape_state
* operand_state
=
1838 operand_node
->state(this->context_
, NULL
);
1839 if (operand_state
->loop_depth
!= 0)
1840 addr_state
->loop_depth
= operand_state
->loop_depth
;
1842 else if ((var
->is_variable()
1843 && var
->var_value()->is_parameter())
1844 || var
->is_result_variable())
1846 Node::Escape_state
* addr_state
=
1847 addr_node
->state(this->context_
, NULL
);
1848 addr_state
->loop_depth
= 1;
1853 case Expression::EXPRESSION_ARRAY_INDEX
:
1855 Array_index_expression
* aie
= (*pexpr
)->array_index_expression();
1856 if (aie
->end() != NULL
&& !aie
->array()->type()->is_slice_type())
1858 // Slicing an array.
1859 Expression
* addr
= Expression::make_unary(OPERATOR_AND
, aie
->array(),
1861 Node
* addr_node
= Node::make_node(addr
);
1862 n
->set_child(addr_node
);
1863 this->context_
->track(addr_node
);
1871 return TRAVERSE_SKIP_COMPONENTS
;
1874 // Model calls within a function as assignments and flows between arguments
1878 Escape_analysis_assign::call(Call_expression
* call
)
1880 Gogo
* gogo
= this->context_
->gogo();
1881 int debug_level
= gogo
->debug_escape_level();
1883 Func_expression
* fn
= call
->fn()->func_expression();
1884 Function_type
* fntype
= call
->get_function_type();
1885 bool indirect
= false;
1887 // Interface method calls or closure calls are indirect calls.
1889 || (fntype
->is_method()
1890 && fntype
->receiver()->type()->interface_type() != NULL
)
1892 || (fn
->named_object()->is_function()
1893 && fn
->named_object()->func_value()->enclosing() != NULL
))
1896 Node
* call_node
= Node::make_node(call
);
1897 std::vector
<Node
*> arg_nodes
;
1898 if (call
->fn()->interface_field_reference_expression() != NULL
)
1900 Interface_field_reference_expression
* ifre
=
1901 call
->fn()->interface_field_reference_expression();
1902 Node
* field_node
= Node::make_node(ifre
->expr());
1903 arg_nodes
.push_back(field_node
);
1906 if (call
->args() != NULL
)
1908 for (Expression_list::const_iterator p
= call
->args()->begin();
1909 p
!= call
->args()->end();
1911 arg_nodes
.push_back(Node::make_node(*p
));
1916 // We don't know what happens to the parameters through indirect calls.
1917 // Be conservative and assume they all flow to theSink.
1918 for (std::vector
<Node
*>::iterator p
= arg_nodes
.begin();
1919 p
!= arg_nodes
.end();
1922 if (debug_level
> 2)
1923 go_inform(call
->location(),
1924 "esccall:: indirect call <- %s, untracked",
1925 (*p
)->ast_format(gogo
).c_str());
1926 this->assign(this->context_
->sink(), *p
);
1929 this->context_
->init_retvals(call_node
, fntype
);
1931 // It could be a closure call that returns captured variable.
1932 // Model this by flowing the func expression to result.
1933 // See issue #14409.
1934 Node
* fn_node
= Node::make_node(call
->fn());
1935 std::vector
<Node
*> retvals
= call_node
->state(this->context_
, NULL
)->retvals
;
1936 for (std::vector
<Node
*>::const_iterator p
= retvals
.begin();
1939 this->assign_deref(*p
, fn_node
);
1944 // If FN is an untagged function.
1946 && fn
->named_object()->is_function()
1947 && !fntype
->is_tagged())
1949 if (debug_level
> 2)
1950 go_inform(call
->location(), "esccall:: %s in recursive group",
1951 call_node
->ast_format(gogo
).c_str());
1953 Function
* f
= fn
->named_object()->func_value();
1954 const Bindings
* callee_bindings
= f
->block()->bindings();
1955 Function::Results
* results
= f
->result_variables();
1956 if (results
!= NULL
)
1958 // Setup output list on this call node.
1959 Node::Escape_state
* state
= call_node
->state(this->context_
, NULL
);
1960 for (Function::Results::const_iterator p1
= results
->begin();
1961 p1
!= results
->end();
1964 Node
* result_node
= Node::make_node(*p1
);
1965 state
->retvals
.push_back(result_node
);
1969 std::vector
<Node
*>::iterator p
= arg_nodes
.begin();
1970 if (fntype
->is_method())
1972 std::string rcvr_name
= fntype
->receiver()->name();
1973 if (rcvr_name
.empty() || Gogo::is_sink_name(rcvr_name
)
1974 || !fntype
->receiver()->type()->has_pointer())
1978 Named_object
* rcvr_no
=
1979 callee_bindings
->lookup_local(fntype
->receiver()->name());
1980 go_assert(rcvr_no
!= NULL
);
1981 Node
* rcvr_node
= Node::make_node(rcvr_no
);
1982 if (fntype
->receiver()->type()->points_to() == NULL
1983 && (*p
)->expr()->type()->points_to() != NULL
)
1984 // This is a call to a value method that has been lowered into a call
1985 // to a pointer method. Gccgo generates a pointer method for all
1986 // method calls and takes the address of the value passed as the
1987 // receiver then immediately dereferences it within the function.
1988 // In this case, the receiver address does not escape; its content
1989 // flows to the call.
1990 this->assign_deref(rcvr_node
, *p
);
1992 this->assign(rcvr_node
, *p
);
1997 const Typed_identifier_list
* til
= fntype
->parameters();
2000 for (Typed_identifier_list::const_iterator p1
= til
->begin();
2004 if (p1
->name().empty() || Gogo::is_sink_name(p1
->name()))
2007 Named_object
* param_no
=
2008 callee_bindings
->lookup_local(p1
->name());
2009 go_assert(param_no
!= NULL
);
2010 Expression
* arg
= (*p
)->expr();
2011 if (arg
->var_expression() != NULL
2012 && arg
->var_expression()->named_object() == param_no
)
2015 Node
* param_node
= Node::make_node(param_no
);
2016 this->assign(param_node
, *p
);
2019 for (; p
!= arg_nodes
.end(); ++p
)
2021 if (debug_level
> 2)
2022 go_inform(call
->location(), "esccall:: ... <- %s, untracked",
2023 (*p
)->ast_format(gogo
).c_str());
2024 this->assign(this->context_
->sink(), *p
);
2031 if (debug_level
> 2)
2032 go_inform(call
->location(), "esccall:: %s not recursive",
2033 call_node
->ast_format(gogo
).c_str());
2035 Node::Escape_state
* call_state
= call_node
->state(this->context_
, NULL
);
2036 if (!call_state
->retvals
.empty())
2037 go_error_at(Linemap::unknown_location(),
2038 "esc already decorated call %s",
2039 call_node
->ast_format(gogo
).c_str());
2040 this->context_
->init_retvals(call_node
, fntype
);
2043 std::vector
<Node
*>::iterator p
= arg_nodes
.begin();
2044 if (fntype
->is_method()
2045 && p
!= arg_nodes
.end())
2047 // First argument to call will be the receiver.
2048 std::string
* note
= fntype
->receiver()->note();
2049 if (fntype
->receiver()->type()->points_to() == NULL
2050 && (*p
)->expr()->type()->points_to() != NULL
)
2051 // This is a call to a value method that has been lowered into a call
2052 // to a pointer method. Gccgo generates a pointer method for all
2053 // method calls and takes the address of the value passed as the
2054 // receiver then immediately dereferences it within the function.
2055 // In this case, the receiver address does not escape; its content
2056 // flows to the call.
2057 this->assign_from_note(note
, call_state
->retvals
,
2058 this->context_
->add_dereference(*p
));
2061 if (!Type::are_identical(fntype
->receiver()->type(),
2062 (*p
)->expr()->type(), true, NULL
))
2064 // This will be converted later, preemptively track it instead
2065 // of its conversion expression which will show up in a later pass.
2066 this->context_
->track(*p
);
2068 this->assign_from_note(note
, call_state
->retvals
, *p
);
2073 const Typed_identifier_list
* til
= fntype
->parameters();
2076 for (Typed_identifier_list::const_iterator pn
= til
->begin();
2077 pn
!= til
->end() && p
!= arg_nodes
.end();
2080 if (!Type::are_identical(pn
->type(), (*p
)->expr()->type(),
2083 // This will be converted later, preemptively track it instead
2084 // of its conversion expression which will show up in a later pass.
2085 this->context_
->track(*p
);
2088 Type
* t
= pn
->type();
2090 && t
->has_pointer())
2092 std::string
* note
= pn
->note();
2093 int enc
= this->assign_from_note(note
, call_state
->retvals
, *p
);
2094 if (enc
== Node::ESCAPE_NONE
2095 && !call
->is_deferred()
2096 && !call
->is_concurrent())
2098 // TODO(cmang): Mark the argument as strictly non-escaping?
2099 // In the gc compiler this is for limiting the lifetime of
2100 // temporaries. We probably don't need this?
2105 for (; p
!= arg_nodes
.end(); ++p
)
2107 if (debug_level
> 2)
2108 go_inform(call
->location(), "esccall:: ... <- %s, untracked",
2109 (*p
)->ast_format(gogo
).c_str());
2110 this->assign(this->context_
->sink(), *p
);
2115 // Model the assignment of DST to SRC.
2116 // Assert that SRC somehow gets assigned to DST.
2117 // DST might need to be examined for evaluations that happen inside of it.
2118 // For example, in [DST]*f(x) = [SRC]y, we lose track of the indirection and
2119 // DST becomes the sink in our model.
2122 Escape_analysis_assign::assign(Node
* dst
, Node
* src
)
2124 Gogo
* gogo
= this->context_
->gogo();
2125 int debug_level
= gogo
->debug_escape_level();
2126 if (debug_level
> 1)
2127 go_inform(dst
->location(), "[%d] %s escassign: %s(%s)[%s] = %s(%s)[%s]",
2128 this->context_
->loop_depth(),
2129 strip_packed_prefix(gogo
, this->context_
->current_function_name()).c_str(),
2130 dst
->ast_format(gogo
).c_str(), dst
->details().c_str(),
2131 dst
->op_format().c_str(),
2132 src
->ast_format(gogo
).c_str(), src
->details().c_str(),
2133 src
->op_format().c_str());
2135 if (dst
->is_indirect())
2136 // Lose track of the dereference.
2137 dst
= this->context_
->sink();
2138 else if (dst
->expr() != NULL
)
2140 // Analyze the lhs of the assignment.
2141 // Replace DST with this->context_->sink() if we can't track it.
2142 Expression
* e
= dst
->expr();
2143 switch (e
->classification())
2145 case Expression::EXPRESSION_VAR_REFERENCE
:
2147 // If DST is a global variable, we have no way to track it.
2148 Named_object
* var
= e
->var_expression()->named_object();
2149 if (var
->is_variable() && var
->var_value()->is_global())
2150 dst
= this->context_
->sink();
2154 case Expression::EXPRESSION_FIELD_REFERENCE
:
2156 Expression
* strct
= e
->field_reference_expression()->expr();
2157 if (strct
->heap_expression() != NULL
)
2159 // When accessing the field of a struct reference, we lose
2160 // track of the indirection.
2161 dst
= this->context_
->sink();
2165 // Treat DST.x = SRC as if it were DST = SRC.
2166 Node
* struct_node
= Node::make_node(strct
);
2167 this->assign(struct_node
, src
);
2171 case Expression::EXPRESSION_ARRAY_INDEX
:
2173 Array_index_expression
* are
= e
->array_index_expression();
2174 if (!are
->array()->type()->is_slice_type())
2176 // Treat DST[i] = SRC as if it were DST = SRC if DST if a fixed
2178 Node
* array_node
= Node::make_node(are
->array());
2179 this->assign(array_node
, src
);
2183 // Lose track of the slice dereference.
2184 dst
= this->context_
->sink();
2188 case Expression::EXPRESSION_UNARY
:
2189 // Lose track of the dereference.
2190 if (e
->unary_expression()->op() == OPERATOR_MULT
)
2191 dst
= this->context_
->sink();
2194 case Expression::EXPRESSION_MAP_INDEX
:
2196 // Lose track of the map's key and value.
2197 Expression
* index
= e
->map_index_expression()->index();
2198 Node
* index_node
= Node::make_node(index
);
2199 this->assign(this->context_
->sink(), index_node
);
2201 dst
= this->context_
->sink();
2205 case Expression::EXPRESSION_TEMPORARY_REFERENCE
:
2207 // Temporary is tracked through the underlying Temporary_statement.
2208 Statement
* t
= dst
->expr()->temporary_reference_expression()->statement();
2209 dst
= Node::make_node(t
);
2214 // TODO(cmang): Add debugging info here: only a few expressions
2215 // should leave DST unmodified.
2220 if (src
->object() != NULL
)
2221 this->flows(dst
, src
);
2222 else if (src
->is_indirect())
2223 this->flows(dst
, src
);
2224 else if (src
->expr() != NULL
)
2226 Expression
* e
= src
->expr();
2227 switch (e
->classification())
2229 case Expression::EXPRESSION_VAR_REFERENCE
:
2230 case Expression::EXPRESSION_ENCLOSED_VAR_REFERENCE
:
2232 case Expression::EXPRESSION_HEAP
:
2234 case Expression::EXPRESSION_FIXED_ARRAY_CONSTRUCTION
:
2235 case Expression::EXPRESSION_SLICE_CONSTRUCTION
:
2236 // DST = [...]T{...}.
2237 case Expression::EXPRESSION_MAP_CONSTRUCTION
:
2238 // DST = map[T]V{...}.
2239 case Expression::EXPRESSION_STRUCT_CONSTRUCTION
:
2241 case Expression::EXPRESSION_ALLOCATION
:
2243 case Expression::EXPRESSION_BOUND_METHOD
:
2245 case Expression::EXPRESSION_STRING_CONCAT
:
2246 // DST = str1 + str2
2247 this->flows(dst
, src
);
2250 case Expression::EXPRESSION_UNSAFE_CONVERSION
:
2252 Expression
* underlying
= e
->unsafe_conversion_expression()->expr();
2253 Node
* underlying_node
= Node::make_node(underlying
);
2254 this->assign(dst
, underlying_node
);
2258 case Expression::EXPRESSION_CALL
:
2260 Call_expression
* call
= e
->call_expression();
2261 if (call
->is_builtin())
2263 Builtin_call_expression
* bce
= call
->builtin_call_expression();
2264 if (bce
->code() == Builtin_call_expression::BUILTIN_APPEND
)
2266 // Append returns the first argument.
2267 // The subsequent arguments are already leaked because
2268 // they are operands to append.
2269 Node
* appendee
= Node::make_node(call
->args()->front());
2270 this->assign(dst
, appendee
);
2274 Func_expression
* fe
= call
->fn()->func_expression();
2275 if (fe
!= NULL
&& fe
->is_runtime_function())
2277 switch (fe
->runtime_code())
2279 case Runtime::MAKECHAN
:
2280 case Runtime::MAKECHAN64
:
2281 case Runtime::MAKEMAP
:
2282 case Runtime::MAKESLICE
:
2283 case Runtime::MAKESLICE64
:
2285 this->flows(dst
, src
);
2294 && fe
->named_object()->is_function()
2295 && fe
->named_object()->func_value()->is_method()
2296 && (call
->is_deferred()
2297 || call
->is_concurrent()))
2299 // For a method call thunk, lose track of the call and treat it
2300 // as if DST = RECEIVER.
2301 Node
* rcvr_node
= Node::make_node(call
->args()->front());
2302 this->assign(dst
, rcvr_node
);
2306 // Result flows to dst.
2307 Node
* call_node
= Node::make_node(e
);
2308 Node::Escape_state
* call_state
= call_node
->state(this->context_
, NULL
);
2309 std::vector
<Node
*> retvals
= call_state
->retvals
;
2310 for (std::vector
<Node
*>::const_iterator p
= retvals
.begin();
2313 this->flows(dst
, *p
);
2317 case Expression::EXPRESSION_CALL_RESULT
:
2319 Call_result_expression
* cre
= e
->call_result_expression();
2320 Call_expression
* call
= cre
->call()->call_expression();
2321 if (call
->is_builtin())
2323 if (call
->fn()->func_expression() != NULL
2324 && call
->fn()->func_expression()->is_runtime_function())
2326 switch (call
->fn()->func_expression()->runtime_code())
2328 case Runtime::IFACEE2E2
:
2329 case Runtime::IFACEI2E2
:
2330 case Runtime::IFACEE2I2
:
2331 case Runtime::IFACEI2I2
:
2332 case Runtime::IFACEE2T2P
:
2333 case Runtime::IFACEI2T2P
:
2335 // x, ok = v.(T), where T is a pointer or interface,
2337 // x, ok = IFACEI2E2(v), or
2338 // x, ok = IFACEI2I2(type, v)
2339 // The last arg flows to the first result.
2340 // Note: IFACEX2T2 has different signature, handled by
2342 if (cre
->index() != 0)
2344 Node
* arg_node
= Node::make_node(call
->args()->back());
2345 this->assign(dst
, arg_node
);
2355 Node
* call_node
= Node::make_node(call
);
2356 Node
* ret_node
= call_node
->state(context_
, NULL
)->retvals
[cre
->index()];
2357 this->assign(dst
, ret_node
);
2361 case Expression::EXPRESSION_FUNC_REFERENCE
:
2362 if (e
->func_expression()->closure() != NULL
)
2363 this->flows(dst
, src
);
2366 case Expression::EXPRESSION_CONVERSION
:
2368 Type_conversion_expression
* tce
= e
->conversion_expression();
2369 Type
* ft
= tce
->expr()->type();
2370 Type
* tt
= tce
->type();
2371 if ((ft
->is_string_type() && tt
->is_slice_type())
2372 || (ft
->is_slice_type() && tt
->is_string_type())
2373 || (ft
->integer_type() != NULL
&& tt
->is_string_type()))
2375 // string([]byte), string([]rune), []byte(string), []rune(string), string(rune)
2376 this->flows(dst
, src
);
2379 // Conversion preserves input value.
2380 Expression
* underlying
= tce
->expr();
2381 this->assign(dst
, Node::make_node(underlying
));
2385 case Expression::EXPRESSION_FIELD_REFERENCE
:
2387 // A non-pointer can't escape from a struct.
2388 if (!e
->type()->has_pointer())
2393 case Expression::EXPRESSION_TYPE_GUARD
:
2394 case Expression::EXPRESSION_ARRAY_INDEX
:
2395 case Expression::EXPRESSION_STRING_INDEX
:
2397 Expression
* left
= NULL
;
2398 if (e
->field_reference_expression() != NULL
)
2400 left
= e
->field_reference_expression()->expr();
2401 if (left
->unary_expression() != NULL
2402 && left
->unary_expression()->op() == OPERATOR_MULT
)
2405 this->flows(dst
, src
);
2409 else if (e
->type_guard_expression() != NULL
)
2410 left
= e
->type_guard_expression()->expr();
2411 else if (e
->array_index_expression() != NULL
)
2413 Array_index_expression
* aie
= e
->array_index_expression();
2414 if (aie
->end() != NULL
)
2416 if (aie
->array()->type()->is_slice_type())
2417 left
= aie
->array();
2421 // The gc compiler has an implicit address operator.
2422 go_assert(src
->child() != NULL
);
2423 this->assign(dst
, src
->child());
2426 else if (!aie
->array()->type()->is_slice_type())
2428 // Indexing an array preserves the input value.
2429 Node
* array_node
= Node::make_node(aie
->array());
2430 this->assign(dst
, array_node
);
2435 this->flows(dst
, src
);
2439 else if (e
->string_index_expression() != NULL
)
2441 String_index_expression
* sie
= e
->string_index_expression();
2442 if (e
->type()->is_string_type())
2444 left
= sie
->string();
2447 this->flows(dst
, src
);
2451 go_assert(left
!= NULL
);
2453 // Conversions, field access, and slicing all preserve the input
2455 Node
* left_node
= Node::make_node(left
);
2456 this->assign(dst
, left_node
);
2460 case Expression::EXPRESSION_BINARY
:
2462 switch (e
->binary_expression()->op())
2465 case OPERATOR_MINUS
:
2471 case OPERATOR_LSHIFT
:
2472 case OPERATOR_RSHIFT
:
2474 case OPERATOR_BITCLEAR
:
2476 Node
* left
= Node::make_node(e
->binary_expression()->left());
2477 this->assign(dst
, left
);
2478 Node
* right
= Node::make_node(e
->binary_expression()->right());
2479 this->assign(dst
, right
);
2489 case Expression::EXPRESSION_UNARY
:
2491 switch (e
->unary_expression()->op())
2494 case OPERATOR_MINUS
:
2498 Node::make_node(e
->unary_expression()->operand());
2499 this->assign(dst
, op_node
);
2507 this->flows(dst
, src
);
2516 case Expression::EXPRESSION_TEMPORARY_REFERENCE
:
2518 Statement
* temp
= e
->temporary_reference_expression()->statement();
2519 this->assign(dst
, Node::make_node(temp
));
2524 // TODO(cmang): Add debug info here; this should not be reachable.
2525 // For now, just to be conservative, we'll just say dst flows to src.
2529 else if (src
->statement() != NULL
&& src
->statement()->temporary_statement() != NULL
)
2530 this->flows(dst
, src
);
2533 // Model the assignment of DST to an indirection of SRC.
2536 Escape_analysis_assign::assign_deref(Node
* dst
, Node
* src
)
2538 if (src
->expr() != NULL
)
2540 switch (src
->expr()->classification())
2542 case Expression::EXPRESSION_BOOLEAN
:
2543 case Expression::EXPRESSION_STRING
:
2544 case Expression::EXPRESSION_INTEGER
:
2545 case Expression::EXPRESSION_FLOAT
:
2546 case Expression::EXPRESSION_COMPLEX
:
2547 case Expression::EXPRESSION_NIL
:
2548 case Expression::EXPRESSION_IOTA
:
2549 // No need to try indirections on literal values
2550 // or numeric constants.
2558 this->assign(dst
, this->context_
->add_dereference(src
));
2561 // Model the input-to-output assignment flow of one of a function call's
2562 // arguments, where the flow is encoded in NOTE.
2565 Escape_analysis_assign::assign_from_note(std::string
* note
,
2566 const std::vector
<Node
*>& dsts
,
2569 int enc
= Escape_note::parse_tag(note
);
2570 if (src
->expr() != NULL
)
2572 switch (src
->expr()->classification())
2574 case Expression::EXPRESSION_BOOLEAN
:
2575 case Expression::EXPRESSION_STRING
:
2576 case Expression::EXPRESSION_INTEGER
:
2577 case Expression::EXPRESSION_FLOAT
:
2578 case Expression::EXPRESSION_COMPLEX
:
2579 case Expression::EXPRESSION_NIL
:
2580 case Expression::EXPRESSION_IOTA
:
2581 // There probably isn't a note for a literal value. Literal values
2582 // usually don't escape unless we lost track of the value some how.
2590 if (this->context_
->gogo()->debug_escape_level() > 2)
2591 go_inform(src
->location(), "assignfromtag:: src=%s em=%s",
2592 src
->ast_format(context_
->gogo()).c_str(),
2593 Escape_note::make_tag(enc
).c_str());
2595 if (enc
== Node::ESCAPE_UNKNOWN
)
2597 // Lost track of the value.
2598 this->assign(this->context_
->sink(), src
);
2601 else if (enc
== Node::ESCAPE_NONE
)
2604 // If the content inside a parameter (reached via indirection) escapes to
2605 // the heap, mark it.
2606 if ((enc
& ESCAPE_CONTENT_ESCAPES
) != 0)
2607 this->assign(this->context_
->sink(), this->context_
->add_dereference(src
));
2610 enc
>>= ESCAPE_RETURN_BITS
;
2611 for (std::vector
<Node
*>::const_iterator p
= dsts
.begin();
2612 enc
!= 0 && p
!= dsts
.end();
2615 // Prefer the lowest-level path to the reference (for escape purposes).
2616 // Two-bit encoding (for example. 1, 3, and 4 bits are other options)
2618 // 10 = 1-level, (content escapes),
2619 // 11 = 2-level, (content of content escapes).
2620 int bits
= enc
& ESCAPE_BITS_MASK_FOR_TAG
;
2624 for (int i
= 0; i
< bits
- 1; ++i
)
2626 // Encode level > 0 as indirections.
2627 n
= this->context_
->add_dereference(n
);
2629 this->assign(*p
, n
);
2631 enc
>>= ESCAPE_BITS_PER_OUTPUT_IN_TAG
;
2634 // If there are too many outputs to fit in the tag, that is handled on the
2635 // encoding end as ESCAPE_HEAP, so there is no need to check here.
2639 // Record the flow of SRC to DST in DST.
2642 Escape_analysis_assign::flows(Node
* dst
, Node
* src
)
2644 // Don't bother capturing the flow from scalars.
2645 if (src
->type() != NULL
&& !src
->type()->has_pointer())
2648 // Don't confuse a blank identifier with the sink.
2649 if (dst
->is_sink() && dst
!= this->context_
->sink())
2652 Node::Escape_state
* dst_state
= dst
->state(this->context_
, NULL
);
2653 Node::Escape_state
* src_state
= src
->state(this->context_
, NULL
);
2655 || dst_state
== src_state
2656 || dst_state
->flows
.find(src
) != dst_state
->flows
.end())
2659 Gogo
* gogo
= this->context_
->gogo();
2660 if (gogo
->debug_escape_level() > 2)
2661 go_inform(Linemap::unknown_location(), "flows:: %s <- %s",
2662 dst
->ast_format(gogo
).c_str(), src
->ast_format(gogo
).c_str());
2664 if (dst_state
->flows
.empty())
2665 this->context_
->add_dst(dst
);
2667 dst_state
->flows
.insert(src
);
2670 // Build a connectivity graph between nodes in the function being analyzed.
2673 Gogo::assign_connectivity(Escape_context
* context
, Named_object
* fn
)
2675 // Must be defined outside of this package.
2676 if (!fn
->is_function())
2679 int save_depth
= context
->loop_depth();
2680 context
->set_loop_depth(1);
2682 Escape_analysis_assign
ea(context
, fn
);
2683 Function::Results
* res
= fn
->func_value()->result_variables();
2686 for (Function::Results::const_iterator p
= res
->begin();
2690 Node
* res_node
= Node::make_node(*p
);
2691 Node::Escape_state
* res_state
= res_node
->state(context
, fn
);
2693 res_state
->loop_depth
= 0;
2695 // If this set of functions is recursive, we lose track of the return values.
2696 // Just say that the result flows to the sink.
2697 if (context
->recursive())
2698 ea
.flows(context
->sink(), res_node
);
2702 const Bindings
* callee_bindings
= fn
->func_value()->block()->bindings();
2703 Function_type
* fntype
= fn
->func_value()->type();
2704 Typed_identifier_list
* params
= (fntype
->parameters() != NULL
2705 ? fntype
->parameters()->copy()
2706 : new Typed_identifier_list
);
2707 if (fntype
->receiver() != NULL
)
2708 params
->push_back(*fntype
->receiver());
2710 for (Typed_identifier_list::const_iterator p
= params
->begin();
2714 if (p
->name().empty() || Gogo::is_sink_name(p
->name()))
2717 Named_object
* param_no
= callee_bindings
->lookup_local(p
->name());
2718 go_assert(param_no
!= NULL
);
2719 Node
* param_node
= Node::make_node(param_no
);
2720 Node::Escape_state
* param_state
= param_node
->state(context
, fn
);
2721 param_state
->fn
= fn
;
2722 param_state
->loop_depth
= 1;
2724 if (!p
->type()->has_pointer())
2727 // External function? Parameters must escape unless //go:noescape is set.
2728 // TODO(cmang): Implement //go:noescape directive.
2729 if (fn
->package() != NULL
)
2730 param_node
->set_encoding(Node::ESCAPE_HEAP
);
2733 param_node
->set_encoding(Node::ESCAPE_NONE
);
2734 context
->track(param_node
);
2738 Escape_analysis_loop el
;
2739 fn
->func_value()->traverse(&el
);
2741 fn
->func_value()->traverse(&ea
);
2742 context
->set_loop_depth(save_depth
);
2745 class Escape_analysis_flood
2748 Escape_analysis_flood(Escape_context
* context
)
2752 // Use the escape information in dst to update the escape information in src
2753 // and src's upstream.
2755 flood(Level
, Node
* dst
, Node
* src
, int);
2758 // The escape context for the group of functions being flooded.
2759 Escape_context
* context_
;
2762 // Whenever we hit a dereference node, the level goes up by one, and whenever
2763 // we hit an address-of, the level goes down by one. as long as we're on a
2764 // level > 0 finding an address-of just means we're following the upstream
2765 // of a dereference, so this address doesn't leak (yet).
2766 // If level == 0, it means the /value/ of this node can reach the root of this
2767 // flood so if this node is an address-of, its argument should be marked as
2768 // escaping iff its current function and loop depth are different from the
2770 // Once an object has been moved to the heap, all of its upstream should be
2771 // considered escaping to the global scope.
2772 // This is an implementation of gc/esc.go:escwalkBody.
2775 Escape_analysis_flood::flood(Level level
, Node
* dst
, Node
* src
,
2776 int extra_loop_depth
)
2778 // No need to flood src if it is a literal.
2779 if (src
->expr() != NULL
)
2781 switch (src
->expr()->classification())
2783 case Expression::EXPRESSION_BOOLEAN
:
2784 case Expression::EXPRESSION_STRING
:
2785 case Expression::EXPRESSION_INTEGER
:
2786 case Expression::EXPRESSION_FLOAT
:
2787 case Expression::EXPRESSION_COMPLEX
:
2788 case Expression::EXPRESSION_NIL
:
2789 case Expression::EXPRESSION_IOTA
:
2797 Node::Escape_state
* src_state
= src
->state(this->context_
, NULL
);
2798 if (src_state
->flood_id
== this->context_
->flood_id())
2800 // Esclevels are vectors, do not compare as integers,
2801 // and must use "min" of old and new to guarantee
2803 level
= level
.min(src_state
->level
);
2804 if (level
== src_state
->level
)
2806 // Have we been here already with an extraloopdepth,
2807 // or is the extraloopdepth provided no improvement on
2808 // what's already been seen?
2809 if (src_state
->max_extra_loop_depth
>= extra_loop_depth
2810 || src_state
->loop_depth
>= extra_loop_depth
)
2812 src_state
->max_extra_loop_depth
= extra_loop_depth
;
2816 src_state
->max_extra_loop_depth
= -1;
2818 src_state
->flood_id
= this->context_
->flood_id();
2819 src_state
->level
= level
;
2820 int mod_loop_depth
= std::max(extra_loop_depth
, src_state
->loop_depth
);
2822 Gogo
* gogo
= this->context_
->gogo();
2823 int debug_level
= gogo
->debug_escape_level();
2824 if (debug_level
> 1)
2825 go_inform(Linemap::unknown_location(),
2826 "escwalk: level:{%d %d} depth:%d "
2829 "extraloopdepth=%d",
2830 level
.value(), level
.suffix_value(), this->context_
->pdepth(),
2831 src
->op_format().c_str(),
2832 src
->ast_format(gogo
).c_str(),
2833 src
->details().c_str(),
2834 debug_function_name(src_state
->fn
).c_str(),
2835 src_state
->loop_depth
,
2838 this->context_
->increase_pdepth();
2840 // Input parameter flowing into output parameter?
2841 Named_object
* src_no
= NULL
;
2842 if (src
->expr() != NULL
&& src
->expr()->var_expression() != NULL
)
2843 src_no
= src
->expr()->var_expression()->named_object();
2845 src_no
= src
->object();
2846 bool src_is_param
= (src_no
!= NULL
2847 && src_no
->is_variable()
2848 && src_no
->var_value()->is_parameter());
2850 Named_object
* dst_no
= NULL
;
2851 if (dst
->expr() != NULL
&& dst
->expr()->var_expression() != NULL
)
2852 dst_no
= dst
->expr()->var_expression()->named_object();
2854 dst_no
= dst
->object();
2855 bool dst_is_result
= dst_no
!= NULL
&& dst_no
->is_result_variable();
2856 Node::Escape_state
* dst_state
= dst
->state(this->context_
, NULL
);
2860 && src_state
->fn
== dst_state
->fn
2861 && (src
->encoding() & ESCAPE_MASK
) < int(Node::ESCAPE_HEAP
)
2862 && dst
->encoding() != Node::ESCAPE_HEAP
)
2864 // This case handles:
2867 // 3. tmp := in; return &tmp
2869 if (debug_level
!= 0)
2871 if (debug_level
== 1)
2872 go_inform(src
->definition_location(),
2873 "leaking param: %s to result %s level=%d",
2874 src
->ast_format(gogo
).c_str(),
2875 dst
->ast_format(gogo
).c_str(),
2878 go_inform(src
->definition_location(),
2879 "leaking param: %s to result %s level={%d %d}",
2880 src
->ast_format(gogo
).c_str(),
2881 dst
->ast_format(gogo
).c_str(),
2882 level
.value(), level
.suffix_value());
2885 if ((src
->encoding() & ESCAPE_MASK
) != Node::ESCAPE_RETURN
)
2888 Node::ESCAPE_RETURN
| (src
->encoding() & ESCAPE_CONTENT_ESCAPES
);
2889 src
->set_encoding(enc
);
2892 int enc
= Node::note_inout_flows(src
->encoding(),
2893 dst_no
->result_var_value()->index(),
2895 src
->set_encoding(enc
);
2897 // In gc/esc.go:escwalkBody, this is a goto to the label for recursively
2898 // flooding the connection graph. Inlined here for convenience.
2899 level
= level
.copy();
2900 for (std::set
<Node
*>::const_iterator p
= src_state
->flows
.begin();
2901 p
!= src_state
->flows
.end();
2903 this->flood(level
, dst
, *p
, extra_loop_depth
);
2907 // If parameter content escape to heap, set ESCAPE_CONTENT_ESCAPES.
2908 // Note minor confusion around escape from pointer-to-struct vs
2909 // escape from struct.
2911 && dst
->encoding() == Node::ESCAPE_HEAP
2912 && (src
->encoding() & ESCAPE_MASK
) < int(Node::ESCAPE_HEAP
)
2913 && level
.value() > 0)
2916 Node::max_encoding((src
->encoding() | ESCAPE_CONTENT_ESCAPES
),
2918 src
->set_encoding(enc
);
2919 if (debug_level
!= 0)
2920 go_inform(src
->definition_location(), "mark escaped content: %s",
2921 src
->ast_format(gogo
).c_str());
2924 // A src object leaks if its value or address is assigned to a dst object
2925 // in a different scope (at a different loop depth).
2926 bool src_leaks
= (level
.value() <= 0
2927 && level
.suffix_value() <= 0
2928 && dst_state
->loop_depth
< mod_loop_depth
);
2929 src_leaks
= src_leaks
|| (level
.value() <= 0
2930 && (dst
->encoding() & ESCAPE_MASK
) == Node::ESCAPE_HEAP
);
2931 // old src encoding, used to prevent duplicate error messages
2932 int osrcesc
= src
->encoding();
2935 && (src_leaks
|| dst_state
->loop_depth
< 0)
2936 && (src
->encoding() & ESCAPE_MASK
) < int(Node::ESCAPE_HEAP
))
2938 if (level
.suffix_value() > 0)
2941 Node::max_encoding((src
->encoding() | ESCAPE_CONTENT_ESCAPES
),
2943 src
->set_encoding(enc
);
2944 if (debug_level
!= 0 && osrcesc
!= src
->encoding())
2945 go_inform(src
->definition_location(), "leaking param content: %s",
2946 src
->ast_format(gogo
).c_str());
2950 if (debug_level
!= 0)
2951 go_inform(src
->definition_location(), "leaking param: %s",
2952 src
->ast_format(gogo
).c_str());
2953 src
->set_encoding(Node::ESCAPE_HEAP
);
2956 else if (src
->expr() != NULL
)
2958 Expression
* e
= src
->expr();
2959 if (e
->enclosed_var_expression() != NULL
)
2961 if (src_leaks
&& debug_level
!= 0)
2962 go_inform(src
->location(), "leaking closure reference %s",
2963 src
->ast_format(gogo
).c_str());
2965 Node
* enclosed_node
=
2966 Node::make_node(e
->enclosed_var_expression()->variable());
2967 this->flood(level
, dst
, enclosed_node
, -1);
2969 else if (e
->heap_expression() != NULL
2970 || (e
->unary_expression() != NULL
2971 && e
->unary_expression()->op() == OPERATOR_AND
))
2973 // Pointer literals and address-of expressions.
2974 Expression
* underlying
;
2975 if (e
->heap_expression())
2976 underlying
= e
->heap_expression()->expr();
2978 underlying
= e
->unary_expression()->operand();
2979 Node
* underlying_node
= Node::make_node(underlying
);
2981 // If the address leaks, the underyling object must be moved
2983 underlying
->address_taken(src_leaks
);
2986 src
->set_encoding(Node::ESCAPE_HEAP
);
2987 if (osrcesc
!= src
->encoding())
2989 move_to_heap(gogo
, underlying
);
2990 if (debug_level
> 1)
2991 go_inform(src
->location(),
2992 "%s escapes to heap, level={%d %d}, "
2993 "dst.eld=%d, src.eld=%d",
2994 src
->ast_format(gogo
).c_str(), level
.value(),
2995 level
.suffix_value(), dst_state
->loop_depth
,
2997 else if (debug_level
> 0)
2998 go_inform(src
->location(), "%s escapes to heap",
2999 src
->ast_format(gogo
).c_str());
3002 this->flood(level
.decrease(), dst
,
3003 underlying_node
, mod_loop_depth
);
3004 extra_loop_depth
= mod_loop_depth
;
3008 // Decrease the level each time we take the address of the object.
3009 this->flood(level
.decrease(), dst
, underlying_node
, -1);
3012 else if (e
->slice_literal() != NULL
)
3014 Slice_construction_expression
* slice
= e
->slice_literal();
3015 if (slice
->vals() != NULL
)
3017 for (Expression_list::const_iterator p
= slice
->vals()->begin();
3018 p
!= slice
->vals()->end();
3022 this->flood(level
.decrease(), dst
, Node::make_node(*p
), -1);
3027 src
->set_encoding(Node::ESCAPE_HEAP
);
3028 if (debug_level
!= 0 && osrcesc
!= src
->encoding())
3029 go_inform(src
->location(), "%s escapes to heap",
3030 src
->ast_format(gogo
).c_str());
3031 extra_loop_depth
= mod_loop_depth
;
3034 else if (e
->call_expression() != NULL
)
3036 Call_expression
* call
= e
->call_expression();
3037 if (call
->is_builtin())
3039 Builtin_call_expression
* bce
= call
->builtin_call_expression();
3040 if (bce
->code() == Builtin_call_expression::BUILTIN_APPEND
)
3042 // Propagate escape information to appendee.
3043 Expression
* appendee
= call
->args()->front();
3044 this->flood(level
, dst
, Node::make_node(appendee
), -1);
3047 else if (call
->fn()->func_expression() != NULL
3048 && call
->fn()->func_expression()->is_runtime_function())
3050 switch (call
->fn()->func_expression()->runtime_code())
3052 case Runtime::MAKECHAN
:
3053 case Runtime::MAKECHAN64
:
3054 case Runtime::MAKEMAP
:
3055 case Runtime::MAKESLICE
:
3056 case Runtime::MAKESLICE64
:
3059 src
->set_encoding(Node::ESCAPE_HEAP
);
3060 if (debug_level
!= 0 && osrcesc
!= src
->encoding())
3061 go_inform(src
->location(), "%s escapes to heap",
3062 src
->ast_format(gogo
).c_str());
3063 extra_loop_depth
= mod_loop_depth
;
3071 else if (src_state
->retvals
.size() > 0)
3073 // In this case a link went directly to a call, but should really go
3074 // to the dummy .outN outputs that were created for the call that
3075 // themselves link to the inputs with levels adjusted.
3077 // This can only happen with functions returning a single result.
3078 go_assert(src_state
->retvals
.size() == 1);
3079 if (debug_level
> 2)
3080 go_inform(src
->location(), "[%d] dst %s escwalk replace src: %s with %s",
3081 this->context_
->loop_depth(),
3082 dst
->ast_format(gogo
).c_str(),
3083 src
->ast_format(gogo
).c_str(),
3084 src_state
->retvals
[0]->ast_format(gogo
).c_str());
3085 src
= src_state
->retvals
[0];
3086 src_state
= src
->state(this->context_
, NULL
);
3089 else if (e
->allocation_expression() != NULL
&& src_leaks
)
3091 // Calls to Runtime::NEW get lowered into an allocation expression.
3092 src
->set_encoding(Node::ESCAPE_HEAP
);
3093 if (debug_level
!= 0 && osrcesc
!= src
->encoding())
3094 go_inform(src
->location(), "%s escapes to heap",
3095 src
->ast_format(gogo
).c_str());
3096 extra_loop_depth
= mod_loop_depth
;
3098 else if ((e
->map_literal() != NULL
3099 || e
->string_concat_expression() != NULL
3100 || (e
->func_expression() != NULL
&& e
->func_expression()->closure() != NULL
)
3101 || e
->bound_method_expression() != NULL
)
3104 src
->set_encoding(Node::ESCAPE_HEAP
);
3105 if (debug_level
!= 0 && osrcesc
!= src
->encoding())
3106 go_inform(src
->location(), "%s escapes to heap",
3107 src
->ast_format(gogo
).c_str());
3108 extra_loop_depth
= mod_loop_depth
;
3110 else if (e
->conversion_expression() != NULL
&& src_leaks
)
3112 Type_conversion_expression
* tce
= e
->conversion_expression();
3113 Type
* ft
= tce
->expr()->type();
3114 Type
* tt
= tce
->type();
3115 if ((ft
->is_string_type() && tt
->is_slice_type())
3116 || (ft
->is_slice_type() && tt
->is_string_type())
3117 || (ft
->integer_type() != NULL
&& tt
->is_string_type()))
3119 // string([]byte), string([]rune), []byte(string), []rune(string), string(rune)
3120 src
->set_encoding(Node::ESCAPE_HEAP
);
3121 if (debug_level
!= 0 && osrcesc
!= src
->encoding())
3122 go_inform(src
->location(), "%s escapes to heap",
3123 src
->ast_format(gogo
).c_str());
3124 extra_loop_depth
= mod_loop_depth
;
3127 else if (e
->array_index_expression() != NULL
3128 && !e
->array_index_expression()->array()->type()->is_slice_type())
3130 Array_index_expression
* aie
= e
->array_index_expression();
3131 if (aie
->end() != NULL
)
3133 // Slicing an array.
3134 // Flow its implicit address-of node to DST.
3135 this->flood(level
, dst
, src
->child(), -1);
3139 // Indexing an array.
3140 // An array element flowing to DST behaves like the array
3142 Expression
* underlying
= e
->array_index_expression()->array();
3143 Node
* underlying_node
= Node::make_node(underlying
);
3144 this->flood(level
, dst
, underlying_node
, -1);
3147 else if ((e
->field_reference_expression() != NULL
3148 && e
->field_reference_expression()->expr()->unary_expression() == NULL
)
3149 || e
->type_guard_expression() != NULL
3150 || (e
->array_index_expression() != NULL
3151 && e
->array_index_expression()->end() != NULL
)
3152 || (e
->string_index_expression() != NULL
3153 && e
->type()->is_string_type()))
3155 Expression
* underlying
;
3156 if (e
->field_reference_expression() != NULL
)
3157 underlying
= e
->field_reference_expression()->expr();
3158 else if (e
->type_guard_expression() != NULL
)
3159 underlying
= e
->type_guard_expression()->expr();
3160 else if (e
->array_index_expression() != NULL
)
3161 underlying
= e
->array_index_expression()->array();
3163 underlying
= e
->string_index_expression()->string();
3165 Node
* underlying_node
= Node::make_node(underlying
);
3166 this->flood(level
, dst
, underlying_node
, -1);
3168 else if ((e
->field_reference_expression() != NULL
3169 && e
->field_reference_expression()->expr()->unary_expression() != NULL
)
3170 || e
->array_index_expression() != NULL
3171 || e
->map_index_expression() != NULL
3172 || (e
->unary_expression() != NULL
3173 && e
->unary_expression()->op() == OPERATOR_MULT
))
3175 Expression
* underlying
;
3176 if (e
->field_reference_expression() != NULL
)
3178 underlying
= e
->field_reference_expression()->expr();
3179 underlying
= underlying
->unary_expression()->operand();
3181 else if (e
->array_index_expression() != NULL
)
3182 underlying
= e
->array_index_expression()->array();
3183 else if (e
->map_index_expression() != NULL
)
3184 underlying
= e
->map_index_expression()->map();
3186 underlying
= e
->unary_expression()->operand();
3188 // Increase the level for a dereference.
3189 Node
* underlying_node
= Node::make_node(underlying
);
3190 this->flood(level
.increase(), dst
, underlying_node
, -1);
3192 else if (e
->temporary_reference_expression() != NULL
)
3194 Statement
* t
= e
->temporary_reference_expression()->statement();
3195 this->flood(level
, dst
, Node::make_node(t
), -1);
3198 else if (src
->is_indirect())
3199 // Increase the level for a dereference.
3200 this->flood(level
.increase(), dst
, src
->child(), -1);
3202 level
= level
.copy();
3203 for (std::set
<Node
*>::const_iterator p
= src_state
->flows
.begin();
3204 p
!= src_state
->flows
.end();
3206 this->flood(level
, dst
, *p
, extra_loop_depth
);
3208 this->context_
->decrease_pdepth();
3211 // Propagate escape information across the nodes modeled in this Analysis_set.
3212 // This is an implementation of gc/esc.go:escflood.
3215 Gogo::propagate_escape(Escape_context
* context
, Node
* dst
)
3217 if (dst
->object() == NULL
3218 && (dst
->expr() == NULL
3219 || (dst
->expr()->var_expression() == NULL
3220 && dst
->expr()->enclosed_var_expression() == NULL
3221 && dst
->expr()->func_expression() == NULL
)))
3224 Node::Escape_state
* state
= dst
->state(context
, NULL
);
3225 Gogo
* gogo
= context
->gogo();
3226 if (gogo
->debug_escape_level() > 1)
3227 go_inform(Linemap::unknown_location(), "escflood:%d: dst %s scope:%s[%d]",
3228 context
->flood_id(), dst
->ast_format(gogo
).c_str(),
3229 debug_function_name(state
->fn
).c_str(),
3232 Escape_analysis_flood
eaf(context
);
3233 for (std::set
<Node
*>::const_iterator p
= state
->flows
.begin();
3234 p
!= state
->flows
.end();
3237 context
->increase_flood_id();
3238 eaf
.flood(Level::From(0), dst
, *p
, -1);
3242 class Escape_analysis_tag
3245 Escape_analysis_tag(Escape_context
* context
)
3249 // Add notes to the function's type about the escape information of its
3250 // input parameters.
3252 tag(Named_object
* fn
);
3255 Escape_context
* context_
;
3259 Escape_analysis_tag::tag(Named_object
* fn
)
3261 // External functions are assumed unsafe
3262 // unless //go:noescape is given before the declaration.
3263 if (fn
->package() != NULL
)
3266 if (fn
->is_function_declaration())
3268 Function_declaration
* fdcl
= fn
->func_declaration_value();
3269 if ((fdcl
->pragmas() & GOPRAGMA_NOESCAPE
) != 0)
3271 Function_type
* fntype
= fdcl
->type();
3272 if (fntype
->parameters() != NULL
)
3274 const Typed_identifier_list
* til
= fntype
->parameters();
3276 for (Typed_identifier_list::const_iterator p
= til
->begin();
3279 if (p
->type()->has_pointer())
3280 fntype
->add_parameter_note(i
, Node::ESCAPE_NONE
);
3285 if (!fn
->is_function())
3288 Function_type
* fntype
= fn
->func_value()->type();
3289 Bindings
* bindings
= fn
->func_value()->block()->bindings();
3291 if (fntype
->is_method()
3292 && !fntype
->receiver()->name().empty()
3293 && !Gogo::is_sink_name(fntype
->receiver()->name()))
3295 Named_object
* rcvr_no
= bindings
->lookup(fntype
->receiver()->name());
3296 go_assert(rcvr_no
!= NULL
);
3297 Node
* rcvr_node
= Node::make_node(rcvr_no
);
3298 switch ((rcvr_node
->encoding() & ESCAPE_MASK
))
3300 case Node::ESCAPE_NONE
: // not touched by flood
3301 case Node::ESCAPE_RETURN
:
3302 if (fntype
->receiver()->type()->has_pointer())
3303 // Don't bother tagging for scalars.
3304 fntype
->add_receiver_note(rcvr_node
->encoding());
3307 case Node::ESCAPE_HEAP
: // flooded, moved to heap.
3316 if (fntype
->parameters() != NULL
)
3318 const Typed_identifier_list
* til
= fntype
->parameters();
3319 for (Typed_identifier_list::const_iterator p
= til
->begin();
3323 if (p
->name().empty() || Gogo::is_sink_name(p
->name()))
3325 // Parameter not used in the function body, does not escape.
3326 if (p
->type()->has_pointer())
3327 fntype
->add_parameter_note(i
, Node::ESCAPE_NONE
);
3331 Named_object
* param_no
= bindings
->lookup(p
->name());
3332 go_assert(param_no
!= NULL
);
3333 Node
* param_node
= Node::make_node(param_no
);
3334 switch ((param_node
->encoding() & ESCAPE_MASK
))
3336 case Node::ESCAPE_NONE
: // not touched by flood
3337 case Node::ESCAPE_RETURN
:
3338 if (p
->type()->has_pointer())
3339 // Don't bother tagging for scalars.
3340 fntype
->add_parameter_note(i
, param_node
->encoding());
3343 case Node::ESCAPE_HEAP
: // flooded, moved to heap.
3351 fntype
->set_is_tagged();
3354 // Tag each top-level function with escape information that will be used to
3355 // retain analysis results across imports.
3358 Gogo::tag_function(Escape_context
* context
, Named_object
* fn
)
3360 Escape_analysis_tag
eat(context
);
3364 // Reclaim memory of escape analysis Nodes.
3367 Gogo::reclaim_escape_nodes()
3369 Node::reclaim_nodes();
3373 Node::reclaim_nodes()
3375 for (std::map
<Named_object
*, Node
*>::iterator p
= Node::objects
.begin();
3376 p
!= Node::objects
.end();
3379 Node::objects
.clear();
3381 for (std::map
<Expression
*, Node
*>::iterator p
= Node::expressions
.begin();
3382 p
!= Node::expressions
.end();
3385 Node::expressions
.clear();
3387 for (std::map
<Statement
*, Node
*>::iterator p
= Node::statements
.begin();
3388 p
!= Node::statements
.end();
3391 Node::statements
.clear();
3393 for (std::vector
<Node
*>::iterator p
= Node::indirects
.begin();
3394 p
!= Node::indirects
.end();
3397 Node::indirects
.clear();