3 * File name: ir/ir/irdump.c
4 * Purpose: Write vcg representation of firm to file.
5 * Author: Martin Trapp, Christian Schaefer
6 * Modified by: Goetz Lindenmaier, Hubert Schmidt
9 * Copyright: (c) 1998-2003 Universit�t Karlsruhe
10 * Licence: This file protected by GPL - GNU GENERAL PUBLIC LICENSE.
24 #include "firm_common_t.h"
37 #include "type_or_entity.h"
41 #include "callgraph.h"
42 #include "irextbb_t.h"
43 #include "dbginfo_t.h"
55 extern void dump_irn_chi_term(FILE *FL, ir_node *n);
56 extern void dump_irn_state(FILE *FL, ir_node *n);
57 extern int get_opt_dump_abstvals(void);
58 typedef unsigned long SeqNo;
59 extern SeqNo get_Block_seqno(ir_node *n);
62 /* basis for a color range for vcg */
63 static int n_colors = 0;
64 static int base_color = 0;
66 /** Dump only irgs with names that start with this string */
67 static ident *dump_file_filter_id = NULL;
69 #define ERROR_TXT "<ERROR>"
71 /*******************************************************************/
72 /* flags to steer output */
73 /*******************************************************************/
75 /** An option to turn off edge labels */
76 static int edge_label = 1;
77 /** An option to turn off dumping values of constant entities */
78 static int const_entities = 1;
79 /** An option to dump the keep alive edges */
80 static int dump_keepalive = 0;
81 /** An option to dump ld_names instead of names. */
82 static int dump_ld_name = 1;
83 /** Compiler options to dump analysis information in dump_ir_graph */
84 int dump_out_edge_flag = 0;
85 int dump_dominator_information_flag = 0;
86 int dump_loop_information_flag = 0;
87 int dump_backedge_information_flag = 1;
88 int dump_const_local = 0;
89 bool opt_dump_analysed_type_info = 1;
90 bool opt_dump_pointer_values_to_info = 0; /* default off: for test compares!! */
92 static dumper_colors overrule_nodecolor = ird_color_default;
94 /** An additional edge hook. */
95 static DUMP_NODE_EDGE_FUNC dump_node_edge_hook = NULL;
97 void set_dump_node_edge_hook(DUMP_NODE_EDGE_FUNC func)
99 dump_node_edge_hook = func;
102 DUMP_NODE_EDGE_FUNC get_dump_node_edge_hook(void)
104 return dump_node_edge_hook;
108 /** The vcg node attribute hook. */
109 static DUMP_IR_GRAPH_FUNC dump_ir_graph_hook = NULL;
110 /** The vcg node attribute hook. */
111 static DUMP_NODE_VCGATTR_FUNC dump_node_vcgattr_hook = NULL;
112 /** The vcg edge attribute hook. */
113 static DUMP_EDGE_VCGATTR_FUNC dump_edge_vcgattr_hook = NULL;
115 /* set the ir graph hook */
116 void set_dump_ir_graph_hook(DUMP_IR_GRAPH_FUNC hook) {
117 dump_ir_graph_hook = hook;
119 /* set the node attribute hook */
120 void set_dump_node_vcgattr_hook(DUMP_NODE_VCGATTR_FUNC hook) {
121 dump_node_vcgattr_hook = hook;
123 /* set the edge attribute hook */
124 void set_dump_edge_vcgattr_hook(DUMP_EDGE_VCGATTR_FUNC hook) {
125 dump_edge_vcgattr_hook = hook;
128 INLINE bool get_opt_dump_const_local(void) {
129 if (!dump_out_edge_flag && !dump_loop_information_flag)
130 return dump_const_local;
135 void only_dump_method_with_name(ident *name) {
136 dump_file_filter_id = name;
139 ident *get_dump_file_filter_ident(void) {
140 return dump_file_filter_id;
143 /** Returns true if dump file filter is not set, or if it is a
145 int is_filtered_dump_name(ident *name) {
146 if (!dump_file_filter_id) return 1;
147 return id_is_prefix(dump_file_filter_id, name);
150 /* To turn off display of edge labels. Edge labels often cause xvcg to
151 abort with a segmentation fault. */
152 void turn_off_edge_labels(void) {
156 void dump_consts_local(bool b) {
157 dump_const_local = b;
160 void dump_constant_entity_values(bool b) {
164 void dump_keepalive_edges(bool b) {
168 bool get_opt_dump_keepalive_edges(void) {
169 return dump_keepalive;
172 void dump_out_edges(bool b) {
173 dump_out_edge_flag = b;
176 void dump_dominator_information(bool b) {
177 dump_dominator_information_flag = b;
180 void dump_loop_information(bool b) {
181 dump_loop_information_flag = b;
184 void dump_backedge_information(bool b) {
185 dump_backedge_information_flag = b;
188 /* Dump the information of type field specified in ana/irtypeinfo.h.
189 * If the flag is set, the type name is output in [] in the node label,
190 * else it is output as info.
192 void set_opt_dump_analysed_type_info(bool b) {
193 opt_dump_analysed_type_info = b;
196 void dump_pointer_values_to_info(bool b) {
197 opt_dump_pointer_values_to_info = b;
200 void dump_ld_names(bool b) {
204 /* -------------- some extended helper functions ----------------- */
207 * returns the name of a mode or <ERROR> if mode is NOT a mode object.
208 * in the later case, sets bad
210 const char *get_mode_name_ex(ir_mode *mode, int *bad)
213 return get_mode_name(mode);
219 * returns the name of a type or <ERROR> if mode is NOT a mode object.
220 * in the later case, sets bad
222 const char *get_type_name_ex(type *tp, int *bad)
225 return get_type_name(tp);
231 * printf the VCG color
233 static void print_vcg_color(FILE *F, dumper_colors color) {
234 static const char *color_names[32] = {
235 "white", "blue", "red", "green",
236 "yellow", "magenta", "cyan", "darkgray",
237 "darkblue", "darkred", "darkgreen", "darkyellow",
238 "darkmagenta", "darkcyan", "gold", "lightgray",
239 "lightblue", "lightred", "lightgreen", "lightyellow",
240 "lightmagenta", "lightcyan", "lilac", "turquoise",
241 "aquamarine", "khaki", "purple", "yellowgreen",
242 "pink", "orange", "orchid", "black"
245 if (color != ird_color_default)
246 fprintf(F, "color:%s", color_names[color]);
250 * prints the edge from a type S to a type T with additional info fmt, ...
253 static void print_type_type_edge(FILE *F, type *S, type *T, const char *fmt, ...)
258 fprintf(F, "edge: { sourcename: "); PRINT_TYPEID(S);
259 fprintf(F, " targetname: "); PRINT_TYPEID(T);
260 vfprintf(F, fmt, ap);
266 * prints the edge from a type T to an entity E with additional info fmt, ...
269 static void print_type_ent_edge(FILE *F, type *T, entity *E, const char *fmt, ...)
274 fprintf(F, "edge: { sourcename: "); PRINT_TYPEID(T);
275 fprintf(F, " targetname: \""); PRINT_ENTID(E); fprintf(F, "\"");
276 vfprintf(F, fmt, ap);
282 * prints the edge from an entity E to an entity T with additional info fmt, ...
285 static void print_ent_ent_edge(FILE *F, entity *E, entity *T, int backedge, const char *fmt, ...)
291 fprintf(F, "backedge: { sourcename: \"");
293 fprintf(F, "edge: { sourcename: \"");
295 fprintf(F, "\" targetname: \""); PRINT_ENTID(T); fprintf(F, "\"");
296 vfprintf(F, fmt, ap);
302 * prints the edge from an entity E to a type T with additional info fmt, ...
305 static void print_ent_type_edge(FILE *F, entity *E, type *T, const char *fmt, ...)
310 fprintf(F, "edge: { sourcename: \""); PRINT_ENTID(E);
311 fprintf(F, "\" targetname: "); PRINT_TYPEID(T);
312 vfprintf(F, fmt, ap);
318 * prints the edge from a node N to a type T with additional info fmt, ...
321 static void print_node_type_edge(FILE *F, const ir_node *N, type *T, const char *fmt, ...)
326 fprintf(F, "edge: { sourcename: \""); PRINT_NODEID(N);
327 fprintf(F, "\" targetname: "); PRINT_TYPEID(T);
328 vfprintf(F, fmt, ap);
334 * prints the edge from a node N to an entity E with additional info fmt, ...
337 static void print_node_ent_edge(FILE *F, const ir_node *N, entity *E, const char *fmt, ...)
342 fprintf(F, "edge: { sourcename: \""); PRINT_NODEID(N);
343 fprintf(F, "\" targetname: \""); PRINT_ENTID(E);
345 vfprintf(F, fmt, ap);
351 * prints the edge from an entity E to a node N with additional info fmt, ...
354 static void print_ent_node_edge(FILE *F, entity *E, const ir_node *N, const char *fmt, ...)
359 fprintf(F, "edge: { sourcename: \""); PRINT_ENTID(E);
360 fprintf(F, "\" targetname: \""); PRINT_NODEID(N); fprintf(F, "\"");
361 vfprintf(F, fmt, ap);
367 * prints the edge from a type E to an enumeration item item with additional info fmt, ...
370 static void print_enum_item_edge(FILE *F, type *E, int item, const char *fmt, ...)
375 fprintf(F, "edge: { sourcename: "); PRINT_TYPEID(E);
376 fprintf(F, " targetname: \""); PRINT_ITEMID(E, item); fprintf(F, "\" ");
377 vfprintf(F, fmt, ap);
382 /*-----------------------------------------------------------------*/
383 /* global and ahead declarations */
384 /*-----------------------------------------------------------------*/
386 static void dump_whole_node(ir_node *n, void *env);
387 static INLINE void dump_loop_nodes_into_graph(FILE *F, ir_graph *irg);
389 /*-----------------------------------------------------------------*/
390 /* Helper functions. */
391 /*-----------------------------------------------------------------*/
394 * This map is used as a private link attr to be able to call dumper
395 * anywhere without destroying link fields.
397 static pmap *irdump_link_map = NULL;
399 /** NOT A STANDARD LIBFIRM INIT METHOD
401 * We do not want to integrate dumping into libfirm, i.e., if the dumpers
402 * are off, we want to have as few interferences as possible. Therefore the
403 * initialization is performed lazily and not called from within init_firm.
405 * Creates the link attribute map. */
406 static void init_irdump(void) {
407 /* We need a new, empty map. */
408 if (irdump_link_map) pmap_destroy(irdump_link_map);
409 irdump_link_map = pmap_create();
410 if (!dump_file_filter_id)
411 dump_file_filter_id = new_id_from_str("");
414 * Returns the private link field.
416 static void *ird_get_irn_link(ir_node *n) {
418 if (!irdump_link_map) return NULL;
420 if (pmap_contains(irdump_link_map, (void *)n))
421 res = pmap_get(irdump_link_map, (void *)n);
426 * Sets the private link field.
428 static void ird_set_irn_link(ir_node *n, void *x) {
429 if (!irdump_link_map)
431 pmap_insert(irdump_link_map, (void *)n, x);
435 * Gets the private link field of an irg.
437 static void *ird_get_irg_link(ir_graph *irg) {
439 if (!irdump_link_map) return NULL;
441 if (pmap_contains(irdump_link_map, (void *)irg))
442 res = pmap_get(irdump_link_map, (void *)irg);
447 * Sets the private link field of an irg.
449 static void ird_set_irg_link(ir_graph *irg, void *x) {
450 if (!irdump_link_map) init_irdump();
451 pmap_insert(irdump_link_map, (void *)irg, x);
455 * Walker, clears the private link field.
457 static void clear_link(ir_node * node, void * env) {
458 ird_set_irn_link(node, NULL);
462 * If the entity has a ld_name, returns it if the dump_ld_name is set,
463 * else returns the name of the entity.
465 static const char *_get_ent_dump_name(entity *ent, int dump_ld_name) {
467 return "<NULL entity>";
469 /* Don't use get_entity_ld_ident (ent) as it computes the mangled name! */
470 if (ent->ld_name) return get_id_str(ent->ld_name);
472 return get_id_str(ent->name);
476 * If the entity has a ld_name, returns it if the option dump_ld_name is set,
477 * else returns the name of the entity.
479 const char *get_ent_dump_name(entity *ent) {
480 return _get_ent_dump_name(ent, dump_ld_name);
483 /* Returns the name of an IRG. */
484 const char *get_irg_dump_name(ir_graph *irg) {
485 /* Don't use get_entity_ld_ident (ent) as it computes the mangled name! */
486 return _get_ent_dump_name(get_irg_entity(irg), 1);
490 * Returns non-zero if a node is in floating state.
492 static int node_floats(ir_node *n) {
493 return ((get_irn_pinned(n) == op_pin_state_floats) &&
494 (get_irg_pinned(current_ir_graph) == op_pin_state_floats));
498 * Walker, allocates an array for all blocks and puts it's nodes non-floating nodes into this array.
500 static void collect_node(ir_node * node, void *env) {
503 || get_irn_op(node) == op_Bad
504 || get_irn_op(node) == op_Unknown
505 || get_irn_op(node) == op_NoMem) {
506 ir_node ** arr = (ir_node **) ird_get_irg_link(get_irn_irg(node));
507 if (!arr) arr = NEW_ARR_F(ir_node *, 0);
508 ARR_APP1(ir_node *, arr, node);
509 ird_set_irg_link(get_irn_irg(node), arr); /* arr is an l-value, APP_ARR might change it! */
511 ir_node * block = get_nodes_block(node);
514 /* this node is in a Bad block, so we must place it into the graph's list */
515 ir_node ** arr = (ir_node **) ird_get_irg_link(get_irn_irg(node));
516 if (!arr) arr = NEW_ARR_F(ir_node *, 0);
517 ARR_APP1(ir_node *, arr, node);
518 ird_set_irg_link(get_irn_irg(node), arr); /* arr is an l-value, APP_ARR might change it! */
521 ird_set_irn_link(node, ird_get_irn_link(block));
522 ird_set_irn_link(block, node);
527 /** Construct lists to walk ir block-wise.
529 * Collects all blocks, nodes not op_pin_state_pinned,
530 * Bad, NoMem and Unknown into a flexible array in link field of
531 * irg they belong to. Sets the irg link field to NULL in all
532 * graphs not visited.
533 * Free the list with DEL_ARR_F().
535 static ir_node **construct_block_lists(ir_graph *irg) {
536 int i, rem_view = get_interprocedural_view();
537 ir_graph *rem = current_ir_graph;
538 current_ir_graph = irg;
540 for (i = 0; i < get_irp_n_irgs(); i++)
541 ird_set_irg_link(get_irp_irg(i), NULL);
543 irg_walk_graph(current_ir_graph, clear_link, collect_node, current_ir_graph);
545 /* Collect also EndReg and EndExcept. We do not want to change the walker. */
546 set_interprocedural_view(false);
548 set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph)-1);
549 irg_walk(get_irg_end_reg(current_ir_graph), clear_link, collect_node, current_ir_graph);
550 set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph)-1);
551 irg_walk(get_irg_end_except(current_ir_graph), clear_link, collect_node, current_ir_graph);
553 set_interprocedural_view(rem_view);
555 current_ir_graph = rem;
556 return ird_get_irg_link(irg);
559 typedef struct _list_tuple {
561 ir_extblk **extbb_list;
564 /** Construct lists to walk ir extended block-wise.
565 * Free the lists in the tuple with DEL_ARR_F().
567 static list_tuple *construct_extblock_lists(ir_graph *irg) {
568 ir_node **blk_list = construct_block_lists(irg);
570 ir_graph *rem = current_ir_graph;
571 list_tuple *lists = xmalloc(sizeof(*lists));
573 current_ir_graph = irg;
575 lists->blk_list = NEW_ARR_F(ir_node *, 0);
576 lists->extbb_list = NEW_ARR_F(ir_extblk *, 0);
578 for (i = ARR_LEN(blk_list) - 1; i >= 0; --i) {
581 if (is_Block(blk_list[i])) {
582 ext = get_Block_extbb(blk_list[i]);
584 if (extbb_not_visited(ext)) {
585 ARR_APP1(ir_extblk *, lists->extbb_list, ext);
586 mark_extbb_visited(ext);
590 ARR_APP1(ir_node *, lists->blk_list, blk_list[i]);
593 current_ir_graph = rem;
595 ird_set_irg_link(irg, lists);
599 /*-----------------------------------------------------------------*/
600 /* Routines to dump information about a single ir node. */
601 /*-----------------------------------------------------------------*/
604 * dump the name of a node n to the File F.
606 int dump_node_opcode(FILE *F, ir_node *n)
609 const ir_op_ops *ops = get_op_ops(get_irn_op(n));
611 /* call the dump_node operation if available */
613 return ops->dump_node(n, F, dump_node_opcode_txt);
615 /* implementation for default nodes */
616 switch (get_irn_opcode(n)) {
621 res = tarval_snprintf(buf, sizeof(buf), get_Const_tarval(n));
622 assert(res < sizeof(buf) && "buffer to small for tarval_snprintf");
627 if (get_SymConst_kind(n) == symconst_addr_name) {
628 /* don't use get_SymConst_ptr_info as it mangles the name. */
629 fprintf (F, "SymC %s", get_id_str(get_SymConst_name(n)));
630 } else if (get_SymConst_kind(n) == symconst_addr_ent) {
631 assert(get_SymConst_entity(n));
632 assert(is_entity(get_SymConst_entity(n)));
633 fprintf (F, "SymC &%s", get_entity_name(get_SymConst_entity(n)));
635 assert(get_kind(get_SymConst_type(n)) == k_type);
636 assert(get_type_ident(get_SymConst_type(n)));
637 fprintf (F, "SymC %s ", get_type_name_ex(get_SymConst_type(n), &bad));
638 if (get_SymConst_kind(n) == symconst_type_tag)
646 if (!get_interprocedural_view())
653 ir_node *pred = get_Proj_pred(n);
655 if (get_irn_opcode(pred) == iro_Cond
656 && get_Proj_proj(n) == get_Cond_defaultProj(pred)
657 && get_irn_mode(get_Cond_selector(pred)) != mode_b)
658 fprintf (F, "defProj");
666 if (get_interprocedural_view()) {
667 fprintf(F, "%s %s", get_irn_opname(n), get_ent_dump_name(get_irg_entity(get_irn_irg(n))));
672 case iro_CallBegin: {
673 ir_node *addr = get_CallBegin_ptr(n);
675 if (get_irn_op(addr) == op_Sel)
676 ent = get_Sel_entity(addr);
677 else if ((get_irn_op(addr) == op_SymConst) && (get_SymConst_kind(addr) == symconst_addr_ent))
678 ent = get_SymConst_entity(addr);
679 fprintf (F, "%s", get_irn_opname(n));
680 if (ent) fprintf (F, " %s", get_entity_name(ent));
684 fprintf (F, "%s[%s]", get_irn_opname(n), get_mode_name_ex(get_Load_mode(n), &bad));
687 fprintf (F, "%s%s", is_Block_dead(n) ? "Dead " : "", get_irn_opname(n));
692 fprintf (F, "%s", get_irn_opname(n));
699 * Dump the mode of a node n to a file F.
700 * Ignore modes that are "always known".
702 static int dump_node_mode(FILE *F, ir_node *n)
705 const ir_op_ops *ops = get_op_ops(get_irn_op(n));
708 /* call the dump_node operation if available */
710 return ops->dump_node(n, F, dump_node_mode_txt);
712 /* default implementation */
713 iro = get_irn_opcode(n);
725 ir_mode *mode = get_irn_mode(n);
727 if (mode && mode != mode_BB && mode != mode_ANY && mode != mode_BAD &&
728 (mode != mode_T || iro == iro_Proj))
729 fprintf(F, "%s", get_mode_name_ex(mode, &bad));
737 * Dump the type of a node n to a file F if it's known.
739 static int dump_node_typeinfo(FILE *F, ir_node *n) {
742 if (opt_dump_analysed_type_info) {
743 if (get_irg_typeinfo_state(current_ir_graph) == ir_typeinfo_consistent ||
744 get_irg_typeinfo_state(current_ir_graph) == ir_typeinfo_inconsistent) {
745 type *tp = get_irn_typeinfo_type(n);
746 if (tp != firm_none_type)
747 fprintf(F, "[%s] ", get_type_name_ex(tp, &bad));
755 typedef struct _pns_lookup {
756 long nr; /**< the proj number */
757 const char *name; /**< the name of the Proj */
760 typedef struct _proj_lookup {
761 opcode code; /**< the opcode of the Proj predecessor */
762 unsigned num_data; /**< number of data entries */
763 const pns_lookup_t *data; /**< the data */
766 #define ARR_SIZE(a) (sizeof(a)/sizeof(a[0]))
768 /** the lookup table for Proj(Start) names */
769 static const pns_lookup_t start_lut[] = {
770 #define X(a) { pn_Start_##a, #a }
779 /** the lookup table for Proj(Cond) names */
780 static const pns_lookup_t cond_lut[] = {
781 #define X(a) { pn_Cond_##a, #a }
787 /** the lookup table for Proj(Call) names */
788 static const pns_lookup_t call_lut[] = {
789 #define X(a) { pn_Call_##a, #a }
798 /** the lookup table for Proj(Quot) names */
799 static const pns_lookup_t quot_lut[] = {
800 #define X(a) { pn_Quot_##a, #a }
807 /** the lookup table for Proj(DivMod) names */
808 static const pns_lookup_t divmod_lut[] = {
809 #define X(a) { pn_DivMod_##a, #a }
817 /** the lookup table for Proj(Div) names */
818 static const pns_lookup_t div_lut[] = {
819 #define X(a) { pn_Div_##a, #a }
826 /** the lookup table for Proj(Mod) names */
827 static const pns_lookup_t mod_lut[] = {
828 #define X(a) { pn_Mod_##a, #a }
835 /** the lookup table for Proj(Load) names */
836 static const pns_lookup_t load_lut[] = {
837 #define X(a) { pn_Load_##a, #a }
844 /** the lookup table for Proj(Store) names */
845 static const pns_lookup_t store_lut[] = {
846 #define X(a) { pn_Store_##a, #a }
852 /** the lookup table for Proj(Alloc) names */
853 static const pns_lookup_t alloc_lut[] = {
854 #define X(a) { pn_Alloc_##a, #a }
862 /** the Proj lookup table */
863 static const proj_lookup_t proj_lut[] = {
864 #define E(a) ARR_SIZE(a), a
865 { iro_Start, E(start_lut) },
866 { iro_Cond, E(cond_lut) },
867 { iro_Call, E(call_lut) },
868 { iro_Quot, E(quot_lut) },
869 { iro_DivMod, E(divmod_lut) },
870 { iro_Div, E(div_lut) },
871 { iro_Mod, E(mod_lut) },
872 { iro_Load, E(load_lut) },
873 { iro_Store, E(store_lut) },
874 { iro_Alloc, E(alloc_lut) }
879 * Dump additional node attributes of some nodes to a file F.
882 dump_node_nodeattr(FILE *F, ir_node *n)
888 const ir_op_ops *ops = get_op_ops(get_irn_op(n));
890 /* call the dump_node operation if available */
892 return ops->dump_node(n, F, dump_node_nodeattr_txt);
894 switch (get_irn_opcode(n)) {
896 if (false && get_interprocedural_view()) {
897 fprintf (F, "%s ", get_ent_dump_name(get_irg_entity(current_ir_graph)));
902 pred = get_Proj_pred(n);
903 proj_nr = get_Proj_proj(n);
905 code = get_irn_opcode(pred);
908 fprintf (F, "%s ", get_pnc_string(get_Proj_proj(n)));
909 else if (code == iro_Proj && get_irn_opcode(get_Proj_pred(pred)) == iro_Start)
910 fprintf (F, "Arg %ld ", proj_nr);
912 unsigned i, j, f = 0;
914 for (i = 0; i < ARR_SIZE(proj_lut); ++i) {
915 if (code == proj_lut[i].code) {
916 for (j = 0; j < proj_lut[i].num_data; ++j) {
917 if (proj_nr == proj_lut[i].data[j].nr) {
918 fprintf (F, "%s ", proj_lut[i].data[j].name);
927 fprintf (F, "%ld ", proj_nr);
928 if (code == iro_Cond && get_Cond_jmp_pred(pred) != COND_JMP_PRED_NONE) {
929 if (proj_nr == pn_Cond_false && get_Cond_jmp_pred(pred) == COND_JMP_PRED_FALSE)
931 if (proj_nr == pn_Cond_true && get_Cond_jmp_pred(pred) == COND_JMP_PRED_TRUE)
937 proj_nr = get_Filter_proj(n);
938 if (! get_interprocedural_view()) {
940 pred = get_Filter_pred(n);
944 fprintf (F, "%ld ", proj_nr);
947 fprintf (F, "%s ", get_ent_dump_name(get_Sel_entity(n)));
950 fprintf (F, "(%s) ", get_type_name_ex(get_Cast_type(n), &bad));
953 fprintf (F, "%s ", get_pnc_string(get_Confirm_cmp(n)));
956 fprintf (F, "(%s) ", get_type_name_ex(get_CopyB_type(n), &bad));
967 #include "execution_frequency.h"
968 #include "callgraph.h"
970 void dump_node_ana_vals(FILE *F, ir_node *n) {
972 fprintf(F, " %lf*(%2.0lf + %2.0lf) = %2.0lf ",
973 get_irn_exec_freq(n),
974 get_irg_method_execution_frequency(get_irn_irg(n)),
975 pow(5, get_irg_recursion_depth(get_irn_irg(n))),
976 get_irn_exec_freq(n) * (get_irg_method_execution_frequency(get_irn_irg(n)) + pow(5, get_irg_recursion_depth(get_irn_irg(n))))
981 /* Dumps a node label without the enclosing ". */
982 int dump_node_label(FILE *F, ir_node *n) {
985 bad |= dump_node_opcode(F, n);
986 bad |= dump_node_mode(F, n);
988 bad |= dump_node_typeinfo(F, n);
989 bad |= dump_node_nodeattr(F, n);
990 fprintf(F, "%ld", get_irn_node_nr(n));
997 * Dumps the attributes of a node n into the file F.
998 * Currently this is only the color of a node.
1000 static void dump_node_vcgattr(FILE *F, ir_node *node, ir_node *local, int bad)
1005 print_vcg_color(F, ird_color_red);
1009 if (dump_node_vcgattr_hook)
1010 if (dump_node_vcgattr_hook(F, node, local))
1013 n = local ? local : node;
1015 if (overrule_nodecolor != ird_color_default) {
1016 print_vcg_color(F, overrule_nodecolor);
1020 switch (get_irn_opcode(n)) {
1027 print_vcg_color(F, ird_color_blue);
1030 if (is_Block_dead(n))
1031 print_vcg_color(F, ird_color_lightred);
1033 print_vcg_color(F, ird_color_lightyellow);
1036 print_vcg_color(F, ird_color_green);
1042 print_vcg_color(F, ird_color_yellow);
1045 PRINT_DEFAULT_NODE_ATTR;
1051 * Dump the node information of a node n to a file F.
1053 static INLINE int dump_node_info(FILE *F, ir_node *n)
1055 fprintf (F, " info1: \"");
1056 bad = dump_irnode_to_file(F, n);
1062 * checks whether a node is "constant-like" ie can be treated "block-less"
1065 bool is_constlike_node(ir_node *n) {
1066 ir_op *op = get_irn_op(n);
1067 return (op == op_Const || op == op_Bad || op == op_NoMem || op == op_SymConst || op == op_Unknown);
1071 /** outputs the predecessors of n, that are constants, local. I.e.,
1072 generates a copy of the constant predecessors for each node called with. */
1073 static void dump_const_node_local(FILE *F, ir_node *n) {
1075 if (!get_opt_dump_const_local()) return;
1077 /* Use visited flag to avoid outputting nodes twice.
1078 initialize it first. */
1079 for (i = 0; i < get_irn_arity(n); i++) {
1080 ir_node *con = get_irn_n(n, i);
1081 if (is_constlike_node(con)) {
1082 set_irn_visited(con, get_irg_visited(current_ir_graph) - 1);
1086 for (i = 0; i < get_irn_arity(n); i++) {
1087 ir_node *con = get_irn_n(n, i);
1088 if (is_constlike_node(con) && irn_not_visited(con)) {
1091 mark_irn_visited(con);
1092 /* Generate a new name for the node by appending the names of
1094 fprintf(F, "node: {title: "); PRINT_CONSTID(n, con);
1095 fprintf(F, " label: \"");
1096 bad |= dump_node_label(F, con);
1098 bad |= dump_node_info(F, con);
1099 dump_node_vcgattr(F, n, con, bad);
1105 /** If the block of an edge is a const_like node, dump it local with an edge */
1106 static void dump_const_block_local(FILE *F, ir_node *n) {
1109 if (!get_opt_dump_const_local()) return;
1111 blk = get_nodes_block(n);
1112 if (is_constlike_node(blk)) {
1115 /* Generate a new name for the node by appending the names of
1117 fprintf(F, "node: {title: \""); PRINT_CONSTBLKID(n, blk);
1118 fprintf(F, "\" label: \"");
1119 bad |= dump_node_label(F, blk);
1121 bad |= dump_node_info(F, blk);
1122 dump_node_vcgattr(F, n, blk, bad);
1125 fprintf (F, "edge: { sourcename: \"");
1127 fprintf (F, "\" targetname: \""); PRINT_CONSTBLKID(n,blk);
1129 if (dump_edge_vcgattr_hook) {
1131 if (dump_edge_vcgattr_hook(F, n, -1)) {
1136 fprintf (F, " " BLOCK_EDGE_ATTR "}\n");
1141 fprintf (F, "\" " BLOCK_EDGE_ATTR "}\n");
1146 * prints the error message of a node to a file F as info2.
1148 static void INLINE print_node_error(FILE *F, const char *err_msg)
1153 fprintf (F, " info2: \"%s\"", err_msg);
1157 * prints debug messages of a node to file F as info3.
1159 static void print_dbg_info(FILE *F, dbg_info *dbg)
1163 if (__dbg_info_snprint) {
1165 if (__dbg_info_snprint(buf, sizeof(buf), dbg) > 0)
1166 fprintf (F, " info3: \"%s\"\n", buf);
1173 static void dump_node(FILE *F, ir_node *n)
1178 if (get_opt_dump_const_local() && is_constlike_node(n))
1181 /* dump this node */
1182 fprintf(F, "node: {title: \""); PRINT_NODEID(n); fprintf(F, "\" label: \"");
1184 bad = ! irn_vrfy_irg_dump(n, current_ir_graph, &p);
1185 bad |= dump_node_label(F, n);
1186 dump_node_ana_vals(F, n);
1187 //dump_node_ana_info(F, n);
1189 bad |= dump_node_info(F, n);
1190 print_node_error(F, p);
1191 print_dbg_info(F, get_irn_dbg_info(n));
1192 dump_node_vcgattr(F, n, NULL, bad);
1194 dump_const_node_local(F, n);
1196 if(dump_node_edge_hook)
1197 dump_node_edge_hook(F, n);
1199 dump_irn_chi_term(F, n);
1200 dump_irn_state(F, n);
1204 /** dump the edge to the block this node belongs to */
1206 dump_ir_block_edge(FILE *F, ir_node *n) {
1207 if (get_opt_dump_const_local() && is_constlike_node(n)) return;
1208 if (is_no_Block(n)) {
1209 ir_node *block = get_nodes_block(n);
1211 if (get_opt_dump_const_local() && is_constlike_node(block)) {
1212 dump_const_block_local(F, n);
1215 fprintf (F, "edge: { sourcename: \"");
1217 fprintf (F, "\" targetname: ");
1218 fprintf(F, "\""); PRINT_NODEID(block); fprintf(F, "\"");
1220 if (dump_edge_vcgattr_hook) {
1222 if (dump_edge_vcgattr_hook(F, n, -1)) {
1227 fprintf (F, " " BLOCK_EDGE_ATTR "}\n");
1232 fprintf (F, " " BLOCK_EDGE_ATTR "}\n");
1238 print_data_edge_vcgattr(FILE *F, ir_node *from, int to) {
1240 * do not use get_nodes_block() here, will fail
1241 * if the irg is not pinned.
1243 if (get_irn_n(from, -1) == get_irn_n(get_irn_n(from, to), -1))
1244 fprintf (F, INTRA_DATA_EDGE_ATTR);
1246 fprintf (F, INTER_DATA_EDGE_ATTR);
1250 print_mem_edge_vcgattr(FILE *F, ir_node *from, int to) {
1252 * do not use get_nodes_block() here, will fail
1253 * if the irg is not pinned.
1255 if (get_irn_n(from, -1) == get_irn_n(get_irn_n(from, to), -1))
1256 fprintf (F, INTRA_MEM_EDGE_ATTR);
1258 fprintf (F, INTER_MEM_EDGE_ATTR);
1262 print_edge_vcgattr(FILE *F, ir_node *from, int to) {
1265 if (dump_edge_vcgattr_hook)
1266 if (dump_edge_vcgattr_hook(F, from, to))
1269 if (dump_backedge_information_flag && is_backedge(from, to))
1270 fprintf (F, BACK_EDGE_ATTR);
1272 switch (get_irn_opcode(from)) {
1274 fprintf (F, CF_EDGE_ATTR);
1276 case iro_Start: break;
1279 if (get_irn_mode(get_End_keepalive(from, to)) == mode_BB)
1280 fprintf (F, CF_EDGE_ATTR);
1281 if (get_irn_mode(get_End_keepalive(from, to)) == mode_X)
1282 fprintf (F, INTER_MEM_EDGE_ATTR);
1290 print_data_edge_vcgattr(F, from, to);
1295 print_mem_edge_vcgattr(F, from, to);
1297 print_data_edge_vcgattr(F, from, to);
1301 print_data_edge_vcgattr(F, from, to);
1306 print_mem_edge_vcgattr(F, from, to);
1308 print_data_edge_vcgattr(F, from, to);
1315 print_data_edge_vcgattr(F, from, to);
1322 print_mem_edge_vcgattr(F, from, to);
1324 print_data_edge_vcgattr(F, from, to);
1336 print_data_edge_vcgattr(F, from, to);
1339 if (get_irn_modecode(from) == irm_M)
1340 fprintf (F, INTER_MEM_EDGE_ATTR);
1342 print_data_edge_vcgattr(F, from, to);
1349 print_mem_edge_vcgattr(F, from, to);
1351 print_data_edge_vcgattr(F, from, to);
1354 print_mem_edge_vcgattr(F, from, to);
1356 case iro_Tuple: break;
1359 switch (get_irn_modecode(from)) {
1361 fprintf (F, CF_EDGE_ATTR);
1364 fprintf (F, INTER_MEM_EDGE_ATTR);
1367 print_data_edge_vcgattr(F, from, to);
1371 case iro_Bad: break;
1372 case iro_Unknown: break;
1374 switch (get_irn_modecode(from)) {
1376 fprintf (F, INTRA_MEM_EDGE_ATTR);
1379 fprintf (F, CF_EDGE_ATTR);
1382 print_data_edge_vcgattr(F, from, to);
1390 /* dump edges to our inputs */
1392 dump_ir_data_edges(FILE *F, ir_node *n) {
1394 unsigned long visited = get_irn_visited(n);
1396 if ((get_irn_op(n) == op_End) && (!dump_keepalive))
1399 for (i = 0; i < get_irn_arity(n); i++) {
1400 ir_node * pred = get_irn_n(n, i);
1403 if ((get_interprocedural_view() && get_irn_visited(pred) < visited))
1404 continue; /* pred not dumped */
1406 if (dump_backedge_information_flag && is_backedge(n, i))
1407 fprintf (F, "backedge: {sourcename: \"");
1409 fprintf (F, "edge: {sourcename: \"");
1411 fprintf (F, "\" targetname: ");
1412 if ((get_opt_dump_const_local()) && is_constlike_node(pred)) {
1413 PRINT_CONSTID(n, pred);
1415 fprintf(F, "\""); PRINT_NODEID(pred); fprintf(F, "\"");
1417 fprintf (F, " label: \"%d\" ", i);
1418 print_edge_vcgattr(F, n, i);
1423 /** Dumps a node and its edges but not the block edge
1426 dump_node_wo_blockedge (ir_node *n, void *env) {
1429 dump_ir_data_edges(F, n);
1432 /** Dumps a node and its edges.
1435 dump_whole_node (ir_node *n, void *env) {
1437 dump_node_wo_blockedge(n, env);
1438 if (!node_floats(n)) dump_ir_block_edge(F, n);
1442 dump_const_node(ir_node *n, void *env) {
1443 if (is_Block(n)) return;
1444 dump_node_wo_blockedge(n, env);
1447 /***********************************************************************/
1448 /* the following routines dump the nodes/irgs bracketed to graphs. */
1449 /***********************************************************************/
1451 /** Dumps a constant expression as entity initializer, array bound ...
1453 static void dump_const_expression(FILE *F, ir_node *value) {
1454 ir_graph *rem = current_ir_graph;
1455 int rem_dump_const_local = dump_const_local;
1456 dump_const_local = 0;
1457 current_ir_graph = get_const_code_irg();
1458 irg_walk(value, dump_const_node, NULL, F);
1459 /* Decrease visited flag so that we walk with the same flag for the next
1460 expression. This guarantees that we don't dump the same node twice,
1461 as for const expressions cse is performed to save memory. */
1462 set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph) -1);
1463 current_ir_graph = rem;
1464 dump_const_local = rem_dump_const_local;
1467 /** Dump a block as graph containing its nodes.
1469 * Expects to find nodes belonging to the block as list in its
1471 * Dumps the edges of all nodes including itself. */
1473 dump_whole_block(FILE *F, ir_node *block) {
1475 dumper_colors color = ird_color_yellow;
1477 assert(is_Block(block));
1479 fprintf(F, "graph: { title: \"");
1480 PRINT_NODEID(block);
1481 fprintf(F, "\" label: \"");
1482 dump_node_label(F, block);
1484 if (get_opt_dump_abstvals())
1485 fprintf (F, " seqno: %d", (int)get_Block_seqno(block));
1488 /* colorize blocks */
1489 if (! get_Block_matured(block))
1490 color = ird_color_red;
1491 if (is_Block_dead(block))
1492 color = ird_color_orange;
1494 fprintf(F, "\" status:clustered ");
1495 print_vcg_color(F, color);
1498 /* yComp can show attributes for blocks, XVCG parses but ignores them */
1499 dump_node_info(F, block);
1500 print_dbg_info(F, get_irn_dbg_info(block));
1502 /* dump the blocks edges */
1503 dump_ir_data_edges(F, block);
1505 /* dump the nodes that go into the block */
1506 for (node = ird_get_irn_link(block); node; node = ird_get_irn_link(node)) {
1508 dump_ir_data_edges(F, node);
1511 /* Close the vcg information for the block */
1513 dump_const_node_local(F, block);
1515 dump_irn_chi_term(F, block);
1520 /** dumps a graph block-wise. Expects all blockless nodes in arr in irgs link.
1521 * The outermost nodes: blocks and nodes not op_pin_state_pinned, Bad, Unknown. */
1523 dump_block_graph(FILE *F, ir_graph *irg) {
1525 ir_graph *rem = current_ir_graph;
1526 ir_node **arr = ird_get_irg_link(irg);
1527 current_ir_graph = irg;
1529 for (i = ARR_LEN(arr) - 1; i >= 0; --i) {
1530 ir_node * node = arr[i];
1531 if (is_Block(node)) {
1532 /* Dumps the block and all the nodes in the block, which are to
1533 be found in Block->link. */
1534 dump_whole_block(F, node);
1536 /* Nodes that are not in a Block. */
1538 if (!node_floats(node) && is_Bad(get_nodes_block(node))) {
1539 dump_const_block_local(F, node);
1541 dump_ir_data_edges(F, node);
1545 if (dump_loop_information_flag && (get_irg_loopinfo_state(irg) & loopinfo_valid))
1546 dump_loop_nodes_into_graph(F, irg);
1548 current_ir_graph = rem;
1552 * Dump the info for an irg.
1553 * Parsed by XVCG but not shown. use yComp.
1555 static void dump_graph_info(FILE *F, ir_graph *irg) {
1556 fprintf(F, "info1: \"");
1557 dump_entity_to_file(F, get_irg_entity(irg), dump_verbosity_entattrs | dump_verbosity_entconsts);
1561 /** Dumps an irg as a graph clustered by block nodes.
1562 * If interprocedural view edges can point to nodes out of this graph.
1564 static void dump_graph_from_list(FILE *F, ir_graph *irg) {
1565 entity *ent = get_irg_entity(irg);
1567 fprintf(F, "graph: { title: \"");
1569 fprintf(F, "\" label: \"%s\" status:clustered color:white \n",
1570 get_ent_dump_name(ent));
1572 dump_graph_info(F, irg);
1573 print_dbg_info(F, get_entity_dbg_info(ent));
1575 dump_block_graph(F, irg);
1577 /* Close the vcg information for the irg */
1578 fprintf(F, "}\n\n");
1581 /** dumps a graph extended block-wise. Expects all blockless nodes in arr in irgs link.
1582 * The outermost nodes: blocks and nodes not op_pin_state_pinned, Bad, Unknown. */
1584 dump_extblock_graph(FILE *F, ir_graph *irg) {
1586 ir_graph *rem = current_ir_graph;
1587 ir_extblk **arr = ird_get_irg_link(irg);
1588 current_ir_graph = irg;
1591 for (i = ARR_LEN(arr) - 1; i >= 0; --i) {
1592 ir_extblk *extbb = arr[i];
1593 ir_node *leader = get_extbb_leader(extbb);
1596 fprintf(F, "graph: { title: \"");
1597 PRINT_EXTBBID(leader);
1598 fprintf(F, "\" label: \"ExtBB %ld\" status:clustered color:lightgreen\n",
1599 get_irn_node_nr(leader));
1601 for (j = ARR_LEN(extbb->blks) - 1; j >= 0; --j) {
1602 ir_node * node = extbb->blks[j];
1603 if (is_Block(node)) {
1604 /* Dumps the block and all the nodes in the block, which are to
1605 be found in Block->link. */
1606 dump_whole_block(F, node);
1608 /* Nodes that are not in a Block. */
1610 if (is_Bad(get_nodes_block(node)) && !node_floats(node)) {
1611 dump_const_block_local(F, node);
1613 dump_ir_data_edges(F, node);
1619 if (dump_loop_information_flag && (get_irg_loopinfo_state(irg) & loopinfo_valid))
1620 dump_loop_nodes_into_graph(F, irg);
1622 current_ir_graph = rem;
1627 /*******************************************************************/
1628 /* Basic type and entity nodes and edges. */
1629 /*******************************************************************/
1631 /** dumps the edges between nodes and their type or entity attributes. */
1632 static void dump_node2type_edges(ir_node *n, void *env)
1637 switch (get_irn_opcode(n)) {
1639 /* @@@ some consts have an entity */
1642 if ( (get_SymConst_kind(n) ==symconst_type_tag)
1643 || (get_SymConst_kind(n) ==symconst_size))
1645 print_node_type_edge(F,n,get_SymConst_type(n),NODE2TYPE_EDGE_ATTR);
1649 print_node_ent_edge(F,n,get_Sel_entity(n),NODE2TYPE_EDGE_ATTR);
1652 print_node_type_edge(F,n,get_Call_type(n),NODE2TYPE_EDGE_ATTR);
1655 print_node_type_edge(F,n,get_Alloc_type(n),NODE2TYPE_EDGE_ATTR);
1658 print_node_type_edge(F,n,get_Free_type(n),NODE2TYPE_EDGE_ATTR);
1661 print_node_type_edge(F,n,get_Cast_type(n),NODE2TYPE_EDGE_ATTR);
1669 static int print_type_info(FILE *F, type *tp) {
1672 if (get_type_state(tp) == layout_undefined) {
1673 fprintf(F, "state: layout_undefined\n");
1675 fprintf(F, "state: layout_fixed,\n");
1677 if (get_type_mode(tp))
1678 fprintf(F, "mode: %s,\n", get_mode_name_ex(get_type_mode(tp), &bad));
1679 fprintf(F, "size: %db,\n", get_type_size_bits(tp));
1684 static void print_typespecific_info(FILE *F, type *tp) {
1685 switch (get_type_tpop_code(tp)) {
1688 fprintf(F, "peculiarity: %s\n", get_peculiarity_string(get_class_peculiarity(tp)));
1695 fprintf(F, "variadicity: %s\n", get_variadicity_name(get_method_variadicity(tp)));
1696 fprintf(F, "params: %d\n", get_method_n_params(tp));
1697 fprintf(F, "results: %d\n", get_method_n_ress(tp));
1705 case tpo_enumeration:
1719 static void print_typespecific_vcgattr(FILE *F, type *tp) {
1720 switch (get_type_tpop_code(tp)) {
1723 if (peculiarity_existent == get_class_peculiarity(tp))
1724 fprintf (F, " " TYPE_CLASS_NODE_ATTR);
1726 fprintf (F, " " TYPE_DESCRIPTION_NODE_ATTR);
1730 fprintf (F, " " TYPE_METH_NODE_ATTR);
1741 case tpo_enumeration:
1755 int dump_type_node(FILE *F, type *tp)
1759 fprintf (F, "node: {title: ");
1761 fprintf (F, " label: \"%s %s\"", get_type_tpop_name(tp), get_type_name_ex(tp, &bad));
1762 fprintf (F, " info1: \"");
1764 bad |= print_type_info(F, tp);
1765 print_typespecific_info(F, tp);
1767 dump_type_to_file(F, tp, dump_verbosity_max);
1769 fprintf (F, "\"\n");
1770 print_dbg_info(F, get_type_dbg_info(tp));
1771 print_typespecific_vcgattr(F, tp);
1778 #define X(a) case a: fprintf(F, #a); break
1779 void dump_entity_node(FILE *F, entity *ent, int color)
1781 fprintf (F, "node: {title: \"");
1782 PRINT_ENTID(ent); fprintf(F, "\"");
1783 fprintf (F, DEFAULT_TYPE_ATTRIBUTE);
1784 fprintf (F, "label: ");
1785 fprintf (F, "\"ent %s\" ", get_ent_dump_name(ent));
1787 fprintf(F, "color:%d", color);
1789 fprintf (F, ENTITY_NODE_ATTR);
1790 fprintf (F, "\n info1: \"");
1792 dump_entity_to_file(F, ent, dump_verbosity_entattrs | dump_verbosity_entconsts);
1795 print_dbg_info(F, get_entity_dbg_info(ent));
1800 static void dump_enum_item(FILE *F, type *tp, int pos)
1803 ident *id = get_enumeration_nameid(tp, pos);
1804 tarval *tv = get_enumeration_enum(tp, pos);
1806 tarval_snprintf(buf, sizeof(buf), tv);
1807 fprintf (F, "node: {title: \"");
1808 PRINT_ITEMID(tp, pos); fprintf(F, "\"");
1809 fprintf (F, DEFAULT_ENUM_ITEM_ATTRIBUTE);
1810 fprintf (F, "label: ");
1811 fprintf (F, "\"enum item %s\" " ENUM_ITEM_NODE_ATTR, get_id_str(id));
1812 fprintf (F, "\n info1: \"value: %s\"}\n", buf);
1815 /* dumps a type or entity and it's edges. */
1817 dump_type_info(type_or_ent *tore, void *env) {
1819 int i = 0; /* to shutup gcc */
1821 /* dump this type or entity */
1823 switch (get_kind(tore)) {
1826 entity *ent = (entity *)tore;
1829 dump_entity_node(F, ent, 0);
1831 /* skip this to reduce graph. Member edge of type is parallel to this edge. *
1832 fprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
1833 ENT_OWN_EDGE_ATTR "}\n", ent, get_entity_owner(ent));*/
1834 print_ent_type_edge(F,ent, get_entity_type(ent), ENT_TYPE_EDGE_ATTR);
1835 if (is_Class_type(get_entity_owner(ent))) {
1836 for(i = 0; i < get_entity_n_overwrites(ent); i++)
1837 print_ent_ent_edge(F,ent, get_entity_overwrites(ent, i), 0, ENT_OVERWRITES_EDGE_ATTR);
1839 /* attached subgraphs */
1840 if (const_entities && (get_entity_variability(ent) != variability_uninitialized)) {
1841 if (is_atomic_entity(ent)) {
1842 value = get_atomic_ent_value(ent);
1844 print_ent_node_edge(F, ent, value, ENT_VALUE_EDGE_ATTR, i);
1845 /* DDMN(value); $$$ */
1846 dump_const_expression(F, value);
1849 if (is_compound_entity(ent)) {
1850 for (i = 0; i < get_compound_ent_n_values(ent); i++) {
1851 value = get_compound_ent_value(ent, i);
1853 print_ent_node_edge(F, ent, value, ENT_VALUE_EDGE_ATTR, i);
1854 dump_const_expression(F, value);
1855 print_ent_ent_edge(F, ent, get_compound_ent_value_member(ent, i), 0, ENT_CORR_EDGE_ATTR, i);
1857 fprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
1858 ENT_CORR_EDGE_ATTR "}\n", GET_ENTID(ent),
1859 get_compound_ent_value_member(ent, i), i);
1868 type *tp = (type *)tore;
1869 dump_type_node(F, tp);
1870 /* and now the edges */
1871 switch (get_type_tpop_code(tp)) {
1874 for (i=0; i < get_class_n_supertypes(tp); i++)
1875 print_type_type_edge(F, tp,get_class_supertype(tp, i),TYPE_SUPER_EDGE_ATTR);
1876 for (i=0; i < get_class_n_members(tp); i++)
1877 print_type_ent_edge(F,tp,get_class_member(tp, i),TYPE_MEMBER_EDGE_ATTR);
1881 for (i=0; i < get_struct_n_members(tp); i++)
1882 print_type_ent_edge(F,tp,get_struct_member(tp, i),TYPE_MEMBER_EDGE_ATTR);
1886 for (i = 0; i < get_method_n_params(tp); i++)
1887 print_type_type_edge(F,tp,get_method_param_type(tp, i),METH_PAR_EDGE_ATTR,i);
1888 for (i = 0; i < get_method_n_ress(tp); i++)
1889 print_type_type_edge(F,tp,get_method_res_type(tp, i),METH_RES_EDGE_ATTR,i);
1893 for (i = 0; i < get_union_n_members(tp); i++)
1894 print_type_ent_edge(F,tp,get_union_member(tp, i),UNION_EDGE_ATTR);
1898 print_type_type_edge(F,tp,get_array_element_type(tp),ARR_ELT_TYPE_EDGE_ATTR);
1899 print_type_ent_edge(F,tp,get_array_element_entity(tp),ARR_ENT_EDGE_ATTR);
1900 for (i = 0; i < get_array_n_dimensions(tp); i++) {
1901 ir_node *upper = get_array_upper_bound(tp, i);
1902 ir_node *lower = get_array_lower_bound(tp, i);
1903 print_node_type_edge(F, upper, tp, "label: \"upper %d\"", get_array_order(tp, i));
1904 print_node_type_edge(F, lower, tp, "label: \"lower %d\"", get_array_order(tp, i));
1905 dump_const_expression(F, upper);
1906 dump_const_expression(F, lower);
1910 case tpo_enumeration:
1912 for (i = 0; i < get_enumeration_n_enums(tp); ++i) {
1913 dump_enum_item(F, tp, i);
1914 print_enum_item_edge(F, tp, i, "label: \"item %d\"", i);
1919 print_type_type_edge(F,tp,get_pointer_points_to_type(tp), PTR_PTS_TO_EDGE_ATTR);
1927 break; /* case k_type */
1930 printf(" *** irdump, dump_type_info(l.%i), faulty type.\n", __LINE__);
1932 } /* switch kind_or_entity */
1935 typedef struct _h_env {
1940 /** For dumping class hierarchies.
1941 * Dumps a class type node and a superclass edge.
1942 * If env->dump_ent dumps entities of classes and overwrites edges.
1945 dump_class_hierarchy_node (type_or_ent *tore, void *ctx) {
1948 int i = 0; /* to shutup gcc */
1950 /* dump this type or entity */
1951 switch (get_kind(tore)) {
1953 entity *ent = (entity *)tore;
1954 if (get_entity_owner(ent) == get_glob_type()) break;
1955 if (!is_Method_type(get_entity_type(ent))) break; /* GL */
1956 if (env->dump_ent && is_Class_type(get_entity_owner(ent))) {
1958 dump_entity_node(F, ent, 0);
1960 print_type_ent_edge(F,get_entity_owner(ent),ent,TYPE_MEMBER_EDGE_ATTR);
1961 for(i = 0; i < get_entity_n_overwrites(ent); i++)
1962 print_ent_ent_edge(F, get_entity_overwrites(ent, i), ent, 0, ENT_OVERWRITES_EDGE_ATTR);
1964 } break; /* case k_entity */
1967 type *tp = (type *)tore;
1968 if (tp == get_glob_type()) break;
1969 switch (get_type_tpop_code(tp)) {
1971 dump_type_node(F, tp);
1972 /* and now the edges */
1973 for (i=0; i < get_class_n_supertypes(tp); i++)
1975 print_type_type_edge(F,tp,get_class_supertype(tp, i),TYPE_SUPER_EDGE_ATTR);
1981 break; /* case k_type */
1984 printf(" *** irdump, dump_class_hierarchy_node(l.%i), faulty type.\n", __LINE__);
1986 } /* switch kind_or_entity */
1989 /*******************************************************************/
1990 /* dump analysis information that is expressed in graph terms. */
1991 /*******************************************************************/
1993 /* dump out edges */
1995 dump_out_edge(ir_node *n, void *env) {
1998 for (i = 0; i < get_irn_n_outs(n); i++) {
1999 assert(get_irn_out(n, i));
2000 fprintf (F, "edge: {sourcename: \"");
2002 fprintf (F, "\" targetname: \"");
2003 PRINT_NODEID(get_irn_out(n, i));
2004 fprintf (F, "\" color: red linestyle: dashed");
2010 dump_loop_label(FILE *F, ir_loop *loop) {
2011 fprintf (F, "loop %d, %d sons, %d nodes",
2012 get_loop_depth(loop), get_loop_n_sons(loop), get_loop_n_nodes(loop));
2015 static INLINE void dump_loop_info(FILE *F, ir_loop *loop) {
2016 fprintf (F, " info1: \"");
2017 fprintf (F, " loop nr: %d", get_loop_loop_nr(loop));
2018 #if DEBUG_libfirm /* GL @@@ debug analyses */
2019 fprintf (F, "\n The loop was analyzed %d times.", PTR_TO_INT(get_loop_link(loop)));
2025 dump_loop_node(FILE *F, ir_loop *loop) {
2026 fprintf (F, "node: {title: \"");
2028 fprintf (F, "\" label: \"");
2029 dump_loop_label(F, loop);
2031 dump_loop_info(F, loop);
2037 dump_loop_node_edge(FILE *F, ir_loop *loop, int i) {
2039 fprintf (F, "edge: {sourcename: \"");
2041 fprintf (F, "\" targetname: \"");
2042 PRINT_NODEID(get_loop_node(loop, i));
2043 fprintf (F, "\" color: green");
2048 dump_loop_son_edge(FILE *F, ir_loop *loop, int i) {
2050 fprintf (F, "edge: {sourcename: \"");
2052 fprintf (F, "\" targetname: \"");
2053 PRINT_LOOPID(get_loop_son(loop, i));
2054 fprintf (F, "\" color: darkgreen label: \"%d\"}\n",
2055 get_loop_element_pos(loop, get_loop_son(loop, i)));
2059 void dump_loops(FILE *F, ir_loop *loop) {
2061 /* dump this loop node */
2062 dump_loop_node(F, loop);
2064 /* dump edges to nodes in loop -- only if it is a real loop */
2065 if (get_loop_depth(loop) != 0) {
2066 for (i = 0; i < get_loop_n_nodes(loop); i++) {
2067 dump_loop_node_edge(F, loop, i);
2070 for (i = 0; i < get_loop_n_sons(loop); i++) {
2071 dump_loops(F, get_loop_son(loop, i));
2072 dump_loop_son_edge(F, loop, i);
2077 void dump_loop_nodes_into_graph(FILE *F, ir_graph *irg) {
2078 ir_graph *rem = current_ir_graph;
2079 current_ir_graph = irg;
2081 if (get_irg_loop(irg)) dump_loops(F, get_irg_loop(irg));
2083 current_ir_graph = rem;
2088 * dumps the VCG header
2090 void dump_vcg_header(FILE *F, const char *name, const char *orientation) {
2099 if (!orientation) orientation = "bottom_to_top";
2103 "graph: { title: \"ir graph of %s\"\n"
2104 "display_edge_labels: %s\n"
2105 "layoutalgorithm: mindepth\n"
2106 "manhattan_edges: yes\n"
2107 "port_sharing: no\n"
2109 "classname 1: \"intrablock Data\"\n"
2110 "classname 16: \"interblock Data\"\n"
2111 "classname 2: \"Block\"\n"
2112 "classname 13: \"Control Flow\"\n"
2113 "classname 18: \"Exception Control Flow for Interval Analysis\"\n"
2114 "classname 14: \"intrablock Memory\"\n"
2115 "classname 17: \"interblock Memory\"\n"
2116 "classname 15: \"Dominators\"\n"
2117 "classname 3: \"Entity type\"\n"
2118 "classname 4: \"Entity owner\"\n"
2119 "classname 5: \"Method Param\"\n"
2120 "classname 6: \"Method Res\"\n"
2121 "classname 7: \"Super\"\n"
2122 "classname 8: \"Union\"\n"
2123 "classname 9: \"Points-to\"\n"
2124 "classname 10: \"Array Element Type\"\n"
2125 "classname 11: \"Overwrites\"\n"
2126 "classname 12: \"Member\"\n"
2127 "infoname 1: \"Attribute\"\n"
2128 "infoname 2: \"Verification errors\"\n"
2129 "infoname 3: \"Debug info\"\n",
2130 name, label, orientation);
2132 /* don't use all, the range is too whith/black. */
2136 "colorentry 100: 0 0 0\n"
2137 "colorentry 101: 20 0 0\n"
2138 "colorentry 102: 40 0 0\n"
2139 "colorentry 103: 60 0 0\n"
2140 "colorentry 104: 80 0 0\n"
2141 "colorentry 105: 100 0 0\n"
2142 "colorentry 106: 120 0 0\n"
2143 "colorentry 107: 140 0 0\n"
2144 "colorentry 108: 150 0 0\n"
2145 "colorentry 109: 180 0 0\n"
2146 "colorentry 110: 200 0 0\n"
2147 "colorentry 111: 220 0 0\n"
2148 "colorentry 112: 240 0 0\n"
2149 "colorentry 113: 255 0 0\n"
2150 "colorentry 113: 255 20 20\n"
2151 "colorentry 114: 255 40 40\n"
2152 "colorentry 115: 255 60 60\n"
2153 "colorentry 116: 255 80 80\n"
2154 "colorentry 117: 255 100 100\n"
2155 "colorentry 118: 255 120 120\n"
2156 "colorentry 119: 255 140 140\n"
2157 "colorentry 120: 255 150 150\n"
2158 "colorentry 121: 255 180 180\n"
2159 "colorentry 122: 255 200 200\n"
2160 "colorentry 123: 255 220 220\n"
2161 "colorentry 124: 255 240 240\n"
2162 "colorentry 125: 255 250 250\n"
2165 fprintf (F, "\n"); /* a separator */
2171 * @param irg The graph to be dumped
2172 * @param suffix1 first filename suffix
2173 * @param suffix2 second filename suffix
2175 FILE *vcg_open (ir_graph *irg, const char * suffix1, const char *suffix2) {
2177 const char *nm = get_irg_dump_name(irg);
2178 int len = strlen(nm), i, j;
2179 char *fname; /* filename to put the vcg information in */
2181 if (!suffix1) suffix1 = "";
2182 if (!suffix2) suffix2 = "";
2184 /* open file for vcg graph */
2185 fname = malloc (len * 2 + strlen(suffix1) + strlen(suffix2) + 5);
2187 /* strncpy (fname, nm, len); */ /* copy the filename */
2189 for (i = 0; i < len; ++i) { /* replace '/' in the name: escape by @. */
2191 fname[j] = '@'; j++; fname[j] = '1'; j++;
2192 } else if (nm[i] == '@') {
2193 fname[j] = '@'; j++; fname[j] = '2'; j++;
2195 fname[j] = nm[i]; j++;
2199 strcat (fname, suffix1); /* append file suffix */
2200 strcat (fname, suffix2); /* append file suffix */
2201 strcat (fname, ".vcg"); /* append the .vcg suffix */
2203 /* vcg really expect only a <CR> at end of line, so
2204 * the "b"inary mode is what you mean (and even needed for Win32)
2206 F = fopen (fname, "wb"); /* open file for writing */
2208 panic("cannot open %s for writing (%m)", fname); /* not reached */
2218 * @param name prefix file name
2219 * @param suffix filename suffix
2221 FILE *vcg_open_name (const char *name, const char *suffix) {
2223 char *fname; /* filename to put the vcg information in */
2224 int i, j, len = strlen(name);
2226 if (!suffix) suffix = "";
2228 /** open file for vcg graph */
2229 fname = xmalloc(len * 2 + 5 + strlen(suffix));
2230 /* strcpy (fname, name);*/ /* copy the filename */
2232 for (i = 0; i < len; ++i) { /* replace '/' in the name: escape by @. */
2233 if (name[i] == '/') {
2234 fname[j] = '@'; j++; fname[j] = '1'; j++;
2235 } else if (name[i] == '@') {
2236 fname[j] = '@'; j++; fname[j] = '2'; j++;
2238 fname[j] = name[i]; j++;
2242 strcat (fname, suffix);
2243 strcat (fname, ".vcg"); /* append the .vcg suffix */
2245 /* vcg really expect only a <CR> at end of line, so
2246 * the "b"inary mode is what you mean (and even needed for Win32)
2248 F = fopen (fname, "wb"); /* open file for writing */
2250 panic ("cannot open %s for writing (%m)", fname); /* not reached */
2258 * Dumps the vcg file footer
2260 static INLINE void dump_vcg_footer (FILE *F) {
2265 * close the vcg file
2267 void vcg_close (FILE *F) {
2268 dump_vcg_footer(F); /* print footer */
2269 fclose (F); /* close vcg file */
2272 /************************************************************************/
2273 /************************************************************************/
2274 /* Routines that dump all or parts of the firm representation to a file */
2275 /************************************************************************/
2276 /************************************************************************/
2278 /************************************************************************/
2279 /* Dump ir graphs, different formats and additional information. */
2280 /************************************************************************/
2282 /** Routine to dump a graph, blocks as conventional nodes. */
2284 dump_ir_graph (ir_graph *irg, const char *suffix )
2289 rem = current_ir_graph;
2291 if (!is_filtered_dump_name(get_entity_ident(get_irg_entity(irg)))) return;
2293 current_ir_graph = irg;
2294 if (get_interprocedural_view()) suffix1 = "-pure-ip";
2295 else suffix1 = "-pure";
2296 f = vcg_open(irg, suffix, suffix1);
2297 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
2299 /* call the dump graph hook */
2300 if (dump_ir_graph_hook)
2301 if (dump_ir_graph_hook(f, irg))
2304 /* walk over the graph */
2305 /* dump_whole_node must be called in post visiting predecessors */
2306 irg_walk(get_irg_end(irg), NULL, dump_whole_node, f);
2308 /* dump the out edges in a separate walk */
2309 if ((dump_out_edge_flag) && (get_irg_outs_state(irg) != outs_none)) {
2310 irg_out_walk(get_irg_start(irg), dump_out_edge, NULL, f);
2315 current_ir_graph = rem;
2318 /* Dump a firm graph without explicit block nodes. */
2319 void dump_ir_block_graph (ir_graph *irg, const char *suffix)
2325 if (!is_filtered_dump_name(get_entity_ident(get_irg_entity(irg))))
2328 if (get_interprocedural_view()) suffix1 = "-ip";
2330 f = vcg_open(irg, suffix, suffix1);
2331 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
2333 construct_block_lists(irg);
2336 * If we are in the interprocedural view, we dump not
2337 * only the requested irg but also all irgs that can be reached
2340 for (i = 0; i < get_irp_n_irgs(); i++) {
2341 ir_node **arr = ird_get_irg_link(get_irp_irg(i));
2343 dump_graph_from_list(f, get_irp_irg(i));
2351 /* Dump a firm graph without explicit block nodes but grouped in extended blocks. */
2352 void dump_ir_extblock_graph (ir_graph *irg, const char *suffix)
2359 if (!is_filtered_dump_name(get_entity_ident(get_irg_entity(irg))))
2364 if (get_interprocedural_view()) suffix1 = "-ip";
2367 ent = get_irg_entity(irg);
2369 F = vcg_open(irg, suffix, suffix1);
2370 dump_vcg_header(F, get_irg_dump_name(irg), NULL);
2372 construct_extblock_lists(irg);
2374 fprintf(F, "graph: { title: \"");
2376 fprintf(F, "\" label: \"%s\" status:clustered color: white \n",
2377 get_ent_dump_name(ent));
2379 dump_graph_info(F, irg);
2380 print_dbg_info(F, get_entity_dbg_info(ent));
2382 for (i = 0; i < get_irp_n_irgs(); i++) {
2383 ir_graph *irg = get_irp_irg(i);
2384 list_tuple *lists = ird_get_irg_link(irg);
2387 /* dump the extended blocks first */
2388 if (ARR_LEN(lists->extbb_list)) {
2389 ird_set_irg_link(irg, lists->extbb_list);
2390 dump_extblock_graph(F, irg);
2393 /* we may have blocks without extended blocks, bad for instance */
2394 if (ARR_LEN(lists->blk_list)) {
2395 ird_set_irg_link(irg, lists->blk_list);
2396 dump_block_graph(F, irg);
2399 DEL_ARR_F(lists->extbb_list);
2400 DEL_ARR_F(lists->blk_list);
2405 /* Close the vcg information for the irg */
2406 fprintf(F, "}\n\n");
2412 /* dumps a graph with type information */
2414 dump_ir_graph_w_types (ir_graph *irg, const char *suffix)
2417 ir_graph *rem = current_ir_graph;
2419 int rem_dump_const_local;
2421 /* if a filter is set, dump only the irg's that match the filter */
2422 if (!is_filtered_dump_name(get_entity_ident(get_irg_entity(irg))))
2425 current_ir_graph = irg;
2426 rem_dump_const_local = dump_const_local;
2427 /* dumping types does not work with local nodes */
2428 dump_const_local = 0;
2430 if (get_interprocedural_view()) suffix1 = "-pure-wtypes-ip";
2431 else suffix1 = "-pure-wtypes";
2432 f = vcg_open(irg,suffix, suffix1);
2433 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
2435 /* dump common ir graph */
2436 irg_walk(get_irg_end(irg), NULL, dump_whole_node, f);
2437 /* dump type info */
2438 type_walk_irg(irg, dump_type_info, NULL, f);
2439 inc_irg_visited(get_const_code_irg());
2440 /* dump edges from graph to type info */
2441 irg_walk(get_irg_end(irg), dump_node2type_edges, NULL, f);
2444 dump_const_local = rem_dump_const_local;
2445 current_ir_graph = rem;
2449 dump_ir_block_graph_w_types (ir_graph *irg, const char *suffix)
2454 ir_graph *rem = current_ir_graph;
2455 int rem_dump_const_local;
2457 /* if a filter is set, dump only the irg's that match the filter */
2458 if (!is_filtered_dump_name(get_entity_ident(get_irg_entity(irg))))
2461 rem_dump_const_local = dump_const_local;
2462 /* dumping types does not work with local nodes */
2463 dump_const_local = 0;
2465 if (get_interprocedural_view()) suffix1 = "-wtypes-ip";
2466 else suffix1 = "-wtypes";
2467 f = vcg_open(irg, suffix, suffix1);
2468 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
2470 /* dump common blocked ir graph */
2471 construct_block_lists(irg);
2473 for (i = 0; i < get_irp_n_irgs(); i++) {
2474 ir_node **arr = ird_get_irg_link(get_irp_irg(i));
2476 dump_graph_from_list(f, get_irp_irg(i));
2481 /* dump type info */
2482 current_ir_graph = irg;
2483 type_walk_irg(irg, dump_type_info, NULL, f);
2484 inc_irg_visited(get_const_code_irg());
2486 /* dump edges from graph to type info */
2487 irg_walk(get_irg_end(irg), dump_node2type_edges, NULL, f);
2490 dump_const_local = rem_dump_const_local;
2491 current_ir_graph = rem;
2494 /*---------------------------------------------------------------------*/
2495 /* The following routines dump a control flow graph. */
2496 /*---------------------------------------------------------------------*/
2499 dump_block_to_cfg(ir_node *block, void *env) {
2504 if (is_Block(block)) {
2505 /* This is a block. Dump a node for the block. */
2506 fprintf (F, "node: {title: \""); PRINT_NODEID(block);
2507 fprintf (F, "\" label: \"");
2508 if (block == get_irg_start_block(get_irn_irg(block)))
2509 fprintf(F, "Start ");
2510 if (block == get_irg_end_block(get_irn_irg(block)))
2513 fprintf (F, "%s ", get_op_name(get_irn_op(block)));
2514 PRINT_NODEID(block);
2516 fprintf(F, "info1:\"");
2519 if (dump_dominator_information_flag) {
2520 fprintf(F, "dom depth %d\n", get_Block_dom_depth(block));
2521 fprintf(F, "tree pre num %d\n", get_Block_dom_tree_pre_num(block));
2522 fprintf(F, "max subtree pre num %d\n", get_Block_dom_max_subtree_pre_num(block));
2525 /* show arity and possible Bad predecessors of the block */
2526 fprintf(F, "arity: %d\n", get_Block_n_cfgpreds(block));
2527 for (fl = i = 0; i < get_Block_n_cfgpreds(block); ++i) {
2528 ir_node *pred = get_Block_cfgpred(block, i);
2531 fprintf(F, "Bad pred at pos: ");
2532 fprintf(F, "%d ", i);
2539 /* the generic version. */
2540 dump_irnode_to_file(F, block);
2542 /* Check whether we have bad predecessors to color the block. */
2543 for (i = 0; i < get_Block_n_cfgpreds(block); ++i)
2544 if ((fl = is_Bad(get_Block_cfgpred(block, i))))
2548 fprintf (F, "\""); /* closing quote of info */
2550 if ((block == get_irg_start_block(get_irn_irg(block))) ||
2551 (block == get_irg_end_block(get_irn_irg(block))) )
2552 fprintf(F, " color:blue ");
2554 fprintf(F, " color:yellow ");
2557 /* Dump the edges */
2558 for ( i = 0; i < get_Block_n_cfgpreds(block); i++)
2559 if (get_irn_op(skip_Proj(get_Block_cfgpred(block, i))) != op_Bad) {
2560 pred = get_nodes_block(skip_Proj(get_Block_cfgpred(block, i)));
2561 fprintf (F, "edge: { sourcename: \"");
2562 PRINT_NODEID(block);
2563 fprintf (F, "\" targetname: \"");
2565 fprintf (F, "\"}\n");
2568 /* Dump dominator edge */
2569 if (dump_dominator_information_flag && get_Block_idom(block)) {
2570 pred = get_Block_idom(block);
2571 fprintf (F, "edge: { sourcename: \"");
2572 PRINT_NODEID(block);
2573 fprintf (F, "\" targetname: \"");
2575 fprintf (F, "\" " DOMINATOR_EDGE_ATTR "}\n");
2581 dump_cfg (ir_graph *irg, const char *suffix)
2584 ir_graph *rem = current_ir_graph;
2585 int ddif = dump_dominator_information_flag;
2586 int ipv = get_interprocedural_view();
2588 /* if a filter is set, dump only the irg's that match the filter */
2589 if (!is_filtered_dump_name(get_entity_ident(get_irg_entity(irg))))
2592 current_ir_graph = irg;
2594 f = vcg_open(irg, suffix, "-cfg");
2595 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
2598 printf("Warning: dumping cfg not in interprocedural view!\n");
2599 set_interprocedural_view(false);
2602 if (get_irg_dom_state(irg) != dom_consistent)
2603 dump_dominator_information_flag = 0;
2605 /* walk over the blocks in the graph */
2606 irg_block_walk(get_irg_end(irg), dump_block_to_cfg, NULL, f);
2607 dump_node(f, get_irg_bad(irg));
2609 dump_dominator_information_flag = ddif;
2610 set_interprocedural_view(ipv);
2612 current_ir_graph = rem;
2616 static void descend_and_dump(FILE *F, ir_node *n, int depth, pset *mark_set) {
2617 if (pset_find_ptr(mark_set, n)) return;
2619 pset_insert_ptr(mark_set, n);
2622 int i, start = is_Block(n) ? 0 : -1;
2623 dump_whole_node(n, F);
2624 for (i = start; i < get_irn_arity(n); ++i)
2625 descend_and_dump(F, get_irn_n(n, i), depth-1, mark_set);
2628 /* Don't dump edges to nodes further out. These might be edges to
2629 nodes we already dumped, if there is a shorter path to these. */
2633 static int subgraph_counter = 0;
2634 void dump_subgraph (ir_node *root, int depth, const char *suffix) {
2637 pset *mark_set = pset_new_ptr(1);
2638 sprintf(buf, "-subg_%03d", subgraph_counter++);
2639 F = vcg_open(get_irn_irg(root), suffix, buf);
2640 dump_vcg_header(F, get_irg_dump_name(get_irn_irg(root)), NULL);
2641 descend_and_dump(F, root, depth, mark_set);
2647 static int weight_overall(int rec, int loop) {
2648 return 2*rec + loop;
2651 static int compute_color (int my, int max) {
2658 /* if small, scale to the full color range. */
2660 my = my * (n_colors/max);
2662 step = 1 + (max / n_colors);
2666 return base_color + n_colors - color;
2669 static int get_entity_color(entity *ent) {
2670 ir_graph *irg = get_entity_irg(ent);
2674 int rec_depth = get_irg_recursion_depth(irg);
2675 int loop_depth = get_irg_loop_depth(irg);
2676 int overall_depth = weight_overall(rec_depth, loop_depth);
2678 int max_rec_depth = irp->max_callgraph_recursion_depth;
2679 int max_loop_depth = irp->max_callgraph_loop_depth;
2680 int max_overall_depth = weight_overall(max_rec_depth, max_loop_depth);
2682 /* int my_rec_color = compute_color(rec_depth, max_rec_depth); */
2683 /* int my_loop_color = compute_color(loop_depth, max_loop_depth); */
2684 int my_overall_color = compute_color(overall_depth, max_overall_depth);;
2686 return my_overall_color;
2690 void dump_callgraph(const char *suffix) {
2692 int i, n_irgs = get_irp_n_irgs();
2693 int rem = edge_label;
2695 //ident *prefix = new_id_from_str("java/");
2697 F = vcg_open_name("Callgraph", suffix);
2698 dump_vcg_header(F, "Callgraph", NULL);
2700 for (i = 0; i < n_irgs; ++i) {
2701 ir_graph *irg = get_irp_irg(i);
2702 entity *ent = get_irg_entity(irg);
2703 int j, n_callees = get_irg_n_callees(irg);
2705 /* Do not dump runtime system. */
2706 //if (id_is_prefix(prefix, get_entity_ld_ident(ent))) continue;
2708 dump_entity_node(F, ent, get_entity_color(ent));
2709 for (j = 0; j < n_callees; ++j) {
2710 entity *c = get_irg_entity(get_irg_callee(irg, j));
2711 //if (id_is_prefix(prefix, get_entity_ld_ident(c))) continue;
2712 int be = is_irg_callee_backedge(irg, j);
2715 "label:\"recursion %d\" color:%d" :
2716 "label:\"calls %d\" color:%d";
2717 print_ent_ent_edge(F, ent, c, be, attr, get_irg_callee_loop_depth(irg, j), get_entity_color(ent));
2725 /* Dump all irgs in interprocedural view to a single file. */
2726 void dump_all_cg_block_graph(const char *suffix) {
2729 int rem_view = get_interprocedural_view();
2730 set_interprocedural_view(true);
2732 f = vcg_open_name("All_graphs", suffix);
2733 dump_vcg_header(f, "All_graphs", NULL);
2735 /* collect nodes in all irgs reachable in call graph*/
2736 for (i = 0; i < get_irp_n_irgs(); i++)
2737 ird_set_irg_link(get_irp_irg(i), NULL);
2739 cg_walk(clear_link, collect_node, NULL);
2741 /* dump all graphs */
2742 for (i = 0; i < get_irp_n_irgs(); i++) {
2743 current_ir_graph = get_irp_irg(i);
2744 assert(ird_get_irg_link(current_ir_graph));
2745 dump_graph_from_list(f, current_ir_graph);
2746 DEL_ARR_F(ird_get_irg_link(current_ir_graph));
2750 set_interprocedural_view(rem_view);
2753 /*---------------------------------------------------------------------*/
2754 /* the following routines dumps type information without any ir nodes. */
2755 /*---------------------------------------------------------------------*/
2758 dump_type_graph (ir_graph *irg, const char *suffix)
2762 rem = current_ir_graph;
2764 /* if a filter is set, dump only the irg's that match the filter */
2765 if (!is_filtered_dump_name(get_entity_ident(get_irg_entity(irg)))) return;
2767 current_ir_graph = irg;
2769 f = vcg_open(irg, suffix, "-type");
2770 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
2772 /* walk over the blocks in the graph */
2773 type_walk_irg(irg, dump_type_info, NULL, f);
2774 /* The walker for the const code can be called several times for the
2775 same (sub) expression. So that no nodes are dumped several times
2776 we decrease the visited flag of the corresponding graph after each
2777 walk. So now increase it finally. */
2778 inc_irg_visited(get_const_code_irg());
2781 current_ir_graph = rem;
2785 dump_all_types (const char *suffix)
2787 FILE *f = vcg_open_name("All_types", suffix);
2788 dump_vcg_header(f, "All_types", NULL);
2789 type_walk(dump_type_info, NULL, f);
2790 inc_irg_visited(get_const_code_irg());
2795 dump_class_hierarchy (bool entities, const char *suffix)
2797 FILE *f = vcg_open_name("class_hierarchy", suffix);
2801 dump_vcg_header(f, "class_hierarchy", NULL);
2806 type_walk(dump_class_hierarchy_node, NULL, &env);
2810 /*---------------------------------------------------------------------*/
2811 /* dumps all graphs with the graph-dumper passed. Possible dumpers: */
2813 /* dump_ir_block_graph */
2815 /* dump_type_graph */
2816 /* dump_ir_graph_w_types */
2817 /*---------------------------------------------------------------------*/
2819 void dump_all_ir_graphs(dump_graph_func *dmp_grph, const char *suffix) {
2821 for (i = get_irp_n_irgs() - 1; i >= 0; --i) {
2822 dmp_grph(get_irp_irg(i), suffix);
2827 /*--------------------------------------------------------------------------------*
2828 * Dumps a stand alone loop graph with firm nodes which belong to one loop node *
2829 * packed together in one subgraph/box *
2830 *--------------------------------------------------------------------------------*/
2832 void dump_loops_standalone(FILE *F, ir_loop *loop) {
2833 int i = 0, loop_node_started = 0, son_number = 0, first = 0;
2835 ir_loop *son = NULL;
2837 /* Dump a new loop node. */
2838 dump_loop_node(F, loop);
2840 /* Dump the loop elements. */
2842 for(i = 0; i < get_loop_n_elements(loop); i++) {
2843 le = get_loop_element(loop, i);
2845 if (get_kind(son) == k_ir_loop) {
2847 /* We are a loop son -> Recurse */
2849 if(loop_node_started) { /* Close the "firm-nodes" node first if we started one. */
2850 fprintf(F, "\" }\n");
2851 fprintf (F, "edge: {sourcename: \"");
2853 fprintf (F, "\" targetname: \"");
2855 fprintf (F, "-%d-nodes\" label:\"%d...%d\"}\n", first, first, i-1);
2856 loop_node_started = 0;
2858 dump_loop_son_edge(F, loop, son_number++);
2859 dump_loops_standalone(F, son);
2860 } else if (get_kind(son) == k_ir_node) {
2861 /* We are a loop node -> Collect firm nodes */
2863 ir_node *n = le.node;
2866 if (!loop_node_started) {
2867 /* Start a new node which contains all firm nodes of the current loop */
2868 fprintf (F, "node: { title: \"");
2870 fprintf (F, "-%d-nodes\" color: lightyellow label: \"", i);
2871 loop_node_started = 1;
2877 bad |= dump_node_label(F, n);
2878 /* Causes indeterministic output: if (is_Block(n)) fprintf (F, "\t ->%d", (int)get_irn_link(n)); */
2879 if (has_backedges(n)) fprintf(F, "\t loop head!");
2880 } else { /* for callgraph loop tree */
2882 assert(get_kind(son) == k_ir_graph);
2884 /* We are a loop node -> Collect firm graphs */
2885 n = (ir_graph *)le.node;
2886 if (!loop_node_started) {
2887 /* Start a new node which contains all firm nodes of the current loop */
2888 fprintf (F, "node: { title: \"");
2890 fprintf (F, "-%d-nodes\" color: lightyellow label: \"", i);
2891 loop_node_started = 1;
2896 fprintf (F, " %s", get_irg_dump_name(n));
2897 /* fprintf (F, " %s (depth %d)", get_irg_dump_name(n), n->callgraph_weighted_loop_depth); */
2901 if (loop_node_started) {
2902 fprintf(F, "\" }\n");
2903 fprintf (F, "edge: {sourcename: \"");
2905 fprintf (F, "\" targetname: \"");
2907 fprintf (F, "-%d-nodes\" label:\"%d...%d\"}\n", first, first, i-1);
2908 loop_node_started = 0;
2912 void dump_loop_tree(ir_graph *irg, const char *suffix)
2915 ir_graph *rem = current_ir_graph;
2916 int el_rem = edge_label;
2919 /* if a filter is set, dump only the irg's that match the filter */
2920 if (!is_filtered_dump_name(get_entity_ident(get_irg_entity(irg)))) return;
2922 current_ir_graph = irg;
2924 f = vcg_open(irg, suffix, "-looptree");
2925 dump_vcg_header(f, get_irg_dump_name(irg), "top_to_bottom");
2927 if (get_irg_loop(irg)) dump_loops_standalone(f, get_irg_loop(irg));
2931 edge_label = el_rem;
2932 current_ir_graph = rem;
2935 void dump_callgraph_loop_tree(const char *suffix) {
2937 F = vcg_open_name("Callgraph_looptree", suffix);
2938 dump_vcg_header(F, "callgraph looptree", "top_to_bottom");
2939 dump_loops_standalone(F, irp->outermost_cg_loop);
2944 /*-----------------------------------------------------------------------------*/
2945 /* Dumps the firm nodes in the loop tree to a graph along with the loop nodes. */
2946 /*-----------------------------------------------------------------------------*/
2948 void collect_nodeloop(FILE *F, ir_loop *loop, eset *loopnodes) {
2949 int i, son_number = 0, node_number = 0;
2951 if (dump_loop_information_flag) dump_loop_node(F, loop);
2953 for (i = 0; i < get_loop_n_elements(loop); i++) {
2954 loop_element le = get_loop_element(loop, i);
2955 if (*(le.kind) == k_ir_loop) {
2956 if (dump_loop_information_flag) dump_loop_son_edge(F, loop, son_number++);
2958 collect_nodeloop(F, le.son, loopnodes);
2960 if (dump_loop_information_flag) dump_loop_node_edge(F, loop, node_number++);
2961 eset_insert(loopnodes, le.node);
2966 void collect_nodeloop_external_nodes(ir_loop *loop, eset *loopnodes, eset *extnodes) {
2969 for(i = 0; i < get_loop_n_elements(loop); i++) {
2970 loop_element le = get_loop_element(loop, i);
2971 if (*(le.kind) == k_ir_loop) {
2973 collect_nodeloop_external_nodes(le.son, loopnodes, extnodes);
2975 if (is_Block(le.node)) start = 0; else start = -1;
2976 for (j = start; j < get_irn_arity(le.node); j++) {
2977 ir_node *pred = get_irn_n(le.node, j);
2978 if (!eset_contains(loopnodes, pred)) {
2979 eset_insert(extnodes, pred);
2980 if (!is_Block(pred)) {
2981 pred = get_nodes_block(pred);
2982 if (!eset_contains(loopnodes, pred)) eset_insert(extnodes, pred);
2990 void dump_loop(ir_loop *l, const char *suffix) {
2993 eset *loopnodes = eset_create();
2994 eset *extnodes = eset_create();
2997 snprintf(name, sizeof(name), "loop_%d", get_loop_loop_nr(l));
2998 F = vcg_open_name (name, suffix);
2999 dump_vcg_header(F, name, NULL);
3001 /* collect all nodes to dump */
3002 collect_nodeloop(F, l, loopnodes);
3003 collect_nodeloop_external_nodes(l, loopnodes, extnodes);
3005 /* build block lists */
3006 for (n = eset_first(loopnodes); n != NULL; n = eset_next(loopnodes))
3007 set_irn_link(n, NULL);
3008 for (n = eset_first(extnodes); n != NULL; n = eset_next(extnodes))
3009 set_irn_link(n, NULL);
3010 for (n = eset_first(loopnodes); n != NULL; n = eset_next(loopnodes))
3012 b = get_nodes_block(n);
3013 set_irn_link(n, get_irn_link(b));
3016 for (n = eset_first(extnodes); n != NULL; n = eset_next(extnodes))
3018 b = get_nodes_block(n);
3019 set_irn_link(n, get_irn_link(b));
3023 for (b = eset_first(loopnodes); b != NULL; b = eset_next(loopnodes))
3025 fprintf(F, "graph: { title: \"");
3027 fprintf(F, "\" label: \"");
3028 dump_node_opcode(F, b);
3029 fprintf (F, " %ld", get_irn_node_nr(b));
3030 fprintf(F, "\" status:clustered color:yellow\n");
3032 /* dump the blocks edges */
3033 dump_ir_data_edges(F, b);
3035 /* dump the nodes that go into the block */
3036 for (n = get_irn_link(b); n; n = get_irn_link(n)) {
3037 if (eset_contains(extnodes, n))
3038 overrule_nodecolor = ird_color_lightblue;
3040 overrule_nodecolor = ird_color_default;
3041 if (!eset_contains(extnodes, n)) dump_ir_data_edges(F, n);
3044 /* Close the vcg information for the block */
3046 dump_const_node_local(F, b);
3049 for (b = eset_first(extnodes); b != NULL; b = eset_next(extnodes))
3051 fprintf(F, "graph: { title: \"");
3053 fprintf(F, "\" label: \"");
3054 dump_node_opcode(F, b);
3055 fprintf (F, " %ld", get_irn_node_nr(b));
3056 fprintf(F, "\" status:clustered color:lightblue\n");
3058 /* dump the nodes that go into the block */
3059 for (n = get_irn_link(b); n; n = get_irn_link(n)) {
3060 if (!eset_contains(loopnodes, n))
3061 overrule_nodecolor = ird_color_lightblue;
3063 overrule_nodecolor = ird_color_default;
3064 if (eset_contains(loopnodes, n)) dump_ir_data_edges(F, n);
3067 /* Close the vcg information for the block */
3069 dump_const_node_local(F, b);
3073 eset_destroy(loopnodes);
3074 eset_destroy(extnodes);