diff options
Diffstat (limited to 'gcc/go/gofrontend/wb.cc')
-rw-r--r-- | gcc/go/gofrontend/wb.cc | 65 |
1 files changed, 57 insertions, 8 deletions
diff --git a/gcc/go/gofrontend/wb.cc b/gcc/go/gofrontend/wb.cc index 77a59ac..fb3ef4d 100644 --- a/gcc/go/gofrontend/wb.cc +++ b/gcc/go/gofrontend/wb.cc @@ -54,14 +54,10 @@ Mark_address_taken::expression(Expression** pexpr) // Slice of an array. The escape analysis models this with // a child Node representing the address of the array. bool escapes = false; - if (!this->gogo_->compiling_runtime() - || this->gogo_->package_name() != "runtime") - { - Node* n = Node::make_node(expr); - if (n->child() == NULL - || (n->child()->encoding() & ESCAPE_MASK) != Node::ESCAPE_NONE) - escapes = true; - } + Node* n = Node::make_node(expr); + if (n->child() == NULL + || (n->child()->encoding() & ESCAPE_MASK) != Node::ESCAPE_NONE) + escapes = true; aie->array()->address_taken(escapes); } @@ -127,6 +123,53 @@ Mark_address_taken::expression(Expression** pexpr) return TRAVERSE_CONTINUE; } +// Check variables and closures do not escape when compiling runtime. + +class Check_escape : public Traverse +{ + public: + Check_escape(Gogo* gogo) + : Traverse(traverse_expressions | traverse_variables), + gogo_(gogo) + { } + + int + expression(Expression**); + + int + variable(Named_object*); + + private: + Gogo* gogo_; +}; + +int +Check_escape::variable(Named_object* no) +{ + if ((no->is_variable() && no->var_value()->is_in_heap()) + || (no->is_result_variable() + && no->result_var_value()->is_in_heap())) + go_error_at(no->location(), + "%s escapes to heap, not allowed in runtime", + no->name().c_str()); + return TRAVERSE_CONTINUE; +} + +int +Check_escape::expression(Expression** pexpr) +{ + Expression* expr = *pexpr; + Func_expression* fe = expr->func_expression(); + if (fe != NULL && fe->closure() != NULL) + { + Node* n = Node::make_node(expr); + if (n->encoding() == Node::ESCAPE_HEAP) + go_error_at(expr->location(), + "heap-allocated closure, not allowed in runtime"); + } + return TRAVERSE_CONTINUE; +} + // Add write barriers to the IR. This are required by the concurrent // garbage collector. A write barrier is needed for any write of a // pointer into memory controlled by the garbage collector. Write @@ -370,6 +413,12 @@ Gogo::add_write_barriers() Mark_address_taken mat(this); this->traverse(&mat); + if (this->compiling_runtime() && this->package_name() == "runtime") + { + Check_escape chk(this); + this->traverse(&chk); + } + Write_barriers wb(this); this->traverse(&wb); } |