This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[patch trunk] gengtype: improved version for plugin support.
- From: Basile STARYNKEVITCH <basile at starynkevitch dot net>
- To: gcc-patches <gcc-patches at gcc dot gnu dot org>
- Date: Thu, 09 Jul 2009 18:43:25 +0200
- Subject: [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.