#include "firm_common_t.h"
+#include "list.h"
+
#include "irnode.h"
#include "irgraph.h"
#include "irprog_t.h"
#include "irloop_t.h"
#include "callgraph.h"
#include "irextbb_t.h"
+#include "irhooks.h"
#include "dbginfo_t.h"
#include "irtools.h"
#include "irvrfy.h"
-#include "panic.h"
+#include "error.h"
#include "array.h"
#include "pmap.h"
#include "eset.h"
/** An option to dump ld_names instead of names. */
static int dump_ld_name = 1;
/** Compiler options to dump analysis information in dump_ir_graph */
-int dump_out_edge_flag = 0;
+static int dump_out_edge_flag = 0;
+static int dump_loop_information_flag = 0;
+static int dump_backedge_information_flag = 1;
+static int dump_const_local = 0;
+/** An option to dump all graph anchors */
+static int dump_anchors = 0;
+
int dump_dominator_information_flag = 0;
-int dump_loop_information_flag = 0;
-int dump_backedge_information_flag = 1;
-int dump_const_local = 0;
int opt_dump_analysed_type_info = 1;
int opt_dump_pointer_values_to_info = 0; /* default off: for test compares!! */
dump_edge_vcgattr_hook = hook;
}
-INLINE int get_opt_dump_const_local(void) {
+int get_opt_dump_const_local(void) {
if (!dump_out_edge_flag && !dump_loop_information_flag)
return dump_const_local;
else
dump_ld_name = flag;
}
+void dump_all_anchors(int flag) {
+ dump_anchors = flag;
+}
+
/* -------------- some extended helper functions ----------------- */
/**
* returns the name of a type or <ERROR> if mode is NOT a mode object.
* in the later case, sets bad
*/
-const char *get_type_name_ex(type *tp, int *bad)
+const char *get_type_name_ex(ir_type *tp, int *bad)
{
if (is_type(tp))
return get_type_name(tp);
* prints the edge from a type S to a type T with additional info fmt, ...
* to the file F
*/
-static void print_type_type_edge(FILE *F, type *S, type *T, const char *fmt, ...)
+static void print_type_type_edge(FILE *F, ir_type *S, ir_type *T, const char *fmt, ...)
{
va_list ap;
* prints the edge from a type T to an entity E with additional info fmt, ...
* to the file F
*/
-static void print_type_ent_edge(FILE *F, type *T, entity *E, const char *fmt, ...)
+static void print_type_ent_edge(FILE *F, ir_type *T, entity *E, const char *fmt, ...)
{
va_list ap;
* prints the edge from an entity E to a type T with additional info fmt, ...
* to the file F
*/
-static void print_ent_type_edge(FILE *F, entity *E, type *T, const char *fmt, ...)
+static void print_ent_type_edge(FILE *F, entity *E, ir_type *T, const char *fmt, ...)
{
va_list ap;
* prints the edge from a node N to a type T with additional info fmt, ...
* to the file F
*/
-static void print_node_type_edge(FILE *F, const ir_node *N, type *T, const char *fmt, ...)
+static void print_node_type_edge(FILE *F, const ir_node *N, ir_type *T, const char *fmt, ...)
{
va_list ap;
* prints the edge from a type E to an enumeration item item with additional info fmt, ...
* to the file F
*/
-static void print_enum_item_edge(FILE *F, type *E, int item, const char *fmt, ...)
+static void print_enum_item_edge(FILE *F, ir_type *E, int item, const char *fmt, ...)
{
va_list ap;
(get_irg_pinned(current_ir_graph) == op_pin_state_floats));
}
+/**
+ * Walker that visits the anchors
+ */
+static void ird_walk_graph(ir_graph *irg, irg_walk_func *pre, irg_walk_func *post, void *env) {
+ irg_walk_graph(irg, pre, post, env);
+
+ if (dump_anchors) {
+ int i;
+
+ for (i = anchor_max - 1; i >= 0; --i) {
+ ir_node *n = irg->anchors[i];
+
+ if (n) {
+ /* reset the visit flag: will be increase in the walker */
+ set_irg_visited(irg, get_irg_visited(irg) - 1);
+ irg_walk(n, pre, post, env);
+ }
+ }
+ }
+}
+
/**
* Walker, allocates an array for all blocks and puts it's nodes non-floating nodes into this array.
*/
ir_graph *rem = current_ir_graph;
current_ir_graph = irg;
- for (i = 0; i < get_irp_n_irgs(); i++)
+ for (i = get_irp_n_irgs() - 1; i >= 0; --i)
ird_set_irg_link(get_irp_irg(i), NULL);
- irg_walk_graph(current_ir_graph, clear_link, collect_node, current_ir_graph);
+ ird_walk_graph(current_ir_graph, clear_link, collect_node, current_ir_graph);
/* Collect also EndReg and EndExcept. We do not want to change the walker. */
set_interprocedural_view(0);
ir_extblk **extbb_list;
} list_tuple;
-/** Construct lists to walk ir extended block-wise.
+/** Construct lists to walk IR extended block-wise.
* Free the lists in the tuple with DEL_ARR_F().
+ * Sets the irg link field to NULL in all
+ * graphs not visited.
*/
static list_tuple *construct_extblock_lists(ir_graph *irg) {
ir_node **blk_list = construct_block_lists(irg);
lists->blk_list = NEW_ARR_F(ir_node *, 0);
lists->extbb_list = NEW_ARR_F(ir_extblk *, 0);
+ inc_irg_block_visited(irg);
for (i = ARR_LEN(blk_list) - 1; i >= 0; --i) {
ir_extblk *ext;
else
ARR_APP1(ir_node *, lists->blk_list, blk_list[i]);
}
+ DEL_ARR_F(blk_list);
current_ir_graph = rem;
- DEL_ARR_F(blk_list);
ird_set_irg_link(irg, lists);
return lists;
}
if (opt_dump_analysed_type_info) {
if (get_irg_typeinfo_state(current_ir_graph) == ir_typeinfo_consistent ||
get_irg_typeinfo_state(current_ir_graph) == ir_typeinfo_inconsistent) {
- type *tp = get_irn_typeinfo_type(n);
+ ir_type *tp = get_irn_typeinfo_type(n);
if (tp != firm_none_type)
fprintf(F, "[%s] ", get_type_name_ex(tp, &bad));
else
#undef X
};
+/** the lookup table for Proj(CopyB) names */
+static const pns_lookup_t copyb_lut[] = {
+#define X(a) { pn_CopyB_##a, #a }
+ X(M),
+ X(X_except),
+ X(M_except)
+#undef X
+};
+
+/** the lookup table for Proj(InstOf) names */
+static const pns_lookup_t instof_lut[] = {
+#define X(a) { pn_InstOf_##a, #a }
+ X(M),
+ X(X_except),
+ X(res),
+ X(M_except),
+#undef X
+};
+
+/** the lookup table for Proj(Raise) names */
+static const pns_lookup_t raise_lut[] = {
+#define X(a) { pn_Raise_##a, #a }
+ X(M),
+ X(X),
+#undef X
+};
+
+/** the lookup table for Proj(Bound) names */
+static const pns_lookup_t bound_lut[] = {
+#define X(a) { pn_Bound_##a, #a }
+ X(M),
+ X(X_except),
+ X(res),
+ X(M_except)
+#undef X
+};
/** the Proj lookup table */
static const proj_lookup_t proj_lut[] = {
{ iro_Mod, E(mod_lut) },
{ iro_Load, E(load_lut) },
{ iro_Store, E(store_lut) },
- { iro_Alloc, E(alloc_lut) }
+ { iro_Alloc, E(alloc_lut) },
+ { iro_CopyB, E(copyb_lut) },
+ { iro_InstOf, E(instof_lut) },
+ { iro_Raise, E(raise_lut) },
+ { iro_Bound, E(bound_lut) }
#undef E
};
fprintf (F, "%s ", get_pnc_string(get_Proj_proj(n)));
else if (code == iro_Proj && get_irn_opcode(get_Proj_pred(pred)) == iro_Start)
fprintf (F, "Arg %ld ", proj_nr);
+ else if (code == iro_Cond && get_irn_mode(get_Cond_selector(pred)) != mode_b)
+ fprintf (F, "%ld ", proj_nr);
else {
unsigned i, j, f = 0;
case iro_Phi:
print_vcg_color(F, ird_color_green);
break;
+ case iro_Mux:
+ case iro_Psi:
+ print_vcg_color(F, ird_color_gold);
+ break;
case iro_Const:
case iro_Proj:
case iro_Filter:
}
}
+/* Adds a new node info dumper callback. */
+void *dump_add_node_info_callback(dump_node_info_cb_t *cb, void *data)
+{
+ hook_entry_t *info = xmalloc(sizeof(*info));
+
+ info->hook._hook_node_info = cb;
+ info->context = data;
+ register_hook(hook_node_info, info);
+
+ return info;
+}
+
+/* Remove a previously added info dumper callback. */
+void dump_remv_node_info_callback(void *handle)
+{
+ hook_entry_t *info = handle;
+ unregister_hook(hook_node_info, info);
+ xfree(info);
+}
/**
* Dump the node information of a node n to a file F.
/* call the dump_node operation if available */
if (ops->dump_node)
bad = ops->dump_node(n, F, dump_node_info_txt);
+
+ /* allow additional info to be added */
+ hook_node_info(F, n);
fprintf(F, "\"\n");
return bad;
case iro_Block:
fprintf (F, CF_EDGE_ATTR);
break;
- case iro_Start: break;
+ case iro_Start: break;
case iro_End:
if (to >= 0) {
if (get_irn_mode(get_End_keepalive(from, to)) == mode_BB)
fprintf (F, INTER_MEM_EDGE_ATTR);
}
break;
- case iro_EndReg:
- case iro_EndExcept:
- case iro_Jmp:
- case iro_Break:
- case iro_Cond:
- print_data_edge_vcgattr(F, from, to);
- break;
- case iro_Return:
- case iro_Raise:
- if (to == 0)
- print_mem_edge_vcgattr(F, from, to);
- else
- print_data_edge_vcgattr(F, from, to);
- break;
- case iro_Const:
- case iro_SymConst:
- print_data_edge_vcgattr(F, from, to);
- break;
- case iro_Sel:
- case iro_Call:
- if (to == 0)
- print_mem_edge_vcgattr(F, from, to);
- else
- print_data_edge_vcgattr(F, from, to);
- break;
- case iro_CallBegin:
- case iro_Add:
- case iro_Sub:
- case iro_Minus:
- case iro_Mul:
- print_data_edge_vcgattr(F, from, to);
- break;
- case iro_Quot:
- case iro_DivMod:
- case iro_Div:
- case iro_Mod:
- if (to == 0)
- print_mem_edge_vcgattr(F, from, to);
- else
- print_data_edge_vcgattr(F, from, to);
- break;
- case iro_Abs:
- case iro_And:
- case iro_Or:
- case iro_Eor:
- case iro_Shl:
- case iro_Shr:
- case iro_Shrs:
- case iro_Rot:
- case iro_Cmp:
- case iro_Conv:
- print_data_edge_vcgattr(F, from, to);
- break;
- case iro_Phi:
- if (get_irn_modecode(from) == irm_M)
- fprintf (F, INTER_MEM_EDGE_ATTR);
- else
- print_data_edge_vcgattr(F, from, to);
- break;
- case iro_Load:
- case iro_Store:
- case iro_Alloc:
- case iro_Free:
- if (to == 0)
- print_mem_edge_vcgattr(F, from, to);
- else
- print_data_edge_vcgattr(F, from, to);
- break;
- case iro_Sync:
- print_mem_edge_vcgattr(F, from, to);
- break;
- case iro_Tuple: break;
- case iro_Proj:
- case iro_Filter:
- switch (get_irn_modecode(from)) {
- case irm_X:
- fprintf (F, CF_EDGE_ATTR);
- break;
- case irm_M:
- fprintf (F, INTER_MEM_EDGE_ATTR);
- break;
- default:
- print_data_edge_vcgattr(F, from, to);
- break;
+ default:
+ if (is_Proj(from)) {
+ if (get_irn_mode(from) == mode_M)
+ print_mem_edge_vcgattr(F, from, to);
+ else if (get_irn_mode(from) == mode_X)
+ fprintf(F, CF_EDGE_ATTR);
+ else
+ print_data_edge_vcgattr(F, from, to);
}
- break;
- case iro_Bad: break;
- case iro_Unknown: break;
- case iro_Id:
- switch (get_irn_modecode(from)) {
- case irm_M:
- fprintf (F, INTRA_MEM_EDGE_ATTR);
- break;
- case irm_X:
+ else if (get_irn_mode(get_irn_n(from, to)) == mode_M)
+ print_mem_edge_vcgattr(F, from, to);
+ else if (get_irn_mode(get_irn_n(from, to)) == mode_X)
fprintf (F, CF_EDGE_ATTR);
- break;
- default:
+ else
print_data_edge_vcgattr(F, from, to);
- break;
- } break;
- default:
- ;
}
}
ir_extblk **arr = ird_get_irg_link(irg);
current_ir_graph = irg;
- compute_extbb(irg);
for (i = ARR_LEN(arr) - 1; i >= 0; --i) {
ir_extblk *extbb = arr[i];
ir_node *leader = get_extbb_leader(extbb);
}
#if 0
-static int print_type_info(FILE *F, type *tp) {
+static int print_type_info(FILE *F, ir_type *tp) {
int bad = 0;
if (get_type_state(tp) == layout_undefined) {
return bad;
}
-static void print_typespecific_info(FILE *F, type *tp) {
+static void print_typespecific_info(FILE *F, ir_type *tp) {
switch (get_type_tpop_code(tp)) {
case tpo_class:
{
}
#endif
-static void print_typespecific_vcgattr(FILE *F, type *tp) {
+static void print_typespecific_vcgattr(FILE *F, ir_type *tp) {
switch (get_type_tpop_code(tp)) {
case tpo_class:
{
}
-int dump_type_node(FILE *F, type *tp)
+int dump_type_node(FILE *F, ir_type *tp)
{
int bad = 0;
}
#undef X
-static void dump_enum_item(FILE *F, type *tp, int pos)
+static void dump_enum_item(FILE *F, ir_type *tp, int pos)
{
char buf[1024];
ident *id = get_enumeration_nameid(tp, pos);
} break;
case k_type:
{
- type *tp = (type *)tore;
+ ir_type *tp = (ir_type *)tore;
dump_type_node(F, tp);
/* and now the edges */
switch (get_type_tpop_code(tp)) {
} break; /* case k_entity */
case k_type:
{
- type *tp = (type *)tore;
+ ir_type *tp = (ir_type *)tore;
if (tp == get_glob_type()) break;
switch (get_type_tpop_code(tp)) {
case tpo_class: {
/* walk over the graph */
/* dump_whole_node must be called in post visiting predecessors */
- irg_walk(get_irg_end(irg), NULL, dump_whole_node, f);
+ ird_walk_graph(irg, NULL, dump_whole_node, f);
/* dump the out edges in a separate walk */
if ((dump_out_edge_flag) && (get_irg_outs_state(irg) != outs_none)) {
* only the requested irg but also all irgs that can be reached
* from irg.
*/
- for (i = 0; i < get_irp_n_irgs(); i++) {
+ for (i = get_irp_n_irgs() - 1; i >= 0; --i) {
ir_node **arr = ird_get_irg_link(get_irp_irg(i));
if (arr) {
dump_graph_from_list(f, get_irp_irg(i));
if (!is_filtered_dump_name(get_entity_ident(get_irg_entity(irg))))
return;
- compute_extbb(irg);
+ if (get_irg_extblk_state(irg) != extblk_valid)
+ compute_extbb(irg);
if (get_interprocedural_view()) suffix1 = "-ip";
else suffix1 = "";
dump_graph_info(F, irg);
print_dbg_info(F, get_entity_dbg_info(ent));
- for (i = 0; i < get_irp_n_irgs(); i++) {
+ for (i = get_irp_n_irgs() - 1; i >= 0; --i) {
ir_graph *irg = get_irp_irg(i);
list_tuple *lists = ird_get_irg_link(irg);
/* dump common blocked ir graph */
construct_block_lists(irg);
- for (i = 0; i < get_irp_n_irgs(); i++) {
+ for (i = get_irp_n_irgs() - 1; i >= 0; --i) {
ir_node **arr = ird_get_irg_link(get_irp_irg(i));
if (arr) {
dump_graph_from_list(f, get_irp_irg(i));
void dump_callgraph(const char *suffix) {
FILE *F;
- int i, n_irgs = get_irp_n_irgs();
+ int i;
int rem = edge_label;
edge_label = 1;
//ident *prefix = new_id_from_str("java/");
F = vcg_open_name("Callgraph", suffix);
dump_vcg_header(F, "Callgraph", NULL);
- for (i = 0; i < n_irgs; ++i) {
+ for (i = get_irp_n_irgs() - 1; i >= 0; --i) {
ir_graph *irg = get_irp_irg(i);
entity *ent = get_irg_entity(irg);
int j, n_callees = get_irg_n_callees(irg);
dump_vcg_header(f, "All_graphs", NULL);
/* collect nodes in all irgs reachable in call graph*/
- for (i = 0; i < get_irp_n_irgs(); i++)
+ for (i = get_irp_n_irgs() - 1; i >= 0; --i)
ird_set_irg_link(get_irp_irg(i), NULL);
cg_walk(clear_link, collect_node, NULL);
/* dump all graphs */
- for (i = 0; i < get_irp_n_irgs(); i++) {
+ for (i = get_irp_n_irgs() - 1; i >= 0; --i) {
current_ir_graph = get_irp_irg(i);
assert(ird_get_irg_link(current_ir_graph));
dump_graph_from_list(f, current_ir_graph);
void dump_all_ir_graphs(dump_graph_func *dmp_grph, const char *suffix) {
int i;
- for (i = get_irp_n_irgs() - 1; i >= 0; --i) {
+ for (i = get_irp_n_irgs() - 1; i >= 0; --i)
dmp_grph(get_irp_irg(i), suffix);
- }
}