#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
};
/* 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)
{
size_t i;
for (i = 0; i < nb_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",
- "target.h", NULL
+ "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;
|| (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);
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);
+ (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);
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)
continue;
}
}
-
- /* At last we emit the functions code. */
+
+ /* 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
break;
if (opt)
continue;
-
+
if (s->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;
{
type_p s;
- if (!output_header)
+ if (!output_header)
return;
oprintf (output_header, "\n/* Local pointer-walking routines. */\n");
for (s = structures; s; s = s->next)
{
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))
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 >= 2 && !strcmp (argv[1], "-d"))
+ {
+ do_dump = 1;
+ argv = &argv[1];
+ argc--;
+ }
+
if (argc >= 6 && !strcmp (argv[1], "-P"))
{
plugin_output_filename = argv[2];
strcpy (plugin_files[i], name);
}
}
- else if (argc == 3)
+ else if (argc == 3)
{
srcdir = argv[1];
inputlist = argv[2];
- }
+ }
else
- fatal ("usage: gengtype [-P pluginout.h] srcdir input-list "
+ fatal ("usage: gengtype [-d] [-P pluginout.h] srcdir input-list "
"[file1 file2 ... fileN]");
srcdir_len = strlen (srcdir);
write_rtx_next ();
close_output_files ();
+ if (do_dump)
+ dump_everything ();
+
if (plugin_files)
{
for (i = 0; i < nb_plugin_files; i++)