#include "gengtype.h"
#include "errors.h" /* for fatal */
#include "double-int.h"
+#include "hashtab.h"
/* Data types, macros, etc. used only in this file. */
{
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
};
static outf_p output_files;
/* The plugin input files and their number; in that case only
- corresponding gt-<plugin>.h are generated in the current
- directory. */
+ a single file is produced. */
static char** plugin_files;
-static int nb_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. */
/* 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;
things there are. (We do not bother resizing the arrays down.) */
num_lang_dirs = langno;
/* Add the plugin files if provided. */
- if (plugin_files)
+ if (plugin_files)
{
- int i;
+ size_t i;
for (i = 0; i < nb_plugin_files; i++)
gt_files[nfiles++] = plugin_files[i];
}
p->name = s;
p->type = t;
p->line = *pos;
+ p->opt = NULL;
typedefs = p;
}
{
outf_p f = get_output_file_with_visibility (NULL);
int i;
- if (!f)
+ if (!f)
return;
oprintf (f, "\n/* Used to implement the RTX_NEXT macro. */\n");
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)
{
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 */
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)
subname = "rt_tree";
break;
- case 'b':
- t = bitmap_tp;
- subname = "rt_bit";
- break;
-
case 'B':
t = basic_block_tp;
subname = "rt_bb";
&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);
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
/* In plugin mode, the O could be a NULL pointer, so avoid crashing
in that case. */
- if (!o)
+ if (!o)
return;
va_start (ap, format);
{
/* 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", "gimple.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;
get_file_realbasename (const char *f)
{
const char * lastslash = strrchr (f, '/');
-
+
return (lastslash != NULL) ? lastslash + 1 : 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)
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;
/* In plugin mode, return NULL unless the input_file is one of the
plugin_files. */
- if (plugin_files && nb_plugin_files > 0)
- {
- int ix= -1, i;
- for (i = 0; i < nb_plugin_files && ix < 0; i++)
- if (strcmp (input_file, plugin_files[i]) == 0)
- ix = i;
- if (ix < 0)
- return NULL;
+ 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. */
|| (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
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);
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,
but don't unnecessarily change modification times. */
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;
}
}
\f
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);
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. */
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;
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, "");
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);
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
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;
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)
/* 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)
&& 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)
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
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);
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)
{
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;
*/
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;
/* 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;
- if (!header_file)
+ if (!output_header)
return;
- oprintf (header_file, "\n/* Local pointer-walking routines. */\n");
+ 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)
|| 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,
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)
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)
{
type_p s;
- if (!header_file)
+ if (!header_file)
return;
oprintf (header_file, "\n/* Enumeration of types known. */\n");
oprintf (header_file, "enum gt_types_enum {\n");
put_mangled_filename (outf_p f, const char *fn)
{
const char *name = get_output_file_name (fn);
- if (!f || !name)
+ if (!f || !name)
return;
for (; *name != 0; name++)
if (ISALNUM (*name))
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)
{
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);
}
}
{
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);
}
}
{
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;
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
{
/* 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;
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",
}
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);
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",
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);
+}
+
\f
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 >= 5 && !strcmp (argv[1], "-p"))
+ if (argc >= 2 && !strcmp (argv[1], "-d"))
{
- srcdir = argv[2];
- inputlist = argv[3];
- plugin_files = argv+4;
- nb_plugin_files = argc-4;
+ 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)
+ else if (argc == 3)
{
srcdir = argv[1];
inputlist = argv[2];
- }
+ }
else
- fatal ("usage: gengtype [-p] srcdir input-list [file1 file2 ... fileN]");
+ fatal ("usage: gengtype [-d] [-P pluginout.h] srcdir input-list "
+ "[file1 file2 ... fileN]");
srcdir_len = strlen (srcdir);
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;