This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[patch trunk] gengtype: improved version for plugin support.


Hello All

The attached patch to trunk rev 149419's gengtype (ported from MELT branch rev149403) offers a more satisfactory support to plugin wanting PLUGIN_REGISTER_GGC_ROOTS. It does work for MELT already (while the previous version of gengtype did not support plugins as complex as MELT, because of various PCH & union related issues).

It offers the following features in plugin mode (the normal mode of gengtype is almost unaffected, except for gt_types_enum in which we add a 0 gt_types_enum_firstempty see below why).

* invocation has changed:
  gengtype -P your-gt-plugin.h plugin.h plugin1.c plugin2.c
You have to specify explicitly the name of the generateed output file.

* a single output file is generated, and you have to give it. No need to generate gtype-desc.h anymore, as I proposed in http://gcc.gnu.org/ml/gcc-patches/2009-07/msg00440.html. All code related to your plugin is inside your-gt-plugin.h file, and you need to name that generated file.

* the generated code relative to precompiled headers is wrapped with #ifdef GCC_PLUGIN_HAVE_PCH. If you do not define that symbol, all PCH related routines are generated empty (and your GTY-ed data in you plugin is only garbage collectable but not expected to be persisted in PCH). Only PCH gurus should dare #define-ing it. And I suppose that PCH support for PLUGIN_REGISTER_GGC_ROOTS is not yet here (it probably should need more code in ggc & pch land; see below).

* there is an issue with PCH which is partly solved. PCH outputs a tag (in the *.gch compiled file of a *.h header passed to gcc), value of the generated enum gt_types_enum in gtype-desc.h. we reserve the 0 value (called gt_types_enum_firstempty, so the first generated index e.g. gt_ggc_e_15interface_tuple in the current trunk is now 1, not 0) f that enum to mean don't persist that type. To permit several advanced plugins to extend this tagging machinery, we need to make it more dynamic. so, if GCC_PLUGIN_HAVE_PCH, we generate a dynamic enum like this:

#ifdef GCC_PLUGIN_HAVE_PCH
static int gccplugin_type_base;
#define gt_ggc_e_16basilocalsptr_st ((gccplugin_type_base>0)?(gccplugin_type_base+0):0)
#define gt_ggc_e_13melttriple_st ((gccplugin_type_base>0)?(gccplugin_type_base+1):0)
#define gt_ggc_e_17VEC_melt_ptr_t_gc ((gccplugin_type_base>0)?(gccplugin_type_base+2):0)


I hope you guess the "dynamic enumeration" pattern in the geneerated code...

This means that a plugin wanting PCH should set its ggcplugin_type_base to a positive integer. This would require support from the plugin machinery (to be provided in a future patch).

I don't have a simple test case for that patch but MELT has been successfully compiled with it (and MELT needs a RTLD_GLOBAL to dlopen - see http://gcc.gnu.org/ml/gcc-patches/2009-07/msg00497.html why).

gcc/ChangeLog is attached.

Comments are welcome.

Ok for trunk?

Regards.
--
Basile STARYNKEVITCH         http://starynkevitch.net/Basile/
email: basile<at>starynkevitch<dot>net mobile: +33 6 8501 2359
8, rue de la Faiencerie, 92340 Bourg La Reine, France
*** opinions {are only mines, sont seulement les miennes} ***

Index: gcc/gengtype.c
===================================================================
--- gcc/gengtype.c	(revision 149419)
+++ gcc/gengtype.c	(working copy)
@@ -24,6 +24,7 @@
 #include "errors.h"	/* for fatal */
 #include "double-int.h"
 
+
 /* Data types, macros, etc. used only in this file.  */
 
 /* Kinds of types we can understand.  */
@@ -64,6 +65,7 @@ struct pair
   type_p type;
   struct fileloc line;
   options_p opt;
+  bool inplugin;		/* flag set if appearing inside a plugin */
 };
 
 #define NUM_PARAM 10
@@ -83,6 +85,7 @@ struct type
   type_p next;
   type_p pointer_to;
   enum gc_used_enum gc_used;
+  bool inplugin;
   union {
     type_p p;
     struct {
@@ -145,7 +148,13 @@ static outf_p output_files;
    directory.  */
 static char** plugin_files;
 static int nb_plugin_files;
+/* index of first plugin file in gt_files */
+static int first_plugin_file_ix= -1;
+/* the generated plugin output name & file */
+static char* plugin_output_filename;
+static outf_p plugin_output;
 
+
 /* The output header file that is included into pretty much every
    source file.  */
 static outf_p header_file;
@@ -167,12 +176,16 @@ static const char * get_file_langdir (const char *
 
 
 /* Nonzero iff an error has occurred.  */
-bool hit_error = false;
+bool hit_error = FALSE;
+/* Flag set when parsing a plugin file */
+bool is_plugin_file = FALSE;
 
+
 static void gen_rtx_next (void);
 static void write_rtx_next (void);
 static void open_base_files (void);
 static void close_output_files (void);
+static void output_delayed_functions (void);
 
 /* Report an error at POS, printing MSG.  */
 
@@ -465,6 +478,7 @@ read_input_list (const char *listname)
       if (plugin_files) 
 	{
 	  int i;
+	  first_plugin_file_ix = nfiles;
 	  for (i = 0; i < nb_plugin_files; i++)
 	    gt_files[nfiles++] = plugin_files[i];
 	}
@@ -512,17 +526,18 @@ read_input_list (const char *listname)
 /* The one and only TYPE_STRING.  */
 
 static struct type string_type = {
-  TYPE_STRING, 0, 0, GC_USED, {0}
+  TYPE_STRING, 0, 0, GC_USED, false, {0}
 };
 
 /* The two and only TYPE_SCALARs.  Their u.scalar_is_char flags are
    set to appropriate values at the beginning of main.  */
 
 static struct type scalar_nonchar = {
-  TYPE_SCALAR, 0, 0, GC_USED, {0}
+  TYPE_SCALAR, 0, 0, GC_USED, false, {0}
 };
+
 static struct type scalar_char = {
-  TYPE_SCALAR, 0, 0, GC_USED, {0}
+  TYPE_SCALAR, 0, 0, GC_USED, false, {0}
 };
 
 /* Lists of various things.  */
@@ -663,8 +678,9 @@ new_structure (const char *name, int isunion, stru
 		     isunion ? "union" : "struct", s->u.s.tag);
       error_at_line (&s->u.s.line, "previous definition here");
     }
-
+  
   s->kind = isunion ? TYPE_UNION : TYPE_STRUCT;
+  s->inplugin = is_plugin_file;
   s->u.s.tag = name;
   s->u.s.line = *pos;
   s->u.s.fields = fields;
@@ -709,6 +725,7 @@ find_structure (const char *name, int isunion)
   s->next = structures;
   structures = s;
   s->kind = isunion ? TYPE_UNION : TYPE_STRUCT;
+  s->inplugin = is_plugin_file;
   s->u.s.tag = name;
   structures = s;
   return s;
@@ -732,6 +749,7 @@ find_param_structure (type_p t, type_p param[NUM_P
     {
       res = XCNEW (struct type);
       res->kind = TYPE_PARAM_STRUCT;
+      res->inplugin = is_plugin_file;
       res->next = param_structs;
       param_structs = res;
       res->u.param_struct.stru = t;
@@ -760,6 +778,7 @@ create_pointer (type_p t)
     {
       type_p r = XCNEW (struct type);
       r->kind = TYPE_POINTER;
+      r->inplugin = is_plugin_file;
       r->u.p = t;
       t->pointer_to = r;
     }
@@ -775,6 +794,7 @@ create_array (type_p t, const char *len)
 
   v = XCNEW (struct type);
   v->kind = TYPE_ARRAY;
+  v->inplugin = is_plugin_file;
   v->u.a.p = t;
   v->u.a.len = len;
   return v;
@@ -819,6 +839,7 @@ note_variable (const char *s, type_p t, options_p
   n->line = *pos;
   n->opt = o;
   n->next = variables;
+  n->inplugin = is_plugin_file;
   variables = n;
 }
 
@@ -1492,6 +1513,9 @@ create_file (const char *name, const char *oname)
   f = XCNEW (struct outf);
   f->next = output_files;
   f->name = oname;
+  i = f->buflength = 4096;
+  f->buf = XNEWVEC (char, i);
+  f->bufused = 0;
   output_files = f;
 
   oprintf (f, "/* Type information for %s.\n", name);
@@ -1508,7 +1532,7 @@ create_file (const char *name, const char *oname)
 void
 oprintf (outf_p o, const char *format, ...)
 {
-  char *s;
+  char *s = NULL;
   size_t slength;
   va_list ap;
 
@@ -1516,7 +1540,11 @@ oprintf (outf_p o, const char *format, ...)
      in that case.  */
   if (!o) 
     return;
-
+  
+  gcc_assert (o->buf != NULL);
+  
+  gcc_assert (o->bufused <= o->buflength);
+  
   va_start (ap, format);
   slength = vasprintf (&s, format, ap);
   if (s == NULL || (int)slength < 0)
@@ -1526,16 +1554,24 @@ oprintf (outf_p o, const char *format, ...)
   if (o->bufused + slength > o->buflength)
     {
       size_t new_len = o->buflength;
+      char *oldbuf = o->buf;
       if (new_len == 0)
 	new_len = 1024;
       do {
 	new_len *= 2;
       } while (o->bufused + slength >= new_len);
-      o->buf = XRESIZEVEC (char, o->buf, new_len);
+      o->buf = XNEWVEC (char, new_len);
+      if (oldbuf) 
+	{
+	  memcpy(o->buf, oldbuf, o->bufused);
+	  oldbuf[0] = 0;
+	}
+      free (oldbuf);
       o->buflength = new_len;
     }
   memcpy (o->buf + o->bufused, s, slength);
   o->bufused += slength;
+  gcc_assert (o->bufused <= o->buflength);
   free (s);
 }
 
@@ -1546,11 +1582,14 @@ open_base_files (void)
 {
   size_t i;
 
-  if (nb_plugin_files > 0 && plugin_files)
+  if (nb_plugin_files > 0 && plugin_files) 
     return;
-
+  
+  /* header file should be generated even in plugin mode */
   header_file = create_file ("GCC", "gtype-desc.h");
+  
 
+
   base_files = XNEWVEC (outf_p, num_lang_dirs);
 
   for (i = 0; i < num_lang_dirs; i++)
@@ -1567,7 +1606,8 @@ open_base_files (void)
       "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", 
+      NULL
     };
     const char *const *ifp;
     outf_p gtype_desc_c;
@@ -1712,15 +1752,19 @@ get_output_file_with_visibility (const char *input
     input_file = "system.h";
 
   /* In plugin mode, return NULL unless the input_file is one of the
-     plugin_files.  */
+     plugin_files or is the specified plugin_output_filename.  */
   if (plugin_files && nb_plugin_files > 0) 
     { 
       int ix= -1, i;
       for (i = 0; i < nb_plugin_files && ix < 0; i++)
-      if (strcmp (input_file, plugin_files[i]) == 0) 
-	ix = i;
-      if (ix < 0) 
+	if (strcmp (input_file, plugin_files[i]) == 0) 
+	  ix = i;
+      if (ix < 0
+	  && plugin_output_filename
+	  && strcmp (input_file, plugin_output_filename)) 
 	return NULL;
+      if (plugin_output_filename)
+	return plugin_output;
     }
 
   /* Determine the output file name.  */
@@ -1761,9 +1805,9 @@ get_output_file_with_visibility (const char *input
 
       if (lang_index >= 0)
 	return base_files[lang_index];
-
+      
       output_name = "gtype-desc.c";
-      for_name = NULL;
+      for_name = "GCC";
     }
 
   /* Look through to see if we've ever seen this output filename before.  */
@@ -1830,6 +1874,9 @@ close_output_files (void)
 	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;
     }
 }
 
@@ -1862,6 +1909,7 @@ struct write_types_data
   const char *reorder_note_routine;
   const char *comment;
   int skip_hooks;		/* skip hook generation if non zero */
+  int is_pch;			/* set for PCH stuff to output ifndef  */
 };
 
 static void output_escaped_param (struct walk_type_data *d,
@@ -1871,6 +1919,7 @@ static void walk_type (type_p t, struct walk_type_
 static void write_func_for_structure
      (type_p orig_s, type_p s, type_p * param,
       const struct write_types_data *wtd);
+static void delay_func_for_structure (type_p s, 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,
@@ -2585,6 +2634,8 @@ write_func_for_structure (type_p orig_s, type_p s,
     }
   oprintf (d.of, " (void *x_p)\n");
   oprintf (d.of, "{\n");
+  if (plugin_output && d.of == plugin_output && wtd->is_pch)
+    oprintf (d.of, "#ifdef GCC_PLUGIN_HAVE_PCH\n");
   oprintf (d.of, "  %s %s * %sx = (%s %s *)x_p;\n",
 	   s->kind == TYPE_UNION ? "union" : "struct", s->u.s.tag,
 	   chain_next == NULL ? "const " : "",
@@ -2689,6 +2740,8 @@ write_func_for_structure (type_p orig_s, type_p s,
   oprintf (d.of, "    }\n");
   if (chain_circular != NULL)
     oprintf (d.of, "  while (x != xlimit);\n");
+  if (plugin_output && d.of == plugin_output && wtd->is_pch)
+    oprintf (d.of, "/* end ifdef GCC_PLUGIN_HAVE_PCH*/\n#endif\n");
   oprintf (d.of, "}\n");
 }
 
@@ -2699,8 +2752,9 @@ write_types (type_p structures, type_p param_struc
 	     const struct write_types_data *wtd)
 {
   type_p s;
-
-  oprintf (header_file, "\n/* %s*/\n", wtd->comment);
+  outf_p outheadf = plugin_output_filename ? plugin_output : header_file;
+  
+  oprintf (outheadf, "\n/* %s*/\n", wtd->comment);
   for (s = structures; s; s = s->next)
     if (s->gc_used == GC_POINTED_TO
 	|| s->gc_used == GC_MAYBE_POINTED_TO)
@@ -2711,13 +2765,13 @@ write_types (type_p structures, type_p param_struc
 	    && 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 (outheadf, "#define gt_%s_", wtd->prefix);
+	output_mangled_typename (outheadf, s);
+	oprintf (outheadf, "(X) do { \\\n");
+	oprintf (outheadf,
 		 "  if (X != NULL) gt_%sx_%s (X);\\\n", wtd->prefix,
 		 s->u.s.tag);
-	oprintf (header_file,
+	oprintf (outheadf,
 		 "  } while (0)\n");
 
 	for (opt = s->u.s.opt; opt; opt = opt->next)
@@ -2727,7 +2781,7 @@ write_types (type_p structures, type_p param_struc
 	      if (t->kind == TYPE_STRUCT
 		  || t->kind == TYPE_UNION
 		  || t->kind == TYPE_LANG_STRUCT)
-		oprintf (header_file,
+		oprintf (outheadf,
 			 "#define gt_%sx_%s gt_%sx_%s\n",
 			 wtd->prefix, s->u.s.tag, wtd->prefix, t->u.s.tag);
 	      else
@@ -2739,7 +2793,7 @@ write_types (type_p structures, type_p param_struc
 	  continue;
 
 	/* Declare the marker procedure only once.  */
-	oprintf (header_file,
+	oprintf (outheadf,
 		 "extern void gt_%sx_%s (void *);\n",
 		 wtd->prefix, s->u.s.tag);
 
@@ -2750,7 +2804,10 @@ write_types (type_p structures, type_p param_struc
 	    continue;
 	  }
 
-	if (s->kind == TYPE_LANG_STRUCT)
+	/* in plugin mode, the write_func_for_structure should be delayed */
+	if (nb_plugin_files > 0 && plugin_output_filename)
+	  delay_func_for_structure (s, wtd);
+	else if (s->kind == TYPE_LANG_STRUCT)
 	  {
 	    type_p ss;
 	    for (ss = s->u.s.lang_struct; ss; ss = ss->next)
@@ -2767,9 +2824,9 @@ write_types (type_p structures, type_p param_struc
 	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");
+	oprintf (outheadf, "extern void gt_%s_", wtd->prefix);
+	output_mangled_typename (outheadf, s);
+	oprintf (outheadf, " (void *);\n");
 
 	if (stru->u.s.line.file == NULL)
 	  {
@@ -2793,6 +2850,7 @@ static const struct write_types_data ggc_wtd =
 {
   "ggc_m", NULL, "ggc_mark", "ggc_test_and_set_mark", NULL,
   "GC marker procedures.  ",
+  FALSE,
   FALSE
 };
 
@@ -2801,6 +2859,7 @@ static const struct write_types_data pch_wtd =
   "pch_n", "pch_p", "gt_pch_note_object", "gt_pch_note_object",
   "gt_pch_note_reorder",
   "PCH type-walking procedures.  ",
+  TRUE,
   TRUE
 };
 
@@ -2873,11 +2932,15 @@ write_local_func_for_structure (type_p orig_s, typ
 	   "\tATTRIBUTE_UNUSED gt_pointer_operator op,\n"
 	   "\tATTRIBUTE_UNUSED void *cookie)\n");
   oprintf (d.of, "{\n");
+  if (plugin_output && d.of == plugin_output)
+    oprintf (d.of, "#ifdef GCC_PLUGIN_HAVE_PCH\n");
   oprintf (d.of, "  %s %s * const x ATTRIBUTE_UNUSED = (%s %s *)x_p;\n",
 	   s->kind == TYPE_UNION ? "union" : "struct", s->u.s.tag,
 	   s->kind == TYPE_UNION ? "union" : "struct", s->u.s.tag);
   d.indent = 2;
   walk_type (s, &d);
+  if (plugin_output && d.of == plugin_output)
+    oprintf (d.of, "/* end ifdef GCC_PLUGIN_HAVE_PCH */\n#endif\n");
   oprintf (d.of, "}\n");
 }
 
@@ -2886,11 +2949,13 @@ write_local_func_for_structure (type_p orig_s, typ
 static void
 write_local (type_p structures, type_p param_structs)
 {
+  outf_p outheadf = plugin_output_filename ? plugin_output : header_file;
+
   type_p s;
 
-  if (!header_file) 
+  if (!outheadf) 
     return;
-  oprintf (header_file, "\n/* Local pointer-walking routines.  */\n");
+  oprintf (outheadf, "\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)
@@ -2908,11 +2973,11 @@ write_local (type_p structures, type_p param_struc
 		  || 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 (outheadf, "#define gt_pch_p_");
+		  output_mangled_typename (outheadf, s);
+		  oprintf (outheadf, " gt_pch_p_");
+		  output_mangled_typename (outheadf, t);
+		  oprintf (outheadf, "\n");
 		}
 	      else
 		error_at_line (&s->u.s.line,
@@ -2923,9 +2988,9 @@ write_local (type_p structures, type_p param_struc
 	  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 (outheadf, "extern void gt_pch_p_");
+	output_mangled_typename (outheadf, s);
+	oprintf (outheadf,
 	 "\n    (void *, void *, gt_pointer_operator, void *);\n");
 
 	if (s->kind == TYPE_LANG_STRUCT)
@@ -2945,9 +3010,9 @@ write_local (type_p structures, type_p param_struc
 	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 (outheadf, "extern void gt_pch_p_");
+	output_mangled_typename (outheadf, s);
+	oprintf (outheadf,
 	 "\n    (void *, void *, gt_pointer_operator, void *);\n");
 
 	if (stru->u.s.line.file == NULL)
@@ -2968,17 +3033,60 @@ write_local (type_p structures, type_p param_struc
       }
 }
 
-/* Write out the 'enum' definition for gt_types_enum.  */
+/* Write out only to header_file the 'enum' definition for gt_types_enum.  */
 
 static void
 write_enum_defn (type_p structures, type_p param_structs)
 {
-  type_p s;
-
+  type_p s = NULL;
+  /* in plugin mode, define dynamically the enumeration values */
+  if (plugin_output)
+    {
+      int cnt = 0;
+      oprintf (plugin_output, "\n/* Dynamic enumeration of plugin types.  */\n");
+      oprintf (plugin_output, "#ifdef GCC_PLUGIN_HAVE_PCH\n");
+      oprintf (plugin_output, "static int gccplugin_type_base;\n");
+      
+      for (s = structures; s; s = s->next)
+	{
+	  if (!s->inplugin)
+	    continue;
+	  if (s->gc_used == GC_POINTED_TO
+	      || s->gc_used == GC_MAYBE_POINTED_TO)
+	    {
+	      if (s->gc_used == GC_MAYBE_POINTED_TO
+		  && s->u.s.line.file == NULL)
+		continue;
+	      oprintf (plugin_output, "#define gt_ggc_e_");
+	      output_mangled_typename (plugin_output, s);
+	      oprintf (plugin_output,
+		       " ((gccplugin_type_base>0)?(gccplugin_type_base+%d):0)\n",
+		       cnt);
+	      cnt++;
+	    }
+	}
+      for (s = param_structs; s; s = s->next)
+	if (s->gc_used == GC_POINTED_TO && s->inplugin)
+	  {
+	    oprintf (plugin_output, "#define gt_e_");
+	    output_mangled_typename (plugin_output, s);
+	    oprintf (plugin_output,
+		     " ((gccplugin_type_base>0)?(gccplugin_type_base+%d):0)\n",
+		     cnt);
+	    cnt++;
+	  }
+      oprintf (plugin_output,
+	       "\n#define GCCPLUGIN_TYPE_COUNT %d\n", cnt);
+      oprintf (plugin_output, "/* end ifdef GCC_PLUGIN_HAVE_PCH */\n#endif\n");
+      return;
+    }
+  
+  /* write only to header_file */
   if (!header_file) 
     return;
-  oprintf (header_file, "\n/* Enumeration of types known.  */\n");
+  oprintf (header_file, "\n/* Enumeration of known types.  */\n");
   oprintf (header_file, "enum gt_types_enum {\n");
+  oprintf (header_file, "  gt_types_enum_firstempty,\n");
   for (s = structures; s; s = s->next)
     if (s->gc_used == GC_POINTED_TO
 	|| s->gc_used == GC_MAYBE_POINTED_TO)
@@ -3330,12 +3438,15 @@ write_roots (pair_p variables)
 
   for (v = variables; v; v = v->next)
     {
-      outf_p f = get_output_file_with_visibility (v->line.file);
+      outf_p f = NULL;
       struct flist *fli;
       const char *length = NULL;
       int deletable_p = 0;
       options_p o;
-
+      if (nb_plugin_files > 0 && plugin_output_filename && v->inplugin)
+	f = plugin_output;
+      else
+	f = get_output_file_with_visibility (v->line.file);
       for (o = v->opt; o; o = o->next)
 	if (strcmp (o->name, "length") == 0)
 	  length = o->info;
@@ -3627,6 +3738,74 @@ note_def_vec_alloc (const char *type, const char *
   do_typedef (astratname, new_structure (astratname, 0, pos, field, 0), pos);
 }
 
+
+/* in plugin mode, the write of functions for structure is delayed to
+   the end; we keep a vector of these */
+struct delayedstructfunc_st 
+{
+  type_p dly_s;
+  const struct write_types_data* dly_wtd;
+};
+static struct delayedstructfunc_st* dlystructab;
+static int dlystructsiz;
+static int dlystructcnt;
+
+
+
+
+static void
+delay_func_for_structure (type_p s, const struct write_types_data* wtd)
+{
+  gcc_assert (s != NULL);
+  gcc_assert (wtd != NULL);
+  if (dlystructcnt + 1 >= dlystructsiz)
+    {
+      struct delayedstructfunc_st* oldtab = dlystructab;
+      int oldsiz = dlystructsiz;
+      int newsiz = (32 + oldsiz) * 2;
+      int i = 0;
+      gcc_assert (newsiz > dlystructcnt);
+      dlystructab = XNEWVEC(struct delayedstructfunc_st, newsiz);
+      for (i = 0; i < dlystructcnt; i++)
+	dlystructab[i] = oldtab[i];
+      for (i = dlystructcnt; i < newsiz; i++)
+	{
+	  dlystructab[i].dly_s = NULL;
+	  dlystructab[i].dly_wtd = NULL;
+	}
+      dlystructsiz = newsiz;
+      free (oldtab);
+    }
+  dlystructab[dlystructcnt].dly_s = s;
+  dlystructab[dlystructcnt].dly_wtd = wtd;
+  dlystructcnt++;
+}
+
+
+static void
+output_delayed_functions(void)
+{
+  int i = 0;
+  gcc_assert (plugin_output);
+  for (i = 0; i<dlystructcnt; i++)
+    {
+      type_p s = dlystructab[i].dly_s;
+      const struct write_types_data* wtd = dlystructab[i].dly_wtd;
+      gcc_assert (s != NULL && wtd != NULL);
+      if (s->kind == TYPE_LANG_STRUCT)
+	  {
+	    type_p ss;
+	    for (ss = s->u.s.lang_struct; ss; ss = ss->next)
+	      write_func_for_structure (s, ss, NULL, wtd);
+	  }
+	else
+	  write_func_for_structure (s, s, NULL, wtd);
+    }
+  free (dlystructab);
+  dlystructab = NULL;
+  dlystructcnt = dlystructsiz = 0;
+}
+
 
 int
 main (int argc, char **argv)
@@ -3637,20 +3816,23 @@ main (int argc, char **argv)
   /* fatal uses this */
   progname = "gengtype";
 
-  if (argc >= 5 && !strcmp (argv[1], "-p")) 
+  if (argc >= 6 && !strcmp (argv[1], "-P"))
     {
-      srcdir = argv[2];
-      inputlist = argv[3];
-      plugin_files = argv+4;
-      nb_plugin_files = argc-4;
+      plugin_output_filename = argv[2];
+      plugin_output = create_file ("GCC", plugin_output_filename);
+      srcdir = argv[3];
+      inputlist = argv[4];
+      plugin_files = argv + 5;
+      nb_plugin_files = argc - 5;
     }
+  
   else if (argc == 3) 
     {
       srcdir = argv[1];
       inputlist = argv[2];
     } 
   else
-    fatal ("usage: gengtype [-p] srcdir input-list [file1 file2 ... fileN]");
+    fatal ("usage: gengtype [-P pluginout.h] srcdir input-list [file1 file2 ... fileN]");
 
   srcdir_len = strlen (srcdir);
 
@@ -3675,9 +3857,14 @@ main (int argc, char **argv)
   do_scalar_typedef ("void", &pos); pos.line++;
   do_typedef ("PTR", create_pointer (resolve_typedef ("void", &pos)), &pos);
 
-  for (i = 0; i < num_gt_files; i++)
-    parse_file (gt_files[i]);
-
+  for (i = 0; i < num_gt_files; i++) 
+    {
+      is_plugin_file = first_plugin_file_ix >= 0
+	&& (int)i >= first_plugin_file_ix;
+      parse_file (gt_files[i]);
+      is_plugin_file = false;
+    }
+  
   if (hit_error)
     return 1;
 
@@ -3690,6 +3877,10 @@ main (int argc, char **argv)
   write_local (structures, param_structs);
   write_roots (variables);
   write_rtx_next ();
+  
+  if (plugin_output)
+    output_delayed_functions ();
+  
   close_output_files ();
 
   if (hit_error)
Index: gcc/gengtype.h
===================================================================
--- gcc/gengtype.h	(revision 149419)
+++ gcc/gengtype.h	(working copy)
@@ -76,6 +76,9 @@ extern void yyend (void);
 extern void parse_file (const char *name);
 extern bool hit_error;
 
+/* flag set when parsing a plugin file */
+extern bool is_plugin_file;
+
 /* Token codes.  */
 enum {
   EOF_TOKEN = 0,
Index: gcc/doc/plugins.texi
===================================================================
--- gcc/doc/plugins.texi	(revision 149419)
+++ gcc/doc/plugins.texi	(working copy)
@@ -226,12 +226,16 @@ Some plugins may need to add extra GGC root tables
 their own @code{GTY}-ed data. This can be done with the
 @code{PLUGIN_REGISTER_GGC_ROOTS} pseudo-event with a null callback and
 the extra root table as @code{user_data}.  Running the @code{gengtype
--p @var{source-dir} @var{file-list} @var{plugin*.c} ...} utility
-generates this extra root table.
+-P @file{gt-plugin.h} @var{source-dir} @var{file-list} @var{plugin*.c}
+...} utility generates this extra root table, with the PCH related
+generated code kept wrapped with the @code{#ifdef
+GCC_PLUGIN_HAVE_PCH}, so disabled by default.
 
 You should understand the details of memory management inside GCC
 before using @code{PLUGIN_GGC_MARKING} or
-@code{PLUGIN_REGISTER_GGC_ROOTS}.
+@code{PLUGIN_REGISTER_GGC_ROOTS}.  Notice that using plugins which
+need these features may break the generation of precompiled headers
+[PCH], unless these plugins take specific measures.
 
 
 @section Giving information about a plugin
2009-07-09  Basile Starynkevitch  <basile@starynkevitch.net>

	* gengtype.h (is_plugin_file): Added new variable.
	* gengtype.c (struct pair, struct type) Added inplugin field.
	(first_plugin_file_ix, plugin_output_filename, plugin_output):
	Added static variables.
	(is_plugin_file): Added & defined variable.
	(output_delayed_functions): Added declaration.
	(read_input_list): Manage first_plugin_file_ix.
	(string_type, scalar_nonchar, scalar_char): Initialized inplugin
	field.
	(new_structure, find_structure, find_param_structure)
	(create_pointer, create_array, note_variable): Sets inplugin.
	(create_file): Allocates buf.
	(oprintf): Clear first byte of oldbuf for ease of debugging &
	added asserts.
	(open_base_files): Moved return when plugins.
	(get_output_file_with_visibility): Handle plugin case.
	"gtype-desc.c" is for "GCC".
	(close_output_files): Free the buffer.
	(struct write_types_data): Added is_pch field.
	(delay_func_for_structure): new static declaration.
	(write_func_for_structure): Emit #ifdef GCC_PLUGIN_HAVE_PCH
	wrapping.
	(write_types): delays the output of func in plugin mode.
	(ggc_wtd, pch_wtd): Sets the is_pch field.
	(write_local_func_for_structure): Emit the wrapping & handle
	plugin mode.
	(write_local): Handle plugin mode.
	(write_enum_defn): Emit gt_types_enum_firstempty & emit the
	dynamic enumeration #define-s in plugin mode.
	(write_roots): Handle plugin mode.
	(struct delayedstructfunc_st): New declaration.
	(dlystructab, dlystructsiz, dlystructcnt): Added static variables.
	(delay_func_for_structure, output_delayed_functions): added
	functions.
	(main): updated for plugin mode which is now with -P outputfile.h
	* doc/plugins.texi (Interacting with the GCC Garbage Collector):
	Added blurb about plugin mode & GCC_PLUGIN_HAVE_PCH.

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]