This patch to the Go frontend checks for a notinheap struct at each
struct field.  When generating write barriers, we were only checking
for a notinheap struct at the outermost struct.  That mishandled the
case of setting a pointer to a notinheap struct as a field of another
struct that not notinheap.  This caused an invalid write barrier error
when building the 1.13 version of the runtime.  Bootstrapped and ran
Go testsuite on x86_64-pc-linux-gnu.  Committed to mainline.

Ian
Index: gcc/go/gofrontend/MERGE
===================================================================
--- gcc/go/gofrontend/MERGE     (revision 275239)
+++ gcc/go/gofrontend/MERGE     (working copy)
@@ -1,4 +1,4 @@
-289d94b9e6303ec74649d1f08d418300f2b4d0fd
+3b8a505824abb2a69f4c04c555a4ba29ab8b102b
 
 The first line of this file holds the git revision number of the last
 merge done from the gofrontend repository.
Index: gcc/go/gofrontend/wb.cc
===================================================================
--- gcc/go/gofrontend/wb.cc     (revision 274890)
+++ gcc/go/gofrontend/wb.cc     (working copy)
@@ -733,6 +733,31 @@ Gogo::assign_needs_write_barrier(
          && !lhs->type()->points_to()->in_heap())
        return false;
 
+      // For a struct assignment, we don't need a write barrier if all
+      // the field types can not be in the heap.
+      Struct_type* st = lhs->type()->struct_type();
+      if (st != NULL)
+       {
+         bool in_heap = false;
+         const Struct_field_list* fields = st->fields();
+         for (Struct_field_list::const_iterator p = fields->begin();
+              p != fields->end();
+              p++)
+           {
+             Type* ft = p->type();
+             if (!ft->has_pointer())
+               continue;
+             if (!ft->in_heap())
+               continue;
+             if (ft->points_to() != NULL && !ft->points_to()->in_heap())
+               continue;
+             in_heap = true;
+             break;
+           }
+         if (!in_heap)
+           return false;
+       }
+
       Field_reference_expression* fre = lhs->field_reference_expression();
       if (fre != NULL)
        {
@@ -788,31 +813,6 @@ Gogo::assign_needs_write_barrier(
       && this->is_nonwb_pointer(ue->operand(), nonwb_pointers))
     return false;
 
-  // For a struct assignment, we don't need a write barrier if all the
-  // pointer types can not be in the heap.
-  Struct_type* st = lhs->type()->struct_type();
-  if (st != NULL)
-    {
-      bool in_heap = false;
-      const Struct_field_list* fields = st->fields();
-      for (Struct_field_list::const_iterator p = fields->begin();
-          p != fields->end();
-          p++)
-       {
-         Type* ft = p->type();
-         if (!ft->has_pointer())
-           continue;
-         if (!ft->in_heap())
-           continue;
-         if (ft->points_to() != NULL && !ft->points_to()->in_heap())
-           continue;
-         in_heap = true;
-         break;
-       }
-      if (!in_heap)
-       return false;
-    }
-
   // Write barrier needed in other cases.
   return true;
 }

Reply via email to