comparison gcc/go/gofrontend/escape.cc @ 145:1830386684a0

gcc-9.2.0
author anatofuz
date Thu, 13 Feb 2020 11:34:05 +0900
parents 84e7813d76e9
children
comparison
equal deleted inserted replaced
131:84e7813d76e9 145:1830386684a0
509 || t->is_sink_type() 509 || t->is_sink_type()
510 || t->is_void_type() 510 || t->is_void_type()
511 || t->is_abstract()) 511 || t->is_abstract())
512 return false; 512 return false;
513 513
514 int64_t size; 514 bool big = false;
515 bool ok = t->backend_type_size(context->gogo(), &size); 515 if (t->struct_type() != NULL
516 bool big = ok && (size < 0 || size > 10 * 1024 * 1024); 516 || (t->array_type() != NULL && !t->is_slice_type()))
517 {
518 int64_t size;
519 bool ok = t->backend_type_size(context->gogo(), &size);
520 big = ok && (size < 0 || size > 10 * 1024 * 1024);
521 }
517 522
518 if (this->expr() != NULL) 523 if (this->expr() != NULL)
519 { 524 {
520 if (this->expr()->allocation_expression() != NULL) 525 if (this->expr()->allocation_expression() != NULL)
521 { 526 {
522 ok = t->deref()->backend_type_size(context->gogo(), &size); 527 Type* pt = t->deref();
523 big = big || size <= 0 || size >= (1 << 16); 528 if (pt->struct_type() != NULL
529 || (pt->array_type() != NULL && !pt->is_slice_type()))
530 {
531 int64_t size;
532 bool ok = pt->backend_type_size(context->gogo(), &size);
533 if (ok)
534 big = big || size <= 0 || size >= (1 << 16);
535 }
524 } 536 }
525 else if (this->expr()->call_expression() != NULL) 537 else if (this->expr()->call_expression() != NULL)
526 { 538 {
527 Call_expression* call = this->expr()->call_expression(); 539 Call_expression* call = this->expr()->call_expression();
528 Func_expression* fn = call->fn()->func_expression(); 540 Func_expression* fn = call->fn()->func_expression();
565 && this->expr()->is_sink_expression()) 577 && this->expr()->is_sink_expression())
566 return true; 578 return true;
567 return false; 579 return false;
568 } 580 }
569 581
570 std::map<Named_object*, Node*> Node::objects; 582 Unordered_map(Named_object*, Node*) Node::objects;
571 std::map<Expression*, Node*> Node::expressions; 583 Unordered_map(Expression*, Node*) Node::expressions;
572 std::map<Statement*, Node*> Node::statements; 584 Unordered_map(Statement*, Node*) Node::statements;
573 std::vector<Node*> Node::indirects; 585 std::vector<Node*> Node::indirects;
574 586
575 // Make a object node or return a cached node for this object. 587 // Make a object node or return a cached node for this object.
576 588
577 Node* 589 Node*
578 Node::make_node(Named_object* no) 590 Node::make_node(Named_object* no)
579 { 591 {
580 if (Node::objects.find(no) != Node::objects.end()) 592 std::pair<Named_object*, Node*> val(no, NULL);
581 return Node::objects[no]; 593 std::pair<Unordered_map(Named_object*, Node*)::iterator, bool> ins =
582 594 Node::objects.insert(val);
583 Node* n = new Node(no); 595 if (ins.second)
584 std::pair<Named_object*, Node*> val(no, n); 596 ins.first->second = new Node(no);
585 Node::objects.insert(val); 597 return ins.first->second;
586 return n;
587 } 598 }
588 599
589 // Make an expression node or return a cached node for this expression. 600 // Make an expression node or return a cached node for this expression.
590 601
591 Node* 602 Node*
592 Node::make_node(Expression* e) 603 Node::make_node(Expression* e)
593 { 604 {
594 if (Node::expressions.find(e) != Node::expressions.end()) 605 std::pair<Expression*, Node*> val(e, NULL);
595 return Node::expressions[e]; 606 std::pair<Unordered_map(Expression*, Node*)::iterator, bool> ins =
596 607 Node::expressions.insert(val);
597 Node* n = new Node(e); 608 if (ins.second)
598 std::pair<Expression*, Node*> val(e, n); 609 ins.first->second = new Node(e);
599 Node::expressions.insert(val); 610 return ins.first->second;
600 return n;
601 } 611 }
602 612
603 // Make a statement node or return a cached node for this statement. 613 // Make a statement node or return a cached node for this statement.
604 614
605 Node* 615 Node*
606 Node::make_node(Statement* s) 616 Node::make_node(Statement* s)
607 { 617 {
608 if (Node::statements.find(s) != Node::statements.end()) 618 std::pair<Statement*, Node*> val(s, NULL);
609 return Node::statements[s]; 619 std::pair<Unordered_map(Statement*, Node*)::iterator, bool> ins =
610 620 Node::statements.insert(val);
611 Node* n = new Node(s); 621 if (ins.second)
612 std::pair<Statement*, Node*> val(s, n); 622 ins.first->second = new Node(s);
613 Node::statements.insert(val); 623 return ins.first->second;
614 return n;
615 } 624 }
616 625
617 // Make an indirect node with given child. 626 // Make an indirect node with given child.
618 627
619 Node* 628 Node*
962 continue; 971 continue;
963 if (escapes[*n] != (*n)->encoding()) 972 if (escapes[*n] != (*n)->encoding())
964 { 973 {
965 done = false; 974 done = false;
966 if (this->debug_escape_level() > 2) 975 if (this->debug_escape_level() > 2)
967 go_inform((*n)->location(), "Reflooding %s %s", 976 go_debug((*n)->location(), "Reflooding %s %s",
968 debug_function_name((*n)->state(context, NULL)->fn).c_str(), 977 debug_function_name((*n)->state(context, NULL)->fn).c_str(),
969 (*n)->ast_format(this).c_str()); 978 (*n)->ast_format(this).c_str());
970 escapes[*n] = (*n)->encoding(); 979 escapes[*n] = (*n)->encoding();
971 this->propagate_escape(context, *n); 980 this->propagate_escape(context, *n);
972 } 981 }
973 } 982 }
974 if (done) 983 if (done)
988 n != noesc.end(); 997 n != noesc.end();
989 ++n) 998 ++n)
990 { 999 {
991 Node::Escape_state* state = (*n)->state(context, NULL); 1000 Node::Escape_state* state = (*n)->state(context, NULL);
992 if ((*n)->encoding() == Node::ESCAPE_NONE) 1001 if ((*n)->encoding() == Node::ESCAPE_NONE)
993 go_inform((*n)->location(), "%s %s does not escape", 1002 go_debug((*n)->location(), "%s %s does not escape",
994 strip_packed_prefix(this, debug_function_name(state->fn)).c_str(), 1003 strip_packed_prefix(this, debug_function_name(state->fn)).c_str(),
995 (*n)->ast_format(this).c_str()); 1004 (*n)->ast_format(this).c_str());
996 } 1005 }
997 } 1006 }
998 delete context; 1007 delete context;
999 } 1008 }
1000 } 1009 }
1331 && s->expression_statement() == NULL 1340 && s->expression_statement() == NULL
1332 && !s->is_block_statement()) 1341 && !s->is_block_statement())
1333 { 1342 {
1334 Node* n = Node::make_node(s); 1343 Node* n = Node::make_node(s);
1335 std::string fn_name = this->context_->current_function_name(); 1344 std::string fn_name = this->context_->current_function_name();
1336 go_inform(s->location(), "[%d] %s esc: %s", 1345 go_debug(s->location(), "[%d] %s esc: %s",
1337 this->context_->loop_depth(), fn_name.c_str(), 1346 this->context_->loop_depth(), fn_name.c_str(),
1338 n->ast_format(gogo).c_str()); 1347 n->ast_format(gogo).c_str());
1339 } 1348 }
1340 1349
1341 switch (s->classification()) 1350 switch (s->classification())
1342 { 1351 {
1343 case Statement::STATEMENT_VARIABLE_DECLARATION: 1352 case Statement::STATEMENT_VARIABLE_DECLARATION:
1493 && !no->var_value()->is_global()) 1502 && !no->var_value()->is_global())
1494 || no->is_result_variable()) 1503 || no->is_result_variable())
1495 { 1504 {
1496 Node* n = Node::make_node(expr); 1505 Node* n = Node::make_node(expr);
1497 if (gogo->debug_escape_level() != 0) 1506 if (gogo->debug_escape_level() != 0)
1498 go_inform(n->definition_location(), 1507 go_debug(n->definition_location(),
1499 "moved to heap: %s", 1508 "moved to heap: %s",
1500 n->ast_format(gogo).c_str()); 1509 n->ast_format(gogo).c_str());
1501 if (gogo->compiling_runtime() && gogo->package_name() == "runtime") 1510 if (gogo->compiling_runtime() && gogo->package_name() == "runtime")
1502 go_error_at(expr->location(), 1511 go_error_at(expr->location(),
1503 "%s escapes to heap, not allowed in runtime", 1512 "%s escapes to heap, not allowed in runtime",
1504 n->ast_format(gogo).c_str()); 1513 n->ast_format(gogo).c_str());
1505 } 1514 }
1517 Node* n = Node::make_node(*pexpr); 1526 Node* n = Node::make_node(*pexpr);
1518 if ((n->encoding() & ESCAPE_MASK) != int(Node::ESCAPE_HEAP) 1527 if ((n->encoding() & ESCAPE_MASK) != int(Node::ESCAPE_HEAP)
1519 && n->is_big(this->context_)) 1528 && n->is_big(this->context_))
1520 { 1529 {
1521 if (debug_level > 1) 1530 if (debug_level > 1)
1522 go_inform((*pexpr)->location(), "%s too large for stack", 1531 go_debug((*pexpr)->location(), "%s too large for stack",
1523 n->ast_format(gogo).c_str()); 1532 n->ast_format(gogo).c_str());
1524 move_to_heap(gogo, *pexpr); 1533 move_to_heap(gogo, *pexpr);
1525 n->set_encoding(Node::ESCAPE_HEAP); 1534 n->set_encoding(Node::ESCAPE_HEAP);
1526 (*pexpr)->address_taken(true); 1535 (*pexpr)->address_taken(true);
1527 this->assign(this->context_->sink(), n); 1536 this->assign(this->context_->sink(), n);
1528 } 1537 }
1530 if ((*pexpr)->func_expression() == NULL) 1539 if ((*pexpr)->func_expression() == NULL)
1531 (*pexpr)->traverse_subexpressions(this); 1540 (*pexpr)->traverse_subexpressions(this);
1532 1541
1533 if (debug_level > 1) 1542 if (debug_level > 1)
1534 { 1543 {
1535 Node* n = Node::make_node(*pexpr);
1536 std::string fn_name = this->context_->current_function_name(); 1544 std::string fn_name = this->context_->current_function_name();
1537 go_inform((*pexpr)->location(), "[%d] %s esc: %s", 1545 go_debug((*pexpr)->location(), "[%d] %s esc: %s",
1538 this->context_->loop_depth(), fn_name.c_str(), 1546 this->context_->loop_depth(), fn_name.c_str(),
1539 n->ast_format(gogo).c_str()); 1547 n->ast_format(gogo).c_str());
1540 } 1548 }
1541 1549
1542 switch ((*pexpr)->classification()) 1550 switch ((*pexpr)->classification())
1543 { 1551 {
1544 case Expression::EXPRESSION_CALL: 1552 case Expression::EXPRESSION_CALL:
1564 { 1572 {
1565 // append(slice1, slice2...) -- slice2 itself does not escape, but contents do 1573 // append(slice1, slice2...) -- slice2 itself does not escape, but contents do
1566 Node* appended = Node::make_node(call->args()->back()); 1574 Node* appended = Node::make_node(call->args()->back());
1567 this->assign_deref(this->context_->sink(), appended); 1575 this->assign_deref(this->context_->sink(), appended);
1568 if (debug_level > 2) 1576 if (debug_level > 2)
1569 go_inform((*pexpr)->location(), 1577 go_debug((*pexpr)->location(),
1570 "special treatment of append(slice1, slice2...)"); 1578 "special treatment of append(slice1, slice2...)");
1571 } 1579 }
1572 else 1580 else
1573 { 1581 {
1574 for (Expression_list::const_iterator pa = 1582 for (Expression_list::const_iterator pa =
1575 call->args()->begin() + 1; 1583 call->args()->begin() + 1;
1617 { 1625 {
1618 // Map key escapes. The last argument is the address 1626 // Map key escapes. The last argument is the address
1619 // of the key. 1627 // of the key.
1620 Node* key_node = Node::make_node(call->args()->back()); 1628 Node* key_node = Node::make_node(call->args()->back());
1621 this->assign_deref(this->context_->sink(), key_node); 1629 this->assign_deref(this->context_->sink(), key_node);
1630 }
1631 break;
1632
1633 case Runtime::MAPASSIGN_FAST32PTR:
1634 case Runtime::MAPASSIGN_FAST64PTR:
1635 case Runtime::MAPASSIGN_FASTSTR:
1636 {
1637 // Map key escapes. The last argument is the key.
1638 Node* key_node = Node::make_node(call->args()->back());
1639 this->assign(this->context_->sink(), key_node);
1622 } 1640 }
1623 break; 1641 break;
1624 1642
1625 case Runtime::IFACEE2T2: 1643 case Runtime::IFACEE2T2:
1626 case Runtime::IFACEI2T2: 1644 case Runtime::IFACEI2T2:
1694 1712
1695 this->assign(tce_node, converted); 1713 this->assign(tce_node, converted);
1696 } 1714 }
1697 break; 1715 break;
1698 1716
1717 case Expression::EXPRESSION_UNSAFE_CONVERSION:
1718 {
1719 Unsafe_type_conversion_expression* uce =
1720 (*pexpr)->unsafe_conversion_expression();
1721 Node* expr_node = Node::make_node(uce->expr());
1722 this->assign(n, expr_node);
1723 }
1724 break;
1725
1699 case Expression::EXPRESSION_FIXED_ARRAY_CONSTRUCTION: 1726 case Expression::EXPRESSION_FIXED_ARRAY_CONSTRUCTION:
1700 case Expression::EXPRESSION_SLICE_CONSTRUCTION: 1727 case Expression::EXPRESSION_SLICE_CONSTRUCTION:
1701 { 1728 {
1702 Node* array_node = Node::make_node(*pexpr); 1729 Node* array_node = Node::make_node(*pexpr);
1703 if ((*pexpr)->slice_literal() != NULL) 1730 if ((*pexpr)->slice_literal() != NULL)
1735 } 1762 }
1736 } 1763 }
1737 } 1764 }
1738 break; 1765 break;
1739 1766
1767 case Expression::EXPRESSION_SLICE_VALUE:
1768 {
1769 // Connect the pointer field to the slice value.
1770 Node* slice_node = Node::make_node(*pexpr);
1771 Node* ptr_node =
1772 Node::make_node((*pexpr)->slice_value_expression()->valmem());
1773 this->assign(slice_node, ptr_node);
1774 }
1775 break;
1776
1740 case Expression::EXPRESSION_HEAP: 1777 case Expression::EXPRESSION_HEAP:
1741 { 1778 {
1742 Node* pointer_node = Node::make_node(*pexpr); 1779 Node* pointer_node = Node::make_node(*pexpr);
1743 Node* lit_node = Node::make_node((*pexpr)->heap_expression()->expr()); 1780 Node* lit_node = Node::make_node((*pexpr)->heap_expression()->expr());
1744 this->context_->track(pointer_node); 1781 this->context_->track(pointer_node);
1867 Node* addr_node = Node::make_node(addr); 1904 Node* addr_node = Node::make_node(addr);
1868 n->set_child(addr_node); 1905 n->set_child(addr_node);
1869 this->context_->track(addr_node); 1906 this->context_->track(addr_node);
1870 1907
1871 Node::Escape_state* addr_state = addr_node->state(this->context_, NULL); 1908 Node::Escape_state* addr_state = addr_node->state(this->context_, NULL);
1872 addr_state->loop_depth = array_state->loop_depth; 1909 if (array_state->loop_depth != 0)
1910 addr_state->loop_depth = array_state->loop_depth;
1873 } 1911 }
1874 } 1912 }
1875 break; 1913 break;
1876 1914
1877 case Expression::EXPRESSION_FIELD_REFERENCE: 1915 case Expression::EXPRESSION_FIELD_REFERENCE:
1938 for (std::vector<Node*>::iterator p = arg_nodes.begin(); 1976 for (std::vector<Node*>::iterator p = arg_nodes.begin();
1939 p != arg_nodes.end(); 1977 p != arg_nodes.end();
1940 ++p) 1978 ++p)
1941 { 1979 {
1942 if (debug_level > 2) 1980 if (debug_level > 2)
1943 go_inform(call->location(), 1981 go_debug(call->location(),
1944 "esccall:: indirect call <- %s, untracked", 1982 "esccall:: indirect call <- %s, untracked",
1945 (*p)->ast_format(gogo).c_str()); 1983 (*p)->ast_format(gogo).c_str());
1946 this->assign(this->context_->sink(), *p); 1984 this->assign(this->context_->sink(), *p);
1947 } 1985 }
1948 1986
1949 this->context_->init_retvals(call_node, fntype); 1987 this->context_->init_retvals(call_node, fntype);
1950 1988
1965 if (fn != NULL 2003 if (fn != NULL
1966 && fn->named_object()->is_function() 2004 && fn->named_object()->is_function()
1967 && !fntype->is_tagged()) 2005 && !fntype->is_tagged())
1968 { 2006 {
1969 if (debug_level > 2) 2007 if (debug_level > 2)
1970 go_inform(call->location(), "esccall:: %s in recursive group", 2008 go_debug(call->location(), "esccall:: %s in recursive group",
1971 call_node->ast_format(gogo).c_str()); 2009 call_node->ast_format(gogo).c_str());
1972 2010
1973 Function* f = fn->named_object()->func_value(); 2011 Function* f = fn->named_object()->func_value();
1974 const Bindings* callee_bindings = f->block()->bindings(); 2012 const Bindings* callee_bindings = f->block()->bindings();
1975 Function::Results* results = f->result_variables(); 2013 Function::Results* results = f->result_variables();
1976 if (results != NULL) 2014 if (results != NULL)
2037 } 2075 }
2038 2076
2039 for (; p != arg_nodes.end(); ++p) 2077 for (; p != arg_nodes.end(); ++p)
2040 { 2078 {
2041 if (debug_level > 2) 2079 if (debug_level > 2)
2042 go_inform(call->location(), "esccall:: ... <- %s, untracked", 2080 go_debug(call->location(), "esccall:: ... <- %s, untracked",
2043 (*p)->ast_format(gogo).c_str()); 2081 (*p)->ast_format(gogo).c_str());
2044 this->assign(this->context_->sink(), *p); 2082 this->assign(this->context_->sink(), *p);
2045 } 2083 }
2046 } 2084 }
2047 2085
2048 return; 2086 return;
2049 } 2087 }
2050 2088
2051 if (debug_level > 2) 2089 if (debug_level > 2)
2052 go_inform(call->location(), "esccall:: %s not recursive", 2090 go_debug(call->location(), "esccall:: %s not recursive",
2053 call_node->ast_format(gogo).c_str()); 2091 call_node->ast_format(gogo).c_str());
2054 2092
2055 Node::Escape_state* call_state = call_node->state(this->context_, NULL); 2093 Node::Escape_state* call_state = call_node->state(this->context_, NULL);
2056 if (!call_state->retvals.empty()) 2094 if (!call_state->retvals.empty())
2057 go_error_at(Linemap::unknown_location(), 2095 go_error_at(Linemap::unknown_location(),
2058 "esc already decorated call %s", 2096 "esc already decorated call %s",
2124 } 2162 }
2125 2163
2126 for (; p != arg_nodes.end(); ++p) 2164 for (; p != arg_nodes.end(); ++p)
2127 { 2165 {
2128 if (debug_level > 2) 2166 if (debug_level > 2)
2129 go_inform(call->location(), "esccall:: ... <- %s, untracked", 2167 go_debug(call->location(), "esccall:: ... <- %s, untracked",
2130 (*p)->ast_format(gogo).c_str()); 2168 (*p)->ast_format(gogo).c_str());
2131 this->assign(this->context_->sink(), *p); 2169 this->assign(this->context_->sink(), *p);
2132 } 2170 }
2133 } 2171 }
2134 } 2172 }
2135 2173
2143 Escape_analysis_assign::assign(Node* dst, Node* src) 2181 Escape_analysis_assign::assign(Node* dst, Node* src)
2144 { 2182 {
2145 Gogo* gogo = this->context_->gogo(); 2183 Gogo* gogo = this->context_->gogo();
2146 int debug_level = gogo->debug_escape_level(); 2184 int debug_level = gogo->debug_escape_level();
2147 if (debug_level > 1) 2185 if (debug_level > 1)
2148 go_inform(dst->location(), "[%d] %s escassign: %s(%s)[%s] = %s(%s)[%s]", 2186 go_debug(dst->location(), "[%d] %s escassign: %s(%s)[%s] = %s(%s)[%s]",
2149 this->context_->loop_depth(), 2187 this->context_->loop_depth(),
2150 strip_packed_prefix(gogo, this->context_->current_function_name()).c_str(), 2188 strip_packed_prefix(gogo, this->context_->current_function_name()).c_str(),
2151 dst->ast_format(gogo).c_str(), dst->details().c_str(), 2189 dst->ast_format(gogo).c_str(), dst->details().c_str(),
2152 dst->op_format().c_str(), 2190 dst->op_format().c_str(),
2153 src->ast_format(gogo).c_str(), src->details().c_str(), 2191 src->ast_format(gogo).c_str(), src->details().c_str(),
2154 src->op_format().c_str()); 2192 src->op_format().c_str());
2155 2193
2156 if (dst->is_indirect()) 2194 if (dst->is_indirect())
2157 // Lose track of the dereference. 2195 // Lose track of the dereference.
2158 dst = this->context_->sink(); 2196 dst = this->context_->sink();
2159 else if (dst->expr() != NULL) 2197 else if (dst->expr() != NULL)
2261 // DST = [...]T{...}. 2299 // DST = [...]T{...}.
2262 case Expression::EXPRESSION_MAP_CONSTRUCTION: 2300 case Expression::EXPRESSION_MAP_CONSTRUCTION:
2263 // DST = map[T]V{...}. 2301 // DST = map[T]V{...}.
2264 case Expression::EXPRESSION_STRUCT_CONSTRUCTION: 2302 case Expression::EXPRESSION_STRUCT_CONSTRUCTION:
2265 // DST = T{...}. 2303 // DST = T{...}.
2304 case Expression::EXPRESSION_SLICE_VALUE:
2305 // DST = slice{ptr, len, cap}
2266 case Expression::EXPRESSION_ALLOCATION: 2306 case Expression::EXPRESSION_ALLOCATION:
2267 // DST = new(T). 2307 // DST = new(T).
2268 case Expression::EXPRESSION_BOUND_METHOD: 2308 case Expression::EXPRESSION_BOUND_METHOD:
2269 // DST = x.M. 2309 // DST = x.M.
2270 case Expression::EXPRESSION_STRING_CONCAT: 2310 case Expression::EXPRESSION_STRING_CONCAT:
2393 Type_conversion_expression* tce = e->conversion_expression(); 2433 Type_conversion_expression* tce = e->conversion_expression();
2394 Type* ft = tce->expr()->type(); 2434 Type* ft = tce->expr()->type();
2395 Type* tt = tce->type(); 2435 Type* tt = tce->type();
2396 if ((ft->is_string_type() && tt->is_slice_type()) 2436 if ((ft->is_string_type() && tt->is_slice_type())
2397 || (ft->is_slice_type() && tt->is_string_type()) 2437 || (ft->is_slice_type() && tt->is_string_type())
2398 || (ft->integer_type() != NULL && tt->is_string_type())) 2438 || (ft->integer_type() != NULL && tt->is_string_type())
2439 || tt->interface_type() != NULL)
2399 { 2440 {
2400 // string([]byte), string([]rune), []byte(string), []rune(string), string(rune) 2441 // string([]byte), string([]rune), []byte(string), []rune(string), string(rune),
2442 // interface(T)
2401 this->flows(dst, src); 2443 this->flows(dst, src);
2402 break; 2444 break;
2403 } 2445 }
2404 // Conversion preserves input value. 2446 // Conversion preserves input value.
2405 Expression* underlying = tce->expr(); 2447 Expression* underlying = tce->expr();
2611 break; 2653 break;
2612 } 2654 }
2613 } 2655 }
2614 2656
2615 if (this->context_->gogo()->debug_escape_level() > 2) 2657 if (this->context_->gogo()->debug_escape_level() > 2)
2616 go_inform(src->location(), "assignfromtag:: src=%s em=%s", 2658 go_debug(src->location(), "assignfromtag:: src=%s em=%s",
2617 src->ast_format(context_->gogo()).c_str(), 2659 src->ast_format(context_->gogo()).c_str(),
2618 Escape_note::make_tag(enc).c_str()); 2660 Escape_note::make_tag(enc).c_str());
2619 2661
2620 if (enc == Node::ESCAPE_UNKNOWN) 2662 if (enc == Node::ESCAPE_UNKNOWN)
2621 { 2663 {
2622 // Lost track of the value. 2664 // Lost track of the value.
2623 this->assign(this->context_->sink(), src); 2665 this->assign(this->context_->sink(), src);
2681 || dst_state->flows.find(src) != dst_state->flows.end()) 2723 || dst_state->flows.find(src) != dst_state->flows.end())
2682 return; 2724 return;
2683 2725
2684 Gogo* gogo = this->context_->gogo(); 2726 Gogo* gogo = this->context_->gogo();
2685 if (gogo->debug_escape_level() > 2) 2727 if (gogo->debug_escape_level() > 2)
2686 go_inform(Linemap::unknown_location(), "flows:: %s <- %s", 2728 go_debug(Linemap::unknown_location(), "flows:: %s <- %s",
2687 dst->ast_format(gogo).c_str(), src->ast_format(gogo).c_str()); 2729 dst->ast_format(gogo).c_str(), src->ast_format(gogo).c_str());
2688 2730
2689 if (dst_state->flows.empty()) 2731 if (dst_state->flows.empty())
2690 this->context_->add_dst(dst); 2732 this->context_->add_dst(dst);
2691 2733
2692 dst_state->flows.insert(src); 2734 dst_state->flows.insert(src);
2747 param_state->loop_depth = 1; 2789 param_state->loop_depth = 1;
2748 2790
2749 if (!p->type()->has_pointer()) 2791 if (!p->type()->has_pointer())
2750 continue; 2792 continue;
2751 2793
2752 // External function? Parameters must escape unless //go:noescape is set. 2794 param_node->set_encoding(Node::ESCAPE_NONE);
2753 // TODO(cmang): Implement //go:noescape directive. 2795 context->track(param_node);
2754 if (fn->package() != NULL)
2755 param_node->set_encoding(Node::ESCAPE_HEAP);
2756 else
2757 {
2758 param_node->set_encoding(Node::ESCAPE_NONE);
2759 context->track(param_node);
2760 }
2761 } 2796 }
2762 2797
2763 Escape_analysis_loop el; 2798 Escape_analysis_loop el;
2764 fn->func_value()->traverse(&el); 2799 fn->func_value()->traverse(&el);
2765 2800
2845 int mod_loop_depth = std::max(extra_loop_depth, src_state->loop_depth); 2880 int mod_loop_depth = std::max(extra_loop_depth, src_state->loop_depth);
2846 2881
2847 Gogo* gogo = this->context_->gogo(); 2882 Gogo* gogo = this->context_->gogo();
2848 int debug_level = gogo->debug_escape_level(); 2883 int debug_level = gogo->debug_escape_level();
2849 if (debug_level > 1) 2884 if (debug_level > 1)
2850 go_inform(Linemap::unknown_location(), 2885 go_debug(Linemap::unknown_location(),
2851 "escwalk: level:{%d %d} depth:%d " 2886 "escwalk: level:{%d %d} depth:%d "
2852 "op=%s %s(%s) " 2887 "op=%s %s(%s) "
2853 "scope:%s[%d] " 2888 "scope:%s[%d] "
2854 "extraloopdepth=%d", 2889 "extraloopdepth=%d",
2855 level.value(), level.suffix_value(), this->context_->pdepth(), 2890 level.value(), level.suffix_value(), this->context_->pdepth(),
2856 src->op_format().c_str(), 2891 src->op_format().c_str(),
2857 src->ast_format(gogo).c_str(), 2892 src->ast_format(gogo).c_str(),
2858 src->details().c_str(), 2893 src->details().c_str(),
2859 debug_function_name(src_state->fn).c_str(), 2894 debug_function_name(src_state->fn).c_str(),
2860 src_state->loop_depth, 2895 src_state->loop_depth,
2861 extra_loop_depth); 2896 extra_loop_depth);
2862 2897
2863 this->context_->increase_pdepth(); 2898 this->context_->increase_pdepth();
2864 2899
2865 // Input parameter flowing into output parameter? 2900 // Input parameter flowing into output parameter?
2866 Named_object* src_no = NULL; 2901 Named_object* src_no = NULL;
2892 // 3. tmp := in; return &tmp 2927 // 3. tmp := in; return &tmp
2893 // 4. return *in 2928 // 4. return *in
2894 if (debug_level != 0) 2929 if (debug_level != 0)
2895 { 2930 {
2896 if (debug_level == 1) 2931 if (debug_level == 1)
2897 go_inform(src->definition_location(), 2932 go_debug(src->definition_location(),
2898 "leaking param: %s to result %s level=%d", 2933 "leaking param: %s to result %s level=%d",
2899 src->ast_format(gogo).c_str(), 2934 src->ast_format(gogo).c_str(),
2900 dst->ast_format(gogo).c_str(), 2935 dst->ast_format(gogo).c_str(),
2901 level.value()); 2936 level.value());
2902 else 2937 else
2903 go_inform(src->definition_location(), 2938 go_debug(src->definition_location(),
2904 "leaking param: %s to result %s level={%d %d}", 2939 "leaking param: %s to result %s level={%d %d}",
2905 src->ast_format(gogo).c_str(), 2940 src->ast_format(gogo).c_str(),
2906 dst->ast_format(gogo).c_str(), 2941 dst->ast_format(gogo).c_str(),
2907 level.value(), level.suffix_value()); 2942 level.value(), level.suffix_value());
2908 } 2943 }
2909 2944
2910 if ((src->encoding() & ESCAPE_MASK) != Node::ESCAPE_RETURN) 2945 if ((src->encoding() & ESCAPE_MASK) != Node::ESCAPE_RETURN)
2911 { 2946 {
2912 int enc = 2947 int enc =
2940 int enc = 2975 int enc =
2941 Node::max_encoding((src->encoding() | ESCAPE_CONTENT_ESCAPES), 2976 Node::max_encoding((src->encoding() | ESCAPE_CONTENT_ESCAPES),
2942 Node::ESCAPE_NONE); 2977 Node::ESCAPE_NONE);
2943 src->set_encoding(enc); 2978 src->set_encoding(enc);
2944 if (debug_level != 0) 2979 if (debug_level != 0)
2945 go_inform(src->definition_location(), "mark escaped content: %s", 2980 go_debug(src->definition_location(), "mark escaped content: %s",
2946 src->ast_format(gogo).c_str()); 2981 src->ast_format(gogo).c_str());
2947 } 2982 }
2948 2983
2949 // A src object leaks if its value or address is assigned to a dst object 2984 // A src object leaks if its value or address is assigned to a dst object
2950 // in a different scope (at a different loop depth). 2985 // in a different scope (at a different loop depth).
2951 bool src_leaks = (level.value() <= 0 2986 bool src_leaks = (level.value() <= 0
2965 int enc = 3000 int enc =
2966 Node::max_encoding((src->encoding() | ESCAPE_CONTENT_ESCAPES), 3001 Node::max_encoding((src->encoding() | ESCAPE_CONTENT_ESCAPES),
2967 Node::ESCAPE_NONE); 3002 Node::ESCAPE_NONE);
2968 src->set_encoding(enc); 3003 src->set_encoding(enc);
2969 if (debug_level != 0 && osrcesc != src->encoding()) 3004 if (debug_level != 0 && osrcesc != src->encoding())
2970 go_inform(src->definition_location(), "leaking param content: %s", 3005 go_debug(src->definition_location(), "leaking param content: %s",
2971 src->ast_format(gogo).c_str()); 3006 src->ast_format(gogo).c_str());
2972 } 3007 }
2973 else 3008 else
2974 { 3009 {
2975 if (debug_level != 0) 3010 if (debug_level != 0)
2976 go_inform(src->definition_location(), "leaking param: %s", 3011 go_debug(src->definition_location(), "leaking param: %s",
2977 src->ast_format(gogo).c_str()); 3012 src->ast_format(gogo).c_str());
2978 src->set_encoding(Node::ESCAPE_HEAP); 3013 src->set_encoding(Node::ESCAPE_HEAP);
2979 } 3014 }
2980 } 3015 }
2981 else if (src->expr() != NULL) 3016 else if (src->expr() != NULL)
2982 { 3017 {
2983 Expression* e = src->expr(); 3018 Expression* e = src->expr();
2984 if (e->enclosed_var_expression() != NULL) 3019 if (e->enclosed_var_expression() != NULL)
2985 { 3020 {
2986 if (src_leaks && debug_level != 0) 3021 if (src_leaks && debug_level != 0)
2987 go_inform(src->location(), "leaking closure reference %s", 3022 go_debug(src->location(), "leaking closure reference %s",
2988 src->ast_format(gogo).c_str()); 3023 src->ast_format(gogo).c_str());
2989 3024
2990 Node* enclosed_node = 3025 Node* enclosed_node =
2991 Node::make_node(e->enclosed_var_expression()->variable()); 3026 Node::make_node(e->enclosed_var_expression()->variable());
2992 this->flood(level, dst, enclosed_node, -1); 3027 this->flood(level, dst, enclosed_node, -1);
2993 } 3028 }
3011 src->set_encoding(Node::ESCAPE_HEAP); 3046 src->set_encoding(Node::ESCAPE_HEAP);
3012 if (osrcesc != src->encoding()) 3047 if (osrcesc != src->encoding())
3013 { 3048 {
3014 move_to_heap(gogo, underlying); 3049 move_to_heap(gogo, underlying);
3015 if (debug_level > 1) 3050 if (debug_level > 1)
3016 go_inform(src->location(), 3051 go_debug(src->location(),
3017 "%s escapes to heap, level={%d %d}, " 3052 "%s escapes to heap, level={%d %d}, "
3018 "dst.eld=%d, src.eld=%d", 3053 "dst.eld=%d, src.eld=%d",
3019 src->ast_format(gogo).c_str(), level.value(), 3054 src->ast_format(gogo).c_str(), level.value(),
3020 level.suffix_value(), dst_state->loop_depth, 3055 level.suffix_value(), dst_state->loop_depth,
3021 mod_loop_depth); 3056 mod_loop_depth);
3022 else if (debug_level > 0) 3057 else if (debug_level > 0)
3023 go_inform(src->location(), "%s escapes to heap", 3058 go_debug(src->location(), "%s escapes to heap",
3024 src->ast_format(gogo).c_str()); 3059 src->ast_format(gogo).c_str());
3025 } 3060 }
3026 3061
3027 this->flood(level.decrease(), dst, 3062 this->flood(level.decrease(), dst,
3028 underlying_node, mod_loop_depth); 3063 underlying_node, mod_loop_depth);
3029 extra_loop_depth = mod_loop_depth; 3064 extra_loop_depth = mod_loop_depth;
3049 } 3084 }
3050 if (src_leaks) 3085 if (src_leaks)
3051 { 3086 {
3052 src->set_encoding(Node::ESCAPE_HEAP); 3087 src->set_encoding(Node::ESCAPE_HEAP);
3053 if (debug_level != 0 && osrcesc != src->encoding()) 3088 if (debug_level != 0 && osrcesc != src->encoding())
3054 go_inform(src->location(), "%s escapes to heap", 3089 go_debug(src->location(), "%s escapes to heap",
3055 src->ast_format(gogo).c_str()); 3090 src->ast_format(gogo).c_str());
3056 extra_loop_depth = mod_loop_depth; 3091 extra_loop_depth = mod_loop_depth;
3057 } 3092 }
3058 } 3093 }
3059 else if (e->call_expression() != NULL) 3094 else if (e->call_expression() != NULL)
3060 { 3095 {
3081 case Runtime::MAKESLICE64: 3116 case Runtime::MAKESLICE64:
3082 if (src_leaks) 3117 if (src_leaks)
3083 { 3118 {
3084 src->set_encoding(Node::ESCAPE_HEAP); 3119 src->set_encoding(Node::ESCAPE_HEAP);
3085 if (debug_level != 0 && osrcesc != src->encoding()) 3120 if (debug_level != 0 && osrcesc != src->encoding())
3086 go_inform(src->location(), "%s escapes to heap", 3121 go_debug(src->location(), "%s escapes to heap",
3087 src->ast_format(gogo).c_str()); 3122 src->ast_format(gogo).c_str());
3088 extra_loop_depth = mod_loop_depth; 3123 extra_loop_depth = mod_loop_depth;
3089 } 3124 }
3090 break; 3125 break;
3091 3126
3092 default: 3127 default:
3100 // themselves link to the inputs with levels adjusted. 3135 // themselves link to the inputs with levels adjusted.
3101 // See e.g. #10466. 3136 // See e.g. #10466.
3102 // This can only happen with functions returning a single result. 3137 // This can only happen with functions returning a single result.
3103 go_assert(src_state->retvals.size() == 1); 3138 go_assert(src_state->retvals.size() == 1);
3104 if (debug_level > 2) 3139 if (debug_level > 2)
3105 go_inform(src->location(), "[%d] dst %s escwalk replace src: %s with %s", 3140 go_debug(src->location(), "[%d] dst %s escwalk replace src: %s with %s",
3106 this->context_->loop_depth(), 3141 this->context_->loop_depth(),
3107 dst->ast_format(gogo).c_str(), 3142 dst->ast_format(gogo).c_str(),
3108 src->ast_format(gogo).c_str(), 3143 src->ast_format(gogo).c_str(),
3109 src_state->retvals[0]->ast_format(gogo).c_str()); 3144 src_state->retvals[0]->ast_format(gogo).c_str());
3110 src = src_state->retvals[0]; 3145 src = src_state->retvals[0];
3111 src_state = src->state(this->context_, NULL); 3146 src_state = src->state(this->context_, NULL);
3112 } 3147 }
3113 } 3148 }
3114 else if (e->allocation_expression() != NULL && src_leaks) 3149 else if (e->allocation_expression() != NULL && src_leaks)
3115 { 3150 {
3116 // Calls to Runtime::NEW get lowered into an allocation expression. 3151 // Calls to Runtime::NEW get lowered into an allocation expression.
3117 src->set_encoding(Node::ESCAPE_HEAP); 3152 src->set_encoding(Node::ESCAPE_HEAP);
3118 if (debug_level != 0 && osrcesc != src->encoding()) 3153 if (debug_level != 0 && osrcesc != src->encoding())
3119 go_inform(src->location(), "%s escapes to heap", 3154 go_debug(src->location(), "%s escapes to heap",
3120 src->ast_format(gogo).c_str()); 3155 src->ast_format(gogo).c_str());
3121 extra_loop_depth = mod_loop_depth; 3156 extra_loop_depth = mod_loop_depth;
3122 } 3157 }
3123 else if ((e->map_literal() != NULL 3158 else if ((e->map_literal() != NULL
3124 || e->string_concat_expression() != NULL 3159 || e->string_concat_expression() != NULL
3125 || (e->func_expression() != NULL && e->func_expression()->closure() != NULL) 3160 || (e->func_expression() != NULL && e->func_expression()->closure() != NULL)
3126 || e->bound_method_expression() != NULL) 3161 || e->bound_method_expression() != NULL)
3127 && src_leaks) 3162 && src_leaks)
3128 { 3163 {
3129 src->set_encoding(Node::ESCAPE_HEAP); 3164 src->set_encoding(Node::ESCAPE_HEAP);
3130 if (debug_level != 0 && osrcesc != src->encoding()) 3165 if (debug_level != 0 && osrcesc != src->encoding())
3131 go_inform(src->location(), "%s escapes to heap", 3166 go_debug(src->location(), "%s escapes to heap",
3132 src->ast_format(gogo).c_str()); 3167 src->ast_format(gogo).c_str());
3133 extra_loop_depth = mod_loop_depth; 3168 extra_loop_depth = mod_loop_depth;
3134 } 3169 }
3135 else if (e->conversion_expression() != NULL && src_leaks) 3170 else if (e->conversion_expression() != NULL && src_leaks)
3136 { 3171 {
3137 Type_conversion_expression* tce = e->conversion_expression(); 3172 Type_conversion_expression* tce = e->conversion_expression();
3138 Type* ft = tce->expr()->type(); 3173 Type* ft = tce->expr()->type();
3139 Type* tt = tce->type(); 3174 Type* tt = tce->type();
3140 if ((ft->is_string_type() && tt->is_slice_type()) 3175 if ((ft->is_string_type() && tt->is_slice_type())
3141 || (ft->is_slice_type() && tt->is_string_type()) 3176 || (ft->is_slice_type() && tt->is_string_type())
3142 || (ft->integer_type() != NULL && tt->is_string_type())) 3177 || (ft->integer_type() != NULL && tt->is_string_type())
3178 || tt->interface_type() != NULL)
3143 { 3179 {
3144 // string([]byte), string([]rune), []byte(string), []rune(string), string(rune) 3180 // string([]byte), string([]rune), []byte(string), []rune(string), string(rune),
3181 // interface(T)
3145 src->set_encoding(Node::ESCAPE_HEAP); 3182 src->set_encoding(Node::ESCAPE_HEAP);
3146 if (debug_level != 0 && osrcesc != src->encoding()) 3183 if (debug_level != 0 && osrcesc != src->encoding())
3147 go_inform(src->location(), "%s escapes to heap", 3184 go_debug(src->location(), "%s escapes to heap",
3148 src->ast_format(gogo).c_str()); 3185 src->ast_format(gogo).c_str());
3149 extra_loop_depth = mod_loop_depth; 3186 extra_loop_depth = mod_loop_depth;
3187 if (tt->interface_type() != NULL
3188 && ft->has_pointer()
3189 && !ft->is_direct_iface_type())
3190 // We're converting from a non-direct interface type.
3191 // The interface will hold a heap copy of the data
3192 // Flow the data to heap. See issue 29353.
3193 this->flood(level, this->context_->sink(),
3194 Node::make_node(tce->expr()), -1);
3150 } 3195 }
3151 } 3196 }
3152 else if (e->array_index_expression() != NULL 3197 else if (e->array_index_expression() != NULL
3153 && !e->array_index_expression()->array()->type()->is_slice_type()) 3198 && !e->array_index_expression()->array()->type()->is_slice_type())
3154 { 3199 {
3247 return; 3292 return;
3248 3293
3249 Node::Escape_state* state = dst->state(context, NULL); 3294 Node::Escape_state* state = dst->state(context, NULL);
3250 Gogo* gogo = context->gogo(); 3295 Gogo* gogo = context->gogo();
3251 if (gogo->debug_escape_level() > 1) 3296 if (gogo->debug_escape_level() > 1)
3252 go_inform(Linemap::unknown_location(), "escflood:%d: dst %s scope:%s[%d]", 3297 go_debug(Linemap::unknown_location(), "escflood:%d: dst %s scope:%s[%d]",
3253 context->flood_id(), dst->ast_format(gogo).c_str(), 3298 context->flood_id(), dst->ast_format(gogo).c_str(),
3254 debug_function_name(state->fn).c_str(), 3299 debug_function_name(state->fn).c_str(),
3255 state->loop_depth); 3300 state->loop_depth);
3256 3301
3257 Escape_analysis_flood eaf(context); 3302 Escape_analysis_flood eaf(context);
3258 for (std::set<Node*>::const_iterator p = state->flows.begin(); 3303 for (std::set<Node*>::const_iterator p = state->flows.begin();
3259 p != state->flows.end(); 3304 p != state->flows.end();
3260 ++p) 3305 ++p)
3283 void 3328 void
3284 Escape_analysis_tag::tag(Named_object* fn) 3329 Escape_analysis_tag::tag(Named_object* fn)
3285 { 3330 {
3286 // External functions are assumed unsafe 3331 // External functions are assumed unsafe
3287 // unless //go:noescape is given before the declaration. 3332 // unless //go:noescape is given before the declaration.
3288 if (fn->package() != NULL)
3289 return;
3290
3291 if (fn->is_function_declaration()) 3333 if (fn->is_function_declaration())
3292 { 3334 {
3293 Function_declaration* fdcl = fn->func_declaration_value(); 3335 Function_declaration* fdcl = fn->func_declaration_value();
3294 if ((fdcl->pragmas() & GOPRAGMA_NOESCAPE) != 0) 3336 if ((fdcl->pragmas() & GOPRAGMA_NOESCAPE) != 0)
3295 { 3337 {
3400 } 3442 }
3401 3443
3402 void 3444 void
3403 Node::reclaim_nodes() 3445 Node::reclaim_nodes()
3404 { 3446 {
3405 for (std::map<Named_object*, Node*>::iterator p = Node::objects.begin(); 3447 for (Unordered_map(Named_object*, Node*)::iterator p =
3448 Node::objects.begin();
3406 p != Node::objects.end(); 3449 p != Node::objects.end();
3407 ++p) 3450 ++p)
3408 delete p->second; 3451 delete p->second;
3409 Node::objects.clear(); 3452 Node::objects.clear();
3410 3453
3411 for (std::map<Expression*, Node*>::iterator p = Node::expressions.begin(); 3454 for (Unordered_map(Expression*, Node*)::iterator p =
3455 Node::expressions.begin();
3412 p != Node::expressions.end(); 3456 p != Node::expressions.end();
3413 ++p) 3457 ++p)
3414 delete p->second; 3458 delete p->second;
3415 Node::expressions.clear(); 3459 Node::expressions.clear();
3416 3460
3417 for (std::map<Statement*, Node*>::iterator p = Node::statements.begin(); 3461 for (Unordered_map(Statement*, Node*)::iterator p =
3462 Node::statements.begin();
3418 p != Node::statements.end(); 3463 p != Node::statements.end();
3419 ++p) 3464 ++p)
3420 delete p->second; 3465 delete p->second;
3421 Node::statements.clear(); 3466 Node::statements.clear();
3422 3467