compiler: check for 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 is not
notinheap.  This caused an invalid write barrier error when building
the 1.13 version of the runtime.

Change-Id: Ib3ccb8d70fd46d81839372d6b43530994b4d2441
Reviewed-on: https://go-review.googlesource.com/c/gofrontend/+/192279
Reviewed-by: Cherry Zhang <cherryyz@google.com>
diff --git a/go/wb.cc b/go/wb.cc
index 41d8f94..1eadb3e 100644
--- a/go/wb.cc
+++ b/go/wb.cc
@@ -733,6 +733,31 @@
 	  && !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 @@
       && 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;
 }