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]

gengtype: improved version for plugin support.


Hello All

I am submitting again for review the http://gcc.gnu.org/ml/gcc-patches/2009-09/msg00047.html

I am attaching a slightly improved patch, to trunk rev 151774.


As a general point, I believe this patch is much more usable for realistic plugins using GGC. As Duncan Sands explained, the current gengtype is very buggy in plugin mode for non trivial plugins.


it is quite a simple patch: in every place gengtype is outputting something relevant to plugins, I added an additional test, and I record in every descriptor of GTY-ed stuff a flag (called in_plugin) which tells if it is from the plugin files.


As I already mentioned in http://gcc.gnu.org/ml/gcc-patches/2009-07/msg00507.html


* 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...

Basically, plugin using GGC won't really work when generating precompiled headers, but my patch added an experimental feature to help future patches for this. (As I tried to explain in several occasions, generating precompiled headers is not currently very compatible with plugins for several reasons).


Notice that in plugin mode, the only generated file is the gt-plugin.h file passed as a program argument.


In plugin mode, gengtype should be invoked as
   gengtype -P gt-outputplugin.h inputplugin.h \
                inputplugin1.c inputplugin2.c


Previous submission of this patch http://gcc.gnu.org/ml/gcc-patches/2009-09/msg00047.html
contained also a gcc/doc/plugins.texi patch and a gcc/Makefile.in patch. Neither are essential (so I will propose them again if asked, or when this patch is approved).


gcc/ChangeLog:
2009-09-16  Basile Starynkevitch  <basile@starynkevitch.net>

	* gengtype.c (struct pair, struct type) Added in_plugin 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 and add the plugin
	files into gt_files with cleared lang_bitmap.
	(string_type, scalar_nonchar, scalar_char): Initialized in_plugin
	field.
	(new_structure, find_structure, find_param_structure)
	(create_pointer, create_array, note_variable): Sets in_plugin.
	(create_file): Allocates buf.
	(oprintf): Clear s for ease of debugging.
	(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


Ok for trunk if it bootstraps?


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 151774)
+++ gcc/gengtype.c	(working copy)
@@ -64,6 +64,7 @@ struct pair
   type_p type;
   struct fileloc line;
   options_p opt;
+  bool in_plugin;		/* flag set if appearing inside a plugin */
 };
 
 #define NUM_PARAM 10
@@ -83,6 +84,7 @@ struct type
   type_p next;
   type_p pointer_to;
   enum gc_used_enum gc_used;
+  bool in_plugin;
   union {
     type_p p;
     struct {
@@ -145,7 +147,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;
@@ -169,10 +177,15 @@ static const char * get_file_langdir (const char *
 /* Nonzero iff an error has occurred.  */
 bool hit_error = false;
 
+/* Flag set when parsing a plugin file */
+static 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,9 +478,20 @@ 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];
+	    {
+	      /* Place an all zero lang_bitmap before the plugin file
+		 name.  */
+	      int plugfilen = strlen (plugin_files[i]);
+	      char* plugent =
+		(char*) xcalloc (1, plugfilen + 1 + sizeof (lang_bitmap));
+	      plugent += sizeof (lang_bitmap);
+	      strcpy (plugent, plugin_files[i]);
+	      gt_files[nfiles++] = plugent;
+	      /* We don't bother freeing plugent! */
 	}
+	}
       num_gt_files = nfiles;
     }
 
@@ -512,17 +536,17 @@ 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.  */
@@ -665,6 +689,7 @@ new_structure (const char *name, int isunion, stru
     }
 
   s->kind = isunion ? TYPE_UNION : TYPE_STRUCT;
+  s->in_plugin = is_plugin_file;
   s->u.s.tag = name;
   s->u.s.line = *pos;
   s->u.s.fields = fields;
@@ -709,6 +734,7 @@ find_structure (const char *name, int isunion)
   s->next = structures;
   structures = s;
   s->kind = isunion ? TYPE_UNION : TYPE_STRUCT;
+  s->in_plugin = is_plugin_file;
   s->u.s.tag = name;
   structures = s;
   return s;
@@ -732,6 +758,7 @@ find_param_structure (type_p t, type_p param[NUM_P
     {
       res = XCNEW (struct type);
       res->kind = TYPE_PARAM_STRUCT;
+      res->in_plugin = is_plugin_file;
       res->next = param_structs;
       param_structs = res;
       res->u.param_struct.stru = t;
@@ -760,6 +787,7 @@ create_pointer (type_p t)
     {
       type_p r = XCNEW (struct type);
       r->kind = TYPE_POINTER;
+      r->in_plugin = is_plugin_file;
       r->u.p = t;
       t->pointer_to = r;
     }
@@ -775,6 +803,7 @@ create_array (type_p t, const char *len)
 
   v = XCNEW (struct type);
   v->kind = TYPE_ARRAY;
+  v->in_plugin = is_plugin_file;
   v->u.a.p = t;
   v->u.a.len = len;
   return v;
@@ -819,6 +848,7 @@ note_variable (const char *s, type_p t, options_p
   n->line = *pos;
   n->opt = o;
   n->next = variables;
+  n->in_plugin = is_plugin_file;
   variables = n;
 }
 
@@ -1492,6 +1522,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 +1541,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;
 
@@ -1713,15 +1746,18 @@ 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 (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.  */
@@ -1833,6 +1869,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;
     }
 }
 
@@ -1865,6 +1904,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,
@@ -1874,6 +1914,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,
@@ -2588,6 +2629,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 " : "",
@@ -2692,6 +2735,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");
 }
 
@@ -2702,8 +2747,9 @@ write_types (type_p structures, type_p param_struc
 	     const struct write_types_data *wtd)
 {
   type_p s;
+  outf_p outheadf = plugin_output_filename ? plugin_output : header_file;
 
-  oprintf (header_file, "\n/* %s*/\n", wtd->comment);
+  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)
@@ -2714,13 +2760,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)
@@ -2730,7 +2776,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
@@ -2742,7 +2788,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);
 
@@ -2753,7 +2799,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)
@@ -2770,9 +2819,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)
 	  {
@@ -2796,6 +2845,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
 };
 
@@ -2804,6 +2854,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
 };
 
@@ -2876,11 +2927,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");
 }
 
@@ -2889,11 +2944,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)
@@ -2911,11 +2968,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,
@@ -2926,9 +2983,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)
@@ -2948,9 +3005,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)
@@ -2976,12 +3033,54 @@ write_local (type_p structures, type_p param_struc
 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->in_plugin)
+	    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->in_plugin)
+	  {
+	    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;
+    }
 
   if (!header_file) 
     return;
   oprintf (header_file, "\n/* Enumeration of types known.  */\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)
@@ -3333,12 +3432,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->in_plugin)
+	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;
@@ -3386,12 +3488,17 @@ 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;
       int skip_p = 0;
       int length_p = 0;
       options_p o;
 
+      if (nb_plugin_files > 0 && plugin_output_filename && v->in_plugin)
+	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_p = 1;
@@ -3630,6 +3737,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)
@@ -3640,12 +3815,17 @@ 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;
+      /* In plugin mode, we carefully trace every stuff defined in the
+	 input files with a in_plugin flag, and output in the sole
+	 generated file only code relevant to that stuff. */
+      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) 
     {
@@ -3653,7 +3833,7 @@ main (int argc, char **argv)
       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);
 
@@ -3680,7 +3860,12 @@ main (int argc, char **argv)
   do_typedef ("PTR", create_pointer (resolve_typedef ("void", &pos)), &pos);
 
   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;
@@ -3694,6 +3879,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 Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]