Patchwork Allow gc roots to be structures with array fields

login
register
mail settings
Submitter Richard Sandiford
Date July 3, 2010, 5:25 p.m.
Message ID <87vd8w4gvg.fsf@firetop.home>
Download mbox | patch
Permalink /patch/57817/
State New
Headers show

Comments

Richard Sandiford - July 3, 2010, 5:25 p.m.
This is a prerequisite for the upcoming "speed up target_reinit" patches.

gengtype supports roots that are arrays of structures, but not roots
that contain array fields.  E.g.:

    struct GTY(()) foo {
      rtx a[4];
      struct {
	rtx b[4];
      } sub;
    };
    struct GTY(()) bar { rtx a; int b; };
    extern GTY(()) struct foo foo_var;
    extern GTY(()) struct bar bar_var[4];

generates the roots:

  {
    &bar_var[0].a,
    1 * (4),
    sizeof (bar_var[0]),
    &gt_ggc_mx_rtx_def,
    &gt_pch_nx_rtx_def
  },
  {
    &foo_var.a[0],
    1,
    sizeof (foo_var),
    &gt_ggc_mx_rtx_def,
    &gt_pch_nx_rtx_def
  },
  {
    &foo_var.sub.b[0],
    1,
    sizeof (foo_var),
    &gt_ggc_mx_rtx_def,
    &gt_pch_nx_rtx_def
  },

The first one is fine (count = 4, stride = sizeof (rtx)), but the last
two are wrong (count = 1, stride = sizeof (whole of foo)).  Only the
foo_var.a[0] and foo_var.sub.b[0] parts of foo get garbage-collected.

The patch adds support for foo-like roots too.  The idea is to treat
top-level fields of structure roots in the same way as separate
variables.

The patch also errors for array fields in an array of structures,
which are in general too complex to handle with a single count and
stride.

Bootstrapped & regression-tested on x86_64-linux-gnu.  OK to install?

Richard


gcc/
	* gengtype.c (write_field_root): New function.
	(write_root): Use it.
Mark Mitchell - July 6, 2010, 12:56 a.m.
Richard Sandiford wrote:

> gcc/
> 	* gengtype.c (write_field_root): New function.
> 	(write_root): Use it.

OK.

Patch

Index: gcc/gengtype.c
===================================================================
--- gcc/gengtype.c	2010-07-03 11:25:24.000000000 +0100
+++ gcc/gengtype.c	2010-07-03 11:49:36.000000000 +0100
@@ -3174,6 +3174,37 @@  finish_root_table (struct flist *flp, co
   }
 }
 
+/* A subroutine of write_root for writing the roots for field FIELD_NAME,
+   which has type FIELD_TYPE.  Parameters F to EMIT_PCH are the parameters
+   of the caller.  */
+
+static void
+write_field_root (outf_p f, pair_p v, type_p type, const char *name,
+		  int has_length, struct fileloc *line, const char *if_marked,
+		  bool emit_pch, type_p field_type, const char *field_name)
+{
+  /* If the field reference is relative to V, rather than to some
+     subcomponent of V, we can mark any subarrays with a single stride.
+     We're effectively treating the field as a global variable in its
+     own right.  */
+  if (type == v->type)
+    {
+      struct pair newv;
+
+      newv = *v;
+      newv.type = field_type;
+      newv.name = ACONCAT ((v->name, ".", field_name, NULL));
+      v = &newv;
+    }
+  /* Otherwise, any arrays nested in the structure are too complex to
+     handle.  */
+  else if (field_type->kind == TYPE_ARRAY)
+    error_at_line (line, "nested array `%s.%s' is too complex to be a root",
+		   name, field_name);
+  write_root (f, v, field_type, ACONCAT ((name, ".", field_name, NULL)),
+	      has_length, line, if_marked, emit_pch);
+}
+
 /* Write out to F the table entry and any marker routines needed to
    mark NAME as TYPE.  The original variable is V, at LINE.
    HAS_LENGTH is nonzero iff V was a variable-length array.  IF_MARKED
@@ -3232,27 +3263,18 @@  write_root (outf_p f, pair_p v, type_p t
 		    validf = ufld;
 		  }
 		if (validf != NULL)
-		  {
-		    char *newname;
-		    newname = xasprintf ("%s.%s.%s",
-					 name, fld->name, validf->name);
-		    write_root (f, v, validf->type, newname, 0, line,
-				if_marked, emit_pch);
-		    free (newname);
-		  }
+		  write_field_root (f, v, type, name, 0, line, if_marked,
+				    emit_pch, validf->type,
+				    ACONCAT ((fld->name, ".",
+					      validf->name, NULL)));
 	      }
 	    else if (desc)
 	      error_at_line (line,
 		     "global `%s.%s' has `desc' option but is not union",
 			     name, fld->name);
 	    else
-	      {
-		char *newname;
-		newname = xasprintf ("%s.%s", name, fld->name);
-		write_root (f, v, fld->type, newname, 0, line, if_marked,
-			    emit_pch);
-		free (newname);
-	      }
+	      write_field_root (f, v, type, name, 0, line, if_marked,
+				emit_pch, fld->type, fld->name);
 	  }
       }
       break;