This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: patch ping^3: gengtype: improved version for plugin support.
- From: Basile STARYNKEVITCH <basile at starynkevitch dot net>
- To: Laurynas Biveinis <laurynas dot biveinis at gmail dot com>, Duncan Sands <baldrick at free dot fr>, "diego dot novillo at gmail dot com" <diego dot novillo at gmail dot com>
- Cc: gcc-patches <gcc-patches at gcc dot gnu dot org>
- Date: Tue, 01 Sep 2009 16:27:17 +0200
- Subject: Re: patch ping^3: gengtype: improved version for plugin support.
- References: <4A600F39.6000003@starynkevitch.net> <4A69A007.20108@starynkevitch.net> <4A9B5C2F.7010007@starynkevitch.net> <4A9CB3E3.5090808@starynkevitch.net> <d1e3ff2b0909010220t6ed8a4bfp1f15db94e754c807@mail.gmail.com>
Hello All
First of all, please accept my apologies for the previous useless email
http://gcc.gnu.org/ml/gcc-patches/2009-09/msg00043.html I just have sent
by error. I clicked to send the email before writing it.
Laurynas Biveinis wrote:
Hello -
Some comments about your patch. Of couse I should mention that I
cannot approve it.
I tried to take into account your comments and those of Duncan Sandis.
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. Hence, in
contrast to what Duncan kindly suggested, I cannot break it into parts;
and 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).
I think a cleaner abstraction would be to make
get_output_file_with_visibility handle plugins too, with extra
parameters passed.
I don't think so: in plugin mode (with this patch), the only written
file is the file explicitly asked by the -P flag. I repeat: in plugin
mode, this gengtype generates only one single file, the gt-*.h
explicitly asked!
At last, in this patch I voluntarily added a possible misfeature (but
documented both in comments and in *.texi documentation the known
weakness): As you should know, gengtype requires an explicit list of
files. In the http://gcc.gnu.org/ml/gcc/2009-07/msg00090.html thread, I
suggested having gtyp-input.list contain only absolute path names, but
Ian Taylor and others told that there are rare occasions (e.g.
automount-ed file systems) where this does not work. So I added an
additional gtyp-real-input.list which contains real paths (so is subject
to the weakness Ian explained) only for possible plugin users needing
gengtype, but I also documented that this might not work both in
plugins.texi and in Makefile.in comments. Could that be ok? I believe
that an insatisfactory solution (my gtyp-real-input.list generated file,
which is rarely useful, since most people don't compile plugins needing
GGC, but which probably should work in the usual case of non-automounted
file systems.) is better than no solution at all (otherwise, people have
to patch their gtyp-input.list by hand in all cases).
Ok for trunk if it bootstraps? Attached patch diff file & gcc/ChangeLog.
Again, apologies for having sent a useless message to the list.
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} ***
2009-09-01 Basile Starynkevitch <basile@starynkevitch.net>
* 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 and add the plugin
files into gt_files with cleared lang_bitmap.
(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
* Makefile.in (MOSTLYCLEANFILES): added gtyp-real-input.list
(REALGTFILES): Added variable and warning in comment.
(gtyp-real-input.list): Added target, useful only for plugins
using GGC.
(mostlyclean): Added removal of gtyp-real-input.list.
* doc/plugins.texi (Interacting with the GCC Garbage Collector):
Added blurb about plugin mode & GCC_PLUGIN_HAVE_PCH. Mentioned
gtyp-real-input.list with a warning.
Index: gcc/doc/plugins.texi
===================================================================
--- gcc/doc/plugins.texi (revision 151271)
+++ gcc/doc/plugins.texi (working copy)
@@ -226,12 +226,21 @@
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. The @var{file-list}
+argument should mention all the files using GGC (mentioning only those
+declaring the types used by the plugin is not enough). For that
+purpose, the @file{gcc/gtyp-real-input.list} file in the build tree
+could be convenient since it lists real absolute file paths; however,
+it might not work with auto-mounted file systems.
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
Index: gcc/gengtype.c
===================================================================
--- gcc/gengtype.c (revision 151271)
+++ gcc/gengtype.c (working copy)
@@ -64,6 +64,7 @@
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 @@
type_p next;
type_p pointer_to;
enum gc_used_enum gc_used;
+ bool in_plugin;
union {
type_p p;
struct {
@@ -145,9 +147,14 @@
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. */
+ source file. It is not generated in plugin mode! */
static outf_p header_file;
/* Source directory. */
@@ -169,10 +176,14 @@
/* 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,8 +476,19 @@
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 +534,18 @@
/* 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 +688,7 @@
}
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 +733,7 @@
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 +757,7 @@
{
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 +786,7 @@
{
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 +802,7 @@
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 +847,7 @@
n->line = *pos;
n->opt = o;
n->next = variables;
+ n->in_plugin = is_plugin_file;
variables = n;
}
@@ -1492,6 +1521,9 @@
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 +1540,7 @@
void
oprintf (outf_p o, const char *format, ...)
{
- char *s;
+ char *s = NULL;
size_t slength;
va_list ap;
@@ -1516,7 +1548,11 @@
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 +1562,24 @@
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,7 +1590,7 @@
{
size_t i;
- if (nb_plugin_files > 0 && plugin_files)
+ if (nb_plugin_files > 0 && plugin_files)
return;
header_file = create_file ("GCC", "gtype-desc.h");
@@ -1567,7 +1611,8 @@
"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 +1757,19 @@
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. */
@@ -1760,12 +1809,10 @@
else
{
int lang_index = get_prefix_langdir_index (basename);
-
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. */
@@ -1832,6 +1879,9 @@
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;
}
}
@@ -1864,6 +1914,7 @@
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,
@@ -1873,6 +1924,8 @@
static void write_func_for_structure
(type_p orig_s, type_p s, type_p * param,
const struct write_types_data *wtd);
+/* Marks the function for later output in plugin mode. */
+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,
@@ -2587,6 +2640,8 @@
}
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 " : "",
@@ -2691,6 +2746,8 @@
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");
}
@@ -2701,8 +2758,9 @@
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)
@@ -2713,13 +2771,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 (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)
@@ -2729,7 +2787,7 @@
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
@@ -2741,7 +2799,7 @@
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);
@@ -2752,7 +2810,10 @@
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)
@@ -2769,9 +2830,9 @@
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)
{
@@ -2795,6 +2856,7 @@
{
"ggc_m", NULL, "ggc_mark", "ggc_test_and_set_mark", NULL,
"GC marker procedures. ",
+ FALSE,
FALSE
};
@@ -2803,6 +2865,7 @@
"pch_n", "pch_p", "gt_pch_note_object", "gt_pch_note_object",
"gt_pch_note_reorder",
"PCH type-walking procedures. ",
+ TRUE,
TRUE
};
@@ -2875,11 +2938,15 @@
"\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");
}
@@ -2888,11 +2955,13 @@
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)
@@ -2910,11 +2979,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 (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,
@@ -2925,9 +2994,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 (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)
@@ -2947,9 +3016,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 (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)
@@ -2970,17 +3039,61 @@
}
}
-/* Write out the 'enum' definition for gt_types_enum. */
+/* Write out (to header_file, unless in plugin mode) 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->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;
+ }
+
+ /* 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)
@@ -3332,12 +3445,15 @@
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;
@@ -3629,6 +3745,77 @@
do_typedef (astratname, new_structure (astratname, 0, pos, field, 0), pos);
}
+
+/* In plugin mode, the writing 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;
+
+
+
+/* In plugin mode, we delay the output of functions by appending them
+ to the above array. */
+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++;
+}
+
+
+/* In plugin mode, output at last the functions which have been
+ kept. */
+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)
@@ -3639,20 +3826,23 @@
/* 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);
@@ -3678,9 +3868,14 @@
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;
@@ -3693,6 +3888,10 @@
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/Makefile.in
===================================================================
--- gcc/Makefile.in (revision 151271)
+++ gcc/Makefile.in (working copy)
@@ -1407,7 +1407,7 @@
insn-attr.h insn-attrtab.c insn-opinit.c insn-preds.c insn-constants.h \
tm-preds.h tm-constrs.h \
tree-check.h min-insn-modes.c insn-modes.c insn-modes.h \
- genrtl.c genrtl.h gt-*.h gtype-*.h gtype-desc.c gtyp-input.list \
+ genrtl.c genrtl.h gt-*.h gtype-*.h gtype-desc.c gtyp-input.list gtyp-real-input.list \
xgcc$(exeext) cpp$(exeext) cc1$(exeext) cc1*-dummy$(exeext) $(EXTRA_PASSES) \
$(EXTRA_PARTS) $(EXTRA_PROGRAMS) gcc-cross$(exeext) \
$(SPECS) collect2$(exeext) \
@@ -3497,6 +3497,13 @@
$(srcdir)/tree-ssa-alias.h \
@all_gtfiles@
+
+## compute the real path of above GTFILES - keeping language tags as
+## before. There are cases where this don't work (e.g. some
+## automount-ed file systems). This could be useful in plugin mode of
+## gengtype.
+REALGTFILES = $(foreach f, $(GTFILES), $(if $(patsubst [%],,$f), $(realpath $f), $f))
+
# Compute the list of GT header files from the corresponding C sources,
# possibly nested within config or language subdirectories. Match gengtype's
# behavior in this respect: gt-LANG-file.h for "file" anywhere within a LANG
@@ -3518,10 +3525,17 @@
$(ALL_GTFILES_H) gtype-desc.c gtype-desc.h : s-gtype ; @true
-gtyp-input.list: s-gtyp-input ; @true
+## we generate the gtyp-real-input.list only for convenience of
+## plugins needing GCC and using gengtype in plugin mode. The
+## gtyp-real-input.list file contains only absolute paths, it may not
+## work in some cases (e.g. perhaps when build tree is auto-mount-ed).
+
+gtyp-input.list gtyp-real-input.list: s-gtyp-input ; @true
s-gtyp-input: Makefile
@: $(call write_entries_to_file,$(GTFILES),tmp-gi.list)
$(SHELL) $(srcdir)/../move-if-change tmp-gi.list gtyp-input.list
+ @: $(call write_entries_to_file,$(REALGTFILES),tmp-realgi.list)
+ $(SHELL) $(srcdir)/../move-if-change tmp-realgi.list gtyp-real-input.list
$(STAMP) s-gtyp-input
s-gtype: build/gengtype$(build_exeext) $(filter-out [%], $(GTFILES)) \
@@ -4065,7 +4079,7 @@
# Delete core dumps.
-rm -f core */core
# Delete file generated for gengtype
- -rm -f gtyp-input.list
+ -rm -f gtyp-input.list gtyp-real-input.list
# Delete files generated by gengtype.c
-rm -f gtype-*
-rm -f gt-*