X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=ir%2Fir%2Firdump.c;h=722b91c0b41c036a07af7bb0fd0511371f01ddcb;hb=9752e3725eb983a735721c79a11812da6ab37361;hp=61be9cbdd360b6bef3edffc419175f1603fe339e;hpb=547c5ad02911176577704dedd5c901ffc0218bb2;p=libfirm diff --git a/ir/ir/irdump.c b/ir/ir/irdump.c index 61be9cbdd..722b91c0b 100644 --- a/ir/ir/irdump.c +++ b/ir/ir/irdump.c @@ -6,7 +6,7 @@ * Modified by: Goetz Lindenmaier, Hubert Schmidt * Created: * CVS-ID: $Id$ - * Copyright: (c) 1998-2003 Universität Karlsruhe + * Copyright: (c) 1998-2003 Universit�t Karlsruhe * Licence: This file protected by GPL - GNU GENERAL PUBLIC LICENSE. */ #ifdef HAVE_CONFIG_H @@ -37,8 +37,11 @@ #include "type_or_entity.h" #include "irouts.h" #include "irdom.h" -#include "irloop.h" +#include "irloop_t.h" #include "callgraph.h" +#include "irextbb_t.h" +#include "dbginfo_t.h" +#include "irtools.h" #include "irvrfy.h" @@ -65,6 +68,141 @@ static ident *dump_file_filter_id = NULL; #define ERROR_TXT "" +/*******************************************************************/ +/* flags to steer output */ +/*******************************************************************/ + +/** An option to turn off edge labels */ +static int edge_label = 1; +/** An option to turn off dumping values of constant entities */ +static int const_entities = 1; +/** An option to dump the keep alive edges */ +static int dump_keepalive = 0; +/** 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; +int dump_dominator_information_flag = 0; +int dump_loop_information_flag = 0; +int dump_backedge_information_flag = 1; +int dump_const_local = 0; +bool opt_dump_analysed_type_info = 1; +bool opt_dump_pointer_values_to_info = 0; /* default off: for test compares!! */ + +static const char *overrule_nodecolor = NULL; + +/** An additional edge hook. */ +static DUMP_NODE_EDGE_FUNC dump_node_edge_hook = NULL; + +void set_dump_node_edge_hook(DUMP_NODE_EDGE_FUNC func) +{ + dump_node_edge_hook = func; +} + +DUMP_NODE_EDGE_FUNC get_dump_node_edge_hook(void) +{ + return dump_node_edge_hook; +} + + +/** The vcg node attribute hook. */ +static DUMP_IR_GRAPH_FUNC dump_ir_graph_hook = NULL; +/** The vcg node attribute hook. */ +static DUMP_NODE_VCGATTR_FUNC dump_node_vcgattr_hook = NULL; +/** The vcg edge attribute hook. */ +static DUMP_EDGE_VCGATTR_FUNC dump_edge_vcgattr_hook = NULL; + +/* set the ir graph hook */ +void set_dump_ir_graph_hook(DUMP_IR_GRAPH_FUNC hook) { + dump_ir_graph_hook = hook; +} +/* set the node attribute hook */ +void set_dump_node_vcgattr_hook(DUMP_NODE_VCGATTR_FUNC hook) { + dump_node_vcgattr_hook = hook; +} +/* set the edge attribute hook */ +void set_dump_edge_vcgattr_hook(DUMP_EDGE_VCGATTR_FUNC hook) { + dump_edge_vcgattr_hook = hook; +} + +INLINE bool get_opt_dump_const_local(void) { + if (!dump_out_edge_flag && !dump_loop_information_flag) + return dump_const_local; + else + return false; +} + +void only_dump_method_with_name(ident *name) { + dump_file_filter_id = name; +} + +ident *get_dump_file_filter_ident(void) { + return dump_file_filter_id; +} + +/** Returns true if dump file filter is not set, or if it is a + * prefix of name. */ +int is_filtered_dump_name(ident *name) { + if (!dump_file_filter_id) return 1; + return id_is_prefix(dump_file_filter_id, name); +} + +/* To turn off display of edge labels. Edge labels often cause xvcg to + abort with a segmentation fault. */ +void turn_off_edge_labels(void) { + edge_label = 0; +} + +void dump_consts_local(bool b) { + dump_const_local = b; +} + +void dump_constant_entity_values(bool b) { + const_entities = b; +} + +void dump_keepalive_edges(bool b) { + dump_keepalive = b; +} + +bool get_opt_dump_keepalive_edges(void) { + return dump_keepalive; +} + +void dump_out_edges(bool b) { + dump_out_edge_flag = b; +} + +void dump_dominator_information(bool b) { + dump_dominator_information_flag = b; +} + +void dump_loop_information(bool b) { + dump_loop_information_flag = b; +} + +void dump_backedge_information(bool b) { + dump_backedge_information_flag = b; +} + +/* Dump the information of type field specified in ana/irtypeinfo.h. + * If the flag is set, the type name is output in [] in the node label, + * else it is output as info. + */ +void set_opt_dump_analysed_type_info(bool b) { + opt_dump_analysed_type_info = b; +} + +void dump_pointer_values_to_info(bool b) { + opt_dump_pointer_values_to_info = b; +} + +void dump_ld_names(bool b) { + dump_ld_name = b; +} + +/* -------------- some extended helper functions ----------------- */ + /** * returns the name of a mode or if mode is NOT a mode object. * in the later case, sets bad @@ -239,12 +377,19 @@ static INLINE void dump_loop_nodes_into_graph(FILE *F, ir_graph *irg); */ static pmap *irdump_link_map = NULL; -/** Creates the link attribut map. */ +/** NOT A STANDARD LIBFIRM INIT METHOD + * + * We do not want to integrate dumping into libfirm, i.e., if the dumpers + * are off, we want to have as few interferences as possible. Therefore the + * initialization is performed lazily and not called from within init_firm. + * + * Creates the link attribute map. */ static void init_irdump(void) { /* We need a new, empty map. */ if (irdump_link_map) pmap_destroy(irdump_link_map); irdump_link_map = pmap_create(); - dump_file_filter_id = new_id_from_str(""); + if (!dump_file_filter_id) + dump_file_filter_id = new_id_from_str(""); } /** * Returns the private link field. @@ -262,7 +407,8 @@ static void *ird_get_irn_link(ir_node *n) { * Sets the private link field. */ static void ird_set_irn_link(ir_node *n, void *x) { - if (!irdump_link_map) init_irdump(); + if (!irdump_link_map) + init_irdump(); pmap_insert(irdump_link_map, (void *)n, x); } @@ -287,28 +433,38 @@ static void ird_set_irg_link(ir_graph *irg, void *x) { } /** - * Walker, clears tzhe private link field + * Walker, clears the private link field. */ static void clear_link(ir_node * node, void * env) { ird_set_irn_link(node, NULL); } /** - * If the entity has a ld_name, returns it, else returns the name of the entity. + * If the entity has a ld_name, returns it if the dump_ld_name is set, + * else returns the name of the entity. */ -const char *get_ent_dump_name(entity *ent) { +static const char *_get_ent_dump_name(entity *ent, int dump_ld_name) { if (!ent) return ""; - /* Don't use get_entity_ld_ident (ent) as it computes the mangled name! */ - if (ent->ld_name) return get_id_str(ent->ld_name); + if (dump_ld_name) { + /* Don't use get_entity_ld_ident (ent) as it computes the mangled name! */ + if (ent->ld_name) return get_id_str(ent->ld_name); + } return get_id_str(ent->name); } +/** + * If the entity has a ld_name, returns it if the option dump_ld_name is set, + * else returns the name of the entity. + */ +const char *get_ent_dump_name(entity *ent) { + return _get_ent_dump_name(ent, dump_ld_name); +} + /* Returns the name of an IRG. */ const char *get_irg_dump_name(ir_graph *irg) { /* Don't use get_entity_ld_ident (ent) as it computes the mangled name! */ - entity *ent = get_irg_entity(irg); - return get_ent_dump_name(ent); + return _get_ent_dump_name(get_irg_entity(irg), 1); } /** @@ -357,7 +513,7 @@ static void collect_node(ir_node * node, void *env) { * graphs not visited. * Free the list with DEL_ARR_F(). */ -static ir_node ** construct_block_lists(ir_graph *irg) { +static ir_node **construct_block_lists(ir_graph *irg) { int i, rem_view = get_interprocedural_view(); ir_graph *rem = current_ir_graph; current_ir_graph = irg; @@ -381,105 +537,44 @@ static ir_node ** construct_block_lists(ir_graph *irg) { return ird_get_irg_link(irg); } -/*******************************************************************/ -/* flags to steer output */ -/*******************************************************************/ - -/** A compiler option to turn off edge labels */ -static int edge_label = 1; -/** A compiler option to turn off dumping values of constant entities */ -static int const_entities = 1; -/** A compiler option to dump the keep alive edges */ -static int dump_keepalive = 0; -/** Compiler options to dump analysis information in dump_ir_graph */ -int dump_out_edge_flag = 0; -int dump_dominator_information_flag = 0; -int dump_loop_information_flag = 0; -int dump_backedge_information_flag = 1; -int dump_const_local = 0; -bool opt_dump_analysed_type_info = 1; -bool opt_dump_pointer_values_to_info = 0; /* default off: for test compares!! */ - -static const char *overrule_nodecolor = NULL; - -/** The vcg attribute hook. */ -static DUMP_NODE_VCGATTR_FUNC dump_node_vcgattr_hook = NULL; - -/* set the hook */ -void set_dump_node_vcgattr_hook(DUMP_NODE_VCGATTR_FUNC hook) -{ - dump_node_vcgattr_hook = hook; -} - -INLINE bool get_opt_dump_const_local(void) { - if (!dump_out_edge_flag && !dump_loop_information_flag) - return dump_const_local; - else - return false; -} - -void only_dump_method_with_name(ident *name) { - dump_file_filter_id = name; -} - -ident *get_dump_file_filter_ident(void) { - return dump_file_filter_id; -} - -/** Returns true if dump file filter is not set, or if it is a - * prefix of name. */ -int is_filtered_dump_name(ident *name) { - return id_is_prefix(dump_file_filter_id, name); -} - -/* To turn off display of edge labels. Edge labels offen cause xvcg to - abort with a segmentation fault. */ -void turn_off_edge_labels(void) { - edge_label = 0; -} - -void dump_consts_local(bool b) { - dump_const_local = b; -} - -void dump_constant_entity_values(bool b) { - const_entities = b; -} +typedef struct _list_tuple { + ir_node **blk_list; + ir_extblk **extbb_list; +} list_tuple; -void dump_keepalive_edges(bool b) { - dump_keepalive = b; -} - -bool get_opt_dump_keepalive_edges(void) { - return dump_keepalive; -} +/** Construct lists to walk ir extended block-wise. + * Free the lists in the tuple with DEL_ARR_F(). + */ +static list_tuple *construct_extblock_lists(ir_graph *irg) { + ir_node **blk_list = construct_block_lists(irg); + int i; + ir_graph *rem = current_ir_graph; + list_tuple *lists = xmalloc(sizeof(*lists)); -void dump_out_edges(bool b) { - dump_out_edge_flag = b; -} + current_ir_graph = irg; -void dump_dominator_information(bool b) { - dump_dominator_information_flag = b; -} + lists->blk_list = NEW_ARR_F(ir_node *, 0); + lists->extbb_list = NEW_ARR_F(ir_extblk *, 0); -void dump_loop_information(bool b) { - dump_loop_information_flag = b; -} + for (i = ARR_LEN(blk_list) - 1; i >= 0; --i) { + ir_extblk *ext; -void dump_backedge_information(bool b) { - dump_backedge_information_flag = b; -} + if (is_Block(blk_list[i])) { + ext = get_Block_extbb(blk_list[i]); -/* Dump the information of type field specified in ana/irtypeinfo.h. - * If the flag is set, the type name is output in [] in the node label, - * else it is output as info. - */ -void set_opt_dump_analysed_type_info(bool b) { - opt_dump_analysed_type_info = b; -} + if (extbb_not_visited(ext)) { + ARR_APP1(ir_extblk *, lists->extbb_list, ext); + mark_extbb_visited(ext); + } + } + else + ARR_APP1(ir_node *, lists->blk_list, blk_list[i]); + } -void dump_pointer_values_to_info(bool b) { - opt_dump_pointer_values_to_info = b; + current_ir_graph = rem; + DEL_ARR_F(blk_list); + ird_set_irg_link(irg, lists); + return lists; } /*-----------------------------------------------------------------*/ @@ -537,10 +632,6 @@ dump_node_opcode(FILE *F, ir_node *n) && get_Proj_proj(n) == get_Cond_defaultProj(pred) && get_irn_mode(get_Cond_selector(pred)) != mode_b) fprintf (F, "defProj"); -/* - * else if (get_irn_opcode(pred) == iro_Proj && get_irn_opcode(get_Proj_pred(pred)) == iro_Start) - * fprintf (F, "Arg"); - */ else goto default_case; } break; @@ -568,9 +659,12 @@ dump_node_opcode(FILE *F, ir_node *n) case iro_Load: fprintf (F, "%s[%s]", get_irn_opname(n), get_mode_name_ex(get_Load_mode(n), &bad)); break; + case iro_Block: + fprintf (F, "%s%s", is_Block_dead(n) ? "Dead " : "", get_irn_opname(n)); + break; -default_case: default: { +default_case: fprintf (F, "%s", get_irn_opname(n)); } @@ -611,7 +705,7 @@ dump_node_mode(FILE *F, ir_node *n) } /** - * Dump the tpe of a node n to a file F if it's known. + * Dump the type of a node n to a file F if it's known. */ static int dump_node_typeinfo(FILE *F, ir_node *n) { int bad = 0; @@ -629,13 +723,139 @@ static int dump_node_typeinfo(FILE *F, ir_node *n) { return bad; } +typedef struct _pns_lookup { + long nr; /**< the proj number */ + const char *name; /**< the name of the Proj */ +} pns_lookup_t; + +typedef struct _proj_lookup { + opcode code; /**< the opcode of the Proj predecessor */ + unsigned num_data; /**< number of data entries */ + const pns_lookup_t *data; /**< the data */ +} proj_lookup_t; + +#define ARR_SIZE(a) (sizeof(a)/sizeof(a[0])) + +/** the lookup table for Proj(Start) names */ +static const pns_lookup_t start_lut[] = { +#define X(a) { pn_Start_##a, #a } + X(X_initial_exec), + X(P_frame_base), + X(P_globals), + X(T_args), + X(P_value_arg_base) +#undef X +}; + +/** the lookup table for Proj(Cond) names */ +static const pns_lookup_t cond_lut[] = { +#define X(a) { pn_Cond_##a, #a } + X(false), + X(true) +#undef X +}; + +/** the lookup table for Proj(Call) names */ +static const pns_lookup_t call_lut[] = { +#define X(a) { pn_Call_##a, #a } + X(M_regular), + X(T_result), + X(P_value_res_base), + X(X_except), + X(M_except) +#undef X +}; + +/** the lookup table for Proj(Quot) names */ +static const pns_lookup_t quot_lut[] = { +#define X(a) { pn_Quot_##a, #a } + X(M), + X(X_except), + X(res) +#undef X +}; + +/** the lookup table for Proj(DivMod) names */ +static const pns_lookup_t divmod_lut[] = { +#define X(a) { pn_DivMod_##a, #a } + X(M), + X(X_except), + X(res_div), + X(res_mod) +#undef X +}; + +/** the lookup table for Proj(Div) names */ +static const pns_lookup_t div_lut[] = { +#define X(a) { pn_Div_##a, #a } + X(M), + X(X_except), + X(res) +#undef X +}; + +/** the lookup table for Proj(Mod) names */ +static const pns_lookup_t mod_lut[] = { +#define X(a) { pn_Mod_##a, #a } + X(M), + X(X_except), + X(res) +#undef X +}; + +/** the lookup table for Proj(Load) names */ +static const pns_lookup_t load_lut[] = { +#define X(a) { pn_Load_##a, #a } + X(M), + X(X_except), + X(res) +#undef X +}; + +/** the lookup table for Proj(Store) names */ +static const pns_lookup_t store_lut[] = { +#define X(a) { pn_Store_##a, #a } + X(M), + X(X_except) +#undef X +}; + +/** the lookup table for Proj(Alloc) names */ +static const pns_lookup_t alloc_lut[] = { +#define X(a) { pn_Alloc_##a, #a } + X(M), + X(X_except), + X(res) +#undef X +}; + + +/** the Proj lookup table */ +static const proj_lookup_t proj_lut[] = { +#define E(a) ARR_SIZE(a), a + { iro_Start, E(start_lut) }, + { iro_Cond, E(cond_lut) }, + { iro_Call, E(call_lut) }, + { iro_Quot, E(quot_lut) }, + { iro_DivMod, E(divmod_lut) }, + { iro_Div, E(div_lut) }, + { iro_Mod, E(mod_lut) }, + { iro_Load, E(load_lut) }, + { iro_Store, E(store_lut) }, + { iro_Alloc, E(alloc_lut) } +#undef E +}; + /** - * Dump addinional node attributes of some nodes to a file F. + * Dump additional node attributes of some nodes to a file F. */ static INLINE int dump_node_nodeattr(FILE *F, ir_node *n) { int bad = 0; + ir_node *pred; + opcode code; + long proj_nr; switch (get_irn_opcode(n)) { case iro_Start: @@ -643,15 +863,51 @@ dump_node_nodeattr(FILE *F, ir_node *n) fprintf (F, "%s ", get_ent_dump_name(get_irg_entity(current_ir_graph))); } break; + case iro_Proj: - if (get_irn_opcode(get_Proj_pred(n)) == iro_Cmp) { + pred = get_Proj_pred(n); + proj_nr = get_Proj_proj(n); +handle_lut: + code = get_irn_opcode(pred); + + if (code == iro_Cmp) fprintf (F, "%s ", get_pnc_string(get_Proj_proj(n))); - } else { - fprintf (F, "%ld ", 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 { + unsigned i, j, f = 0; + + for (i = 0; i < ARR_SIZE(proj_lut); ++i) { + if (code == proj_lut[i].code) { + for (j = 0; j < proj_lut[i].num_data; ++j) { + if (proj_nr == proj_lut[i].data[j].nr) { + fprintf (F, "%s ", proj_lut[i].data[j].name); + f = 1; + break; + } + } + break; + } + } + if (! f) + fprintf (F, "%ld ", proj_nr); + if (code == iro_Cond && get_Cond_jmp_pred(pred) != COND_JMP_PRED_NONE) { + if (proj_nr == pn_Cond_false && get_Cond_jmp_pred(pred) == COND_JMP_PRED_FALSE) + fprintf(F, "PRED "); + if (proj_nr == pn_Cond_true && get_Cond_jmp_pred(pred) == COND_JMP_PRED_TRUE) + fprintf(F, "PRED "); + } } break; case iro_Filter: - fprintf (F, "%ld ", get_Filter_proj(n)); + proj_nr = get_Filter_proj(n); + if (! get_interprocedural_view()) { + /* it's a Proj' */ + pred = get_Filter_pred(n); + goto handle_lut; + } + else + fprintf (F, "%ld ", proj_nr); break; case iro_Sel: fprintf (F, "%s ", get_ent_dump_name(get_Sel_entity(n))); @@ -670,9 +926,23 @@ dump_node_nodeattr(FILE *F, ir_node *n) return bad; } +#include +#include "execution_frequency.h" +#include "callgraph.h" -/** Dumps a node label without the enclosing ". */ -static int dump_node_label(FILE *F, ir_node *n) { +void dump_node_ana_vals(FILE *F, ir_node *n) { + return; + fprintf(F, " %lf*(%2.0lf + %2.0lf) = %2.0lf ", + get_irn_exec_freq(n), + get_irg_method_execution_frequency(get_irn_irg(n)), + pow(5, get_irg_recursion_depth(get_irn_irg(n))), + get_irn_exec_freq(n) * (get_irg_method_execution_frequency(get_irn_irg(n)) + pow(5, get_irg_recursion_depth(get_irn_irg(n)))) + ); +} + + +/* Dumps a node label without the enclosing ". */ +int dump_node_label(FILE *F, ir_node *n) { int bad = 0; bad |= dump_node_opcode(F, n); @@ -749,7 +1019,7 @@ static INLINE int dump_node_info(FILE *F, ir_node *n) } /** - * checks wheater a node is "constant-like", ie can be treated "block-less" + * checks whether a node is "constant-like" ie can be treated "block-less" */ static INLINE bool is_constlike_node(ir_node *n) { @@ -815,6 +1085,19 @@ static void dump_const_block_local(FILE *F, ir_node *n) { fprintf (F, "edge: { sourcename: \""); PRINT_NODEID(n); fprintf (F, "\" targetname: \""); PRINT_CONSTBLKID(n,blk); + + if (dump_edge_vcgattr_hook) { + fprintf (F, "\" "); + if (dump_edge_vcgattr_hook(F, n, -1)) { + fprintf (F, "}\n"); + return; + } + else { + fprintf (F, " " BLOCK_EDGE_ATTR "}\n"); + return; + } + } + fprintf (F, "\" " BLOCK_EDGE_ATTR "}\n"); } } @@ -830,6 +1113,20 @@ static void INLINE print_node_error(FILE *F, const char *err_msg) fprintf (F, " info2: \"%s\"", err_msg); } +/** + * prints debug messages of a node to file F as info3. + */ +static void print_node_dbg_info(FILE *F, dbg_info *dbg) +{ + char buf[1024]; + + if (__dbg_info_snprint) { + buf[0] = '\0'; + if (__dbg_info_snprint(buf, sizeof(buf), dbg) > 0) + fprintf (F, " info3: \"%s\"\n", buf); + } +} + /** * Dump a node */ @@ -846,13 +1143,18 @@ static void dump_node(FILE *F, ir_node *n) bad = ! irn_vrfy_irg_dump(n, current_ir_graph, &p); bad |= dump_node_label(F, n); + dump_node_ana_vals(F, n); //dump_node_ana_info(F, n); fprintf(F, "\" "); bad |= dump_node_info(F, n); print_node_error(F, p); + print_node_dbg_info(F, get_irn_dbg_info(n)); dump_node_vcgattr(F, n, NULL, bad); fprintf(F, "}\n"); dump_const_node_local(F, n); + + if(dump_node_edge_hook) + dump_node_edge_hook(F, n); #if DO_HEAPANALYSIS dump_irn_chi_term(F, n); dump_irn_state(F, n); @@ -874,6 +1176,19 @@ dump_ir_block_edge(FILE *F, ir_node *n) { PRINT_NODEID(n); fprintf (F, "\" targetname: "); fprintf(F, "\""); PRINT_NODEID(block); fprintf(F, "\""); + + if (dump_edge_vcgattr_hook) { + fprintf (F, " "); + if (dump_edge_vcgattr_hook(F, n, -1)) { + fprintf (F, "}\n"); + return; + } + else { + fprintf (F, " " BLOCK_EDGE_ATTR "}\n"); + return; + } + } + fprintf (F, " " BLOCK_EDGE_ATTR "}\n"); } } @@ -881,7 +1196,11 @@ dump_ir_block_edge(FILE *F, ir_node *n) { static void print_data_edge_vcgattr(FILE *F, ir_node *from, int to) { - if (get_nodes_block(from) == get_nodes_block(get_irn_n(from, to))) + /* + * do not use get_nodes_block() here, will fail + * if the irg is not pinned. + */ + if (get_irn_n(from, -1) == get_irn_n(get_irn_n(from, to), -1)) fprintf (F, INTRA_DATA_EDGE_ATTR); else fprintf (F, INTER_DATA_EDGE_ATTR); @@ -889,7 +1208,11 @@ print_data_edge_vcgattr(FILE *F, ir_node *from, int to) { static void print_mem_edge_vcgattr(FILE *F, ir_node *from, int to) { - if (get_nodes_block(from) == get_nodes_block(get_irn_n(from, to))) + /* + * do not use get_nodes_block() here, will fail + * if the irg is not pinned. + */ + if (get_irn_n(from, -1) == get_irn_n(get_irn_n(from, to), -1)) fprintf (F, INTRA_MEM_EDGE_ATTR); else fprintf (F, INTER_MEM_EDGE_ATTR); @@ -899,6 +1222,10 @@ static void print_edge_vcgattr(FILE *F, ir_node *from, int to) { assert(from); + if (dump_edge_vcgattr_hook) + if (dump_edge_vcgattr_hook(F, from, to)) + return; + if (dump_backedge_information_flag && is_backedge(from, to)) fprintf (F, BACK_EDGE_ATTR); @@ -1090,7 +1417,7 @@ static void dump_const_expression(FILE *F, ir_node *value) { current_ir_graph = get_const_code_irg(); irg_walk(value, dump_const_node, NULL, F); /* Decrease visited flag so that we walk with the same flag for the next - expresssion. This guarantees that we don't dump the same node twice, + expression. This guarantees that we don't dump the same node twice, as for const expressions cse is performed to save memory. */ set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph) -1); current_ir_graph = rem; @@ -1105,6 +1432,8 @@ static void dump_const_expression(FILE *F, ir_node *value) { static void dump_whole_block(FILE *F, ir_node *block) { ir_node *node; + const char *color = "yellow"; + assert(is_Block(block)); fprintf(F, "graph: { title: \""); @@ -1115,8 +1444,17 @@ dump_whole_block(FILE *F, ir_node *block) { if (get_opt_dump_abstvals()) fprintf (F, " seqno: %d", (int)get_Block_seqno(block)); #endif - fprintf(F, "\" status:clustered color:%s \n", - get_Block_matured(block) ? "yellow" : "red"); + + /* colorize blocks */ + if (! get_Block_matured(block)) + color = "red"; + if (is_Block_dead(block)) + color = "orange"; + + fprintf(F, "\" status:clustered color:%s \n", color); + + /* ycomp can show attributs for blocks, VCG parses but ignores them */ + dump_node_info(F, block); /* dump the blocks edges */ dump_ir_data_edges(F, block); @@ -1154,7 +1492,7 @@ dump_block_graph(FILE *F, ir_graph *irg) { } else { /* Nodes that are not in a Block. */ dump_node(F, node); - if (is_Bad(get_nodes_block(node)) && !node_floats(node)) { + if (!node_floats(node) && is_Bad(get_nodes_block(node))) { dump_const_block_local(F, node); } dump_ir_data_edges(F, node); @@ -1167,7 +1505,7 @@ dump_block_graph(FILE *F, ir_graph *irg) { current_ir_graph = rem; } -/** Dumps an irg as a graph. +/** Dumps an irg as a graph clustered by block nodes. * If interprocedural view edges can point to nodes out of this graph. */ static void dump_graph_from_list(FILE *F, ir_graph *irg) { @@ -1183,6 +1521,52 @@ static void dump_graph_from_list(FILE *F, ir_graph *irg) { fprintf(F, "}\n\n"); } +/** dumps a graph extended block-wise. Expects all blockless nodes in arr in irgs link. + * The outermost nodes: blocks and nodes not op_pin_state_pinned, Bad, Unknown. */ +static void +dump_extblock_graph(FILE *F, ir_graph *irg) { + int i; + ir_graph *rem = current_ir_graph; + 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); + int j; + + fprintf(F, "graph: { title: \""); + PRINT_EXTBBID(leader); + fprintf(F, "\" label: \"ExtBB %ld\" status:clustered color:lightgreen\n", + get_irn_node_nr(leader)); + + for (j = ARR_LEN(extbb->blks) - 1; j >= 0; --j) { + ir_node * node = extbb->blks[j]; + if (is_Block(node)) { + /* Dumps the block and all the nodes in the block, which are to + be found in Block->link. */ + dump_whole_block(F, node); + } else { + /* Nodes that are not in a Block. */ + dump_node(F, node); + if (is_Bad(get_nodes_block(node)) && !node_floats(node)) { + dump_const_block_local(F, node); + } + dump_ir_data_edges(F, node); + } + } + fprintf(F, "}\n"); + } + + if (dump_loop_information_flag && (get_irg_loopinfo_state(irg) & loopinfo_valid)) + dump_loop_nodes_into_graph(F, irg); + + current_ir_graph = rem; + free_extbb(irg); +} + + /*******************************************************************/ /* Basic type and entity nodes and edges. */ /*******************************************************************/ @@ -1224,7 +1608,7 @@ static void dump_node2type_edges(ir_node *n, void *env) } } - +#if 0 static int print_type_info(FILE *F, type *tp) { int bad = 0; @@ -1273,7 +1657,7 @@ static void print_typespecific_info(FILE *F, type *tp) { default: break; } /* switch type */ } - +#endif static void print_typespecific_vcgattr(FILE *F, type *tp) { switch (get_type_tpop_code(tp)) { @@ -1310,7 +1694,8 @@ static void print_typespecific_vcgattr(FILE *F, type *tp) { } /* switch type */ } -static int print_type_node(FILE *F, type *tp) + +int dump_type_node(FILE *F, type *tp) { int bad = 0; @@ -1318,15 +1703,21 @@ static int print_type_node(FILE *F, type *tp) PRINT_TYPEID(tp); fprintf (F, " label: \"%s %s\"", get_type_tpop_name(tp), get_type_name_ex(tp, &bad)); fprintf (F, " info1: \""); +#if 0 bad |= print_type_info(F, tp); print_typespecific_info(F, tp); - fprintf (F, "\""); +#else + dump_type_to_file(F, tp, dump_verbosity_max); +#endif + fprintf (F, "\"\n"); + print_node_dbg_info(F, get_type_dbg_info(tp)); print_typespecific_vcgattr(F, tp); fprintf (F, "}\n"); return bad; } + #define X(a) case a: fprintf(F, #a); break void dump_entity_node(FILE *F, entity *ent, int color) { @@ -1343,7 +1734,9 @@ void dump_entity_node(FILE *F, entity *ent, int color) dump_entity_to_file(F, ent, dump_verbosity_entattrs | dump_verbosity_entconsts); - fprintf(F, "\"\n}\n"); + fprintf(F, "\"\n"); + print_node_dbg_info(F, get_entity_dbg_info(ent)); + fprintf(F, "}\n"); } #undef X @@ -1416,7 +1809,7 @@ dump_type_info(type_or_ent *tore, void *env) { case k_type: { type *tp = (type *)tore; - print_type_node(F, tp); + dump_type_node(F, tp); /* and now the edges */ switch (get_type_tpop_code(tp)) { case tpo_class: @@ -1518,7 +1911,7 @@ dump_class_hierarchy_node (type_or_ent *tore, void *ctx) { if (tp == get_glob_type()) break; switch (get_type_tpop_code(tp)) { case tpo_class: { - print_type_node(F, tp); + dump_type_node(F, tp); /* and now the edges */ for (i=0; i < get_class_n_supertypes(tp); i++) { @@ -1566,7 +1959,7 @@ static INLINE void dump_loop_info(FILE *F, ir_loop *loop) { fprintf (F, " info1: \""); fprintf (F, " loop nr: %d", get_loop_loop_nr(loop)); #if DEBUG_libfirm /* GL @@@ debug analyses */ - fprintf (F, "\n The loop was analyzed %d times.", (int)get_loop_link(loop)); + fprintf (F, "\n The loop was analyzed %d times.", PTR_TO_INT(get_loop_link(loop))); #endif fprintf (F, "\""); } @@ -1637,7 +2030,7 @@ void dump_loop_nodes_into_graph(FILE *F, ir_graph *irg) { /** * dumps the VCG header */ -INLINE void dump_vcg_header(FILE *F, const char *name, const char *orientation) { +void dump_vcg_header(FILE *F, const char *name, const char *orientation) { char *label; if (edge_label) { @@ -1675,7 +2068,8 @@ INLINE void dump_vcg_header(FILE *F, const char *name, const char *orientation) "classname 11: \"Overwrites\"\n" "classname 12: \"Member\"\n" "infoname 1: \"Attribute\"\n" - "infoname 2: \"Verification errors\"\n", + "infoname 2: \"Verification errors\"\n" + "infoname 3: \"Debug info\"\n", name, label, orientation); /* don't use all, the range is too whith/black. */ @@ -1764,7 +2158,7 @@ FILE *vcg_open (ir_graph *irg, const char * suffix1, const char *suffix2) { /** * open a vcg file * - * @param irg The graph to be dumped + * @param name prefix file name * @param suffix filename suffix */ FILE *vcg_open_name (const char *name, const char *suffix) { @@ -1775,7 +2169,7 @@ FILE *vcg_open_name (const char *name, const char *suffix) { if (!suffix) suffix = ""; /** open file for vcg graph */ - fname = malloc (len * 2 + 5 + strlen(suffix)); + fname = xmalloc(len * 2 + 5 + strlen(suffix)); /* strcpy (fname, name);*/ /* copy the filename */ j = 0; for (i = 0; i < len; ++i) { /* replace '/' in the name: escape by @. */ @@ -1845,6 +2239,11 @@ dump_ir_graph (ir_graph *irg, const char *suffix ) f = vcg_open(irg, suffix, suffix1); dump_vcg_header(f, get_irg_dump_name(irg), NULL); + /* call the dump graph hook */ + if (dump_ir_graph_hook) + if (dump_ir_graph_hook(f, irg)) + return; + /* 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); @@ -1859,9 +2258,8 @@ dump_ir_graph (ir_graph *irg, const char *suffix ) current_ir_graph = rem; } - -void -dump_ir_block_graph (ir_graph *irg, const char *suffix) +/* Dump a firm graph without explicit block nodes. */ +void dump_ir_block_graph (ir_graph *irg, const char *suffix) { FILE *f; int i; @@ -1877,6 +2275,11 @@ dump_ir_block_graph (ir_graph *irg, const char *suffix) construct_block_lists(irg); + /* + * If we are in the interprocedural view, we dump not + * only the requested irg but also all irgs that can be reached + * from irg. + */ for (i = 0; i < get_irp_n_irgs(); i++) { ir_node **arr = ird_get_irg_link(get_irp_irg(i)); if (arr) { @@ -1888,19 +2291,77 @@ dump_ir_block_graph (ir_graph *irg, const char *suffix) vcg_close(f); } -/** dumps a graph with type information */ +/* Dump a firm graph without explicit block nodes but grouped in extended blocks. */ +void dump_ir_extblock_graph (ir_graph *irg, const char *suffix) +{ + FILE *F; + int i; + char *suffix1; + + if (!is_filtered_dump_name(get_entity_ident(get_irg_entity(irg)))) + return; + + compute_extbb(irg); + + if (get_interprocedural_view()) suffix1 = "-ip"; + else suffix1 = ""; + F = vcg_open(irg, suffix, suffix1); + dump_vcg_header(F, get_irg_dump_name(irg), NULL); + + construct_extblock_lists(irg); + + fprintf(F, "graph: { title: \""); + PRINT_IRGID(irg); + fprintf(F, "\" label: \"%s\" status:clustered color:white \n", + get_ent_dump_name(get_irg_entity(irg))); + + for (i = 0; i < get_irp_n_irgs(); i++) { + ir_graph *irg = get_irp_irg(i); + list_tuple *lists = ird_get_irg_link(irg); + + if (lists) { + /* dump the extended blocks first */ + if (ARR_LEN(lists->extbb_list)) { + ird_set_irg_link(irg, lists->extbb_list); + dump_extblock_graph(F, irg); + } + + /* we may have blocks without extended blocks, bad for instance */ + if (ARR_LEN(lists->blk_list)) { + ird_set_irg_link(irg, lists->blk_list); + dump_block_graph(F, irg); + } + + DEL_ARR_F(lists->extbb_list); + DEL_ARR_F(lists->blk_list); + xfree(lists); + } + } + + /* Close the vcg information for the irg */ + fprintf(F, "}\n\n"); + + vcg_close(F); + free_extbb(irg); +} + +/* dumps a graph with type information */ void dump_ir_graph_w_types (ir_graph *irg, const char *suffix) { FILE *f; ir_graph *rem = current_ir_graph; char *suffix1; + int rem_dump_const_local; /* if a filter is set, dump only the irg's that match the filter */ if (!is_filtered_dump_name(get_entity_ident(get_irg_entity(irg)))) return; current_ir_graph = irg; + rem_dump_const_local = dump_const_local; + /* dumping types does not work with local nodes */ + dump_const_local = 0; if (get_interprocedural_view()) suffix1 = "-pure-wtypes-ip"; else suffix1 = "-pure-wtypes"; @@ -1916,6 +2377,7 @@ dump_ir_graph_w_types (ir_graph *irg, const char *suffix) irg_walk(get_irg_end(irg), dump_node2type_edges, NULL, f); vcg_close(f); + dump_const_local = rem_dump_const_local; current_ir_graph = rem; } @@ -1926,11 +2388,16 @@ dump_ir_block_graph_w_types (ir_graph *irg, const char *suffix) int i; char *suffix1; ir_graph *rem = current_ir_graph; + int rem_dump_const_local; /* if a filter is set, dump only the irg's that match the filter */ if (!is_filtered_dump_name(get_entity_ident(get_irg_entity(irg)))) return; + rem_dump_const_local = dump_const_local; + /* dumping types does not work with local nodes */ + dump_const_local = 0; + if (get_interprocedural_view()) suffix1 = "-wtypes-ip"; else suffix1 = "-wtypes"; f = vcg_open(irg, suffix, suffix1); @@ -1955,8 +2422,9 @@ dump_ir_block_graph_w_types (ir_graph *irg, const char *suffix) /* dump edges from graph to type info */ irg_walk(get_irg_end(irg), dump_node2type_edges, NULL, f); - current_ir_graph = rem; vcg_close(f); + dump_const_local = rem_dump_const_local; + current_ir_graph = rem; } /*---------------------------------------------------------------------*/ @@ -1966,7 +2434,7 @@ dump_ir_block_graph_w_types (ir_graph *irg, const char *suffix) static void dump_block_to_cfg(ir_node *block, void *env) { FILE *F = env; - int i, fl; + int i, fl = 0; ir_node *pred; if (is_Block(block)) { @@ -1982,25 +2450,36 @@ dump_block_to_cfg(ir_node *block, void *env) { PRINT_NODEID(block); fprintf (F, "\" "); fprintf(F, "info1:\""); + +#if 0 if (dump_dominator_information_flag) { fprintf(F, "dom depth %d\n", get_Block_dom_depth(block)); fprintf(F, "tree pre num %d\n", get_Block_dom_tree_pre_num(block)); fprintf(F, "max subtree pre num %d\n", get_Block_dom_max_subtree_pre_num(block)); - } + } /* show arity and possible Bad predecessors of the block */ fprintf(F, "arity: %d\n", get_Block_n_cfgpreds(block)); for (fl = i = 0; i < get_Block_n_cfgpreds(block); ++i) { ir_node *pred = get_Block_cfgpred(block, i); if (is_Bad(pred)) { - if (! fl) - fprintf(F, "Bad pred at pos: "); - fprintf(F, "%d ", i); - fl = 1; + if (! fl) + fprintf(F, "Bad pred at pos: "); + fprintf(F, "%d ", i); + fl = 1; } } if (fl) fprintf(F, "\n"); +#else + /* the generic version. */ + dump_irnode_to_file(F, block); + + /* Check whether we have bad predecessors to color the block. */ + for (i = 0; i < get_Block_n_cfgpreds(block); ++i) + if ((fl = is_Bad(get_Block_cfgpred(block, i)))) + break; +#endif fprintf (F, "\""); /* closing quote of info */