compiler: check for notinheap struct at each struct field
authorIan Lance Taylor <ian@gcc.gnu.org>
Sat, 31 Aug 2019 03:07:48 +0000 (03:07 +0000)
committerIan Lance Taylor <ian@gcc.gnu.org>
Sat, 31 Aug 2019 03:07:48 +0000 (03:07 +0000)
    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 is not
    notinheap.  This caused an invalid write barrier error when building
    the 1.13 version of the runtime.

    Reviewed-on: https://go-review.googlesource.com/c/gofrontend/+/192279

From-SVN: r275240

gcc/go/gofrontend/MERGE
gcc/go/gofrontend/wb.cc

index 025e66ea99b416b129e62dd97b46570cdd7fc1fc..0add2f0a9ae4e7c668fdb084facfef21dd78fb5d 100644 (file)
@@ -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 41d8f94c0744197d014f1cb393c8d14be19c6da7..1eadb3e9e6299bae1c2f535b19c266b0dbcface9 100644 (file)
@@ -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;
 }