diff gcc/gengtype.c @ 55:77e2b8dfacca gcc-4.4.5

update it from 4.4.3 to 4.5.0
author ryoma <e075725@ie.u-ryukyu.ac.jp>
date Fri, 12 Feb 2010 23:39:51 +0900
parents a06113de4d67
children b7f97abdc517
line wrap: on
line diff
--- a/gcc/gengtype.c	Sun Feb 07 18:28:00 2010 +0900
+++ b/gcc/gengtype.c	Fri Feb 12 23:39:51 2010 +0900
@@ -1,5 +1,5 @@
 /* Process source files and output type information.
-   Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008
+   Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
    Free Software Foundation, Inc.
 
    This file is part of GCC.
@@ -128,18 +128,25 @@
 
 /* An output file, suitable for definitions, that can see declarations
    made in INPUT_FILE and is linked into every language that uses
-   INPUT_FILE.  */
+   INPUT_FILE.  May return NULL in plugin mode. */
 extern outf_p get_output_file_with_visibility
    (const char *input_file);
 const char *get_output_file_name (const char *);
 
-/* Print, like fprintf, to O.  */
+/* Print, like fprintf, to O.  No-op if O is NULL. */
 static void oprintf (outf_p o, const char *S, ...)
      ATTRIBUTE_PRINTF_2;
 
 /* The list of output files.  */
 static outf_p output_files;
 
+/* The plugin input files and their number; in that case only
+   a single file is produced.  */
+static char** plugin_files;
+static size_t nb_plugin_files;
+/* the generated plugin output name & file */
+static outf_p plugin_output;
+
 /* The output header file that is included into pretty much every
    source file.  */
 static outf_p header_file;
@@ -274,7 +281,7 @@
   int c;
   bool atbol = true;
   num_lang_dirs = 0;
-  num_gt_files = 0;
+  num_gt_files = plugin_files ? nb_plugin_files : 0;
   while ((c = getc (list)) != EOF)
     {
       n++;
@@ -455,6 +462,13 @@
       /* Update the global counts now that we know accurately how many
 	 things there are.  (We do not bother resizing the arrays down.)  */
       num_lang_dirs = langno;
+      /* Add the plugin files if provided.  */
+      if (plugin_files)
+	{
+	  size_t i;
+	  for (i = 0; i < nb_plugin_files; i++)
+	    gt_files[nfiles++] = plugin_files[i];
+	}
       num_gt_files = nfiles;
     }
 
@@ -962,9 +976,11 @@
 {
   outf_p f = get_output_file_with_visibility (NULL);
   int i;
+  if (!f)
+    return;
 
   oprintf (f, "\n/* Used to implement the RTX_NEXT macro.  */\n");
-  oprintf (f, "const unsigned char rtx_next[NUM_RTX_CODE] = {\n");
+  oprintf (f, "EXPORTED_CONST unsigned char rtx_next[NUM_RTX_CODE] = {\n");
   for (i = 0; i < NUM_RTX_CODE; i++)
     if (rtx_next_new[i] == -1)
       oprintf (f, "  0,\n");
@@ -1016,6 +1032,7 @@
 	switch (c)
 	  {
 	  case NOTE_INSN_MAX:
+	  case NOTE_INSN_DELETED_LABEL:
 	    note_flds = create_field (note_flds, &string_type, "rt_str");
 	    break;
 
@@ -1100,6 +1117,8 @@
 		t = scalar_tp, subname = "rt_int";
 	      else if (i == VALUE && aindex == 0)
 		t = scalar_tp, subname = "rt_int";
+	      else if (i == DEBUG_EXPR && aindex == 0)
+		t = tree_tp, subname = "rt_tree";
 	      else if (i == REG && aindex == 1)
 		t = scalar_tp, subname = "rt_int";
 	      else if (i == REG && aindex == 2)
@@ -1374,7 +1393,7 @@
 				&length, &skip, &nested_ptr);
 
 	    if (nested_ptr && f->type->kind == TYPE_POINTER)
-	      set_gc_used_type (nested_ptr, GC_POINTED_TO, 
+	      set_gc_used_type (nested_ptr, GC_POINTED_TO,
 				pass_param ? param : NULL);
 	    else if (length && f->type->kind == TYPE_POINTER)
 	      set_gc_used_type (f->type->u.p, GC_USED, NULL);
@@ -1448,7 +1467,7 @@
 create_file (const char *name, const char *oname)
 {
   static const char *const hdr[] = {
-    "   Copyright (C) 2004, 2007 Free Software Foundation, Inc.\n",
+    "   Copyright (C) 2004, 2007, 2009 Free Software Foundation, Inc.\n",
     "\n",
     "This file is part of GCC.\n",
     "\n",
@@ -1471,6 +1490,8 @@
   outf_p f;
   size_t i;
 
+  gcc_assert (name != NULL);
+  gcc_assert (oname != NULL);
   f = XCNEW (struct outf);
   f->next = output_files;
   f->name = oname;
@@ -1482,7 +1503,7 @@
   return f;
 }
 
-/* Print, like fprintf, to O.  
+/* Print, like fprintf, to O.
    N.B. You might think this could be implemented more efficiently
    with vsnprintf().  Unfortunately, there are C libraries that
    provide that function but without the C99 semantics for its return
@@ -1494,6 +1515,11 @@
   size_t slength;
   va_list ap;
 
+  /* In plugin mode, the O could be a NULL pointer, so avoid crashing
+     in that case.  */
+  if (!o)
+    return;
+
   va_start (ap, format);
   slength = vasprintf (&s, format, ap);
   if (s == NULL || (int)slength < 0)
@@ -1523,6 +1549,9 @@
 {
   size_t i;
 
+  if (nb_plugin_files > 0 && plugin_files)
+    return;
+
   header_file = create_file ("GCC", "gtype-desc.h");
 
   base_files = XNEWVEC (outf_p, num_lang_dirs);
@@ -1535,13 +1564,14 @@
   {
     /* The order of files here matters very much.  */
     static const char *const ifiles [] = {
-      "config.h", "system.h", "coretypes.h", "tm.h", "varray.h", 
+      "config.h", "system.h", "coretypes.h", "tm.h", "varray.h",
       "hashtab.h", "splay-tree.h",  "obstack.h", "bitmap.h", "input.h",
       "tree.h", "rtl.h", "function.h", "insn-config.h", "expr.h",
       "hard-reg-set.h", "basic-block.h", "cselib.h", "insn-addr.h",
       "optabs.h", "libfuncs.h", "debug.h", "ggc.h", "cgraph.h",
       "tree-flow.h", "reload.h", "cpp-id-data.h", "tree-chrec.h",
-      "cfglayout.h", "except.h", "output.h", "gimple.h", "cfgloop.h", NULL
+      "cfglayout.h", "except.h", "output.h", "gimple.h", "cfgloop.h",
+      "target.h", "ipa-prop.h", NULL
     };
     const char *const *ifp;
     outf_p gtype_desc_c;
@@ -1563,7 +1593,7 @@
 get_file_realbasename (const char *f)
 {
   const char * lastslash = strrchr (f, '/');
-  
+
   return (lastslash != NULL) ? lastslash + 1 : f;
 }
 
@@ -1605,7 +1635,7 @@
     {
       const char * langdir = lang_dir_names [lang_index];
       size_t langdir_len = strlen (langdir);
-	  
+
       if (f_len > langdir_len
 	  && IS_DIR_SEPARATOR (f[langdir_len])
 	  && memcmp (f, langdir, langdir_len) == 0)
@@ -1646,7 +1676,7 @@
 
   const char *basename = get_file_realbasename (f);
   const char *langdir = get_file_langdir (f);
-  
+
   char * result =
     (langdir ? xasprintf ("gt-%s-%s", langdir, basename)
      : xasprintf ("gt-%s", basename));
@@ -1685,6 +1715,18 @@
   if (input_file == NULL)
     input_file = "system.h";
 
+  /* In plugin mode, return NULL unless the input_file is one of the
+     plugin_files.  */
+  if (plugin_files)
+    {
+      size_t i;
+      for (i = 0; i < nb_plugin_files; i++)
+	if (strcmp (input_file, plugin_files[i]) == 0)
+	  return plugin_output;
+
+      return NULL;
+    }
+
   /* Determine the output file name.  */
   basename = get_file_basename (input_file);
 
@@ -1693,7 +1735,7 @@
       || (len > 2 && memcmp (basename+len-2, ".y", 2) == 0)
       || (len > 3 && memcmp (basename+len-3, ".in", 3) == 0))
     {
-      output_name = get_file_gtfilename (input_file); 
+      output_name = get_file_gtfilename (input_file);
       for_name = basename;
     }
   /* Some headers get used by more than one front-end; hence, it
@@ -1703,6 +1745,8 @@
      headers with source files (and their special purpose gt-*.h headers).  */
   else if (strcmp (basename, "c-common.h") == 0)
     output_name = "gt-c-common.h", for_name = "c-common.c";
+  else if (strcmp (basename, "c-lang.h") == 0)
+    output_name = "gt-c-decl.h", for_name = "c-decl.c";
   else if (strcmp (basename, "c-tree.h") == 0)
     output_name = "gt-c-decl.h", for_name = "c-decl.c";
   else if (strncmp (basename, "cp", 2) == 0 && IS_DIR_SEPARATOR (basename[2])
@@ -1717,7 +1761,7 @@
   else if (strncmp (basename, "objc", 4) == 0 && IS_DIR_SEPARATOR (basename[4])
 	   && strcmp (basename + 5, "objc-act.h") == 0)
     output_name = "gt-objc-objc-act.h", for_name = "objc/objc-act.c";
-  else 
+  else
     {
       int lang_index = get_prefix_langdir_index (basename);
 
@@ -1736,6 +1780,7 @@
   /* If not, create it.  */
   r = create_file (for_name, output_name);
 
+  gcc_assert (r && r->name);
   return r;
 }
 
@@ -1746,7 +1791,36 @@
 const char *
 get_output_file_name (const char *input_file)
 {
-  return get_output_file_with_visibility (input_file)->name;
+  outf_p o =  get_output_file_with_visibility (input_file);
+  if (o)
+    return o->name;
+  return NULL;
+}
+
+/* Check if existing file is equal to the in memory buffer. */
+
+static bool
+is_file_equal (outf_p of)
+{
+  FILE *newfile = fopen (of->name, "r");
+  size_t i;
+  bool equal;
+  if (newfile == NULL)
+    return false;
+
+  equal = true;
+  for (i = 0; i < of->bufused; i++)
+    {
+      int ch;
+      ch = fgetc (newfile);
+      if (ch == EOF || ch != (unsigned char) of->buf[i])
+	{
+	  equal = false;
+	  break;
+	}
+    }
+  fclose (newfile);
+  return equal;
 }
 
 /* Copy the output to its final destination,
@@ -1759,35 +1833,20 @@
 
   for (of = output_files; of; of = of->next)
     {
-      FILE * newfile;
-
-      newfile = fopen (of->name, "r");
-      if (newfile != NULL )
-	{
-	  int no_write_p;
-	  size_t i;
-
-	  for (i = 0; i < of->bufused; i++)
-	    {
-	      int ch;
-	      ch = fgetc (newfile);
-	      if (ch == EOF || ch != (unsigned char) of->buf[i])
-		break;
-	    }
-	  no_write_p = i == of->bufused && fgetc (newfile) == EOF;
-	  fclose (newfile);
-
-	  if (no_write_p)
-	    continue;
-	}
-
-      newfile = fopen (of->name, "w");
-      if (newfile == NULL)
-	fatal ("opening output file %s: %s", of->name, strerror (errno));
-      if (fwrite (of->buf, 1, of->bufused, newfile) != of->bufused)
-	fatal ("writing output file %s: %s", of->name, strerror (errno));
-      if (fclose (newfile) != 0)
-	fatal ("closing output file %s: %s", of->name, strerror (errno));
+
+      if (!is_file_equal(of))
+      {
+        FILE *newfile = fopen (of->name, "w");
+        if (newfile == NULL)
+          fatal ("opening output file %s: %s", of->name, strerror (errno));
+        if (fwrite (of->buf, 1, of->bufused, newfile) != of->bufused)
+          fatal ("writing output file %s: %s", of->name, strerror (errno));
+        if (fclose (newfile) != 0)
+          fatal ("closing output file %s: %s", of->name, strerror (errno));
+      }
+      free(of->buf);
+      of->buf = NULL;
+      of->bufused = of->buflength = 0;
     }
 }
 
@@ -1831,14 +1890,16 @@
       const struct write_types_data *wtd);
 static void write_types_process_field
      (type_p f, const struct walk_type_data *d);
-static void write_types (type_p structures,
+static void write_types (outf_p output_header,
+                         type_p structures,
 			 type_p param_structs,
 			 const struct write_types_data *wtd);
 static void write_types_local_process_field
      (type_p f, const struct walk_type_data *d);
 static void write_local_func_for_structure
      (type_p orig_s, type_p s, type_p * param);
-static void write_local (type_p structures,
+static void write_local (outf_p output_header,
+                         type_p structures,
 			 type_p param_structs);
 static void write_enum_defn (type_p structures, type_p param_structs);
 static int contains_scalar_p (type_p t);
@@ -1847,10 +1908,10 @@
 			       const char *tname, const char *lastname,
 			       const char *name);
 static void write_root (outf_p , pair_p, type_p, const char *, int,
-			struct fileloc *, const char *);
+			struct fileloc *, const char *, bool);
 static void write_array (outf_p f, pair_p v,
 			 const struct write_types_data *wtd);
-static void write_roots (pair_p);
+static void write_roots (pair_p, bool);
 
 /* Parameters for walk_type.  */
 
@@ -2111,9 +2172,9 @@
 		d->indent += 2;
 		d->val = xasprintf ("x%d", d->counter++);
 		oprintf (d->of, "%*s%s %s * %s%s =\n", d->indent, "",
-			 (nested_ptr_d->type->kind == TYPE_UNION 
-			  ? "union" : "struct"), 
-			 nested_ptr_d->type->u.s.tag, 
+			 (nested_ptr_d->type->kind == TYPE_UNION
+			  ? "union" : "struct"),
+			 nested_ptr_d->type->u.s.tag,
 			 d->fn_wants_lvalue ? "" : "const ",
 			 d->val);
 		oprintf (d->of, "%*s", d->indent + 2, "");
@@ -2201,7 +2262,7 @@
 	else
 	  oprintf (d->of, "%s", t->u.a.len);
 	oprintf (d->of, ");\n");
-	
+
 	oprintf (d->of, "%*sfor (i%d = 0; i%d != l%d; i%d++) {\n",
 		 d->indent, "",
 		 loopcounter, loopcounter, loopcounter, loopcounter);
@@ -2653,12 +2714,15 @@
 /* Write out marker routines for STRUCTURES and PARAM_STRUCTS.  */
 
 static void
-write_types (type_p structures, type_p param_structs,
+write_types (outf_p output_header, type_p structures, type_p param_structs,
 	     const struct write_types_data *wtd)
 {
   type_p s;
 
-  oprintf (header_file, "\n/* %s*/\n", wtd->comment);
+  oprintf (output_header, "\n/* %s*/\n", wtd->comment);
+  /* We first emit the macros and the declarations. Functions' code is
+     emitted afterwards.  This is needed in plugin mode.  */
+  oprintf (output_header, "/* macros and declarations */\n");
   for (s = structures; s; s = s->next)
     if (s->gc_used == GC_POINTED_TO
 	|| s->gc_used == GC_MAYBE_POINTED_TO)
@@ -2669,13 +2733,13 @@
 	    && s->u.s.line.file == NULL)
 	  continue;
 
-	oprintf (header_file, "#define gt_%s_", wtd->prefix);
-	output_mangled_typename (header_file, s);
-	oprintf (header_file, "(X) do { \\\n");
-	oprintf (header_file,
+	oprintf (output_header, "#define gt_%s_", wtd->prefix);
+	output_mangled_typename (output_header, s);
+	oprintf (output_header, "(X) do { \\\n");
+	oprintf (output_header,
 		 "  if (X != NULL) gt_%sx_%s (X);\\\n", wtd->prefix,
 		 s->u.s.tag);
-	oprintf (header_file,
+	oprintf (output_header,
 		 "  } while (0)\n");
 
 	for (opt = s->u.s.opt; opt; opt = opt->next)
@@ -2685,7 +2749,7 @@
 	      if (t->kind == TYPE_STRUCT
 		  || t->kind == TYPE_UNION
 		  || t->kind == TYPE_LANG_STRUCT)
-		oprintf (header_file,
+		oprintf (output_header,
 			 "#define gt_%sx_%s gt_%sx_%s\n",
 			 wtd->prefix, s->u.s.tag, wtd->prefix, t->u.s.tag);
 	      else
@@ -2697,7 +2761,7 @@
 	  continue;
 
 	/* Declare the marker procedure only once.  */
-	oprintf (header_file,
+	oprintf (output_header,
 		 "extern void gt_%sx_%s (void *);\n",
 		 wtd->prefix, s->u.s.tag);
 
@@ -2707,6 +2771,42 @@
 		     s->u.s.tag);
 	    continue;
 	  }
+      }
+
+  for (s = param_structs; s; s = s->next)
+    if (s->gc_used == GC_POINTED_TO)
+      {
+	type_p stru = s->u.param_struct.stru;
+
+	/* Declare the marker procedure.  */
+	oprintf (output_header, "extern void gt_%s_", wtd->prefix);
+	output_mangled_typename (output_header, s);
+	oprintf (output_header, " (void *);\n");
+
+	if (stru->u.s.line.file == NULL)
+	  {
+	    fprintf (stderr, "warning: structure `%s' used but not defined\n",
+		     s->u.s.tag);
+	    continue;
+	  }
+      }
+
+  /* At last we emit the functions code.  */
+  oprintf (output_header, "\n/* functions code */\n");
+  for (s = structures; s; s = s->next)
+    if (s->gc_used == GC_POINTED_TO
+	|| s->gc_used == GC_MAYBE_POINTED_TO)
+      {
+	options_p opt;
+
+	if (s->gc_used == GC_MAYBE_POINTED_TO
+	    && s->u.s.line.file == NULL)
+	  continue;
+	for (opt = s->u.s.opt; opt; opt = opt->next)
+	  if (strcmp (opt->name, "ptr_alias") == 0)
+	    break;
+	if (opt)
+	  continue;
 
 	if (s->kind == TYPE_LANG_STRUCT)
 	  {
@@ -2717,25 +2817,13 @@
 	else
 	  write_func_for_structure (s, s, NULL, wtd);
       }
-
   for (s = param_structs; s; s = s->next)
     if (s->gc_used == GC_POINTED_TO)
       {
-	type_p * param = s->u.param_struct.param;
+	type_p *param = s->u.param_struct.param;
 	type_p stru = s->u.param_struct.stru;
-
-	/* Declare the marker procedure.  */
-	oprintf (header_file, "extern void gt_%s_", wtd->prefix);
-	output_mangled_typename (header_file, s);
-	oprintf (header_file, " (void *);\n");
-
 	if (stru->u.s.line.file == NULL)
-	  {
-	    fprintf (stderr, "warning: structure `%s' used but not defined\n",
-		     s->u.s.tag);
-	    continue;
-	  }
-
+	  continue;
 	if (stru->kind == TYPE_LANG_STRUCT)
 	  {
 	    type_p ss;
@@ -2811,7 +2899,6 @@
 
   memset (&d, 0, sizeof (d));
   d.of = get_output_file_with_visibility (fn);
-
   d.process_field = write_types_local_process_field;
   d.opt = s->u.s.opt;
   d.line = &s->u.s.line;
@@ -2843,11 +2930,13 @@
 /* Write out local marker routines for STRUCTURES and PARAM_STRUCTS.  */
 
 static void
-write_local (type_p structures, type_p param_structs)
+write_local (outf_p output_header, type_p structures, type_p param_structs)
 {
   type_p s;
 
-  oprintf (header_file, "\n/* Local pointer-walking routines.  */\n");
+  if (!output_header)
+    return;
+  oprintf (output_header, "\n/* Local pointer-walking routines.  */\n");
   for (s = structures; s; s = s->next)
     if (s->gc_used == GC_POINTED_TO
 	|| s->gc_used == GC_MAYBE_POINTED_TO)
@@ -2865,11 +2954,11 @@
 		  || t->kind == TYPE_UNION
 		  || t->kind == TYPE_LANG_STRUCT)
 		{
-		  oprintf (header_file, "#define gt_pch_p_");
-		  output_mangled_typename (header_file, s);
-		  oprintf (header_file, " gt_pch_p_");
-		  output_mangled_typename (header_file, t);
-		  oprintf (header_file, "\n");
+		  oprintf (output_header, "#define gt_pch_p_");
+		  output_mangled_typename (output_header, s);
+		  oprintf (output_header, " gt_pch_p_");
+		  output_mangled_typename (output_header, t);
+		  oprintf (output_header, "\n");
 		}
 	      else
 		error_at_line (&s->u.s.line,
@@ -2880,9 +2969,9 @@
 	  continue;
 
 	/* Declare the marker procedure only once.  */
-	oprintf (header_file, "extern void gt_pch_p_");
-	output_mangled_typename (header_file, s);
-	oprintf (header_file,
+	oprintf (output_header, "extern void gt_pch_p_");
+	output_mangled_typename (output_header, s);
+	oprintf (output_header,
 	 "\n    (void *, void *, gt_pointer_operator, void *);\n");
 
 	if (s->kind == TYPE_LANG_STRUCT)
@@ -2902,9 +2991,9 @@
 	type_p stru = s->u.param_struct.stru;
 
 	/* Declare the marker procedure.  */
-	oprintf (header_file, "extern void gt_pch_p_");
-	output_mangled_typename (header_file, s);
-	oprintf (header_file,
+	oprintf (output_header, "extern void gt_pch_p_");
+	output_mangled_typename (output_header, s);
+	oprintf (output_header,
 	 "\n    (void *, void *, gt_pointer_operator, void *);\n");
 
 	if (stru->u.s.line.file == NULL)
@@ -2932,6 +3021,8 @@
 {
   type_p s;
 
+  if (!header_file)
+    return;
   oprintf (header_file, "\n/* Enumeration of types known.  */\n");
   oprintf (header_file, "enum gt_types_enum {\n");
   for (s = structures; s; s = s->next)
@@ -2982,6 +3073,8 @@
 put_mangled_filename (outf_p f, const char *fn)
 {
   const char *name = get_output_file_name (fn);
+  if (!f || !name)
+    return;
   for (; *name != 0; name++)
     if (ISALNUM (*name))
       oprintf (f, "%c", *name);
@@ -3006,7 +3099,7 @@
 	oprintf (fli2->f, "};\n\n");
       }
 
-  for (fli2 = flp; fli2; fli2 = fli2->next)
+  for (fli2 = flp; fli2 && base_files; fli2 = fli2->next)
     if (fli2->started_p)
       {
 	lang_bitmap bitmap = get_lang_bitmap (fli2->name);
@@ -3025,9 +3118,9 @@
 
   {
     size_t fnum;
-    for (fnum = 0; fnum < num_lang_dirs; fnum++)
+    for (fnum = 0; base_files && fnum < num_lang_dirs; fnum++)
       oprintf (base_files [fnum],
-	       "const struct %s * const %s[] = {\n",
+	       "EXPORTED_CONST struct %s * const %s[] = {\n",
 	       tname, name);
   }
 
@@ -3040,7 +3133,7 @@
 
 	fli2->started_p = 0;
 
-	for (fnum = 0; bitmap != 0; fnum++, bitmap >>= 1)
+	for (fnum = 0; base_files && bitmap != 0; fnum++, bitmap >>= 1)
 	  if (bitmap & 1)
 	    {
 	      oprintf (base_files[fnum], "  gt_%s_", pfx);
@@ -3051,7 +3144,7 @@
 
   {
     size_t fnum;
-    for (fnum = 0; fnum < num_lang_dirs; fnum++)
+    for (fnum = 0; base_files && fnum < num_lang_dirs; fnum++)
       {
 	oprintf (base_files[fnum], "  NULL\n");
 	oprintf (base_files[fnum], "};\n");
@@ -3066,7 +3159,7 @@
 
 static void
 write_root (outf_p f, pair_p v, type_p type, const char *name, int has_length,
-	    struct fileloc *line, const char *if_marked)
+	    struct fileloc *line, const char *if_marked, bool emit_pch)
 {
   switch (type->kind)
     {
@@ -3122,7 +3215,7 @@
 		    newname = xasprintf ("%s.%s.%s",
 					 name, fld->name, validf->name);
 		    write_root (f, v, validf->type, newname, 0, line,
-				if_marked);
+				if_marked, emit_pch);
 		    free (newname);
 		  }
 	      }
@@ -3134,7 +3227,8 @@
 	      {
 		char *newname;
 		newname = xasprintf ("%s.%s", name, fld->name);
-		write_root (f, v, fld->type, newname, 0, line, if_marked);
+		write_root (f, v, fld->type, newname, 0, line, if_marked,
+			    emit_pch);
 		free (newname);
 	      }
 	  }
@@ -3145,7 +3239,8 @@
       {
 	char *newname;
 	newname = xasprintf ("%s[0]", name);
-	write_root (f, v, type->u.a.p, newname, has_length, line, if_marked);
+	write_root (f, v, type->u.a.p, newname, has_length, line, if_marked,
+		    emit_pch);
 	free (newname);
       }
       break;
@@ -3174,20 +3269,31 @@
 	if (! has_length && UNION_OR_STRUCT_P (tp))
 	  {
 	    oprintf (f, "    &gt_ggc_mx_%s,\n", tp->u.s.tag);
-	    oprintf (f, "    &gt_pch_nx_%s", tp->u.s.tag);
+	    if (emit_pch)
+	      oprintf (f, "    &gt_pch_nx_%s", tp->u.s.tag);
+	    else
+	      oprintf (f, "    NULL");
 	  }
 	else if (! has_length && tp->kind == TYPE_PARAM_STRUCT)
 	  {
 	    oprintf (f, "    &gt_ggc_m_");
 	    output_mangled_typename (f, tp);
-	    oprintf (f, ",\n    &gt_pch_n_");
-	    output_mangled_typename (f, tp);
+	    if (emit_pch)
+	      {
+		oprintf (f, ",\n    &gt_pch_n_");
+		output_mangled_typename (f, tp);
+	      }
+	    else
+	      oprintf (f, ",\n    NULL");
 	  }
 	else if (has_length
 		 && (tp->kind == TYPE_POINTER || UNION_OR_STRUCT_P (tp)))
 	  {
 	    oprintf (f, "    &gt_ggc_ma_%s,\n", name);
-	    oprintf (f, "    &gt_pch_na_%s", name);
+	    if (emit_pch)
+	      oprintf (f, "    &gt_pch_na_%s", name);
+	    else
+	      oprintf (f, "    NULL");
 	  }
 	else
 	  {
@@ -3276,7 +3382,7 @@
 /* Output a table describing the locations and types of VARIABLES.  */
 
 static void
-write_roots (pair_p variables)
+write_roots (pair_p variables, bool emit_pch)
 {
   pair_p v;
   struct flist *flp = NULL;
@@ -3308,7 +3414,7 @@
 			 v->name, o->name);
 
       for (fli = flp; fli; fli = fli->next)
-	if (fli->f == f)
+	if (fli->f == f && f)
 	  break;
       if (fli == NULL)
 	{
@@ -3317,6 +3423,7 @@
 	  fli->next = flp;
 	  fli->started_p = 0;
 	  fli->name = v->line.file;
+	  gcc_assert(fli->name);
 	  flp = fli;
 
 	  oprintf (f, "\n/* GC roots.  */\n\n");
@@ -3358,12 +3465,12 @@
 	{
 	  fli->started_p = 1;
 
-	  oprintf (f, "const struct ggc_root_tab gt_ggc_r_");
+	  oprintf (f, "EXPORTED_CONST struct ggc_root_tab gt_ggc_r_");
 	  put_mangled_filename (f, v->line.file);
 	  oprintf (f, "[] = {\n");
 	}
 
-      write_root (f, v, v->type, v->name, length_p, &v->line, NULL);
+      write_root (f, v, v->type, v->name, length_p, &v->line, NULL, emit_pch);
     }
 
   finish_root_table (flp, "ggc_r", "LAST_GGC_ROOT_TAB", "ggc_root_tab",
@@ -3392,7 +3499,7 @@
 	{
 	  fli->started_p = 1;
 
-	  oprintf (f, "const struct ggc_root_tab gt_ggc_rd_");
+	  oprintf (f, "EXPORTED_CONST struct ggc_root_tab gt_ggc_rd_");
 	  put_mangled_filename (f, v->line.file);
 	  oprintf (f, "[] = {\n");
 	}
@@ -3436,18 +3543,21 @@
 	{
 	  fli->started_p = 1;
 
-	  oprintf (f, "const struct ggc_cache_tab gt_ggc_rc_");
+	  oprintf (f, "EXPORTED_CONST struct ggc_cache_tab gt_ggc_rc_");
 	  put_mangled_filename (f, v->line.file);
 	  oprintf (f, "[] = {\n");
 	}
 
       write_root (f, v, v->type->u.p->u.param_struct.param[0],
-		     v->name, length_p, &v->line, if_marked);
+		  v->name, length_p, &v->line, if_marked, emit_pch);
     }
 
   finish_root_table (flp, "ggc_rc", "LAST_GGC_CACHE_TAB", "ggc_cache_tab",
 		     "gt_ggc_cache_rtab");
 
+  if (!emit_pch)
+    return;
+
   for (v = variables; v; v = v->next)
     {
       outf_p f = get_output_file_with_visibility (v->line.file);
@@ -3472,12 +3582,12 @@
 	{
 	  fli->started_p = 1;
 
-	  oprintf (f, "const struct ggc_root_tab gt_pch_rc_");
+	  oprintf (f, "EXPORTED_CONST struct ggc_root_tab gt_pch_rc_");
 	  put_mangled_filename (f, v->line.file);
 	  oprintf (f, "[] = {\n");
 	}
 
-      write_root (f, v, v->type, v->name, length_p, &v->line, NULL);
+      write_root (f, v, v->type, v->name, length_p, &v->line, NULL, emit_pch);
     }
 
   finish_root_table (flp, "pch_rc", "LAST_GGC_ROOT_TAB", "ggc_root_tab",
@@ -3508,7 +3618,7 @@
 	{
 	  fli->started_p = 1;
 
-	  oprintf (f, "const struct ggc_root_tab gt_pch_rs_");
+	  oprintf (f, "EXPORTED_CONST struct ggc_root_tab gt_pch_rs_");
 	  put_mangled_filename (f, v->line.file);
 	  oprintf (f, "[] = {\n");
 	}
@@ -3585,17 +3695,42 @@
 {
   size_t i;
   static struct fileloc pos = { this_file, 0 };
-
+  char* inputlist = 0;
+  outf_p output_header;
+  char* plugin_output_filename = NULL;
   /* fatal uses this */
   progname = "gengtype";
 
-  if (argc != 3)
-    fatal ("usage: gengtype srcdir input-list");
-
-  srcdir = argv[1];
+  if (argc >= 6 && !strcmp (argv[1], "-P"))
+    {
+      plugin_output_filename = argv[2];
+      plugin_output = create_file ("GCC", plugin_output_filename);
+      srcdir = argv[3];
+      inputlist = argv[4];
+      nb_plugin_files = argc - 5;
+      plugin_files = XCNEWVEC (char *, nb_plugin_files);
+      for (i = 0; i < nb_plugin_files; i++)
+      {
+        /* Place an all zero lang_bitmap before the plugin file
+	   name.  */
+        char *name = argv[i + 5];
+        int len = strlen(name) + 1 + sizeof (lang_bitmap);
+        plugin_files[i] = XCNEWVEC (char, len) + sizeof (lang_bitmap);
+        strcpy (plugin_files[i], name);
+      }
+    }
+  else if (argc == 3)
+    {
+      srcdir = argv[1];
+      inputlist = argv[2];
+    }
+  else
+    fatal ("usage: gengtype [-P pluginout.h] srcdir input-list "
+           "[file1 file2 ... fileN]");
+
   srcdir_len = strlen (srcdir);
 
-  read_input_list (argv[2]);
+  read_input_list (inputlist);
   if (hit_error)
     return 1;
 
@@ -3610,6 +3745,7 @@
   do_scalar_typedef ("REAL_VALUE_TYPE", &pos); pos.line++;
   do_scalar_typedef ("FIXED_VALUE_TYPE", &pos); pos.line++;
   do_scalar_typedef ("double_int", &pos); pos.line++;
+  do_scalar_typedef ("uint64_t", &pos); pos.line++;
   do_scalar_typedef ("uint8", &pos); pos.line++;
   do_scalar_typedef ("jword", &pos); pos.line++;
   do_scalar_typedef ("JCF_u2", &pos); pos.line++;
@@ -3626,13 +3762,24 @@
 
   open_base_files ();
   write_enum_defn (structures, param_structs);
-  write_types (structures, param_structs, &ggc_wtd);
-  write_types (structures, param_structs, &pch_wtd);
-  write_local (structures, param_structs);
-  write_roots (variables);
+  output_header = plugin_output ? plugin_output : header_file;
+  write_types (output_header, structures, param_structs, &ggc_wtd);
+  if (plugin_files == NULL)
+    {
+      write_types (header_file, structures, param_structs, &pch_wtd);
+      write_local (header_file, structures, param_structs);
+    }
+  write_roots (variables, plugin_files == NULL);
   write_rtx_next ();
   close_output_files ();
 
+  if (plugin_files)
+  {
+    for (i = 0; i < nb_plugin_files; i++)
+      free (plugin_files[i] - sizeof (lang_bitmap));
+    free (plugin_files);
+  }
+
   if (hit_error)
     return 1;
   return 0;