X-Git-Url: http://git.sourceforge.jp/view?p=pf3gnuchains%2Fgcc-fork.git;a=blobdiff_plain;f=gcc%2Fgengtype.c;h=cb3d9bbf2211e87ec844e6a1f0571d836890a071;hp=dc428a8b608e2a44893dec5b4aa4a0cd9df276e1;hb=4c594a7d3aecfb70e5f1b238c93aadc704913a8b;hpb=2ac441f789cfb646ead90083ad6a933f72e24b42 diff --git a/gcc/gengtype.c b/gcc/gengtype.c index dc428a8b608..cb3d9bbf221 100644 --- a/gcc/gengtype.c +++ b/gcc/gengtype.c @@ -1,5 +1,5 @@ /* Process source files and output type information. - Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008 + Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc. This file is part of GCC. @@ -23,6 +23,7 @@ #include "gengtype.h" #include "errors.h" /* for fatal */ #include "double-int.h" +#include "hashtab.h" /* Data types, macros, etc. used only in this file. */ @@ -73,6 +74,10 @@ enum gc_used_enum { GC_UNUSED = 0, GC_USED, + /* Used for structures whose definitions we haven't seen so far when + we encounter a pointer to it that is annotated with ``maybe_undef''. + If after reading in everything we don't have source file + information for it, we assume that it never has been defined. */ GC_MAYBE_POINTED_TO, GC_POINTED_TO }; @@ -128,18 +133,25 @@ 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 NULL. */ 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 + a single file is produced. */ +static char** plugin_files; +static size_t nb_plugin_files; +/* the generated plugin output name & file */ +static outf_p plugin_output; + /* The output header file that is included into pretty much every source file. */ static outf_p header_file; @@ -171,7 +183,7 @@ static void close_output_files (void); /* Report an error at POS, printing MSG. */ void -error_at_line (struct fileloc *pos, const char *msg, ...) +error_at_line (const struct fileloc *pos, const char *msg, ...) { va_list ap; @@ -274,7 +286,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++; @@ -314,6 +326,10 @@ read_input_line (FILE *list, char **herep, char **linep, char *line; int c = getc (list); + /* Read over whitespace. */ + while (c == '\n' || c == ' ') + c = getc (list); + if (c == EOF) { *linep = 0; @@ -439,7 +455,7 @@ read_input_list (const char *listname) : lang_dir_names[langno - 1]); bmap |= curlangs; - set_lang_bitmap ((char *)gt_files[i], bmap); + set_lang_bitmap (CONST_CAST(char *, gt_files[i]), bmap); here = committed; goto next_line; } @@ -451,6 +467,13 @@ 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) + { + size_t i; + for (i = 0; i < nb_plugin_files; i++) + gt_files[nfiles++] = plugin_files[i]; + } num_gt_files = nfiles; } @@ -550,6 +573,7 @@ do_typedef (const char *s, type_p t, struct fileloc *pos) p->name = s; p->type = t; p->line = *pos; + p->opt = NULL; typedefs = p; } @@ -958,9 +982,11 @@ 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, "const unsigned char rtx_next[NUM_RTX_CODE] = {\n"); + oprintf (f, "EXPORTED_CONST unsigned char rtx_next[NUM_RTX_CODE] = {\n"); for (i = 0; i < NUM_RTX_CODE; i++) if (rtx_next_new[i] == -1) oprintf (f, " 0,\n"); @@ -982,7 +1008,7 @@ adjust_field_rtx_def (type_p t, options_p ARG_UNUSED (opt)) options_p nodot; int i; type_p rtx_tp, rtvec_tp, tree_tp, mem_attrs_tp, note_union_tp, scalar_tp; - type_p bitmap_tp, basic_block_tp, reg_attrs_tp, constant_tp, symbol_union_tp; + type_p basic_block_tp, reg_attrs_tp, constant_tp, symbol_union_tp; if (t->kind != TYPE_UNION) { @@ -998,7 +1024,6 @@ adjust_field_rtx_def (type_p t, options_p ARG_UNUSED (opt)) tree_tp = create_pointer (find_structure ("tree_node", 1)); mem_attrs_tp = create_pointer (find_structure ("mem_attrs", 0)); reg_attrs_tp = create_pointer (find_structure ("reg_attrs", 0)); - bitmap_tp = create_pointer (find_structure ("bitmap_element_def", 0)); basic_block_tp = create_pointer (find_structure ("basic_block_def", 0)); constant_tp = create_pointer (find_structure ("constant_descriptor_rtx", 0)); scalar_tp = &scalar_nonchar; /* rtunion int */ @@ -1012,6 +1037,7 @@ adjust_field_rtx_def (type_p t, options_p ARG_UNUSED (opt)) switch (c) { case NOTE_INSN_MAX: + case NOTE_INSN_DELETED_LABEL: note_flds = create_field (note_flds, &string_type, "rt_str"); break; @@ -1096,6 +1122,8 @@ adjust_field_rtx_def (type_p t, options_p ARG_UNUSED (opt)) t = scalar_tp, subname = "rt_int"; else if (i == VALUE && aindex == 0) t = scalar_tp, subname = "rt_int"; + else if (i == DEBUG_EXPR && aindex == 0) + t = tree_tp, subname = "rt_tree"; else if (i == REG && aindex == 1) t = scalar_tp, subname = "rt_int"; else if (i == REG && aindex == 2) @@ -1142,11 +1170,6 @@ adjust_field_rtx_def (type_p t, options_p ARG_UNUSED (opt)) subname = "rt_tree"; break; - case 'b': - t = bitmap_tp; - subname = "rt_bit"; - break; - case 'B': t = basic_block_tp; subname = "rt_bb"; @@ -1272,9 +1295,9 @@ adjust_field_type (type_p t, options_p opt) if (params[num] != NULL) error_at_line (&lexer_line, "duplicate `%s' option", opt->name); if (! ISDIGIT (opt->name[5])) - params[num] = create_pointer ((type_p) opt->info); + params[num] = create_pointer (CONST_CAST2(type_p, const char *, opt->info)); else - params[num] = (type_p) opt->info; + params[num] = CONST_CAST2 (type_p, const char *, opt->info); } else if (strcmp (opt->name, "special") == 0) { @@ -1323,7 +1346,8 @@ process_gc_options (options_p opt, enum gc_used_enum level, int *maybe_undef, options_p o; for (o = opt; o; o = o->next) if (strcmp (o->name, "ptr_alias") == 0 && level == GC_POINTED_TO) - set_gc_used_type ((type_p) o->info, GC_POINTED_TO, NULL); + set_gc_used_type (CONST_CAST2 (type_p, const char *, o->info), + GC_POINTED_TO, NULL); else if (strcmp (o->name, "maybe_undef") == 0) *maybe_undef = 1; else if (strcmp (o->name, "use_params") == 0) @@ -1369,7 +1393,7 @@ set_gc_used_type (type_p t, enum gc_used_enum level, type_p param[NUM_PARAM]) &length, &skip, &nested_ptr); if (nested_ptr && f->type->kind == TYPE_POINTER) - set_gc_used_type (nested_ptr, GC_POINTED_TO, + set_gc_used_type (nested_ptr, GC_POINTED_TO, pass_param ? param : NULL); else if (length && f->type->kind == TYPE_POINTER) set_gc_used_type (f->type->u.p, GC_USED, NULL); @@ -1443,7 +1467,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", @@ -1466,6 +1490,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; @@ -1477,7 +1503,7 @@ create_file (const char *name, const char *oname) return f; } -/* Print, like fprintf, to O. +/* Print, like fprintf, to O. N.B. You might think this could be implemented more efficiently with vsnprintf(). Unfortunately, there are C libraries that provide that function but without the C99 semantics for its return @@ -1489,6 +1515,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) @@ -1518,6 +1549,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); @@ -1530,13 +1564,14 @@ open_base_files (void) { /* The order of files here matters very much. */ static const char *const ifiles [] = { - "config.h", "system.h", "coretypes.h", "tm.h", "varray.h", + "config.h", "system.h", "coretypes.h", "tm.h", "hashtab.h", "splay-tree.h", "obstack.h", "bitmap.h", "input.h", "tree.h", "rtl.h", "function.h", "insn-config.h", "expr.h", "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", "cfgloop.h", NULL + "cfglayout.h", "except.h", "output.h", "gimple.h", "cfgloop.h", + "target.h", "ipa-prop.h", "lto-streamer.h", NULL }; const char *const *ifp; outf_p gtype_desc_c; @@ -1558,7 +1593,7 @@ static const char * get_file_realbasename (const char *f) { const char * lastslash = strrchr (f, '/'); - + return (lastslash != NULL) ? lastslash + 1 : f; } @@ -1600,7 +1635,7 @@ get_prefix_langdir_index (const char *f) { const char * langdir = lang_dir_names [lang_index]; size_t langdir_len = strlen (langdir); - + if (f_len > langdir_len && IS_DIR_SEPARATOR (f[langdir_len]) && memcmp (f, langdir, langdir_len) == 0) @@ -1641,13 +1676,13 @@ get_file_gtfilename (const char *f) const char *basename = get_file_realbasename (f); const char *langdir = get_file_langdir (f); - + char * result = (langdir ? xasprintf ("gt-%s-%s", langdir, basename) : xasprintf ("gt-%s", basename)); /* Then replace all non alphanumerics characters by '-' and change the - extenstion to ".h". We expect the input filename extension was at least + extension to ".h". We expect the input filename extension was at least one character long. */ char *s = result; @@ -1680,6 +1715,18 @@ get_output_file_with_visibility (const char *input_file) 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) + { + size_t i; + for (i = 0; i < nb_plugin_files; i++) + if (strcmp (input_file, plugin_files[i]) == 0) + return plugin_output; + + return NULL; + } + /* Determine the output file name. */ basename = get_file_basename (input_file); @@ -1688,7 +1735,7 @@ get_output_file_with_visibility (const char *input_file) || (len > 2 && memcmp (basename+len-2, ".y", 2) == 0) || (len > 3 && memcmp (basename+len-3, ".in", 3) == 0)) { - output_name = get_file_gtfilename (input_file); + output_name = get_file_gtfilename (input_file); for_name = basename; } /* Some headers get used by more than one front-end; hence, it @@ -1698,6 +1745,8 @@ get_output_file_with_visibility (const char *input_file) headers with source files (and their special purpose gt-*.h headers). */ else if (strcmp (basename, "c-common.h") == 0) output_name = "gt-c-common.h", for_name = "c-common.c"; + else if (strcmp (basename, "c-lang.h") == 0) + output_name = "gt-c-decl.h", for_name = "c-decl.c"; else if (strcmp (basename, "c-tree.h") == 0) output_name = "gt-c-decl.h", for_name = "c-decl.c"; else if (strncmp (basename, "cp", 2) == 0 && IS_DIR_SEPARATOR (basename[2]) @@ -1712,7 +1761,7 @@ get_output_file_with_visibility (const char *input_file) else if (strncmp (basename, "objc", 4) == 0 && IS_DIR_SEPARATOR (basename[4]) && strcmp (basename + 5, "objc-act.h") == 0) output_name = "gt-objc-objc-act.h", for_name = "objc/objc-act.c"; - else + else { int lang_index = get_prefix_langdir_index (basename); @@ -1731,6 +1780,7 @@ get_output_file_with_visibility (const char *input_file) /* If not, create it. */ r = create_file (for_name, output_name); + gcc_assert (r && r->name); return r; } @@ -1741,7 +1791,36 @@ get_output_file_with_visibility (const char *input_file) 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; +} + +/* Check if existing file is equal to the in memory buffer. */ + +static bool +is_file_equal (outf_p of) +{ + FILE *newfile = fopen (of->name, "r"); + size_t i; + bool equal; + if (newfile == NULL) + return false; + + equal = true; + for (i = 0; i < of->bufused; i++) + { + int ch; + ch = fgetc (newfile); + if (ch == EOF || ch != (unsigned char) of->buf[i]) + { + equal = false; + break; + } + } + fclose (newfile); + return equal; } /* Copy the output to its final destination, @@ -1754,35 +1833,20 @@ close_output_files (void) for (of = output_files; of; of = of->next) { - FILE * newfile; - newfile = fopen (of->name, "r"); - if (newfile != NULL ) - { - int no_write_p; - size_t i; - - for (i = 0; i < of->bufused; i++) - { - int ch; - ch = fgetc (newfile); - if (ch == EOF || ch != (unsigned char) of->buf[i]) - break; - } - no_write_p = i == of->bufused && fgetc (newfile) == EOF; - fclose (newfile); - - if (no_write_p) - continue; - } - - newfile = fopen (of->name, "w"); - if (newfile == NULL) - 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 (fclose (newfile) != 0) - fatal ("closing output file %s: %s", of->name, strerror (errno)); + if (!is_file_equal(of)) + { + FILE *newfile = fopen (of->name, "w"); + if (newfile == NULL) + 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 (fclose (newfile) != 0) + fatal ("closing output file %s: %s", of->name, strerror (errno)); + } + free(of->buf); + of->buf = NULL; + of->bufused = of->buflength = 0; } } @@ -1826,14 +1890,16 @@ static void write_func_for_structure 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, +static void write_types (outf_p output_header, + type_p structures, type_p param_structs, const struct write_types_data *wtd); static void write_types_local_process_field (type_p f, const struct walk_type_data *d); static void write_local_func_for_structure - (type_p orig_s, type_p s, type_p * param); -static void write_local (type_p structures, + (const_type_p orig_s, type_p s, type_p * param); +static void write_local (outf_p output_header, + type_p structures, type_p param_structs); static void write_enum_defn (type_p structures, type_p param_structs); static int contains_scalar_p (type_p t); @@ -1842,10 +1908,10 @@ static void finish_root_table (struct flist *flp, const char *pfx, const char *tname, const char *lastname, const char *name); static void write_root (outf_p , pair_p, type_p, const char *, int, - struct fileloc *, const char *); + struct fileloc *, const char *, bool); static void write_array (outf_p f, pair_p v, const struct write_types_data *wtd); -static void write_roots (pair_p); +static void write_roots (pair_p, bool); /* Parameters for walk_type. */ @@ -1859,7 +1925,7 @@ struct walk_type_data const char *prev_val[4]; int indent; int counter; - struct fileloc *line; + const struct fileloc *line; lang_bitmap bitmap; type_p *param; int used_length; @@ -2106,9 +2172,9 @@ walk_type (type_p t, struct walk_type_data *d) d->indent += 2; d->val = xasprintf ("x%d", d->counter++); oprintf (d->of, "%*s%s %s * %s%s =\n", d->indent, "", - (nested_ptr_d->type->kind == TYPE_UNION - ? "union" : "struct"), - nested_ptr_d->type->u.s.tag, + (nested_ptr_d->type->kind == TYPE_UNION + ? "union" : "struct"), + nested_ptr_d->type->u.s.tag, d->fn_wants_lvalue ? "" : "const ", d->val); oprintf (d->of, "%*s", d->indent + 2, ""); @@ -2196,7 +2262,7 @@ walk_type (type_p t, struct walk_type_data *d) else oprintf (d->of, "%s", t->u.a.len); oprintf (d->of, ");\n"); - + oprintf (d->of, "%*sfor (i%d = 0; i%d != l%d; i%d++) {\n", d->indent, "", loopcounter, loopcounter, loopcounter, loopcounter); @@ -2468,6 +2534,24 @@ output_type_enum (outf_p of, type_p s) oprintf (of, ", gt_types_enum_last"); } +/* Return an output file that is suitable for definitions which can + reference struct S */ + +static outf_p +get_output_file_for_structure (const_type_p s, type_p *param) +{ + const char * fn = s->u.s.line.file; + int i; + + /* This is a hack, and not the good kind either. */ + for (i = NUM_PARAM - 1; i >= 0; i--) + if (param && param[i] && param[i]->kind == TYPE_POINTER + && UNION_OR_STRUCT_P (param[i]->u.p)) + fn = param[i]->u.p->u.s.line.file; + + return get_output_file_with_visibility (fn); +} + /* For S, a structure that's part of ORIG_S, and using parameters PARAM, write out a routine that: - Takes a parameter, a void * but actually of type *S @@ -2480,8 +2564,6 @@ static void write_func_for_structure (type_p orig_s, type_p s, type_p *param, const struct write_types_data *wtd) { - const char *fn = s->u.s.line.file; - int i; const char *chain_next = NULL; const char *chain_prev = NULL; const char *chain_circular = NULL; @@ -2489,14 +2571,8 @@ write_func_for_structure (type_p orig_s, type_p s, type_p *param, options_p opt; struct walk_type_data d; - /* This is a hack, and not the good kind either. */ - for (i = NUM_PARAM - 1; i >= 0; i--) - if (param && param[i] && param[i]->kind == TYPE_POINTER - && UNION_OR_STRUCT_P (param[i]->u.p)) - fn = param[i]->u.p->u.s.line.file; - memset (&d, 0, sizeof (d)); - d.of = get_output_file_with_visibility (fn); + d.of = get_output_file_for_structure (s, param); for (opt = s->u.s.opt; opt; opt = opt->next) if (strcmp (opt->name, "chain_next") == 0) @@ -2648,12 +2724,15 @@ write_func_for_structure (type_p orig_s, type_p s, type_p *param, /* Write out marker routines for STRUCTURES and PARAM_STRUCTS. */ static void -write_types (type_p structures, type_p param_structs, +write_types (outf_p output_header, type_p structures, type_p param_structs, const struct write_types_data *wtd) { type_p s; - oprintf (header_file, "\n/* %s*/\n", wtd->comment); + oprintf (output_header, "\n/* %s*/\n", wtd->comment); + /* We first emit the macros and the declarations. Functions' code is + emitted afterwards. This is needed in plugin mode. */ + oprintf (output_header, "/* macros and declarations */\n"); for (s = structures; s; s = s->next) if (s->gc_used == GC_POINTED_TO || s->gc_used == GC_MAYBE_POINTED_TO) @@ -2664,13 +2743,13 @@ write_types (type_p structures, type_p param_structs, && 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 (output_header, "#define gt_%s_", wtd->prefix); + output_mangled_typename (output_header, s); + oprintf (output_header, "(X) do { \\\n"); + oprintf (output_header, " if (X != NULL) gt_%sx_%s (X);\\\n", wtd->prefix, s->u.s.tag); - oprintf (header_file, + oprintf (output_header, " } while (0)\n"); for (opt = s->u.s.opt; opt; opt = opt->next) @@ -2680,7 +2759,7 @@ write_types (type_p structures, type_p param_structs, if (t->kind == TYPE_STRUCT || t->kind == TYPE_UNION || t->kind == TYPE_LANG_STRUCT) - oprintf (header_file, + oprintf (output_header, "#define gt_%sx_%s gt_%sx_%s\n", wtd->prefix, s->u.s.tag, wtd->prefix, t->u.s.tag); else @@ -2692,7 +2771,7 @@ write_types (type_p structures, type_p param_structs, continue; /* Declare the marker procedure only once. */ - oprintf (header_file, + oprintf (output_header, "extern void gt_%sx_%s (void *);\n", wtd->prefix, s->u.s.tag); @@ -2702,27 +2781,17 @@ write_types (type_p structures, type_p param_structs, s->u.s.tag); continue; } - - 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); } for (s = param_structs; s; s = s->next) if (s->gc_used == GC_POINTED_TO) { - type_p * param = s->u.param_struct.param; 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 (output_header, "extern void gt_%s_", wtd->prefix); + output_mangled_typename (output_header, s); + oprintf (output_header, " (void *);\n"); if (stru->u.s.line.file == NULL) { @@ -2730,7 +2799,41 @@ write_types (type_p structures, type_p param_structs, s->u.s.tag); continue; } + } + /* At last we emit the functions code. */ + oprintf (output_header, "\n/* functions code */\n"); + for (s = structures; s; s = s->next) + if (s->gc_used == GC_POINTED_TO + || s->gc_used == GC_MAYBE_POINTED_TO) + { + options_p opt; + + if (s->gc_used == GC_MAYBE_POINTED_TO + && s->u.s.line.file == NULL) + continue; + for (opt = s->u.s.opt; opt; opt = opt->next) + if (strcmp (opt->name, "ptr_alias") == 0) + break; + if (opt) + continue; + + 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); + } + for (s = param_structs; s; s = s->next) + if (s->gc_used == GC_POINTED_TO) + { + type_p *param = s->u.param_struct.param; + type_p stru = s->u.param_struct.stru; + if (stru->u.s.line.file == NULL) + continue; if (stru->kind == TYPE_LANG_STRUCT) { type_p ss; @@ -2792,21 +2895,12 @@ write_types_local_process_field (type_p f, const struct walk_type_data *d) */ static void -write_local_func_for_structure (type_p orig_s, type_p s, type_p *param) +write_local_func_for_structure (const_type_p orig_s, type_p s, type_p *param) { - const char *fn = s->u.s.line.file; - int i; struct walk_type_data d; - /* This is a hack, and not the good kind either. */ - for (i = NUM_PARAM - 1; i >= 0; i--) - if (param && param[i] && param[i]->kind == TYPE_POINTER - && UNION_OR_STRUCT_P (param[i]->u.p)) - fn = param[i]->u.p->u.s.line.file; - memset (&d, 0, sizeof (d)); - d.of = get_output_file_with_visibility (fn); - + d.of = get_output_file_for_structure (s, param); d.process_field = write_types_local_process_field; d.opt = s->u.s.opt; d.line = &s->u.s.line; @@ -2838,11 +2932,13 @@ write_local_func_for_structure (type_p orig_s, type_p s, type_p *param) /* Write out local marker routines for STRUCTURES and PARAM_STRUCTS. */ static void -write_local (type_p structures, type_p param_structs) +write_local (outf_p output_header, type_p structures, type_p param_structs) { type_p s; - oprintf (header_file, "\n/* Local pointer-walking routines. */\n"); + if (!output_header) + return; + oprintf (output_header, "\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) @@ -2860,11 +2956,11 @@ write_local (type_p structures, type_p param_structs) || 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 (output_header, "#define gt_pch_p_"); + output_mangled_typename (output_header, s); + oprintf (output_header, " gt_pch_p_"); + output_mangled_typename (output_header, t); + oprintf (output_header, "\n"); } else error_at_line (&s->u.s.line, @@ -2875,9 +2971,9 @@ write_local (type_p structures, type_p param_structs) 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 (output_header, "extern void gt_pch_p_"); + output_mangled_typename (output_header, s); + oprintf (output_header, "\n (void *, void *, gt_pointer_operator, void *);\n"); if (s->kind == TYPE_LANG_STRUCT) @@ -2897,9 +2993,9 @@ write_local (type_p structures, type_p param_structs) 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 (output_header, "extern void gt_pch_p_"); + output_mangled_typename (output_header, s); + oprintf (output_header, "\n (void *, void *, gt_pointer_operator, void *);\n"); if (stru->u.s.line.file == NULL) @@ -2927,6 +3023,8 @@ write_enum_defn (type_p structures, type_p param_structs) { 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) @@ -2977,6 +3075,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); @@ -3001,7 +3101,7 @@ finish_root_table (struct flist *flp, const char *pfx, const char *lastname, 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); @@ -3020,9 +3120,9 @@ finish_root_table (struct flist *flp, const char *pfx, const char *lastname, { 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], - "const struct %s * const %s[] = {\n", + "EXPORTED_CONST struct %s * const %s[] = {\n", tname, name); } @@ -3035,7 +3135,7 @@ finish_root_table (struct flist *flp, const char *pfx, const char *lastname, 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); @@ -3046,7 +3146,7 @@ finish_root_table (struct flist *flp, const char *pfx, const char *lastname, { 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"); @@ -3061,7 +3161,7 @@ finish_root_table (struct flist *flp, const char *pfx, const char *lastname, static void write_root (outf_p f, pair_p v, type_p type, const char *name, int has_length, - struct fileloc *line, const char *if_marked) + struct fileloc *line, const char *if_marked, bool emit_pch) { switch (type->kind) { @@ -3117,7 +3217,7 @@ write_root (outf_p f, pair_p v, type_p type, const char *name, int has_length, newname = xasprintf ("%s.%s.%s", name, fld->name, validf->name); write_root (f, v, validf->type, newname, 0, line, - if_marked); + if_marked, emit_pch); free (newname); } } @@ -3129,7 +3229,8 @@ write_root (outf_p f, pair_p v, type_p type, const char *name, int has_length, { char *newname; newname = xasprintf ("%s.%s", name, fld->name); - write_root (f, v, fld->type, newname, 0, line, if_marked); + write_root (f, v, fld->type, newname, 0, line, if_marked, + emit_pch); free (newname); } } @@ -3140,7 +3241,8 @@ write_root (outf_p f, pair_p v, type_p type, const char *name, int has_length, { char *newname; newname = xasprintf ("%s[0]", name); - write_root (f, v, type->u.a.p, newname, has_length, line, if_marked); + write_root (f, v, type->u.a.p, newname, has_length, line, if_marked, + emit_pch); free (newname); } break; @@ -3169,20 +3271,31 @@ write_root (outf_p f, pair_p v, type_p type, const char *name, int has_length, if (! has_length && UNION_OR_STRUCT_P (tp)) { oprintf (f, " >_ggc_mx_%s,\n", tp->u.s.tag); - oprintf (f, " >_pch_nx_%s", tp->u.s.tag); + if (emit_pch) + oprintf (f, " >_pch_nx_%s", tp->u.s.tag); + else + oprintf (f, " NULL"); } else if (! has_length && tp->kind == TYPE_PARAM_STRUCT) { oprintf (f, " >_ggc_m_"); output_mangled_typename (f, tp); - oprintf (f, ",\n >_pch_n_"); - output_mangled_typename (f, tp); + if (emit_pch) + { + oprintf (f, ",\n >_pch_n_"); + output_mangled_typename (f, tp); + } + else + oprintf (f, ",\n NULL"); } else if (has_length && (tp->kind == TYPE_POINTER || UNION_OR_STRUCT_P (tp))) { oprintf (f, " >_ggc_ma_%s,\n", name); - oprintf (f, " >_pch_na_%s", name); + if (emit_pch) + oprintf (f, " >_pch_na_%s", name); + else + oprintf (f, " NULL"); } else { @@ -3271,7 +3384,7 @@ write_array (outf_p f, pair_p v, const struct write_types_data *wtd) /* Output a table describing the locations and types of VARIABLES. */ static void -write_roots (pair_p variables) +write_roots (pair_p variables, bool emit_pch) { pair_p v; struct flist *flp = NULL; @@ -3303,7 +3416,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) { @@ -3312,6 +3425,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"); @@ -3353,12 +3467,12 @@ write_roots (pair_p variables) { fli->started_p = 1; - oprintf (f, "const struct ggc_root_tab gt_ggc_r_"); + oprintf (f, "EXPORTED_CONST struct ggc_root_tab gt_ggc_r_"); put_mangled_filename (f, v->line.file); oprintf (f, "[] = {\n"); } - write_root (f, v, v->type, v->name, length_p, &v->line, NULL); + write_root (f, v, v->type, v->name, length_p, &v->line, NULL, emit_pch); } finish_root_table (flp, "ggc_r", "LAST_GGC_ROOT_TAB", "ggc_root_tab", @@ -3387,7 +3501,7 @@ write_roots (pair_p variables) { fli->started_p = 1; - oprintf (f, "const struct ggc_root_tab gt_ggc_rd_"); + oprintf (f, "EXPORTED_CONST struct ggc_root_tab gt_ggc_rd_"); put_mangled_filename (f, v->line.file); oprintf (f, "[] = {\n"); } @@ -3431,18 +3545,21 @@ write_roots (pair_p variables) { fli->started_p = 1; - oprintf (f, "const struct ggc_cache_tab gt_ggc_rc_"); + oprintf (f, "EXPORTED_CONST struct ggc_cache_tab gt_ggc_rc_"); put_mangled_filename (f, v->line.file); oprintf (f, "[] = {\n"); } write_root (f, v, v->type->u.p->u.param_struct.param[0], - v->name, length_p, &v->line, if_marked); + v->name, length_p, &v->line, if_marked, emit_pch); } finish_root_table (flp, "ggc_rc", "LAST_GGC_CACHE_TAB", "ggc_cache_tab", "gt_ggc_cache_rtab"); + if (!emit_pch) + return; + for (v = variables; v; v = v->next) { outf_p f = get_output_file_with_visibility (v->line.file); @@ -3467,12 +3584,12 @@ write_roots (pair_p variables) { fli->started_p = 1; - oprintf (f, "const struct ggc_root_tab gt_pch_rc_"); + oprintf (f, "EXPORTED_CONST struct ggc_root_tab gt_pch_rc_"); put_mangled_filename (f, v->line.file); oprintf (f, "[] = {\n"); } - write_root (f, v, v->type, v->name, length_p, &v->line, NULL); + write_root (f, v, v->type, v->name, length_p, &v->line, NULL, emit_pch); } finish_root_table (flp, "pch_rc", "LAST_GGC_ROOT_TAB", "ggc_root_tab", @@ -3503,7 +3620,7 @@ write_roots (pair_p variables) { fli->started_p = 1; - oprintf (f, "const struct ggc_root_tab gt_pch_rs_"); + oprintf (f, "EXPORTED_CONST struct ggc_root_tab gt_pch_rs_"); put_mangled_filename (f, v->line.file); oprintf (f, "[] = {\n"); } @@ -3528,22 +3645,22 @@ write_roots (pair_p variables) where the GTY(()) tags are only present if is_scalar is _false_. */ void -note_def_vec (const char *typename, bool is_scalar, struct fileloc *pos) +note_def_vec (const char *type_name, bool is_scalar, struct fileloc *pos) { pair_p fields; type_p t; options_p o; type_p len_ty = create_scalar_type ("unsigned"); - const char *name = concat ("VEC_", typename, "_base", (char *)0); + const char *name = concat ("VEC_", type_name, "_base", (char *)0); if (is_scalar) { - t = create_scalar_type (typename); + t = create_scalar_type (type_name); o = 0; } else { - t = resolve_typedef (typename, pos); + t = resolve_typedef (type_name, pos); o = create_option (0, "length", "%h.num"); } @@ -3574,23 +3691,295 @@ note_def_vec_alloc (const char *type, const char *astrat, struct fileloc *pos) do_typedef (astratname, new_structure (astratname, 0, pos, field, 0), pos); } +static void dump_pair (int indent, pair_p p); +static void dump_type (int indent, type_p p); +static void dump_type_list (int indent, type_p p); + +#define INDENT 2 + +/* Dumps the value of typekind KIND. */ + +static void +dump_typekind (int indent, enum typekind kind) +{ + printf ("%*ckind = ", indent, ' '); + switch (kind) + { + case TYPE_SCALAR: printf ("TYPE_SCALAR"); break; + case TYPE_STRING: printf ("TYPE_STRING"); break; + case TYPE_STRUCT: printf ("TYPE_STRUCT"); break; + case TYPE_UNION: printf ("TYPE_UNION"); break; + case TYPE_POINTER: printf ("TYPE_POINTER"); break; + case TYPE_ARRAY: printf ("TYPE_ARRAY"); break; + case TYPE_LANG_STRUCT: printf ("TYPE_LANG_STRUCT"); break; + case TYPE_PARAM_STRUCT: printf ("TYPE_PARAM_STRUCT"); break; + default: gcc_unreachable (); + } + printf ("\n"); +} + +/* Dumps the value of GC_USED flag. */ + +static void +dump_gc_used (int indent, enum gc_used_enum gc_used) +{ + printf ("%*cgc_used = ", indent, ' '); + switch (gc_used) + { + case GC_UNUSED: printf ("GC_UNUSED"); break; + case GC_USED: printf ("GC_USED"); break; + case GC_MAYBE_POINTED_TO: printf ("GC_MAYBE_POINTED_TO"); break; + case GC_POINTED_TO: printf ("GC_POINTED_TO"); break; + default: gcc_unreachable (); + } + printf ("\n"); +} + +/* Dumps the type options OPT. */ + +static void +dump_options (int indent, options_p opt) +{ + options_p o; + printf ("%*coptions = ", indent, ' '); + o = opt; + while (o) + { + printf ("%s:%s ", o->name, o->info); + o = o->next; + } + printf ("\n"); +} + +/* Dumps the source file location in LINE. */ + +static void +dump_fileloc (int indent, struct fileloc line) +{ + printf ("%*cfileloc: file = %s, line = %d\n", indent, ' ', line.file, + line.line); +} + +/* Recursively dumps the struct, union, or a language-specific + struct T. */ + +static void +dump_type_u_s (int indent, type_p t) +{ + pair_p fields; + + gcc_assert (t->kind == TYPE_STRUCT || t->kind == TYPE_UNION + || t->kind == TYPE_LANG_STRUCT); + printf ("%*cu.s.tag = %s\n", indent, ' ', t->u.s.tag); + dump_fileloc (indent, t->u.s.line); + printf ("%*cu.s.fields =\n", indent, ' '); + fields = t->u.s.fields; + while (fields) + { + dump_pair (indent + INDENT, fields); + fields = fields->next; + } + printf ("%*cend of fields of type %p\n", indent, ' ', (void *) t); + dump_options (indent, t->u.s.opt); + printf ("%*cu.s.bitmap = %X\n", indent, ' ', t->u.s.bitmap); + if (t->kind == TYPE_LANG_STRUCT) + { + printf ("%*cu.s.lang_struct:\n", indent, ' '); + dump_type_list (indent + INDENT, t->u.s.lang_struct); + } +} + +/* Recursively dumps the array T. */ + +static void +dump_type_u_a (int indent, type_p t) +{ + gcc_assert (t->kind == TYPE_ARRAY); + printf ("%*clen = %s, u.a.p:\n", indent, ' ', t->u.a.len); + dump_type_list (indent + INDENT, t->u.a.p); +} + +/* Recursively dumps the parameterized struct T. */ + +static void +dump_type_u_param_struct (int indent, type_p t) +{ + int i; + gcc_assert (t->kind == TYPE_PARAM_STRUCT); + printf ("%*cu.param_struct.stru:\n", indent, ' '); + dump_type_list (indent, t->u.param_struct.stru); + dump_fileloc (indent, t->u.param_struct.line); + for (i = 0; i < NUM_PARAM; i++) + { + if (t->u.param_struct.param[i] == NULL) + continue; + printf ("%*cu.param_struct.param[%d]:\n", indent, ' ', i); + dump_type (indent + INDENT, t->u.param_struct.param[i]); + } +} + +/* Recursively dumps the type list T. */ + +static void +dump_type_list (int indent, type_p t) +{ + type_p p = t; + while (p) + { + dump_type (indent, p); + p = p->next; + } +} + +static htab_t seen_types; + +/* Recursively dumps the type T if it was not dumped previously. */ + +static void +dump_type (int indent, type_p t) +{ + PTR *slot; + + printf ("%*cType at %p: ", indent, ' ', (void *)t); + slot = htab_find_slot (seen_types, t, INSERT); + if (*slot != NULL) + { + printf ("already seen.\n"); + return; + } + *slot = t; + printf ("\n"); + + dump_typekind (indent, t->kind); + printf ("%*cpointer_to = %p\n", indent + INDENT, ' ', + (void *)t->pointer_to); + dump_gc_used (indent + INDENT, t->gc_used); + switch (t->kind) + { + case TYPE_SCALAR: + printf ("%*cscalar_is_char = %s\n", indent + INDENT, ' ', + t->u.scalar_is_char ? "true" : "false"); + break; + case TYPE_STRING: + break; + case TYPE_STRUCT: + case TYPE_UNION: + case TYPE_LANG_STRUCT: + dump_type_u_s (indent + INDENT, t); + break; + case TYPE_POINTER: + printf ("%*cp:\n", indent + INDENT, ' '); + dump_type (indent + INDENT, t->u.p); + break; + case TYPE_ARRAY: + dump_type_u_a (indent + INDENT, t); + break; + case TYPE_PARAM_STRUCT: + dump_type_u_param_struct (indent + INDENT, t); + break; + default: + gcc_unreachable (); + } + printf ("%*cEnd of type at %p\n", indent, ' ', (void *)t); +} + +/* Dumps the pair P. */ + +static void +dump_pair (int indent, pair_p p) +{ + printf ("%*cpair: name = %s\n", indent, ' ', p->name); + dump_type (indent, p->type); + dump_fileloc (indent, p->line); + dump_options (indent, p->opt); + printf ("%*cEnd of pair %s\n", indent, ' ', p->name); +} + +/* Dumps the list of pairs PP. */ + +static void +dump_pair_list (const char * name, pair_p pp) +{ + pair_p p; + printf ("%s:\n", name); + for (p = pp; p != NULL; p = p->next) + dump_pair (0, p); + printf ("End of %s\n\n", name); +} + +/* Dumps the STRUCTURES. */ + +static void +dump_structures (const char * name, type_p structures) +{ + printf ("%s:\n", name); + dump_type_list (0, structures); + printf ("End of %s\n\n", name); +} + +/* Dumps the internal structures of gengtype. */ + +static void +dump_everything (void) +{ + seen_types = htab_create (100, htab_hash_pointer, htab_eq_pointer, NULL); + dump_pair_list ("typedefs", typedefs); + dump_structures ("structures", structures); + dump_structures ("param_structs", param_structs); + dump_pair_list ("variables", variables); + htab_delete (seen_types); +} + int main (int argc, char **argv) { size_t i; static struct fileloc pos = { this_file, 0 }; - + char* inputlist = 0; + int do_dump = 0; + outf_p output_header; + char* plugin_output_filename = NULL; /* fatal uses this */ progname = "gengtype"; - if (argc != 3) - fatal ("usage: gengtype srcdir input-list"); + if (argc >= 2 && !strcmp (argv[1], "-d")) + { + do_dump = 1; + argv = &argv[1]; + argc--; + } + + if (argc >= 6 && !strcmp (argv[1], "-P")) + { + plugin_output_filename = argv[2]; + plugin_output = create_file ("GCC", plugin_output_filename); + srcdir = argv[3]; + inputlist = argv[4]; + nb_plugin_files = argc - 5; + plugin_files = XCNEWVEC (char *, nb_plugin_files); + for (i = 0; i < nb_plugin_files; i++) + { + /* Place an all zero lang_bitmap before the plugin file + name. */ + char *name = argv[i + 5]; + int len = strlen(name) + 1 + sizeof (lang_bitmap); + plugin_files[i] = XCNEWVEC (char, len) + sizeof (lang_bitmap); + strcpy (plugin_files[i], name); + } + } + else if (argc == 3) + { + srcdir = argv[1]; + inputlist = argv[2]; + } + else + fatal ("usage: gengtype [-d] [-P pluginout.h] srcdir input-list " + "[file1 file2 ... fileN]"); - srcdir = argv[1]; srcdir_len = strlen (srcdir); - read_input_list (argv[2]); + read_input_list (inputlist); if (hit_error) return 1; @@ -3605,6 +3994,7 @@ main (int argc, char **argv) do_scalar_typedef ("REAL_VALUE_TYPE", &pos); pos.line++; do_scalar_typedef ("FIXED_VALUE_TYPE", &pos); pos.line++; do_scalar_typedef ("double_int", &pos); pos.line++; + do_scalar_typedef ("uint64_t", &pos); pos.line++; do_scalar_typedef ("uint8", &pos); pos.line++; do_scalar_typedef ("jword", &pos); pos.line++; do_scalar_typedef ("JCF_u2", &pos); pos.line++; @@ -3621,13 +4011,27 @@ main (int argc, char **argv) open_base_files (); write_enum_defn (structures, param_structs); - write_types (structures, param_structs, &ggc_wtd); - write_types (structures, param_structs, &pch_wtd); - write_local (structures, param_structs); - write_roots (variables); + output_header = plugin_output ? plugin_output : header_file; + write_types (output_header, structures, param_structs, &ggc_wtd); + if (plugin_files == NULL) + { + write_types (header_file, structures, param_structs, &pch_wtd); + write_local (header_file, structures, param_structs); + } + write_roots (variables, plugin_files == NULL); write_rtx_next (); close_output_files (); + if (do_dump) + dump_everything (); + + if (plugin_files) + { + for (i = 0; i < nb_plugin_files; i++) + free (plugin_files[i] - sizeof (lang_bitmap)); + free (plugin_files); + } + if (hit_error) return 1; return 0;