From patchwork Wed Oct 20 20:09:35 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Basile Starynkevitch X-Patchwork-Id: 68469 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) by ozlabs.org (Postfix) with SMTP id 42C371007D3 for ; Thu, 21 Oct 2010 07:10:05 +1100 (EST) Received: (qmail 6712 invoked by alias); 20 Oct 2010 20:09:59 -0000 Received: (qmail 6682 invoked by uid 22791); 20 Oct 2010 20:09:50 -0000 X-SWARE-Spam-Status: No, hits=2.2 required=5.0 tests=AWL, BAYES_50, RCVD_IN_DNSWL_NONE, RCVD_IN_JMF_BL, RCVD_IN_RP_RNBL, TW_BJ, TW_CP, TW_FL, TW_GT, TW_PF, TW_VF, TW_WT, TW_YY X-Spam-Check-By: sourceware.org Received: from smtp-103-wednesday.noc.nerim.net (HELO mallaury.nerim.net) (62.4.17.103) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Wed, 20 Oct 2010 20:09:40 +0000 Received: from hector.lesours (ours.starynkevitch.net [213.41.244.95]) by mallaury.nerim.net (Postfix) with ESMTPS id DBF8EA1053; Wed, 20 Oct 2010 22:09:36 +0200 (CEST) Received: from glinka.lesours ([192.168.0.1] helo=glinka) by hector.lesours with smtp (Exim 4.72) (envelope-from ) id 1P8eye-0000FJ-Ax; Wed, 20 Oct 2010 22:09:36 +0200 Date: Wed, 20 Oct 2010 22:09:35 +0200 From: Basile Starynkevitch To: Laurynas Biveinis Cc: gcc-patches@gcc.gnu.org Subject: gengtype plugin improvement last2round - patch3 [inputfile] Message-Id: <20101020220935.cac67eac.basile@starynkevitch.net> In-Reply-To: References: <20100921210301.d92889be.basile@starynkevitch.net> <20100921210829.5f2ea8b0.basile@starynkevitch.net> <20100921211217.df1ef337.basile@starynkevitch.net> <20101018190058.f77cb42c.basile@starynkevitch.net> <20101019085617.7384e0af.basile@starynkevitch.net> Mime-Version: 1.0 X-IsSubscribed: yes Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org Hello all, References: http://gcc.gnu.org/ml/gcc-patches/2010-09/msg01742.html http://gcc.gnu.org/ml/gcc-patches/2010-10/msg01536.html http://gcc.gnu.org/ml/gcc-patches/2010-10/msg01452.html and others linked from them. After having separately commited the removal of location_s and having taken account Laurynas's comments http://gcc.gnu.org/ml/gcc-patches/2010-10/msg01452.html I am attaching a patch on gengtype adding a real input_file structure relative to trunk rev 165733. ### gcc/ChangeLog entry ### 2010-10-20 Basile Starynkevitch Jeremie Salvucci * gengtype.c (plugin_files, gt_files, this_file, system_file): Change type to input_file. (get_file_basename, get_file_realbasename) (get_file_srcdir_relative_path, get_file_langdir): Change argument type to input_file. (error_at_line): Use input_file. (lang_dir_names, num_lang_dirs): Not static anymore. (get_lang_bitmap, set_lang_bitmap): Moved to gengtype.h. (read_input_file_name, read_input_list, note_variable) (create_field_all, get_file_realbasename) (get_file_srcdir_relative_path, get_file_basename) (get_file_langdir, get_file_gtfilename) (get_output_file_with_visibility, get_output_file_name) (put_mangled_filename, walk_type, get_output_file_for_structure) (parse_program_options) (struct flist): Use input_file. (input_file_htab): Add variable. (input_file_by_name, htab_hash_inputfile, htab_eq_inputfile): Added functions. (main): Initialize input_file_htab and this_file and system_file, use input_file. * gengtype.h (struct input_file_st, input_file): Add struct and type. (CHECK_INPUT_FILE_MAGIC): Added macro. (gt_files, num_gt_files, this_file, system_file): Moved from gengtype.c and declared as input_file-s. (input_file_by_name, get_file_srcdir_relative_path) (get_lang_bitmap, set_lang_bitmap) (get_output_file_with_visibility, get_output_file_name): Ditto. (get_input_file_name): New inlined function. (struct fileloc): Use input_file. (lang_dir_names, num_lang_dirs): Moved from gengtype.c. * gengtype-lex.l: Include errors.h. (yybegin): Use input_file_by_name. * gengtype-parse.c: Includes errors.h. (parse_error): Use input_file. (type): Counts the anonymous pseudo-identifiers. * Makefile.in (gengtype-lex.o, gengtype-parse.o): Depends upon errors.h ##### Ok for trunk? PS. I might not have time to send more patches before the GCC Summit next week (my slides are unfinished). Index: gcc/gengtype.c =================================================================== --- gcc/gengtype.c (revision 165733) +++ gcc/gengtype.c (working copy) @@ -128,7 +128,6 @@ struct type -const char *get_output_file_name (const char *); /* The list of output files. */ @@ -142,12 +141,11 @@ outf_p header_file; /* The name of the file containing the list of input files. */ static char *inputlist; -/* The plugin input files and their number; in that case only - a single file is produced. */ -static char **plugin_files; +/* The plugin input files and their number. */ +static input_file** plugin_files; static size_t nb_plugin_files; -/* The generated plugin output file and name. */ +/* the generated plugin output file and name in plugin mode. */ static outf_p plugin_output; static char *plugin_output_filename; @@ -174,12 +172,11 @@ static const char* backup_dir; /* (-B) program opt static outf_p create_file (const char *, const char *); -static const char *get_file_basename (const char *); -static const char *get_file_realbasename (const char *); -static const char *get_file_srcdir_relative_path (const char *); +static const char * get_file_basename (const input_file *); +static const char * get_file_realbasename (const input_file *); static int get_prefix_langdir_index (const char *); -static const char *get_file_langdir (const char *); +static const char * get_file_langdir (const input_file *); /* Nonzero iff an error has occurred. */ @@ -199,7 +196,8 @@ error_at_line (const struct fileloc *pos, const ch va_start (ap, msg); - fprintf (stderr, "%s:%d: ", pos->file, pos->line); + gcc_assert (pos != NULL && pos->file != NULL); + fprintf (stderr, "%s:%d: ", get_input_file_name (pos->file), pos->line); vfprintf (stderr, msg, ap); fputc ('\n', stderr); hit_error = true; @@ -227,76 +225,30 @@ xasprintf (const char *format, ...) /* Input file handling. */ /* Table of all input files. */ -static const char **gt_files; -static size_t num_gt_files; +input_file** gt_files; +size_t num_gt_files; -/* A number of places use the name of this "gengtype.h" file for a +/* A number of places use the name of this "gengtype.c" file for a location for things that we can't rely on the source to define. - Make sure we can still use pointer comparison on filenames. */ -const char this_file[] = __FILE__; + Initialized early in main. */ +input_file* this_file; /* The "system.h" file is likewise specially useful. */ -const char system_h_file[] = "system.h"; +input_file* system_h_file; /* Vector of per-language directories. */ -static const char **lang_dir_names; -static size_t num_lang_dirs; +const char **lang_dir_names; +size_t num_lang_dirs; /* An array of output files suitable for definitions. There is one BASE_FILES entry for each language. */ static outf_p *base_files; -/* Return a bitmap which has bit `1 << BASE_FILE_' set iff - INPUT_FILE is used by . - This function should be written to assume that a file _is_ used - if the situation is unclear. If it wrongly assumes a file _is_ used, - a linker error will result. If it wrongly assumes a file _is not_ used, - some GC roots may be missed, which is a much harder-to-debug problem. - - The relevant bitmap is stored immediately before the file's name in the - buffer set up by read_input_list. It may be unaligned, so we have to - read it byte-by-byte. */ - -static lang_bitmap -get_lang_bitmap (const char *gtfile) -{ - - if (gtfile == this_file || gtfile == system_h_file) - { - /* Things defined in this "gengtype.c" file or in "system.h" are - universal (and there is no space for their lang_bitmap before - their file names). */ - return (((lang_bitmap) 1) << num_lang_dirs) - 1; - } - else - { - lang_bitmap n = 0; - int i; - for (i = -(int) sizeof (lang_bitmap); i < 0; i++) - n = (n << CHAR_BIT) + (unsigned char) gtfile[i]; - return n; - } -} - -/* Set the bitmap returned by get_lang_bitmap. The only legitimate - caller of this function is read_input_list. */ -static void -set_lang_bitmap (char *gtfile, lang_bitmap n) -{ - int i; - for (i = -1; i >= -(int) sizeof (lang_bitmap); i--) - { - gtfile[i] = n & ((1U << CHAR_BIT) - 1); - n >>= CHAR_BIT; - } -} - - #if ENABLE_CHECKING /* Utility debugging function, printing the various type counts within a list of types. Called thru the DBGPRINT_COUNT_TYPE macro. */ void -dbgprint_count_type_at (const char *fil, int lin, const char *msg, type_p t) +dbgprint_count_type_at (const char *fil, int lin, const char*msg, type_p t) { int nb_types = 0, nb_scalar = 0, nb_string = 0; int nb_struct = 0, nb_union = 0, nb_array = 0, nb_pointer = 0; @@ -482,11 +434,11 @@ read_input_list (const char *listname) size_t nfiles = 0; lang_bitmap curlangs = (1 << num_lang_dirs) - 1; - epos.file = listname; + epos.file = input_file_by_name (listname); epos.line = 0; lang_dir_names = XNEWVEC (const char *, num_lang_dirs); - gt_files = XNEWVEC (const char *, num_gt_files); + gt_files = XNEWVEC (input_file *, num_gt_files); for (;;) { @@ -517,29 +469,30 @@ read_input_list (const char *listname) else { size_t i; + input_file *inpf = input_file_by_name (line); gcc_assert (nfiles <= num_gt_files); for (i = 0; i < nfiles; i++) - if (strcmp (gt_files[i], line) == 0) + /* Since the input_file-s are uniquely hash-consed, we + can just compare pointers! */ + if (gt_files[i] == inpf) { /* Throw away the string we just read, and add the current language to the existing string's bitmap. */ - lang_bitmap bmap = get_lang_bitmap (gt_files[i]); + lang_bitmap bmap = get_lang_bitmap (inpf); if (bmap & curlangs) - error_at_line (&epos, - "file %s specified more than once " + error_at_line (&epos, "file %s specified more than once " "for language %s", line, - langno == - 0 ? "(all)" : lang_dir_names[langno - - 1]); + langno == 0 + ? "(all)" : lang_dir_names[langno - 1]); bmap |= curlangs; - set_lang_bitmap (CONST_CAST (char *, gt_files[i]), bmap); + set_lang_bitmap (inpf, bmap); here = committed; goto next_line; } - set_lang_bitmap (line, curlangs); - gt_files[nfiles++] = line; + set_lang_bitmap (inpf, curlangs); + gt_files[nfiles++] = inpf; } } /* Update the global counts now that we know accurately how many @@ -886,7 +839,7 @@ note_variable (const char *s, type_p t, options_p /* Most-general structure field creator. */ static pair_p create_field_all (pair_p next, type_p type, const char *name, options_p opt, - const char *file, int line) + const input_file* inpf, int line) { pair_p field; @@ -895,7 +848,7 @@ create_field_all (pair_p next, type_p type, const field->type = type; field->name = name; field->opt = opt; - field->line.file = file; + field->line.file = inpf; field->line.line = line; return field; } @@ -1080,7 +1033,7 @@ adjust_field_rtx_def (type_p t, options_p ARG_UNUS mem_attrs_tp = create_pointer (find_structure ("mem_attrs", 0)); reg_attrs_tp = create_pointer (find_structure ("reg_attrs", 0)); basic_block_tp = create_pointer (find_structure ("basic_block_def", 0)); - constant_tp = + constant_tp = create_pointer (find_structure ("constant_descriptor_rtx", 0)); scalar_tp = &scalar_nonchar; /* rtunion int */ @@ -1350,7 +1303,7 @@ 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] = + params[num] = create_pointer (CONST_CAST2 (type_p, const char *, opt->info)); else params[num] = CONST_CAST2 (type_p, const char *, opt->info); @@ -1395,7 +1348,7 @@ static void set_gc_used (pair_p); static void process_gc_options (options_p opt, enum gc_used_enum level, int *maybe_undef, - int *pass_param, int *length, int *skip, + int *pass_param, int *length, int *skip, type_p *nested_ptr) { options_p o; @@ -1508,6 +1461,7 @@ set_gc_used (pair_p variables) pair_p p; for (p = variables; p; p = p->next) { + DBGPRINTF ("set_gc_used p %p '%s' nbvars %d", (void*) p, p->name, nbvars); set_gc_used_type (p->type, GC_USED, NULL); nbvars++; }; @@ -1592,10 +1546,10 @@ oprintf (outf_p o, const char *format, ...) size_t new_len = o->buflength; if (new_len == 0) new_len = 1024; - do + do { new_len *= 2; - } + } while (o->bufused + slength >= new_len); o->buf = XRESIZEVEC (char, o->buf, new_len); o->buflength = new_len; @@ -1653,8 +1607,9 @@ open_base_files (void) components skipped. */ static const char * -get_file_realbasename (const char *f) +get_file_realbasename (const input_file *inpf) { + const char* f = get_input_file_name (inpf); const char *lastslash = strrchr (f, '/'); return (lastslash != NULL) ? lastslash + 1 : f; @@ -1663,26 +1618,28 @@ static const char * /* For F a filename, return the relative path to F from $(srcdir) if the latter is a prefix in F, NULL otherwise. */ -static const char * -get_file_srcdir_relative_path (const char *f) +const char * +get_file_srcdir_relative_path (const input_file *inpf) { - if (strlen (f) > srcdir_len - && IS_DIR_SEPARATOR (f[srcdir_len]) - && memcmp (f, srcdir, srcdir_len) == 0) - return f + srcdir_len + 1; + const char* fname = get_input_file_name (inpf); + if (strlen (fname) > srcdir_len + && IS_DIR_SEPARATOR (fname[srcdir_len]) + && memcmp (fname, srcdir, srcdir_len) == 0) + return fname + srcdir_len + 1; else return NULL; } -/* For F a filename, return the relative path to F from $(srcdir) if the - latter is a prefix in F, or the real basename of F otherwise. */ +/* For INPF an input_file, return the relative path to INPF from + $(srcdir) if the latter is a prefix in INPF, or the real basename + of INPF otherwise. */ static const char * -get_file_basename (const char *f) +get_file_basename (const input_file *inpf) { - const char *srcdir_path = get_file_srcdir_relative_path (f); + const char * srcdir_path = get_file_srcdir_relative_path (inpf); - return (srcdir_path != NULL) ? srcdir_path : get_file_realbasename (f); + return (srcdir_path != NULL) ? srcdir_path : get_file_realbasename (inpf); } /* For F a filename, return the lang_dir_names relative index of the language @@ -1708,18 +1665,18 @@ get_prefix_langdir_index (const char *f) return -1; } -/* For F a filename, return the name of language directory where F is located, - if any, NULL otherwise. */ +/* For INPF an input_file, return the name of language directory where + INPF is located, if any, NULL otherwise. */ static const char * -get_file_langdir (const char *f) +get_file_langdir (const input_file *inpf) { /* Get the relative path to F from $(srcdir) and find the language by comparing the prefix with language directory names. If F is not even srcdir relative, no point in looking further. */ int lang_index; - const char *srcdir_relative_path = get_file_srcdir_relative_path (f); + const char *srcdir_relative_path = get_file_srcdir_relative_path (inpf); const char *r; if (!srcdir_relative_path) @@ -1736,16 +1693,15 @@ static const char * return r; } -/* The gt- output file name for F. */ - +/* The gt- output file name for INPF. */ static const char * -get_file_gtfilename (const char *f) +get_file_gtfilename (const input_file *inpf) { /* Cook up an initial version of the gt- file name from the file real basename and the language name, if any. */ - const char *basename = get_file_realbasename (f); - const char *langdir = get_file_langdir (f); + const char *basename = get_file_realbasename (inpf); + const char *langdir = get_file_langdir (inpf); char *result = (langdir ? xasprintf ("gt-%s-%s", langdir, basename) @@ -1767,11 +1723,12 @@ static const char * } /* An output file, suitable for definitions, that can see declarations - made in INPUT_FILE and is linked into every language that uses - INPUT_FILE. */ + made in INPF and is linked into every language that uses INPF. + Since the result is cached inside INPF, that argument cannot be + declared constant. */ outf_p -get_output_file_with_visibility (const char *input_file) +get_output_file_with_visibility (input_file* inpf) { outf_p r; size_t len; @@ -1782,30 +1739,30 @@ outf_p /* This can happen when we need a file with visibility on a structure that we've never seen. We have to just hope that it's globally visible. */ - if (input_file == NULL) - input_file = "system.h"; + if (inpf == NULL) + inpf = system_h_file; - /* In plugin mode, return NULL unless the input_file is one of the - plugin_files. */ + /* In plugin mode, return NULL unless the INPF is one of the + plugin_files. We can compare input_file-s by pointer equality. */ if (plugin_files) { size_t i; for (i = 0; i < nb_plugin_files; i++) - if (strcmp (input_file, plugin_files[i]) == 0) + if (inpf == plugin_files[i]) return plugin_output; return NULL; } /* Determine the output file name. */ - basename = get_file_basename (input_file); + basename = get_file_basename (inpf); len = strlen (basename); if ((len > 2 && memcmp (basename + len - 2, ".c", 2) == 0) || (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 (inpf); for_name = basename; } /* Some headers get used by more than one front-end; hence, it @@ -1830,8 +1787,7 @@ outf_p else if (strncmp (basename, "cp", 2) == 0 && IS_DIR_SEPARATOR (basename[2]) && strcmp (basename + 3, "name-lookup.h") == 0) output_name = "gt-cp-name-lookup.h", for_name = "cp/name-lookup.c"; - else if (strncmp (basename, "objc", 4) == 0 - && IS_DIR_SEPARATOR (basename[4]) + 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 @@ -1858,13 +1814,13 @@ outf_p } /* The name of an output file, suitable for definitions, that can see - declarations made in INPUT_FILE and is linked into every language - that uses INPUT_FILE. */ + declarations made in INPF and is linked into every language + that uses INPF. */ const char * -get_output_file_name (const char *input_file) +get_output_file_name (input_file *inpf) { - outf_p o = get_output_file_with_visibility (input_file); + outf_p o = get_output_file_with_visibility (inpf); if (o) return o->name; return NULL; @@ -1902,8 +1858,8 @@ is_file_equal (outf_p of) static void close_output_files (void) { + outf_p of; int nbwrittenfiles = 0; - outf_p of; for (of = output_files; of; of = of->next) { @@ -1936,11 +1892,12 @@ close_output_files (void) progname, nbwrittenfiles, of->name, backupname); else if (verbosity_level >= 1) printf ("%s write #%-3d %s\n", progname, nbwrittenfiles, of->name); + if (backupname) free (backupname); } else { - /* output file remains unchanged. */ + /* Output file remains unchanged. */ if (verbosity_level >= 2) printf ("%s keep %s\n", progname, of->name); } @@ -1952,11 +1909,12 @@ close_output_files (void) printf ("%s wrote %d files.\n", progname, nbwrittenfiles); } -struct flist + +struct flist { struct flist *next; int started_p; - const char *name; + const input_file *file; outf_p f; }; @@ -1966,8 +1924,8 @@ struct walk_type_data; For structures, given a pointer to the item in 'val'. For misc. pointers, given the item in 'val'. */ -typedef void (*process_field_fn) (type_p f, const struct walk_type_data * p); -typedef void (*func_name_fn) (type_p s, const struct walk_type_data * p); +typedef void (*process_field_fn) (type_p f, const struct walk_type_data *p); +typedef void (*func_name_fn) (type_p s, const struct walk_type_data *p); /* Parameters for write_types. */ @@ -1999,10 +1957,10 @@ static void write_types_local_process_field static void write_local_func_for_structure (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); + 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); -static void put_mangled_filename (outf_p, const char *); +static void put_mangled_filename (outf_p, const input_file *); static void finish_root_table (struct flist *flp, const char *pfx, const char *tname, const char *lastname, const char *name); @@ -2041,7 +1999,7 @@ output_mangled_typename (outf_p of, const_type_p t { if (t == NULL) oprintf (of, "Z"); - else + else switch (t->kind) { case TYPE_POINTER: @@ -2057,8 +2015,8 @@ output_mangled_typename (outf_p of, const_type_p t case TYPE_STRUCT: case TYPE_UNION: case TYPE_LANG_STRUCT: - oprintf (of, "%lu%s", (unsigned long) strlen (t->u.s.tag), - t->u.s.tag); + oprintf (of, "%lu%s", (unsigned long) strlen (t->u.s.tag), + t->u.s.tag); break; case TYPE_PARAM_STRUCT: { @@ -2088,7 +2046,7 @@ output_escaped_param (struct walk_type_data *d, co for (p = param; *p; p++) if (*p != '%') oprintf (d->of, "%c", *p); - else + else switch (*++p) { case 'h': @@ -2311,7 +2269,7 @@ walk_type (type_p t, struct walk_type_data *d) oprintf (d->of, "%*sif (%s != NULL) {\n", d->indent, "", d->val); d->indent += 2; oprintf (d->of, "%*ssize_t i%d;\n", d->indent, "", loopcounter); - oprintf (d->of, "%*sfor (i%d = 0; i%d != (size_t)(", d->indent, + oprintf (d->of, "%*sfor (i%d = 0; i%d != (size_t)(", d->indent, "", loopcounter, loopcounter); output_escaped_param (d, length, "length"); oprintf (d->of, "); i%d++) {\n", loopcounter); @@ -2472,7 +2430,7 @@ walk_type (type_p t, struct walk_type_data *d) { fprintf (stderr, "%s:%d: warning: field `%s' is missing `tag' or `default' option\n", - d->line->file, d->line->line, f->name); + get_input_file_name (d->line->file), d->line->line, f->name); continue; } else if (union_p && !(default_p || tagid)) @@ -2639,16 +2597,27 @@ output_type_enum (outf_p of, type_p s) static outf_p get_output_file_for_structure (const_type_p s, type_p *param) { - const char *fn = s->u.s.line.file; + const input_file* fn = NULL; int i; + if (UNION_OR_STRUCT_P (s)) + fn = s->u.s.line.file; + else if (s->kind == TYPE_PARAM_STRUCT) + fn = s->u.param_struct.line.file; + + CHECK_INPUT_FILE_MAGIC (fn); + /* 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); + CHECK_INPUT_FILE_MAGIC (fn); + + /* The call to get_output_file_with_visibility may update fn by + caching its result inside, so we need the CONST_CAST. */ + return get_output_file_with_visibility (CONST_CAST (input_file*, fn)); } /* For S, a structure that's part of ORIG_S, and using parameters @@ -2825,8 +2794,8 @@ static void write_types (outf_p output_header, type_p structures, type_p param_structs, const struct write_types_data *wtd) { + type_p s; int nbfun = 0; /* Count the emitted functions. */ - type_p s; oprintf (output_header, "\n/* %s*/\n", wtd->comment); /* We first emit the macros and the declarations. Functions' code is @@ -2931,12 +2900,9 @@ write_types (outf_p output_header, type_p structur } } else - { - /* Structure s is not possibly pointed to, so can be ignored. */ DBGPRINTF ("ignored s @ %p '%s' gc_used#%d", (void*)s, s->u.s.tag, (int) s->gc_used); - } for (s = param_structs; s; s = s->next) if (s->gc_used == GC_POINTED_TO) @@ -2966,22 +2932,21 @@ write_types (outf_p output_header, type_p structur } } else - { - /* Param structure s is not pointed to, so should be ignored. */ DBGPRINTF ("ignored s @ %p", (void*)s); - } if (verbosity_level >= 2) printf ("%s emitted %d routines for %s\n", progname, nbfun, wtd->comment); } -static const struct write_types_data ggc_wtd = { +static const struct write_types_data ggc_wtd = +{ "ggc_m", NULL, "ggc_mark", "ggc_test_and_set_mark", NULL, "GC marker procedures. ", FALSE }; -static const struct write_types_data pch_wtd = { +static const struct write_types_data pch_wtd = +{ "pch_n", "pch_p", "gt_pch_note_object", "gt_pch_note_object", "gt_pch_note_reorder", "PCH type-walking procedures. ", @@ -3068,7 +3033,8 @@ write_local (outf_p output_header, type_p structur 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) + if (s->gc_used == GC_POINTED_TO + || s->gc_used == GC_MAYBE_POINTED_TO) { options_p opt; @@ -3080,7 +3046,8 @@ write_local (outf_p output_header, type_p structur { const_type_p const t = (const_type_p) opt->info; if (t->kind == TYPE_STRUCT - || t->kind == TYPE_UNION || t->kind == TYPE_LANG_STRUCT) + || t->kind == TYPE_UNION + || t->kind == TYPE_LANG_STRUCT) { oprintf (output_header, "#define gt_pch_p_"); output_mangled_typename (output_header, s); @@ -3169,10 +3136,10 @@ write_enum_defn (type_p structures, type_p param_s 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) if (USED_BY_TYPED_GC_P (s)) { - nbstruct++; DBGPRINTF ("write_enum_defn s @ %p nbstruct %d", (void*) s, nbstruct); if (UNION_OR_STRUCT_P (s)) @@ -3181,23 +3148,25 @@ write_enum_defn (type_p structures, type_p param_s oprintf (header_file, " gt_ggc_e_"); output_mangled_typename (header_file, s); oprintf (header_file, ",\n"); + nbstruct++; } + for (s = param_structs; s; s = s->next) if (s->gc_used == GC_POINTED_TO) { - nbparamstruct++; DBGPRINTF ("write_enum_defn s %p nbparamstruct %d", (void*) s, nbparamstruct); oprintf (header_file, " gt_e_"); output_mangled_typename (header_file, s); oprintf (header_file, ",\n"); + nbparamstruct++; } + oprintf (header_file, " gt_types_enum_last\n"); oprintf (header_file, "};\n"); if (verbosity_level >= 2) printf ("%s handled %d GTY-ed structures & %d parameterized structures.\n", progname, nbstruct, nbparamstruct); - } /* Might T contain any non-pointer elements? */ @@ -3222,9 +3191,12 @@ contains_scalar_p (type_p t) /* Mangle FN and print it to F. */ static void -put_mangled_filename (outf_p f, const char *fn) +put_mangled_filename (outf_p f, const input_file *inpf) { - const char *name = get_output_file_name (fn); + /* The call to get_output_file_name may indirectly update fn since + get_output_file_with_visibility caches its result inside, so we + need the CONST_CAST. */ + const char *name = get_output_file_name (CONST_CAST (input_file*, inpf)); if (!f || !name) return; for (; *name != 0; name++) @@ -3254,15 +3226,16 @@ finish_root_table (struct flist *flp, const char * for (fli2 = flp; fli2 && base_files; fli2 = fli2->next) if (fli2->started_p) { - lang_bitmap bitmap = get_lang_bitmap (fli2->name); + lang_bitmap bitmap = get_lang_bitmap (fli2->file); int fnum; for (fnum = 0; bitmap != 0; fnum++, bitmap >>= 1) if (bitmap & 1) { oprintf (base_files[fnum], - "extern const struct %s gt_%s_", tname, pfx); - put_mangled_filename (base_files[fnum], fli2->name); + "extern const struct %s gt_%s_", + tname, pfx); + put_mangled_filename (base_files[fnum], fli2->file); oprintf (base_files[fnum], "[];\n"); } } @@ -3271,14 +3244,15 @@ finish_root_table (struct flist *flp, const char * size_t fnum; for (fnum = 0; base_files && fnum < num_lang_dirs; fnum++) oprintf (base_files[fnum], - "EXPORTED_CONST struct %s * const %s[] = {\n", tname, name); + "EXPORTED_CONST struct %s * const %s[] = {\n", + tname, name); } for (fli2 = flp; fli2; fli2 = fli2->next) if (fli2->started_p) { - lang_bitmap bitmap = get_lang_bitmap (fli2->name); + lang_bitmap bitmap = get_lang_bitmap (fli2->file); int fnum; fli2->started_p = 0; @@ -3287,7 +3261,7 @@ finish_root_table (struct flist *flp, const char * if (bitmap & 1) { oprintf (base_files[fnum], " gt_%s_", pfx); - put_mangled_filename (base_files[fnum], fli2->name); + put_mangled_filename (base_files[fnum], fli2->file); oprintf (base_files[fnum], ",\n"); } } @@ -3428,7 +3402,8 @@ write_root (outf_p f, pair_p v, type_p type, const error_at_line (line, "both `%s.%s.%s' and `%s.%s.%s' have tag `%s'", name, fld->name, validf->name, - name, fld->name, ufld->name, tag); + name, fld->name, ufld->name, + tag); validf = ufld; } if (validf != NULL) @@ -3523,7 +3498,9 @@ write_root (outf_p f, pair_p v, type_p type, const break; default: - error_at_line (line, "global `%s' is unimplemented type", name); + error_at_line (line, + "global `%s' is unimplemented type", + name); } } @@ -3549,7 +3526,8 @@ write_array (outf_p f, pair_p v, const struct writ if (wtd->param_prefix) { oprintf (f, "static void gt_%sa_%s\n", wtd->param_prefix, v->name); - oprintf (f, " (void *, void *, gt_pointer_operator, void *);\n"); + oprintf (f, + " (void *, void *, gt_pointer_operator, void *);\n"); oprintf (f, "static void gt_%sa_%s (ATTRIBUTE_UNUSED void *this_obj,\n", wtd->param_prefix, v->name); oprintf (d.of, @@ -3564,7 +3542,8 @@ write_array (outf_p f, pair_p v, const struct writ } d.opt = v->opt; - oprintf (f, "static void gt_%sa_%s (void *);\n", wtd->prefix, v->name); + oprintf (f, "static void gt_%sa_%s (void *);\n", + wtd->prefix, v->name); oprintf (f, "static void\ngt_%sa_%s (ATTRIBUTE_UNUSED void *x_p)\n", wtd->prefix, v->name); oprintf (f, "{\n"); @@ -3585,7 +3564,9 @@ write_roots (pair_p variables, bool emit_pch) for (v = variables; v; v = v->next) { - outf_p f = get_output_file_with_visibility (v->line.file); + outf_p f = + get_output_file_with_visibility (CONST_CAST (input_file*, + v->line.file)); struct flist *fli; const char *length = NULL; int deletable_p = 0; @@ -3599,7 +3580,8 @@ write_roots (pair_p variables, bool emit_pch) else if (strcmp (o->name, "param_is") == 0) ; else if (strncmp (o->name, "param", 5) == 0 - && ISDIGIT (o->name[5]) && strcmp (o->name + 6, "_is") == 0) + && ISDIGIT (o->name[5]) + && strcmp (o->name + 6, "_is") == 0) ; else if (strcmp (o->name, "if_marked") == 0) ; @@ -3617,8 +3599,8 @@ write_roots (pair_p variables, bool emit_pch) fli->f = f; fli->next = flp; fli->started_p = 0; - fli->name = v->line.file; - gcc_assert (fli->name); + fli->file = v->line.file; + gcc_assert (fli->file); flp = fli; oprintf (f, "\n/* GC roots. */\n\n"); @@ -3637,7 +3619,9 @@ write_roots (pair_p variables, bool emit_pch) for (v = variables; v; v = v->next) { - outf_p f = get_output_file_with_visibility (v->line.file); + outf_p f = + get_output_file_with_visibility (CONST_CAST (input_file*, + v->line.file)); struct flist *fli; int skip_p = 0; int length_p = 0; @@ -3673,7 +3657,9 @@ write_roots (pair_p variables, bool emit_pch) for (v = variables; v; v = v->next) { - outf_p f = get_output_file_with_visibility (v->line.file); + outf_p f = + get_output_file_with_visibility (CONST_CAST (input_file*, + v->line.file)); struct flist *fli; int skip_p = 1; options_p o; @@ -3708,7 +3694,9 @@ write_roots (pair_p variables, bool emit_pch) for (v = variables; v; v = v->next) { - outf_p f = get_output_file_with_visibility (v->line.file); + outf_p f = + get_output_file_with_visibility (CONST_CAST (input_file*, + v->line.file)); struct flist *fli; const char *if_marked = NULL; int length_p = 0; @@ -3727,8 +3715,7 @@ write_roots (pair_p variables, bool emit_pch) || v->type->u.p->kind != TYPE_PARAM_STRUCT || v->type->u.p->u.param_struct.stru != find_structure ("htab", 0)) { - error_at_line (&v->line, - "if_marked option used but not hash table"); + error_at_line (&v->line, "if_marked option used but not hash table"); continue; } @@ -3756,7 +3743,9 @@ write_roots (pair_p variables, bool emit_pch) for (v = variables; v; v = v->next) { - outf_p f = get_output_file_with_visibility (v->line.file); + outf_p f = + get_output_file_with_visibility (CONST_CAST (input_file*, + v->line.file)); struct flist *fli; int length_p = 0; int if_marked_p = 0; @@ -3791,7 +3780,9 @@ write_roots (pair_p variables, bool emit_pch) for (v = variables; v; v = v->next) { - outf_p f = get_output_file_with_visibility (v->line.file); + outf_p f = + get_output_file_with_visibility (CONST_CAST (input_file*, + v->line.file)); struct flist *fli; int skip_p = 0; options_p o; @@ -3910,10 +3901,8 @@ variable_size_p (const type_p s) return false; } -enum alloc_quantity -{ single, vector }; -enum alloc_zone -{ any_zone, specific_zone }; +enum alloc_quantity { single, vector }; +enum alloc_zone { any_zone, specific_zone }; /* Writes one typed allocator definition for type identifier TYPE_NAME with optional type specifier TYPE_SPECIFIER. The allocator name will contain @@ -4045,8 +4034,7 @@ output_typename (outf_p of, const_type_p t) { int i; for (i = 0; i < NUM_PARAM; i++) - if (t->u.param_struct.param[i] != NULL) - { + if (t->u.param_struct.param[i] != NULL) { output_typename (of, t->u.param_struct.param[i]); oprintf (of, "_"); } @@ -4109,32 +4097,15 @@ 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 (); + 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"); } @@ -4147,20 +4118,11 @@ dump_gc_used (int indent, enum gc_used_enum gc_use 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 (); + 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"); } @@ -4186,8 +4148,8 @@ dump_options (int indent, options_p opt) static void dump_fileloc (int indent, struct fileloc line) { - printf ("%*cfileloc: file = %s, line = %d\n", indent, ' ', line.file, - line.line); + printf ("%*cfileloc: file = %s, line = %d\n", indent, ' ', + get_input_file_name (line.file), line.line); } /* Recursively dumps the struct, union, or a language-specific @@ -4384,12 +4346,17 @@ static void print_usage (void) { printf ("Usage: %s\n", progname); - printf ("\t -h | --help " " \t# Give this help.\n"); + printf ("\t -h | --help " + " \t# Give this help.\n"); printf ("\t -D | --debug " - " \t# Give debug output to debug %s itself.\n", progname); - printf ("\t -V | --version " " \t# Give version information.\n"); - printf ("\t -v | --verbose \t# Increase verbosity. Can be given several times.\n"); - printf ("\t -d | --dump " " \t# Dump state for debugging.\n"); + " \t# Give debug output to debug %s itself.\n", + progname); + printf ("\t -V | --version " + " \t# Give version information.\n"); + printf ("\t -v | --verbose " + " \t# Increase verbosity. Can be given several times.\n"); + printf ("\t -d | --dump " + " \t# Dump state for debugging.\n"); printf ("\t -P | --plugin ... " " \t# Generate for plugin.\n"); printf ("\t -S | --srcdir " @@ -4398,8 +4365,10 @@ print_usage (void) " \t# Specify the backup directory for updated files.\n"); printf ("\t -I | --inputs " " \t# Specify the file with source files list.\n"); - printf ("\t -w | --write-state " " \t# Write a state file.\n"); - printf ("\t -r | --read-state " " \t# Read a state file.\n"); + printf ("\t -w | --write-state " + " \t# Write a state file.\n"); + printf ("\t -r | --read-state " + " \t# Read a state file.\n"); } static void @@ -4414,7 +4383,7 @@ static void parse_program_options (int argc, char **argv) { int opt = -1; - while ((opt = getopt_long (argc, argv, "hVvdP:S:B:I:w:r:D", + while ((opt = getopt_long (argc, argv, "hvVdP:S:B:I:w:r:D", gengtype_long_options, NULL)) >= 0) { switch (opt) @@ -4422,6 +4391,9 @@ parse_program_options (int argc, char **argv) case 'h': /* --help */ print_usage (); break; + case 'v': /* --verbose */ + verbosity_level++; + break; case 'V': /* --version */ print_version (); break; @@ -4431,9 +4403,6 @@ parse_program_options (int argc, char **argv) case 'D': /* --debug */ do_debug = 1; break; - case 'v': /* --verbose */ - verbosity_level++; - break; case 'P': /* --plugin */ if (optarg) plugin_output_filename = optarg; @@ -4486,16 +4455,69 @@ parse_program_options (int argc, char **argv) if (optind >= argc) fatal ("no source files given in plugin mode"); nb_plugin_files = argc - optind; - plugin_files = XNEWVEC (char*, nb_plugin_files); + plugin_files = XNEWVEC (input_file*, nb_plugin_files); for (i = 0; i < (int) nb_plugin_files; i++) { char *name = argv[i + optind]; - plugin_files[i] = name; + plugin_files[i] = input_file_by_name (name); } } } + +/******* Manage input files. ******/ + +/* Hash table of unique input file names. */ +static htab_t input_file_htab; + +/* Find or allocate a new input_file by hash-consing it. */ +input_file* +input_file_by_name (const char* name) +{ + PTR* slot; + input_file* f = NULL; + int namlen = 0; + if (!name) + return NULL; + namlen = strlen (name); + f = XCNEWVAR (input_file, sizeof (input_file)+namlen+2); + f->inpbitmap = 0; + f->inpoutf = NULL; + f->inpmagic = INPUT_FILE_MAGIC; + strcpy (f->inpname, name); + slot = htab_find_slot (input_file_htab, f, INSERT); + gcc_assert (slot != NULL); + if (*slot) + { + /* Already known input file. */ + free (f); + return (input_file*)(*slot); + } + /* New input file. */ + *slot = f; + return f; + } + +/* Hash table support routines for input_file-s. */ +static hashval_t +htab_hash_inputfile (const void *p) +{ + const input_file *inpf = (const input_file *) p; + gcc_assert (inpf); + return htab_hash_string (get_input_file_name (inpf)); +} + +static int +htab_eq_inputfile (const void *x, const void *y) +{ + const input_file *inpfx = (const input_file *) x; + const input_file *inpfy = (const input_file *) y; + gcc_assert (inpfx != NULL && inpfy != NULL); + return !strcmp (get_input_file_name (inpfx), get_input_file_name (inpfy)); +} + + int main (int argc, char **argv) { @@ -4508,6 +4530,12 @@ main (int argc, char **argv) /* Set the scalar_is_char union number for predefined scalar types. */ scalar_nonchar.u.scalar_is_char = FALSE; scalar_char.u.scalar_is_char = TRUE; + /* Create the hash-table used to hash-cons input files. */ + input_file_htab = + htab_create (800, htab_hash_inputfile, htab_eq_inputfile, NULL); + /* Initialize our special input files. */ + this_file = input_file_by_name (__FILE__); + system_h_file = input_file_by_name ("system.h"); parse_program_options (argc, argv); @@ -4519,7 +4547,7 @@ main (int argc, char **argv) DBGPRINTF ("gengtype started pid %d at %s", (int) getpid (), ctime (&now)); } -#endif /* ENABLE_CHECKING */ +#endif /* ENABLE_CHECKING */ /* Parse the input list and the input files. */ DBGPRINTF ("inputlist %s", inputlist); @@ -4535,38 +4563,27 @@ main (int argc, char **argv) read_input_list. */ pos.file = this_file; pos.line = __LINE__ + 1; - do_scalar_typedef ("CUMULATIVE_ARGS", &pos); - pos.line++; - 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++; - do_scalar_typedef ("void", &pos); - pos.line++; - do_typedef ("PTR", create_pointer (resolve_typedef ("void", &pos)), - &pos); + do_scalar_typedef ("CUMULATIVE_ARGS", &pos); pos.line++; + 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++; + do_scalar_typedef ("void", &pos); pos.line++; + do_typedef ("PTR", create_pointer (resolve_typedef ("void", &pos)), &pos); read_input_list (inputlist); for (i = 0; i < num_gt_files; i++) { - parse_file (gt_files[i]); - DBGPRINTF ("parsed file #%d %s", (int) i, gt_files[i]); + parse_file (get_input_file_name (gt_files[i])); + DBGPRINTF ("parsed file #%d %s", (int) i, get_input_file_name (gt_files[i])); } + DBGPRINT_COUNT_TYPE ("structures after parsing", structures); + DBGPRINT_COUNT_TYPE ("param_structs after parsing", param_structs); if (verbosity_level >= 1) printf ("%s parsed %d files\n", progname, (int) num_gt_files); - DBGPRINT_COUNT_TYPE ("structures after parsing", structures); - DBGPRINT_COUNT_TYPE ("param_structs after parsing", param_structs); - } else fatal ("either an input list or a read state file should be given"); @@ -4577,23 +4594,24 @@ main (int argc, char **argv) if (plugin_output_filename) { size_t ix = 0; - /* In plugin mode, we should have read a state file, and have + /* In plugin mode, we better have read a state file, and have given at least one plugin file. */ if (!read_state_filename) - fatal ("No read state given in plugin mode for %s", - plugin_output_filename); + warning ("No read state given in plugin mode for %s", plugin_output_filename); - if (nb_plugin_files == 0 || !plugin_files) - fatal ("No plugin files given in plugin mode for %s", - plugin_output_filename); + if (nb_plugin_files <= 0 || !plugin_files) + fatal ("No plugin files given in plugin mode for %s", plugin_output_filename); /* Parse our plugin files. */ for (ix = 0; ix < nb_plugin_files; ix++) - parse_file (plugin_files[ix]); + { + parse_file (get_input_file_name (plugin_files[ix])); + DBGPRINTF ("parsed plugin file #%d %s", (int) ix, + get_input_file_name (plugin_files[ix])); + } if (hit_error) return 1; - plugin_output = create_file ("GCC", plugin_output_filename); DBGPRINTF ("created plugin_output %p named %s", (void *) plugin_output, plugin_output->name); Index: gcc/gengtype.h =================================================================== --- gcc/gengtype.h (revision 165733) +++ gcc/gengtype.h (working copy) @@ -25,14 +25,117 @@ represented by a bitmap. */ typedef unsigned lang_bitmap; -/* A file position, mostly for error messages. - The FILE element may be compared using pointer equality. */ +/* Variable length structure representing an input file. A hash table + ensure uniqueness for a given input file name. The only function + allocating input_file-s is input_file_by_name. */ +struct input_file_st +{ +#if ENABLE_CHECKING + /* The magic number is intended to help debugging gengtype. We + check that it is indeed what it should be. This could help + catching bugs where an input_file pointer is bogus. */ + int inpmagic; /* Always INPUT_FILE_MAGIC. */ +#endif /*ENABLE_CHECKING*/ + struct outf* inpoutf; /* Cached corresponding output file, computed + in get_output_file_with_visibility. */ + lang_bitmap inpbitmap; /* The set of languages using this file. */ + char inpname[1]; /* a flexible array, ended by a null char. */ +}; +typedef struct input_file_st input_file; + +#if ENABLE_CHECKING +/* 0x371c433f is 924599103 in decimal, and was randomly choosen. The + input file magic number is intended to help catching bugs. */ +#define INPUT_FILE_MAGIC 0x371c433f + /* This is a fancy assert which displays a more precise message. It + should never happen! But it can help a lot when hacking + gengtype. */ +#define CHECK_INPUT_FILE_MAGIC(Inpf) \ + do { \ + const input_file* badinpf = Inpf; \ + if (badinpf && badinpf->inpmagic != INPUT_FILE_MAGIC) \ + fatal ("corrupted input file %p bad magic %d in %s:%d", \ + (const void*) badinpf, badinpf->inpmagic, \ + lbasename (__FILE__), __LINE__); \ + } while (0) +#else +#define CHECK_INPUT_FILE_MAGIC(Inpf) do{} while (0) +#endif /* ENABLE_CHECKING */ + +/* Table of all input files, and its size. */ +extern input_file** gt_files; +extern size_t num_gt_files; + +/* A number of places use the name of this "gengtype.c" file for a + location for things that we can't rely on the source to define. We + also need to refer to the "system.h" file specifically. These two + pointers are initialized early in main. */ +extern input_file* this_file; +extern input_file* system_h_file; + +/* Retrieve or create the input_file for a given name, which is a file + path. This is the only function allocating input_file-s and it is + hash-consing them. */ +input_file* input_file_by_name (const char* name); + + +/* For F an input_file, return the relative path to F from $(srcdir) + if the latter is a prefix in F, NULL otherwise. */ +const char *get_file_srcdir_relative_path (const input_file *inpf); + +/* Get the name of an input file. */ +static inline const char* +get_input_file_name (const input_file *inpf) +{ + if (inpf) + { + CHECK_INPUT_FILE_MAGIC (inpf); + return inpf->inpname; + } + return NULL; +} + +/* Return a bitmap which has bit `1 << BASE_FILE_' set iff + INPUT_FILE is used by . + + This function should be written to assume that a file _is_ used + if the situation is unclear. If it wrongly assumes a file _is_ used, + a linker error will result. If it wrongly assumes a file _is not_ used, + some GC roots may be missed, which is a much harder-to-debug problem. + */ + +static inline lang_bitmap +get_lang_bitmap (const input_file* inpf) +{ + if (inpf == NULL) + return 0; + CHECK_INPUT_FILE_MAGIC (inpf); + return inpf->inpbitmap; +} + +/* Set the bitmap returned by get_lang_bitmap. The only legitimate + callers of this function are read_input_list & read_state_*. */ +static inline void +set_lang_bitmap (input_file* inpf, lang_bitmap n) +{ + gcc_assert (inpf); + CHECK_INPUT_FILE_MAGIC (inpf); + inpf->inpbitmap = n; +} + +/* A file position, mostly for error messages. The FILE element may + be compared using pointer equality since it is hash-consed. */ struct fileloc { - const char *file; + const input_file *file; int line; }; + +/* Vector of per-language directories. */ +extern const char **lang_dir_names; +extern size_t num_lang_dirs; + /* Data types handed around within, but opaque to, the lexer and parser. */ typedef struct pair *pair_p; typedef struct type *type_p; @@ -67,10 +170,18 @@ oprintf (outf_p o, const char *S, ...) ATTRIBUTE_PRINTF_2; /* An output file, suitable for definitions, that can see declarations - made in INPUT_FILE and is linked into every language that uses - INPUT_FILE. May return NULL in plugin mode. */ -extern outf_p get_output_file_with_visibility (const char *input_file); + made in INPF and is linked into every language that uses INPF. May + return NULL in plugin mode. The INPF argument is almost const, but + since the result is cached in its inpoutf field it cannot be + declared const, because this function stores the computed output + file in that field to speed it up for further invocations. */ +outf_p get_output_file_with_visibility (input_file* inpf); +/* The name of an output file, suitable for definitions, that can see + declarations made in INPF and is linked into every language that + uses INPF. May return NULL. */ +const char *get_output_file_name (input_file *inpf); + /* Source directory. */ extern const char *srcdir; /* (-S) program argument. */ Index: gcc/gengtype-lex.l =================================================================== --- gcc/gengtype-lex.l (revision 165733) +++ gcc/gengtype-lex.l (working copy) @@ -1,6 +1,6 @@ /* -*- indented-text -*- */ /* Process source files and output type information. - Copyright (C) 2002, 2003, 2004, 2005, 2007, 2008, 2009 + Copyright (C) 2002, 2003, 2004, 2005, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. This file is part of GCC. @@ -24,7 +24,9 @@ along with GCC; see the file COPYING3. If not see %{ #include "bconfig.h" #include "system.h" +#include "errors.h" /* for fatal, needed by gengtype.h */ + #define malloc xmalloc #define realloc xrealloc @@ -202,7 +204,7 @@ yybegin (const char *fname) perror (fname); exit (1); } - lexer_line.file = fname; + lexer_line.file = input_file_by_name (fname); lexer_line.line = 1; } Index: gcc/gengtype-parse.c =================================================================== --- gcc/gengtype-parse.c (revision 165733) +++ gcc/gengtype-parse.c (working copy) @@ -1,5 +1,5 @@ /* Process source files and output type information. - Copyright (C) 2006, 2007 Free Software Foundation, Inc. + Copyright (C) 2006, 2007, 2010 Free Software Foundation, Inc. This file is part of GCC. @@ -19,6 +19,7 @@ #include "bconfig.h" #include "system.h" +#include "errors.h" /* for fatal, needed by gengtype.h */ #include "gengtype.h" /* This is a simple recursive-descent parser which understands a subset of @@ -135,7 +136,8 @@ parse_error (const char *msg, ...) { va_list ap; - fprintf (stderr, "%s:%d: parse error: ", lexer_line.file, lexer_line.line); + fprintf (stderr, "%s:%d: parse error: ", + get_input_file_name (lexer_line.file), lexer_line.line); va_start (ap, msg); vfprintf (stderr, msg, ap); @@ -708,6 +710,7 @@ static type_p type (options_p *optsp, bool nested) { const char *s; + static int anonymous_count; /* To generate unique pseudo-identifiers! */ *optsp = 0; switch (token ()) { @@ -750,7 +753,32 @@ type (options_p *optsp, bool nested) if (token () == ID) s = advance (); else - s = xasprintf ("anonymous:%s:%d", lexer_line.file, lexer_line.line); + { + /* We don't want to wire in the source directory (because + in plugin mode, the source directory can be unavailable + since gengtype has read its state). So if the input is + from GCC source directory, we use its relative path to + build an anonymous unique tag. */ + const char* relp = get_file_srcdir_relative_path (lexer_line.file); + anonymous_count++; + if (relp) + { + /* The input file is a GCC source file, we use a double + colon after anonymous. To be sure s is truly unique, + we also use anonymous_count. */ + s = xasprintf ("anonymous::%s:%d::%d", + relp, lexer_line.line, anonymous_count); + } + else + { + /* The input file is outside of GCC source tree, we use + a single colon after anonymous. To be sure s is + truly unique, we also use anonymous_count. */ + s = xasprintf ("anonymous:%s:%d::%d", + get_input_file_name (lexer_line.file), + lexer_line.line, anonymous_count); + } + } /* Unfortunately above GTY_TOKEN check does not capture the typedef struct_type GTY case. */ @@ -787,7 +815,19 @@ type (options_p *optsp, bool nested) if (token () == ID) s = advance (); else - s = xasprintf ("anonymous:%s:%d", lexer_line.file, lexer_line.line); + { + /* Again, we don't want to wire in the GCC source tree + directory. */ + const char* relp = get_file_srcdir_relative_path (lexer_line.file); + anonymous_count++; + if (relp) + s = xasprintf ("anonymous::%s:%d::%d", + relp, lexer_line.line, anonymous_count); + else + s = xasprintf ("anonymous:%s:%d::%d", + get_input_file_name (lexer_line.file), + lexer_line.line, anonymous_count); + } if (token () == '{') consume_balanced ('{', '}'); Index: gcc/Makefile.in =================================================================== --- gcc/Makefile.in (revision 165733) +++ gcc/Makefile.in (working copy) @@ -3893,9 +3893,10 @@ build/genextract.o : genextract.c $(RTL_BASE_H) $( build/genflags.o : genflags.c $(RTL_BASE_H) $(OBSTACK_H) $(BCONFIG_H) \ $(SYSTEM_H) coretypes.h $(GTM_H) errors.h $(READ_MD_H) gensupport.h build/gengenrtl.o : gengenrtl.c $(BCONFIG_H) $(SYSTEM_H) rtl.def -build/gengtype-lex.o : gengtype-lex.c gengtype.h $(BCONFIG_H) $(SYSTEM_H) +build/gengtype-lex.o : gengtype-lex.c gengtype.h $(BCONFIG_H) $(SYSTEM_H) \ + errors.h build/gengtype-parse.o : gengtype-parse.c gengtype.h $(BCONFIG_H) \ - $(SYSTEM_H) + $(SYSTEM_H) errors.h build/gengtype.o : gengtype.c $(BCONFIG_H) $(SYSTEM_H) gengtype.h \ rtl.def insn-notes.def errors.h double-int.h $(HASHTAB_H) build/genmddeps.o: genmddeps.c $(BCONFIG_H) $(SYSTEM_H) coretypes.h \