compiler: make heap expression's write barrier conditional
authorIan Lance Taylor <ian@gcc.gnu.org>
Mon, 10 Jun 2019 21:08:42 +0000 (21:08 +0000)
committerIan Lance Taylor <ian@gcc.gnu.org>
Mon, 10 Jun 2019 21:08:42 +0000 (21:08 +0000)
    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

gcc/go/gofrontend/MERGE
gcc/go/gofrontend/expressions.cc
gcc/go/gofrontend/gogo.cc
gcc/go/gofrontend/gogo.h

index 9dfa0670c5a962623ecfc05fc7aafd348b4988cc..84c00ae570eb51f4b7f1f9ea2d6fdd41ac26ec0e 100644 (file)
@@ -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.
index 3481d0008682bb4751f24d2c23e71bd40e830eab..d82eebd521e1a5eab62ea4b9c8125bfbf7921d41 100644 (file)
@@ -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);
index 6d51d9e0c9082658c0dd59387f93ca69a310a7f9..62d687056711f13fe2da012d0e3e90999e1d640e 100644 (file)
@@ -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<Bvariable*> vars;
-  std::vector<Bexpression*> var_inits;
+  std::vector<Expression*> var_inits;
   std::vector<Statement*> 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<Bstatement*> 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);
index 7f0cfc52ae7b2a718b18d9a951ea704ad63a3ea1..e50314b62090de1f38ef3b8546067c7ccaf40af5 100644 (file)
@@ -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<std::string, Package*> Imports;