From: Ian Lance Taylor Date: Mon, 10 Jun 2019 21:08:42 +0000 (+0000) Subject: compiler: make heap expression's write barrier conditional X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=35c19de69645b18eeef7dbecfcd98b19f9948c84;p=gcc.git compiler: make heap expression's write barrier conditional Heap_expression::do_get_backend emits an unconditional write barrier if the type has pointers and it is not a stack allocation. This CL changes it to use a write barrier for the assignment only when write barriers are enabled. While here, also change it to call gcWriteBarrier instead of typedmemmove for pointer-shaped types. For this to work, Function::build needs to be adjusted so that Heap_expression::do_get_backend is called when there is a parent block. Reviewed-on: https://go-review.googlesource.com/c/gofrontend/+/181540 From-SVN: r272132 --- diff --git a/gcc/go/gofrontend/MERGE b/gcc/go/gofrontend/MERGE index 9dfa0670c5a..84c00ae570e 100644 --- a/gcc/go/gofrontend/MERGE +++ b/gcc/go/gofrontend/MERGE @@ -1,4 +1,4 @@ -11d96c36198b75b0485d16524d521e558cf03312 +764fe6702f2bb8650622d4102de31058e484ecb5 The first line of this file holds the git revision number of the last merge done from the gofrontend repository. diff --git a/gcc/go/gofrontend/expressions.cc b/gcc/go/gofrontend/expressions.cc index 3481d000868..d82eebd521e 100644 --- a/gcc/go/gofrontend/expressions.cc +++ b/gcc/go/gofrontend/expressions.cc @@ -16387,17 +16387,43 @@ Heap_expression::do_get_backend(Translate_context* context) &edecl); Bexpression* btempref = gogo->backend()->var_expression(btemp, loc); - Bexpression* addr = gogo->backend()->address_expression(btempref, loc); - - Expression* td = Expression::make_type_descriptor(etype, loc); - Type* etype_ptr = Type::make_pointer_type(etype); space = gogo->backend()->var_expression(space_temp, loc); + Type* etype_ptr = Type::make_pointer_type(etype); Expression* elhs = Expression::make_backend(space, etype_ptr, loc); - Expression* erhs = Expression::make_backend(addr, etype_ptr, loc); - Expression* call = Runtime::make_call(Runtime::TYPEDMEMMOVE, loc, 3, - td, elhs, erhs); - Bexpression* bcall = call->get_backend(context); - Bstatement* s = gogo->backend()->expression_statement(fndecl, bcall); + Expression* erhs; + Expression* call; + if (etype->is_direct_iface_type()) + { + // Single pointer. + Type* uintptr_type = Type::lookup_integer_type("uintptr"); + erhs = Expression::make_backend(btempref, etype, loc); + erhs = Expression::unpack_direct_iface(erhs, loc); + erhs = Expression::make_unsafe_cast(uintptr_type, erhs, loc); + call = Runtime::make_call(Runtime::GCWRITEBARRIER, loc, 2, + elhs, erhs); + } + else + { + Expression* td = Expression::make_type_descriptor(etype, loc); + Bexpression* addr = + gogo->backend()->address_expression(btempref, loc); + erhs = Expression::make_backend(addr, etype_ptr, loc); + call = Runtime::make_call(Runtime::TYPEDMEMMOVE, loc, 3, + td, elhs, erhs); + } + Statement* cs = Statement::make_statement(call, false); + + space = gogo->backend()->var_expression(space_temp, loc); + Bexpression* ref = + gogo->backend()->indirect_expression(expr_btype, space, true, loc); + Expression* eref = Expression::make_backend(ref, etype, loc); + btempref = gogo->backend()->var_expression(btemp, loc); + erhs = Expression::make_backend(btempref, etype, loc); + Statement* as = Statement::make_assignment(eref, erhs, loc); + + as = gogo->check_write_barrier(context->block(), as, cs); + Bstatement* s = as->get_backend(context); + assn = gogo->backend()->compound_statement(edecl, s); } decl = gogo->backend()->compound_statement(decl, assn); diff --git a/gcc/go/gofrontend/gogo.cc b/gcc/go/gofrontend/gogo.cc index 6d51d9e0c90..62d68705671 100644 --- a/gcc/go/gofrontend/gogo.cc +++ b/gcc/go/gofrontend/gogo.cc @@ -6323,7 +6323,7 @@ Function::build(Gogo* gogo, Named_object* named_function) // Variables that need to be declared for this function and their // initial values. std::vector vars; - std::vector var_inits; + std::vector var_inits; std::vector var_decls_stmts; for (Bindings::const_definitions_iterator p = this->block_->bindings()->begin_definitions(); @@ -6366,7 +6366,7 @@ Function::build(Gogo* gogo, Named_object* named_function) loc); if ((*p)->var_value()->is_in_heap()) parm_ref = Expression::make_heap_expression(parm_ref, loc); - var_inits.push_back(parm_ref->get_backend(&context)); + var_inits.push_back(parm_ref); } else if ((*p)->var_value()->is_in_heap()) { @@ -6383,7 +6383,7 @@ Function::build(Gogo* gogo, Named_object* named_function) Expression* var_ref = Expression::make_var_reference(parm_no, loc); var_ref = Expression::make_heap_expression(var_ref, loc); - var_inits.push_back(var_ref->get_backend(&context)); + var_inits.push_back(var_ref); } param_vars.push_back(parm_bvar); } @@ -6392,15 +6392,15 @@ Function::build(Gogo* gogo, Named_object* named_function) Bvariable* bvar = (*p)->get_backend_variable(gogo, named_function); Type* type = (*p)->result_var_value()->type(); - Bexpression* init; + Expression* init; if (!(*p)->result_var_value()->is_in_heap()) { Btype* btype = type->get_backend(gogo); - init = gogo->backend()->zero_expression(btype); + Bexpression* binit = gogo->backend()->zero_expression(btype); + init = Expression::make_backend(binit, type, loc); } else - init = Expression::make_allocation(type, - loc)->get_backend(&context); + init = Expression::make_allocation(type, loc); vars.push_back(bvar); var_inits.push_back(init); @@ -6473,13 +6473,16 @@ Function::build(Gogo* gogo, Named_object* named_function) Bblock* code_block = this->block_->get_backend(&context); // Initialize variables if necessary. + Translate_context icontext(gogo, named_function, this->block_, + var_decls); std::vector init; go_assert(vars.size() == var_inits.size()); for (size_t i = 0; i < vars.size(); ++i) { + Bexpression* binit = var_inits[i]->get_backend(&icontext); Bstatement* init_stmt = gogo->backend()->init_statement(this->fndecl_, vars[i], - var_inits[i]); + binit); init.push_back(init_stmt); } Bstatement* var_init = gogo->backend()->statement_list(init); diff --git a/gcc/go/gofrontend/gogo.h b/gcc/go/gofrontend/gogo.h index 7f0cfc52ae7..e50314b6209 100644 --- a/gcc/go/gofrontend/gogo.h +++ b/gcc/go/gofrontend/gogo.h @@ -765,6 +765,12 @@ class Gogo assign_with_write_barrier(Function*, Block*, Statement_inserter*, Expression* lhs, Expression* rhs, Location); + // Return a statement that tests whether write barriers are enabled + // and executes either the efficient code (WITHOUT) or the write + // barrier function call (WITH), depending. + Statement* + check_write_barrier(Block*, Statement* without, Statement* with); + // Flatten parse tree. void flatten(); @@ -999,9 +1005,6 @@ class Gogo Named_object* write_barrier_variable(); - Statement* - check_write_barrier(Block*, Statement*, Statement*); - // Type used to map import names to packages. typedef std::map Imports;