diff options
Diffstat (limited to 'gcc/go/gofrontend/escape.cc')
-rw-r--r-- | gcc/go/gofrontend/escape.cc | 79 |
1 files changed, 48 insertions, 31 deletions
diff --git a/gcc/go/gofrontend/escape.cc b/gcc/go/gofrontend/escape.cc index 01329e1..7bab3cb 100644 --- a/gcc/go/gofrontend/escape.cc +++ b/gcc/go/gofrontend/escape.cc @@ -873,13 +873,12 @@ escape_hash_match(std::string suffix, std::string name) void Gogo::analyze_escape() { - if (!optimize_allocation_flag.is_enabled() || saw_errors()) + if (saw_errors()) return; - // Currently runtime is hard-coded to non-escape in various places. - // Don't run escape analysis for runtime. - // TODO: remove this once it works for runtime. - if (this->compiling_runtime() && this->package_name() == "runtime") + if (!optimize_allocation_flag.is_enabled() + && !this->compiling_runtime()) + // We always run escape analysis when compiling runtime. return; // Discover strongly connected groups of functions to analyze for escape @@ -1473,6 +1472,35 @@ Escape_analysis_assign::statement(Block*, size_t*, Statement* s) return TRAVERSE_SKIP_COMPONENTS; } +// Helper function to emit moved-to-heap diagnostics. + +static void +move_to_heap(Gogo* gogo, Expression *expr) +{ + Named_object* no; + if (expr->var_expression() != NULL) + no = expr->var_expression()->named_object(); + else if (expr->enclosed_var_expression() != NULL) + no = expr->enclosed_var_expression()->variable(); + else + return; + + if ((no->is_variable() + && !no->var_value()->is_global()) + || no->is_result_variable()) + { + Node* n = Node::make_node(expr); + if (gogo->debug_escape_level() != 0) + go_inform(n->definition_location(), + "moved to heap: %s", + n->ast_format(gogo).c_str()); + if (gogo->compiling_runtime() && gogo->package_name() == "runtime") + go_error_at(expr->location(), + "%s escapes to heap, not allowed in runtime", + n->ast_format(gogo).c_str()); + } +} + // Model expressions within a function as assignments and flows between nodes. int @@ -1489,13 +1517,7 @@ Escape_analysis_assign::expression(Expression** pexpr) if (debug_level > 1) go_inform((*pexpr)->location(), "%s too large for stack", n->ast_format(gogo).c_str()); - if (debug_level != 0 - && ((*pexpr)->var_expression() != NULL - || (*pexpr)->enclosed_var_expression() != NULL)) - go_inform(n->definition_location(), - "moved to heap: %s", - n->ast_format(gogo).c_str()); - + move_to_heap(gogo, *pexpr); n->set_encoding(Node::ESCAPE_HEAP); (*pexpr)->address_taken(true); this->assign(this->context_->sink(), n); @@ -2968,25 +2990,20 @@ Escape_analysis_flood::flood(Level level, Node* dst, Node* src, if (src_leaks) { src->set_encoding(Node::ESCAPE_HEAP); - if (debug_level != 0 && osrcesc != src->encoding()) - { - if (underlying->var_expression() != NULL - || underlying->enclosed_var_expression() != NULL) - go_inform(underlying_node->definition_location(), - "moved to heap: %s", - underlying_node->ast_format(gogo).c_str()); - - if (debug_level > 1) - go_inform(src->location(), - "%s escapes to heap, level={%d %d}, " - "dst.eld=%d, src.eld=%d", - src->ast_format(gogo).c_str(), level.value(), - level.suffix_value(), dst_state->loop_depth, - mod_loop_depth); - else - go_inform(src->location(), "%s escapes to heap", - src->ast_format(gogo).c_str()); - } + if (osrcesc != src->encoding()) + { + move_to_heap(gogo, underlying); + if (debug_level > 1) + go_inform(src->location(), + "%s escapes to heap, level={%d %d}, " + "dst.eld=%d, src.eld=%d", + src->ast_format(gogo).c_str(), level.value(), + level.suffix_value(), dst_state->loop_depth, + mod_loop_depth); + else if (debug_level > 0) + go_inform(src->location(), "%s escapes to heap", + src->ast_format(gogo).c_str()); + } this->flood(level.decrease(), dst, underlying_node, mod_loop_depth); |