| Index: lto/gcc/doc/plugins.texi |
| =================================================================== |
| --- lto.orig/gcc/doc/plugins.texi 2009-09-01 00:16:27.962891836 +0200 |
| +++ lto/gcc/doc/plugins.texi 2009-09-01 10:21:15.728775623 +0200 |
| @@ -226,12 +226,16 @@ |
| 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 |
| Index: lto/gcc/gengtype.c |
| =================================================================== |
| --- lto.orig/gcc/gengtype.c 2009-09-01 10:20:35.755693766 +0200 |
| +++ lto/gcc/gengtype.c 2009-09-01 10:21:15.732708428 +0200 |
| @@ -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 @@ |
| 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 @@ |
| type_p next; |
| type_p pointer_to; |
| enum gc_used_enum gc_used; |
| + bool inplugin; |
| union { |
| type_p p; |
| struct { |
| @@ -145,6 +148,12 @@ |
| 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. */ |
| @@ -167,12 +176,16 @@ |
| |
| |
| /* 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,8 +478,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]; |
| + { |
| + /* Each added entry in gt_files should have additional |
| + space for its lang_bitmap before. */ |
| + 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,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. */ |
| @@ -663,8 +688,9 @@ |
| 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 +735,7 @@ |
| 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 +759,7 @@ |
| { |
| 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 +788,7 @@ |
| { |
| 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 +804,7 @@ |
| |
| 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 +849,7 @@ |
| n->line = *pos; |
| n->opt = o; |
| n->next = variables; |
| + n->inplugin = is_plugin_file; |
| variables = n; |
| } |
| |
| @@ -1492,6 +1523,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 +1542,7 @@ |
| void |
| oprintf (outf_p o, const char *format, ...) |
| { |
| - char *s; |
| + char *s = NULL; |
| size_t slength; |
| va_list ap; |
| |
| @@ -1516,7 +1550,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 +1564,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,10 +1592,13 @@ |
| { |
| 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); |
| |
| @@ -1567,7 +1616,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 +1762,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. */ |
| @@ -1763,9 +1817,9 @@ |
| |
| 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 +1886,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 +1921,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 +1931,7 @@ |
| 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, |
| @@ -2587,6 +2646,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 +2752,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 +2764,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 +2777,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 +2793,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 +2805,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 +2816,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 +2836,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 +2862,7 @@ |
| { |
| "ggc_m", NULL, "ggc_mark", "ggc_test_and_set_mark", NULL, |
| "GC marker procedures. ", |
| + FALSE, |
| FALSE |
| }; |
| |
| @@ -2803,6 +2871,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 +2944,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 +2961,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 +2985,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 +3000,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 +3022,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 +3045,60 @@ |
| } |
| } |
| |
| -/* 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) |
| @@ -3332,12 +3450,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->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; |
| @@ -3629,6 +3750,74 @@ |
| 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) |
| @@ -3639,20 +3828,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 +3870,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 +3890,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: lto/gcc/gengtype.h |
| =================================================================== |
| --- lto.orig/gcc/gengtype.h 2009-09-01 00:16:27.942856818 +0200 |
| +++ lto/gcc/gengtype.h 2009-09-01 10:21:15.728775623 +0200 |
| @@ -76,6 +76,9 @@ |
| 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, |