This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: [patch] enhancing gengtype for plugins?
Hello All,
I am pinging http://gcc.gnu.org/ml/gcc-patches/2009-06/msg00254.html
with a small improvement (ability to handle several plugin files) and
some documentation.
Please note that the PLUGIN_REGISTER_GGC_ROOTS pseudo-event nearly requires
such a facility, or an equivalent one. How could one use
PLUGIN_REGISTER_GGC_ROOTS
without a GGC root table generated by gengtype (the alternative would be to hack gengtype to generate additional stuff, and cut&paste generated code into the plugin.c; that would be dirty!).
On Wed, Jun 03, 2009 at 11:07:45AM +0200, Basile Starynkevitch wrote:
Dear All,
I suggest to enhance the gengtype generator, so that,
1. It behaves as usual with the two arguments (sourcedir and filelist)
-hence nothing is broken...
2. In addition, when invoked as
gengtype -p sourcedir filelist plugin1.c plugin2.c
here the sourcedir & filelist is as usual, and the plugin*.c are new
files (you can have one or more such files) inside a plugin (not listed
in the filelist), its generates a gt-plugin1.h
and gt-plugin2.h (one for each file plugin*.c, which are using GTY).
I am resubmitting the enhanced patch (including documentation) to trunk
rev148178.
gcc/ChangeLog:
2009-06-04 Basile Starynkevitch <basile@starynkevitch.net>
* doc/plugins.texi (Interacting with the GCC Garbage Collector):
Mention the plugin mode
of gengtype.
* doc/gty.texi (Source Files Containing Type Information): Likewise.
* gengtype.c: Updated copyright.
(plugin_files, nb_plugin_files) Added new static variables.
(measure_input_list) Care about plugin_files.
(write_rtx_next): Added early return in plugin mode.
(create_file): Updated copyright year in generated file. Added asserts.
(oprintf): Added early return if null outf.
(get_output_file_with_visibility): Care of plugin_files.
(get_output_file_name): May return null.
(close_output_files) Emit a verbose message in plugin mode.
(write_local): Added early return.
(put_mangled_filename): Ditto.
(finish_root_table): Added check for base_files.
(write_roots): Care about null when plugins.
(main): added plugin mode.
Bootstrapped on x86_64-linux-gnu (Debian/Sid/AMD64). The extra
functionality has been tested - see
http://gcc.gnu.org/ml/gcc-patches/2009-06/msg00255.html.
The usual functionality (the GTY handling inside GCC) did not change.
Ok for trunk?
--
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/doc/plugins.texi
===================================================================
--- gcc/doc/plugins.texi (revision 148178)
+++ gcc/doc/plugins.texi (working copy)
@@ -198,13 +198,15 @@ Some plugins may need to have GGC mark additional
done by registering a callback (called with a null @code{gcc_data})
for the @code{PLUGIN_GGC_MARKING} event. Such callbacks can call the
@code{ggc_set_mark} routine, preferably thru the @code{ggc_mark} macro
-(and conversly, these routines should usually not be used in plugins
-outside of the @code{PLUGIN_GGC_MARKING} event).
+(and conversely, these routines should usually not be used in plugins
+outside of the @code{PLUGIN_GGC_MARKING} event).
Some plugins may need to add extra GGC root tables, e.g. to handle
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}.
+@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.
You should understand the details of memory management inside GCC
before using @code{PLUGIN_GGC_MARKING} or
Index: gcc/doc/gty.texi
===================================================================
--- gcc/doc/gty.texi (revision 148178)
+++ gcc/doc/gty.texi (working copy)
@@ -450,6 +450,13 @@ For language frontends, there is another file that
somewhere. It will be called @file{gtype-@var{lang}.h}, where
@var{lang} is the name of the subdirectory the language is contained in.
+Plugins can add additional root tables. Run the @code{gengtype}
+utility in plugin mode as @code{gengtype -p @var{source-dir}
+@var{file-list} @var{plugin*.c}} with your plugin files
+@var{plugin*.c} using @code{GTY} to generate the corresponding
+@var{gt-plugin*.h} files.
+
+
@node Invoking the garbage collector
@section How to invoke the garbage collector
@cindex garbage collector, invocation
Index: gcc/gengtype.c
===================================================================
--- gcc/gengtype.c (revision 148178)
+++ gcc/gengtype.c (working copy)
@@ -128,18 +128,24 @@ typedef struct outf * outf_p;
/* An output file, suitable for definitions, that can see declarations
made in INPUT_FILE and is linked into every language that uses
- INPUT_FILE. */
+ INPUT_FILE. May return null in plugin mode. */
extern outf_p get_output_file_with_visibility
(const char *input_file);
const char *get_output_file_name (const char *);
-/* Print, like fprintf, to O. */
+/* Print, like fprintf, to O. No-op if O is nil. */
static void oprintf (outf_p o, const char *S, ...)
ATTRIBUTE_PRINTF_2;
/* The list of output files. */
static outf_p output_files;
+/* the plugin input files and their number; in that case only
+ corresponding gt-<plugin>.h are generated in the current
+ directory. */
+static char** plugin_files;
+static int nb_plugin_files;
+
/* The output header file that is included into pretty much every
source file. */
static outf_p header_file;
@@ -274,7 +280,7 @@ measure_input_list (FILE *list)
int c;
bool atbol = true;
num_lang_dirs = 0;
- num_gt_files = 0;
+ num_gt_files = plugin_files ? nb_plugin_files : 0;
while ((c = getc (list)) != EOF)
{
n++;
@@ -455,6 +461,12 @@ read_input_list (const char *listname)
/* Update the global counts now that we know accurately how many
things there are. (We do not bother resizing the arrays down.) */
num_lang_dirs = langno;
+ /* add the plugin files if provided */
+ if (plugin_files) {
+ int i=0;
+ for (i=0; i<nb_plugin_files; i++)
+ gt_files[nfiles++] = plugin_files[i];
+ }
num_gt_files = nfiles;
}
@@ -962,6 +974,8 @@ write_rtx_next (void)
{
outf_p f = get_output_file_with_visibility (NULL);
int i;
+ if (!f)
+ return;
oprintf (f, "\n/* Used to implement the RTX_NEXT macro. */\n");
oprintf (f, "EXPORTED_CONST unsigned char rtx_next[NUM_RTX_CODE] = {\n");
@@ -1449,7 +1463,7 @@ static outf_p
create_file (const char *name, const char *oname)
{
static const char *const hdr[] = {
- " Copyright (C) 2004, 2007 Free Software Foundation, Inc.\n",
+ " Copyright (C) 2004, 2007, 2009 Free Software Foundation, Inc.\n",
"\n",
"This file is part of GCC.\n",
"\n",
@@ -1472,6 +1486,8 @@ create_file (const char *name, const char *oname)
outf_p f;
size_t i;
+ gcc_assert (name != NULL);
+ gcc_assert (oname != NULL);
f = XCNEW (struct outf);
f->next = output_files;
f->name = oname;
@@ -1495,6 +1511,11 @@ oprintf (outf_p o, const char *format, ...)
size_t slength;
va_list ap;
+ /* in plugin mode, the O could be a null pointer, so avoid crashing
+ in that case */
+ if (!o)
+ return;
+
va_start (ap, format);
slength = vasprintf (&s, format, ap);
if (s == NULL || (int)slength < 0)
@@ -1524,6 +1545,9 @@ open_base_files (void)
{
size_t i;
+ if (nb_plugin_files > 0 && plugin_files)
+ return;
+
header_file = create_file ("GCC", "gtype-desc.h");
base_files = XNEWVEC (outf_p, num_lang_dirs);
@@ -1686,6 +1710,18 @@ get_output_file_with_visibility (const char *input
if (input_file == NULL)
input_file = "system.h";
+ /* in plugin mode, return null unless the input_file is one of the
+ plugin_files */
+ if (plugin_files && 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]))
+ ix=i;
+ if (ix<0)
+ return NULL;
+ }
+
/* Determine the output file name. */
basename = get_file_basename (input_file);
@@ -1737,6 +1773,7 @@ get_output_file_with_visibility (const char *input
/* If not, create it. */
r = create_file (for_name, output_name);
+ gcc_assert(r && r->name);
return r;
}
@@ -1747,7 +1784,10 @@ get_output_file_with_visibility (const char *input
const char *
get_output_file_name (const char *input_file)
{
- return get_output_file_with_visibility (input_file)->name;
+ outf_p o = get_output_file_with_visibility (input_file);
+ if (o)
+ return o->name;
+ return NULL;
}
/* Copy the output to its final destination,
@@ -1787,6 +1827,9 @@ close_output_files (void)
fatal ("opening output file %s: %s", of->name, strerror (errno));
if (fwrite (of->buf, 1, of->bufused, newfile) != of->bufused)
fatal ("writing output file %s: %s", of->name, strerror (errno));
+ if (plugin_files && nb_plugin_files > 0)
+ fprintf (stderr, "gengtype wrote output file %s for plugins\n",
+ of->name);
if (fclose (newfile) != 0)
fatal ("closing output file %s: %s", of->name, strerror (errno));
}
@@ -2812,7 +2855,6 @@ write_local_func_for_structure (type_p orig_s, typ
memset (&d, 0, sizeof (d));
d.of = get_output_file_with_visibility (fn);
-
d.process_field = write_types_local_process_field;
d.opt = s->u.s.opt;
d.line = &s->u.s.line;
@@ -2848,6 +2890,8 @@ write_local (type_p structures, type_p param_struc
{
type_p s;
+ if (!header_file)
+ return;
oprintf (header_file, "\n/* Local pointer-walking routines. */\n");
for (s = structures; s; s = s->next)
if (s->gc_used == GC_POINTED_TO
@@ -2933,6 +2977,8 @@ write_enum_defn (type_p structures, type_p param_s
{
type_p s;
+ if (!header_file)
+ return;
oprintf (header_file, "\n/* Enumeration of types known. */\n");
oprintf (header_file, "enum gt_types_enum {\n");
for (s = structures; s; s = s->next)
@@ -2983,6 +3029,8 @@ static void
put_mangled_filename (outf_p f, const char *fn)
{
const char *name = get_output_file_name (fn);
+ if (!f || !name)
+ return;
for (; *name != 0; name++)
if (ISALNUM (*name))
oprintf (f, "%c", *name);
@@ -2998,7 +3046,7 @@ static void
finish_root_table (struct flist *flp, const char *pfx, const char *lastname,
const char *tname, const char *name)
{
- struct flist *fli2;
+ struct flist *fli2 = NULL;
for (fli2 = flp; fli2; fli2 = fli2->next)
if (fli2->started_p)
@@ -3007,7 +3055,7 @@ finish_root_table (struct flist *flp, const char *
oprintf (fli2->f, "};\n\n");
}
- for (fli2 = flp; fli2; fli2 = fli2->next)
+ for (fli2 = flp; fli2 && base_files; fli2 = fli2->next)
if (fli2->started_p)
{
lang_bitmap bitmap = get_lang_bitmap (fli2->name);
@@ -3026,7 +3074,7 @@ finish_root_table (struct flist *flp, const char *
{
size_t fnum;
- for (fnum = 0; fnum < num_lang_dirs; fnum++)
+ for (fnum = 0; base_files && fnum < num_lang_dirs; fnum++)
oprintf (base_files [fnum],
"EXPORTED_CONST struct %s * const %s[] = {\n",
tname, name);
@@ -3041,7 +3089,7 @@ finish_root_table (struct flist *flp, const char *
fli2->started_p = 0;
- for (fnum = 0; bitmap != 0; fnum++, bitmap >>= 1)
+ for (fnum = 0; base_files && bitmap != 0; fnum++, bitmap >>= 1)
if (bitmap & 1)
{
oprintf (base_files[fnum], " gt_%s_", pfx);
@@ -3052,7 +3100,7 @@ finish_root_table (struct flist *flp, const char *
{
size_t fnum;
- for (fnum = 0; fnum < num_lang_dirs; fnum++)
+ for (fnum = 0; base_files && fnum < num_lang_dirs; fnum++)
{
oprintf (base_files[fnum], " NULL\n");
oprintf (base_files[fnum], "};\n");
@@ -3285,7 +3333,7 @@ write_roots (pair_p variables)
for (v = variables; v; v = v->next)
{
outf_p f = get_output_file_with_visibility (v->line.file);
- struct flist *fli;
+ struct flist *fli = NULL;
const char *length = NULL;
int deletable_p = 0;
options_p o;
@@ -3309,7 +3357,7 @@ write_roots (pair_p variables)
v->name, o->name);
for (fli = flp; fli; fli = fli->next)
- if (fli->f == f)
+ if (fli->f == f && f)
break;
if (fli == NULL)
{
@@ -3318,6 +3366,7 @@ write_roots (pair_p variables)
fli->next = flp;
fli->started_p = 0;
fli->name = v->line.file;
+ gcc_assert(fli->name);
flp = fli;
oprintf (f, "\n/* GC roots. */\n\n");
@@ -3337,7 +3386,7 @@ write_roots (pair_p variables)
for (v = variables; v; v = v->next)
{
outf_p f = get_output_file_with_visibility (v->line.file);
- struct flist *fli;
+ struct flist *fli = NULL;
int skip_p = 0;
int length_p = 0;
options_p o;
@@ -3586,17 +3635,29 @@ main (int argc, char **argv)
{
size_t i;
static struct fileloc pos = { this_file, 0 };
-
+ char* inputlist = 0;
/* fatal uses this */
progname = "gengtype";
- if (argc != 3)
- fatal ("usage: gengtype srcdir input-list");
+ if (argc >= 5 && !strcmp(argv[1], "-p"))
+ {
+ srcdir = argv[2];
+ inputlist = argv[3];
+ plugin_files = argv+4;
+ nb_plugin_files = argc-4;
+ }
+ else if (argc == 3)
+ {
+ srcdir = argv[1];
+ inputlist = argv[2];
+ }
+ else
+ fatal ("usage: gengtype srcdir input-list\n"
+ "\t| gengtype -p srcdir input-list plugin... #for plugins");
- srcdir = argv[1];
srcdir_len = strlen (srcdir);
- read_input_list (argv[2]);
+ read_input_list (inputlist);
if (hit_error)
return 1;