#include "diagnostic.h"
#include "toplev.h"
#include "tree-dump.h"
+#include "tree-pass.h"
#include "langhooks.h"
#include "tree-iterator.h"
static void dump_new_line (dump_info_p);
static void dump_maybe_newline (dump_info_p);
static void dump_string_field (dump_info_p, const char *, const char *);
-static void dump_enable_all (int);
+static int dump_enable_all (int, int);
/* Add T to the end of the queue of nodes to dump. Returns the index
assigned to T. */
tree t;
unsigned int index;
enum tree_code code;
- char code_class;
+ enum tree_code_class code_class;
const char* code_name;
/* Get the next node from the queue. */
if (dni->binfo_p)
{
unsigned ix;
- tree bases = BINFO_BASETYPES (t);
- unsigned n_bases = bases ? TREE_VEC_LENGTH (bases): 0;
- tree accesses = BINFO_BASEACCESSES (t);
+ tree base;
+ VEC (tree) *accesses = BINFO_BASE_ACCESSES (t);
dump_child ("type", BINFO_TYPE (t));
if (BINFO_VIRTUAL_P (t))
dump_string (di, "virt");
- dump_int (di, "bases", n_bases);
- for (ix = 0; ix != n_bases; ix++)
+ dump_int (di, "bases", BINFO_N_BASE_BINFOS (t));
+ for (ix = 0; BINFO_BASE_ITERATE (t, ix, base); ix++)
{
- tree base = TREE_VEC_ELT (bases, ix);
- tree access = (accesses ? TREE_VEC_ELT (accesses, ix)
+ tree access = (accesses ? VEC_index (tree, accesses, ix)
: access_public_node);
const char *string = NULL;
else if (access == access_private_node)
string = "priv";
else
- abort ();
+ gcc_unreachable ();
dump_string (di, string);
queue_and_dump_index (di, "binf", base, DUMP_BINFO);
switch (code_class)
{
- case '1':
+ case tcc_unary:
dump_child ("op 0", TREE_OPERAND (t, 0));
break;
- case '2':
- case '<':
+ case tcc_binary:
+ case tcc_comparison:
dump_child ("op 0", TREE_OPERAND (t, 0));
dump_child ("op 1", TREE_OPERAND (t, 1));
break;
- case 'e':
- case 'r':
- case 's':
+ case tcc_expression:
+ case tcc_reference:
+ case tcc_statement:
/* These nodes are handled explicitly below. */
break;
default:
- abort ();
+ gcc_unreachable ();
}
}
else if (DECL_P (t))
if (TREE_CHAIN (t) && !dump_flag (di, TDF_SLIM, NULL))
dump_child ("chan", TREE_CHAIN (t));
}
- else if (code_class == 't')
+ else if (code_class == tcc_type)
{
/* All types have qualifiers. */
int quals = lang_hooks.tree_dump.type_quals (t);
/* All types have alignments. */
dump_int (di, "algn", TYPE_ALIGN (t));
}
- else if (code_class == 'c')
+ else if (code_class == tcc_constant)
/* All constants can have types. */
queue_and_dump_type (di, t);
case TRUTH_NOT_EXPR:
case ADDR_EXPR:
case INDIRECT_REF:
+ case ALIGN_INDIRECT_REF:
+ case MISALIGNED_INDIRECT_REF:
case CLEANUP_POINT_EXPR:
case SAVE_EXPR:
case REALPART_EXPR:
}
splay_tree_delete (di.nodes);
}
-
-/* Define a tree dump switch. */
-struct dump_file_info
-{
- const char *suffix; /* suffix to give output file. */
- const char *swtch; /* command line switch */
- int flags; /* user flags */
- int state; /* state of play */
-};
+\f
/* Table of tree dump switches. This must be consistent with the
TREE_DUMP_INDEX enumeration in tree.h */
static struct dump_file_info dump_files[TDI_end] =
{
- {NULL, NULL, 0, 0},
- {".tu", "translation-unit", 0, 0},
- {".class", "class-hierarchy", 0, 0},
- {".original", "tree-original", 0, 0},
- {".generic", "tree-generic", 0, 0},
- {".nested", "tree-nested", 0, 0},
- {".inlined", "tree-inlined", 0, 0},
- {".vcg", "tree-vcg", 0, 0},
- {".xml", "call-graph", 0, 0},
- {NULL, "tree-all", 0, 0},
+ {NULL, NULL, 0, 0, 0, 0},
+ {".tu", "translation-unit", TDF_TREE, 0, 0, 0},
+ {".class", "class-hierarchy", TDF_TREE, 0, 1, 0},
+ {".original", "tree-original", TDF_TREE, 0, 2, 0},
+ {".generic", "tree-generic", TDF_TREE, 0, 3, 0},
+ {".nested", "tree-nested", TDF_TREE, 0, 4, 0},
+ {".inlined", "tree-inlined", TDF_TREE, 0, 5, 0},
+ {".vcg", "tree-vcg", TDF_TREE, 0, 6, 0},
+ {NULL, "tree-all", TDF_TREE, 0, 0, 0},
+ {NULL, "rtl-all", TDF_RTL, 0, 0, 0},
+ {NULL, "ipa-all", TDF_IPA, 0, 0, 0},
+
+ { ".cgraph", "ipa-cgraph", TDF_IPA, 0, 1, 0},
+
+ { ".sibling", "rtl-sibling", TDF_RTL, 0, 1, 'i'},
+ { ".eh", "rtl-eh", TDF_RTL, 0, 2, 'h'},
+ { ".jump", "rtl-jump", TDF_RTL, 0, 3, 'j'},
+ { ".cse", "rtl-cse", TDF_RTL, 0, 4, 's'},
+ { ".gcse", "rtl-gcse", TDF_RTL, 0, 5, 'G'},
+ { ".loop", "rtl-loop", TDF_RTL, 0, 6, 'L'},
+ { ".bypass", "rtl-bypass", TDF_RTL, 0, 7, 'G'},
+ { ".cfg", "rtl-cfg", TDF_RTL, 0, 8, 'f'},
+ { ".bp", "rtl-bp", TDF_RTL, 0, 9, 'b'},
+ { ".vpt", "rtl-vpt", TDF_RTL, 0, 10, 'V'},
+ { ".ce1", "rtl-ce1", TDF_RTL, 0, 11, 'C'},
+ { ".tracer", "rtl-tracer", TDF_RTL, 0, 12, 'T'},
+ { ".loop2", "rtl-loop2", TDF_RTL, 0, 13, 'L'},
+ { ".web", "rtl-web", TDF_RTL, 0, 14, 'Z'},
+ { ".cse2", "rtl-cse2", TDF_RTL, 0, 15, 't'},
+ { ".life", "rtl-life", TDF_RTL, 0, 16, 'f'},
+ { ".combine", "rtl-combine", TDF_RTL, 0, 17, 'c'},
+ { ".ce2", "rtl-ce2", TDF_RTL, 0, 18, 'C'},
+ { ".regmove", "rtl-regmove", TDF_RTL, 0, 19, 'N'},
+ { ".sms", "rtl-sms", TDF_RTL, 0, 20, 'm'},
+ { ".sched", "rtl-sched", TDF_RTL, 0, 21, 'S'},
+ { ".lreg", "rtl-lreg", TDF_RTL, 0, 22, 'l'},
+ { ".greg", "rtl-greg", TDF_RTL, 0, 23, 'g'},
+ { ".postreload", "rtl-postreload", TDF_RTL, 0, 24, 'o'},
+ { ".gcse2", "rtl-gcse2", TDF_RTL, 0, 25, 'J'},
+ { ".flow2", "rtl-flow2", TDF_RTL, 0, 26, 'w'},
+ { ".peephole2", "rtl-peephole2", TDF_RTL, 0, 27, 'z'},
+ { ".ce3", "rtl-ce3", TDF_RTL, 0, 28, 'E'},
+ { ".rnreg", "rtl-rnreg", TDF_RTL, 0, 29, 'n'},
+ { ".bbro", "rtl-bbro", TDF_RTL, 0, 30, 'B'},
+ { ".btl", "rtl-btl", TDF_RTL, 0, 31, 'd'},
+ { ".sched2", "rtl-sched2", TDF_RTL, 0, 32, 'R'},
+ { ".stack", "rtl-stack", TDF_RTL, 0, 33, 'k'},
+ { ".vartrack", "rtl-vartrack", TDF_RTL, 0, 34, 'V'},
+ { ".mach", "rtl-mach", TDF_RTL, 0, 35, 'M'},
+ { ".dbr", "rtl-dbr", TDF_RTL, 0, 36, 'd'}
};
/* Dynamically registered tree dump files and switches. */
};
unsigned int
-dump_register (const char *suffix, const char *swtch)
+dump_register (const char *suffix, const char *swtch, int flags,
+ unsigned int num, int letter)
{
size_t this = extra_dump_files_in_use++;
memset (&extra_dump_files[this], 0, sizeof (struct dump_file_info));
extra_dump_files[this].suffix = suffix;
extra_dump_files[this].swtch = swtch;
+ extra_dump_files[this].flags = flags;
+ extra_dump_files[this].num = num;
+ extra_dump_files[this].letter = letter;
return this + TDI_end;
}
+
/* Return the dump_file_info for the given phase. */
-static struct dump_file_info *
+struct dump_file_info *
get_dump_file_info (enum tree_dump_index phase)
{
if (phase < TDI_end)
return &dump_files[phase];
else if (phase - TDI_end >= extra_dump_files_in_use)
- abort ();
+ return NULL;
else
return extra_dump_files + (phase - TDI_end);
}
+/* Return the name of the dump file for the given phase.
+ If the dump is not enabled, returns NULL. */
+
+char *
+get_dump_file_name (enum tree_dump_index phase)
+{
+ char dump_id[7];
+ struct dump_file_info *dfi;
+
+ if (phase == TDI_none)
+ return NULL;
+
+ dfi = get_dump_file_info (phase);
+ if (dfi->state == 0)
+ return NULL;
+
+ if (dfi->num < 0)
+ dump_id[0] = '\0';
+ else
+ {
+ const char *template;
+ if (dfi->flags & TDF_TREE)
+ template = ".t%02d";
+ else if (dfi->flags & TDF_IPA)
+ template = ".i%02d";
+ else
+ template = ".%02d";
+
+ if (snprintf (dump_id, sizeof (dump_id), template, dfi->num) < 0)
+ dump_id[0] = '\0';
+ }
+
+ return concat (dump_base_name, dump_id, dfi->suffix, NULL);
+}
+
/* Begin a tree dump for PHASE. Stores any user supplied flag in
*FLAG_PTR and returns a stream to write to. If the dump is not
enabled, returns NULL.
FILE *
dump_begin (enum tree_dump_index phase, int *flag_ptr)
{
- FILE *stream;
char *name;
- char dump_id[10];
struct dump_file_info *dfi;
+ FILE *stream;
- if (phase == TDI_none)
+ if (phase == TDI_none || !dump_enabled_p (phase))
return NULL;
+ name = get_dump_file_name (phase);
dfi = get_dump_file_info (phase);
- if (dfi->state == 0)
- return NULL;
-
- if (snprintf (dump_id, sizeof (dump_id), ".t%02d", phase) < 0)
- dump_id[0] = '\0';
-
- name = concat (dump_base_name, dump_id, dfi->suffix, NULL);
stream = fopen (name, dfi->state < 0 ? "w" : "a");
if (!stream)
- error ("could not open dump file `%s': %s", name, strerror (errno));
+ error ("could not open dump file %qs: %s", name, strerror (errno));
else
dfi->state = 1;
free (name);
return dfi->state;
}
+/* Returns nonzero if tree dump PHASE has been initialized. */
+
+int
+dump_initialized_p (enum tree_dump_index phase)
+{
+ struct dump_file_info *dfi = get_dump_file_info (phase);
+ return dfi->state > 0;
+}
+
/* Returns the switch name of PHASE. */
const char *
fclose (stream);
}
-/* Enable all tree dumps. */
+/* Enable all tree dumps. Return number of enabled tree dumps. */
-static void
-dump_enable_all (int flags)
+static int
+dump_enable_all (int flags, int letter)
{
+ int n = 0;
size_t i;
for (i = TDI_none + 1; i < (size_t) TDI_end; i++)
- {
- dump_files[i].state = -1;
- dump_files[i].flags = flags;
- }
+ if ((dump_files[i].flags & flags)
+ && (letter == 0 || letter == dump_files[i].letter))
+ {
+ dump_files[i].state = -1;
+ dump_files[i].flags = flags;
+ n++;
+ }
for (i = 0; i < extra_dump_files_in_use; i++)
- {
- extra_dump_files[i].state = -1;
- extra_dump_files[i].flags = flags;
- }
+ if ((extra_dump_files[i].flags & flags)
+ && (letter == 0 || letter == extra_dump_files[i].letter))
+ {
+ extra_dump_files[i].state = -1;
+ extra_dump_files[i].flags = flags;
+ n++;
+ }
- /* FIXME -fdump-call-graph is broken. */
- dump_files[TDI_xml].state = 0;
- dump_files[TDI_xml].flags = 0;
+ return n;
}
/* Parse ARG as a dump switch. Return nonzero if it is, and store the
flags |= option_ptr->value;
goto found;
}
- warning ("ignoring unknown option `%.*s' in `-fdump-%s'",
+ warning ("ignoring unknown option %q.*s in %<-fdump-%s%>",
length, ptr, dfi->swtch);
found:;
ptr = end_ptr;
}
dfi->state = -1;
- dfi->flags = flags;
+ dfi->flags |= flags;
- /* Process -fdump-tree-all by enabling all the known dumps. */
+ /* Process -fdump-tree-all and -fdump-rtl-all, by enabling all the
+ known dumps. */
if (dfi->suffix == NULL)
- dump_enable_all (flags);
+ dump_enable_all (dfi->flags, 0);
return 1;
}
dump_end (phase, stream);
}
}
+
+bool
+enable_rtl_dump_file (int letter)
+{
+ if (letter == 'a')
+ letter = 0;
+
+ return dump_enable_all (TDF_RTL, letter) > 0;
+}
+
+