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"
27 #include "irgraph_t.h"
37 #include "type_or_entity.h"
41 #include "callgraph.h"
42 #include "irextbb_t.h"
43 #include "dbginfo_t.h"
54 extern void dump_irn_chi_term(FILE *FL, ir_node *n);
55 extern void dump_irn_state(FILE *FL, ir_node *n);
56 extern int get_opt_dump_abstvals(void);
57 typedef unsigned long SeqNo;
58 extern SeqNo get_Block_seqno(ir_node *n);
61 /* basis for a color range for vcg */
62 static int n_colors = 0;
63 static int base_color = 0;
65 /** Dump only irgs with names that start with this string */
66 static ident *dump_file_filter_id = NULL;
68 #define ERROR_TXT "<ERROR>"
70 /*******************************************************************/
71 /* flags to steer output */
72 /*******************************************************************/
74 /** An option to turn off edge labels */
75 static int edge_label = 1;
76 /** An option to turn off dumping values of constant entities */
77 static int const_entities = 1;
78 /** An option to dump the keep alive edges */
79 static int dump_keepalive = 0;
80 /** An option to dump ld_names instead of names. */
81 static int dump_ld_name = 1;
82 /** Compiler options to dump analysis information in dump_ir_graph */
83 int dump_out_edge_flag = 0;
84 int dump_dominator_information_flag = 0;
85 int dump_loop_information_flag = 0;
86 int dump_backedge_information_flag = 1;
87 int dump_const_local = 0;
88 bool opt_dump_analysed_type_info = 1;
89 bool opt_dump_pointer_values_to_info = 0; /* default off: for test compares!! */
91 static const char *overrule_nodecolor = NULL;
93 /** An additional edge hook. */
94 static DUMP_NODE_EDGE_FUNC dump_node_edge_hook = NULL;
96 void set_dump_node_edge_hook(DUMP_NODE_EDGE_FUNC func)
98 dump_node_edge_hook = func;
101 DUMP_NODE_EDGE_FUNC get_dump_node_edge_hook(void)
103 return dump_node_edge_hook;
107 /** The vcg attribute hook. */
108 static DUMP_NODE_VCGATTR_FUNC dump_node_vcgattr_hook = NULL;
111 void set_dump_node_vcgattr_hook(DUMP_NODE_VCGATTR_FUNC hook) {
112 dump_node_vcgattr_hook = hook;
115 INLINE bool get_opt_dump_const_local(void) {
116 if (!dump_out_edge_flag && !dump_loop_information_flag)
117 return dump_const_local;
122 void only_dump_method_with_name(ident *name) {
123 dump_file_filter_id = name;
126 ident *get_dump_file_filter_ident(void) {
127 return dump_file_filter_id;
130 /** Returns true if dump file filter is not set, or if it is a
132 int is_filtered_dump_name(ident *name) {
133 if (!dump_file_filter_id) return 1;
134 return id_is_prefix(dump_file_filter_id, name);
137 /* To turn off display of edge labels. Edge labels offen cause xvcg to
138 abort with a segmentation fault. */
139 void turn_off_edge_labels(void) {
143 void dump_consts_local(bool b) {
144 dump_const_local = b;
147 void dump_constant_entity_values(bool b) {
151 void dump_keepalive_edges(bool b) {
155 bool get_opt_dump_keepalive_edges(void) {
156 return dump_keepalive;
159 void dump_out_edges(bool b) {
160 dump_out_edge_flag = b;
163 void dump_dominator_information(bool b) {
164 dump_dominator_information_flag = b;
167 void dump_loop_information(bool b) {
168 dump_loop_information_flag = b;
171 void dump_backedge_information(bool b) {
172 dump_backedge_information_flag = b;
175 /* Dump the information of type field specified in ana/irtypeinfo.h.
176 * If the flag is set, the type name is output in [] in the node label,
177 * else it is output as info.
179 void set_opt_dump_analysed_type_info(bool b) {
180 opt_dump_analysed_type_info = b;
183 void dump_pointer_values_to_info(bool b) {
184 opt_dump_pointer_values_to_info = b;
187 void dump_ld_names(bool b) {
191 /* -------------- some extended helper functions ----------------- */
194 * returns the name of a mode or <ERROR> if mode is NOT a mode object.
195 * in the later case, sets bad
197 const char *get_mode_name_ex(ir_mode *mode, int *bad)
200 return get_mode_name(mode);
206 * returns the name of a type or <ERROR> if mode is NOT a mode object.
207 * in the later case, sets bad
209 const char *get_type_name_ex(type *tp, int *bad)
212 return get_type_name(tp);
218 * prints the edge from a type S to a type T with additional info fmt, ...
221 static void print_type_type_edge(FILE *F, type *S, type *T, const char *fmt, ...)
226 fprintf(F, "edge: { sourcename: "); PRINT_TYPEID(S);
227 fprintf(F, " targetname: "); PRINT_TYPEID(T);
228 vfprintf(F, fmt, ap);
234 * prints the edge from a type T to an entity E with additional info fmt, ...
237 static void print_type_ent_edge(FILE *F, type *T, entity *E, const char *fmt, ...)
242 fprintf(F, "edge: { sourcename: "); PRINT_TYPEID(T);
243 fprintf(F, " targetname: \""); PRINT_ENTID(E); fprintf(F, "\"");
244 vfprintf(F, fmt, ap);
250 * prints the edge from an entity E to an entity T with additional info fmt, ...
253 static void print_ent_ent_edge(FILE *F, entity *E, entity *T, int backedge, const char *fmt, ...)
259 fprintf(F, "backedge: { sourcename: \"");
261 fprintf(F, "edge: { sourcename: \"");
263 fprintf(F, "\" targetname: \""); PRINT_ENTID(T); fprintf(F, "\"");
264 vfprintf(F, fmt, ap);
270 * prints the edge from an entity E to a type T with additional info fmt, ...
273 static void print_ent_type_edge(FILE *F, entity *E, type *T, const char *fmt, ...)
278 fprintf(F, "edge: { sourcename: \""); PRINT_ENTID(E);
279 fprintf(F, "\" targetname: "); PRINT_TYPEID(T);
280 vfprintf(F, fmt, ap);
286 * prints the edge from a node N to a type T with additional info fmt, ...
289 static void print_node_type_edge(FILE *F, const ir_node *N, type *T, const char *fmt, ...)
294 fprintf(F, "edge: { sourcename: \""); PRINT_NODEID(N);
295 fprintf(F, "\" targetname: "); PRINT_TYPEID(T);
296 vfprintf(F, fmt, ap);
302 * prints the edge from a node N to an entity E with additional info fmt, ...
305 static void print_node_ent_edge(FILE *F, const ir_node *N, entity *E, const char *fmt, ...)
310 fprintf(F, "edge: { sourcename: \""); PRINT_NODEID(N);
311 fprintf(F, "\" targetname: \""); PRINT_ENTID(E);
313 vfprintf(F, fmt, ap);
319 * prints the edge from an entity E to a node N with additional info fmt, ...
322 static void print_ent_node_edge(FILE *F, entity *E, const ir_node *N, const char *fmt, ...)
327 fprintf(F, "edge: { sourcename: \""); PRINT_ENTID(E);
328 fprintf(F, "\" targetname: \""); PRINT_NODEID(N); fprintf(F, "\"");
329 vfprintf(F, fmt, ap);
335 * prints the edge from a type E to an enumeration item item with additional info fmt, ...
338 static void print_enum_item_edge(FILE *F, type *E, int item, const char *fmt, ...)
343 fprintf(F, "edge: { sourcename: "); PRINT_TYPEID(E);
344 fprintf(F, " targetname: \""); PRINT_ITEMID(E, item); fprintf(F, "\" ");
345 vfprintf(F, fmt, ap);
350 /*-----------------------------------------------------------------*/
351 /* global and ahead declarations */
352 /*-----------------------------------------------------------------*/
354 static void dump_whole_node(ir_node *n, void *env);
355 static INLINE void dump_loop_nodes_into_graph(FILE *F, ir_graph *irg);
357 /*-----------------------------------------------------------------*/
358 /* Helper functions. */
359 /*-----------------------------------------------------------------*/
362 * This map is used as a private link attr to be able to call dumper
363 * anywhere without destroying link fields.
365 static pmap *irdump_link_map = NULL;
367 /** NOT A STANDARD LIBFIRM INIT METHOD
369 * We do not want to integrate dumping into libfirm, i.e., if the dumpers
370 * are off, we want to have as few interferences as possible. Therefore the
371 * initialization is performed lazily and not called from within init_firm.
373 * Creates the link attribute map. */
374 static void init_irdump(void) {
375 /* We need a new, empty map. */
376 if (irdump_link_map) pmap_destroy(irdump_link_map);
377 irdump_link_map = pmap_create();
378 if (!dump_file_filter_id)
379 dump_file_filter_id = new_id_from_str("");
382 * Returns the private link field.
384 static void *ird_get_irn_link(ir_node *n) {
386 if (!irdump_link_map) return NULL;
388 if (pmap_contains(irdump_link_map, (void *)n))
389 res = pmap_get(irdump_link_map, (void *)n);
394 * Sets the private link field.
396 static void ird_set_irn_link(ir_node *n, void *x) {
397 if (!irdump_link_map) init_irdump();
398 pmap_insert(irdump_link_map, (void *)n, x);
402 * Gets the private link field of an irg.
404 static void *ird_get_irg_link(ir_graph *irg) {
406 if (!irdump_link_map) return NULL;
408 if (pmap_contains(irdump_link_map, (void *)irg))
409 res = pmap_get(irdump_link_map, (void *)irg);
414 * Sets the private link field of an irg.
416 static void ird_set_irg_link(ir_graph *irg, void *x) {
417 if (!irdump_link_map) init_irdump();
418 pmap_insert(irdump_link_map, (void *)irg, x);
422 * Walker, clears the private link field.
424 static void clear_link(ir_node * node, void * env) {
425 ird_set_irn_link(node, NULL);
429 * If the entity has a ld_name, returns it if the option dump_ld_name is set,
430 * else returns the name of the entity.
432 const char *get_ent_dump_name(entity *ent) {
434 return "<NULL entity>";
436 /* Don't use get_entity_ld_ident (ent) as it computes the mangled name! */
437 if (ent->ld_name) return get_id_str(ent->ld_name);
439 return get_id_str(ent->name);
442 /* Returns the name of an IRG. */
443 const char *get_irg_dump_name(ir_graph *irg) {
444 /* Don't use get_entity_ld_ident (ent) as it computes the mangled name! */
445 entity *ent = get_irg_entity(irg);
446 return get_ent_dump_name(ent);
450 * Returns non-zero if a node is in floating state.
452 static int node_floats(ir_node *n) {
453 return ((get_irn_pinned(n) == op_pin_state_floats) &&
454 (get_irg_pinned(current_ir_graph) == op_pin_state_floats));
458 * Walker, allocates an array for all blocks and puts it's nodes non-floating nodes into this array.
460 static void collect_node(ir_node * node, void *env) {
463 || get_irn_op(node) == op_Bad
464 || get_irn_op(node) == op_Unknown
465 || get_irn_op(node) == op_NoMem) {
466 ir_node ** arr = (ir_node **) ird_get_irg_link(get_irn_irg(node));
467 if (!arr) arr = NEW_ARR_F(ir_node *, 0);
468 ARR_APP1(ir_node *, arr, node);
469 ird_set_irg_link(get_irn_irg(node), arr); /* arr is an l-value, APP_ARR might change it! */
471 ir_node * block = get_nodes_block(node);
474 /* this node is in a Bad block, so we must place it into the graph's list */
475 ir_node ** arr = (ir_node **) ird_get_irg_link(get_irn_irg(node));
476 if (!arr) arr = NEW_ARR_F(ir_node *, 0);
477 ARR_APP1(ir_node *, arr, node);
478 ird_set_irg_link(get_irn_irg(node), arr); /* arr is an l-value, APP_ARR might change it! */
481 ird_set_irn_link(node, ird_get_irn_link(block));
482 ird_set_irn_link(block, node);
487 /** Construct lists to walk ir block-wise.
489 * Collects all blocks, nodes not op_pin_state_pinned,
490 * Bad, NoMem and Unknown into a flexible array in link field of
491 * irg they belong to. Sets the irg link field to NULL in all
492 * graphs not visited.
493 * Free the list with DEL_ARR_F().
495 static ir_node **construct_block_lists(ir_graph *irg) {
496 int i, rem_view = get_interprocedural_view();
497 ir_graph *rem = current_ir_graph;
498 current_ir_graph = irg;
500 for (i = 0; i < get_irp_n_irgs(); i++)
501 ird_set_irg_link(get_irp_irg(i), NULL);
503 irg_walk_graph(current_ir_graph, clear_link, collect_node, current_ir_graph);
505 /* Collect also EndReg and EndExcept. We do not want to change the walker. */
506 set_interprocedural_view(false);
508 set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph)-1);
509 irg_walk(get_irg_end_reg(current_ir_graph), clear_link, collect_node, current_ir_graph);
510 set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph)-1);
511 irg_walk(get_irg_end_except(current_ir_graph), clear_link, collect_node, current_ir_graph);
513 set_interprocedural_view(rem_view);
515 current_ir_graph = rem;
516 return ird_get_irg_link(irg);
519 typedef struct _list_tuple {
521 ir_extblk **extbb_list;
524 /** Construct lists to walk ir extended block-wise.
525 * Free the lists in the tuple with DEL_ARR_F().
527 static list_tuple *construct_extblock_lists(ir_graph *irg) {
528 ir_node **blk_list = construct_block_lists(irg);
530 ir_graph *rem = current_ir_graph;
531 list_tuple *lists = xmalloc(sizeof(*lists));
533 current_ir_graph = irg;
535 lists->blk_list = NEW_ARR_F(ir_node *, 0);
536 lists->extbb_list = NEW_ARR_F(ir_extblk *, 0);
538 for (i = ARR_LEN(blk_list) - 1; i >= 0; --i) {
541 if (is_Block(blk_list[i])) {
542 ext = get_Block_extbb(blk_list[i]);
544 if (extbb_not_visited(ext)) {
545 ARR_APP1(ir_extblk *, lists->extbb_list, ext);
546 mark_extbb_visited(ext);
550 ARR_APP1(ir_node *, lists->blk_list, blk_list[i]);
553 current_ir_graph = rem;
555 ird_set_irg_link(irg, lists);
559 /*-----------------------------------------------------------------*/
560 /* Routines to dump information about a single ir node. */
561 /*-----------------------------------------------------------------*/
564 * dump the name of a node n to the File F.
567 dump_node_opcode(FILE *F, ir_node *n)
571 switch(get_irn_opcode(n)) {
576 res = tarval_snprintf(buf, sizeof(buf), get_Const_tarval(n));
577 assert(res < sizeof(buf) && "buffer to small for tarval_snprintf");
582 if (get_SymConst_kind(n) == symconst_addr_name) {
583 /* don't use get_SymConst_ptr_info as it mangles the name. */
584 fprintf (F, "SymC %s", get_id_str(get_SymConst_name(n)));
585 } else if (get_SymConst_kind(n) == symconst_addr_ent) {
586 assert(get_SymConst_entity(n));
587 assert(is_entity(get_SymConst_entity(n)));
588 fprintf (F, "SymC &%s", get_entity_name(get_SymConst_entity(n)));
590 assert(get_kind(get_SymConst_type(n)) == k_type);
591 assert(get_type_ident(get_SymConst_type(n)));
592 fprintf (F, "SymC %s ", get_type_name_ex(get_SymConst_type(n), &bad));
593 if (get_SymConst_kind(n) == symconst_type_tag)
601 if (!get_interprocedural_view())
608 ir_node *pred = get_Proj_pred(n);
610 if (get_irn_opcode(pred) == iro_Cond
611 && get_Proj_proj(n) == get_Cond_defaultProj(pred)
612 && get_irn_mode(get_Cond_selector(pred)) != mode_b)
613 fprintf (F, "defProj");
621 if (get_interprocedural_view()) {
622 fprintf(F, "%s %s", get_irn_opname(n), get_ent_dump_name(get_irg_entity(get_irn_irg(n))));
627 case iro_CallBegin: {
628 ir_node *addr = get_CallBegin_ptr(n);
630 if (get_irn_op(addr) == op_Sel)
631 ent = get_Sel_entity(addr);
632 else if ((get_irn_op(addr) == op_SymConst) && (get_SymConst_kind(addr) == symconst_addr_ent))
633 ent = get_SymConst_entity(addr);
634 fprintf (F, "%s", get_irn_opname(n));
635 if (ent) fprintf (F, " %s", get_entity_name(ent));
639 fprintf (F, "%s[%s]", get_irn_opname(n), get_mode_name_ex(get_Load_mode(n), &bad));
644 fprintf (F, "%s", get_irn_opname(n));
652 * Dump the mode of a node n to a file F.
653 * Ignore modes that are "always known".
656 dump_node_mode(FILE *F, ir_node *n)
659 opcode iro = get_irn_opcode(n);
672 ir_mode *mode = get_irn_mode(n);
674 if (mode && mode != mode_BB && mode != mode_ANY && mode != mode_BAD &&
675 (mode != mode_T || iro == iro_Proj))
676 fprintf(F, "%s", get_mode_name_ex(mode, &bad));
684 * Dump the type of a node n to a file F if it's known.
686 static int dump_node_typeinfo(FILE *F, ir_node *n) {
689 if (opt_dump_analysed_type_info) {
690 if (get_irg_typeinfo_state(current_ir_graph) == ir_typeinfo_consistent ||
691 get_irg_typeinfo_state(current_ir_graph) == ir_typeinfo_inconsistent) {
692 type *tp = get_irn_typeinfo_type(n);
693 if (tp != firm_none_type)
694 fprintf(F, "[%s] ", get_type_name_ex(tp, &bad));
702 typedef struct _pns_lookup {
703 long nr; /**< the proj number */
704 const char *name; /**< the name of the Proj */
707 typedef struct _proj_lookup {
708 opcode code; /**< the opcode of the Proj predecessor */
709 unsigned num_data; /**< number of data entries */
710 const pns_lookup_t *data; /**< the data */
713 #define ARR_SIZE(a) (sizeof(a)/sizeof(a[0]))
715 /** the lookup table for Proj(Start) names */
716 static const pns_lookup_t start_lut[] = {
717 #define X(a) { pn_Start_##a, #a }
726 /** the lookup table for Proj(Cond) names */
727 static const pns_lookup_t cond_lut[] = {
728 #define X(a) { pn_Cond_##a, #a }
734 /** the lookup table for Proj(Call) names */
735 static const pns_lookup_t call_lut[] = {
736 #define X(a) { pn_Call_##a, #a }
745 /** the lookup table for Proj(Quot) names */
746 static const pns_lookup_t quot_lut[] = {
747 #define X(a) { pn_Quot_##a, #a }
754 /** the lookup table for Proj(DivMod) names */
755 static const pns_lookup_t divmod_lut[] = {
756 #define X(a) { pn_DivMod_##a, #a }
764 /** the lookup table for Proj(Div) names */
765 static const pns_lookup_t div_lut[] = {
766 #define X(a) { pn_Div_##a, #a }
773 /** the lookup table for Proj(Mod) names */
774 static const pns_lookup_t mod_lut[] = {
775 #define X(a) { pn_Mod_##a, #a }
782 /** the lookup table for Proj(Load) names */
783 static const pns_lookup_t load_lut[] = {
784 #define X(a) { pn_Load_##a, #a }
791 /** the lookup table for Proj(Store) names */
792 static const pns_lookup_t store_lut[] = {
793 #define X(a) { pn_Store_##a, #a }
799 /** the lookup table for Proj(Alloc) names */
800 static const pns_lookup_t alloc_lut[] = {
801 #define X(a) { pn_Alloc_##a, #a }
809 /** the Proj lookup table */
810 static const proj_lookup_t proj_lut[] = {
811 #define E(a) ARR_SIZE(a), a
812 { iro_Start, E(start_lut) },
813 { iro_Cond, E(cond_lut) },
814 { iro_Call, E(call_lut) },
815 { iro_Quot, E(quot_lut) },
816 { iro_DivMod, E(divmod_lut) },
817 { iro_Div, E(div_lut) },
818 { iro_Mod, E(mod_lut) },
819 { iro_Load, E(load_lut) },
820 { iro_Store, E(store_lut) },
821 { iro_Alloc, E(alloc_lut) }
826 * Dump additional node attributes of some nodes to a file F.
829 dump_node_nodeattr(FILE *F, ir_node *n)
836 switch (get_irn_opcode(n)) {
838 if (false && get_interprocedural_view()) {
839 fprintf (F, "%s ", get_ent_dump_name(get_irg_entity(current_ir_graph)));
844 pred = get_Proj_pred(n);
845 proj_nr = get_Proj_proj(n);
847 code = get_irn_opcode(pred);
850 fprintf (F, "%s ", get_pnc_string(get_Proj_proj(n)));
851 else if (code == iro_Proj && get_irn_opcode(get_Proj_pred(pred)) == iro_Start)
852 fprintf (F, "Arg %ld ", proj_nr);
854 unsigned i, j, f = 0;
856 for (i = 0; i < ARR_SIZE(proj_lut); ++i) {
857 if (code == proj_lut[i].code) {
858 for (j = 0; j < proj_lut[i].num_data; ++j) {
859 if (proj_nr == proj_lut[i].data[j].nr) {
860 fprintf (F, "%s ", proj_lut[i].data[j].name);
869 fprintf (F, "%ld ", proj_nr);
873 proj_nr = get_Filter_proj(n);
874 if (! get_interprocedural_view()) {
876 pred = get_Filter_pred(n);
880 fprintf (F, "%ld ", proj_nr);
883 fprintf (F, "%s ", get_ent_dump_name(get_Sel_entity(n)));
886 fprintf (F, "(%s) ", get_type_name_ex(get_Cast_type(n), &bad));
889 fprintf (F, "%s ", get_pnc_string(get_Confirm_cmp(n)));
900 #include "execution_frequency.h"
901 #include "callgraph.h"
903 void dump_node_ana_vals(FILE *F, ir_node *n) {
905 fprintf(F, " %lf*(%2.0lf + %2.0lf) = %2.0lf ",
906 get_irn_exec_freq(n),
907 get_irg_method_execution_frequency(get_irn_irg(n)),
908 pow(5, get_irg_recursion_depth(get_irn_irg(n))),
909 get_irn_exec_freq(n) * (get_irg_method_execution_frequency(get_irn_irg(n)) + pow(5, get_irg_recursion_depth(get_irn_irg(n))))
914 /* Dumps a node label without the enclosing ". */
915 int dump_node_label(FILE *F, ir_node *n) {
918 bad |= dump_node_opcode(F, n);
919 bad |= dump_node_mode(F, n);
921 bad |= dump_node_typeinfo(F, n);
922 bad |= dump_node_nodeattr(F, n);
923 fprintf(F, "%ld", get_irn_node_nr(n));
930 * Dumps the attributes of a node n into the file F.
931 * Currently this is only the color of a node.
933 static void dump_node_vcgattr(FILE *F, ir_node *node, ir_node *local, int bad)
938 fprintf(F, "color: red");
942 if (dump_node_vcgattr_hook)
943 if (dump_node_vcgattr_hook(F, node, local))
946 n = local ? local : node;
948 switch (get_irn_opcode(n)) {
955 fprintf (F, "color: blue");
958 if (is_Block_dead(n))
959 fprintf (F, "color: lightred");
961 fprintf (F, "color: lightyellow");
964 fprintf (F, "color: green");
970 fprintf (F, "color: yellow");
973 PRINT_DEFAULT_NODE_ATTR;
976 if (overrule_nodecolor) fprintf(F, " color: %s", overrule_nodecolor);
981 * Dump the node information of a node n to a file F.
983 static INLINE int dump_node_info(FILE *F, ir_node *n)
985 fprintf (F, " info1: \"");
986 bad = dump_irnode_to_file(F, n);
992 * checks whether a node is "constant-like" ie can be treated "block-less"
995 bool is_constlike_node(ir_node *n) {
996 ir_op *op = get_irn_op(n);
997 return (op == op_Const || op == op_Bad || op == op_NoMem || op == op_SymConst || op == op_Unknown);
1001 /** outputs the predecessors of n, that are constants, local. I.e.,
1002 generates a copy of the constant predecessors for each node called with. */
1003 static void dump_const_node_local(FILE *F, ir_node *n) {
1005 if (!get_opt_dump_const_local()) return;
1007 /* Use visited flag to avoid outputting nodes twice.
1008 initialize it first. */
1009 for (i = 0; i < get_irn_arity(n); i++) {
1010 ir_node *con = get_irn_n(n, i);
1011 if (is_constlike_node(con)) {
1012 set_irn_visited(con, get_irg_visited(current_ir_graph) - 1);
1016 for (i = 0; i < get_irn_arity(n); i++) {
1017 ir_node *con = get_irn_n(n, i);
1018 if (is_constlike_node(con) && irn_not_visited(con)) {
1021 mark_irn_visited(con);
1022 /* Generate a new name for the node by appending the names of
1024 fprintf(F, "node: {title: "); PRINT_CONSTID(n, con);
1025 fprintf(F, " label: \"");
1026 bad |= dump_node_label(F, con);
1028 bad |= dump_node_info(F, con);
1029 dump_node_vcgattr(F, n, con, bad);
1035 /** If the block of an edge is a const_like node, dump it local with an edge */
1036 static void dump_const_block_local(FILE *F, ir_node *n) {
1039 if (!get_opt_dump_const_local()) return;
1041 blk = get_nodes_block(n);
1042 if (is_constlike_node(blk)) {
1045 /* Generate a new name for the node by appending the names of
1047 fprintf(F, "node: {title: \""); PRINT_CONSTBLKID(n, blk);
1048 fprintf(F, "\" label: \"");
1049 bad |= dump_node_label(F, blk);
1051 bad |= dump_node_info(F, blk);
1052 dump_node_vcgattr(F, n, blk, bad);
1055 fprintf (F, "edge: { sourcename: \"");
1057 fprintf (F, "\" targetname: \""); PRINT_CONSTBLKID(n,blk);
1058 fprintf (F, "\" " BLOCK_EDGE_ATTR "}\n");
1063 * prints the error message of a node to a file F as info2.
1065 static void INLINE print_node_error(FILE *F, const char *err_msg)
1070 fprintf (F, " info2: \"%s\"", err_msg);
1074 * prints debug messages of a node to file F as info3.
1076 static void print_node_dbg_info(FILE *F, dbg_info *dbg)
1080 if (__dbg_info_snprint) {
1082 if (__dbg_info_snprint(buf, sizeof(buf), dbg) > 0)
1083 fprintf (F, " info3: \"%s\"\n", buf);
1090 static void dump_node(FILE *F, ir_node *n)
1095 if (get_opt_dump_const_local() && is_constlike_node(n))
1098 /* dump this node */
1099 fprintf(F, "node: {title: \""); PRINT_NODEID(n); fprintf(F, "\" label: \"");
1101 bad = ! irn_vrfy_irg_dump(n, current_ir_graph, &p);
1102 bad |= dump_node_label(F, n);
1103 dump_node_ana_vals(F, n);
1104 //dump_node_ana_info(F, n);
1106 bad |= dump_node_info(F, n);
1107 print_node_error(F, p);
1108 print_node_dbg_info(F, get_irn_dbg_info(n));
1109 dump_node_vcgattr(F, n, NULL, bad);
1111 dump_const_node_local(F, n);
1113 if(dump_node_edge_hook)
1114 dump_node_edge_hook(F, n);
1116 dump_irn_chi_term(F, n);
1117 dump_irn_state(F, n);
1121 /** dump the edge to the block this node belongs to */
1123 dump_ir_block_edge(FILE *F, ir_node *n) {
1124 if (get_opt_dump_const_local() && is_constlike_node(n)) return;
1125 if (is_no_Block(n)) {
1126 ir_node *block = get_nodes_block(n);
1128 if (get_opt_dump_const_local() && is_constlike_node(block)) {
1129 dump_const_block_local(F, n);
1132 fprintf (F, "edge: { sourcename: \"");
1134 fprintf (F, "\" targetname: ");
1135 fprintf(F, "\""); PRINT_NODEID(block); fprintf(F, "\"");
1136 fprintf (F, " " BLOCK_EDGE_ATTR "}\n");
1142 print_data_edge_vcgattr(FILE *F, ir_node *from, int to) {
1144 * do not use get_nodes_block() here, will fail
1145 * if the irg is not pinned.
1147 if (get_irn_n(from, -1) == get_irn_n(get_irn_n(from, to), -1))
1148 fprintf (F, INTRA_DATA_EDGE_ATTR);
1150 fprintf (F, INTER_DATA_EDGE_ATTR);
1154 print_mem_edge_vcgattr(FILE *F, ir_node *from, int to) {
1156 * do not use get_nodes_block() here, will fail
1157 * if the irg is not pinned.
1159 if (get_irn_n(from, -1) == get_irn_n(get_irn_n(from, to), -1))
1160 fprintf (F, INTRA_MEM_EDGE_ATTR);
1162 fprintf (F, INTER_MEM_EDGE_ATTR);
1166 print_edge_vcgattr(FILE *F, ir_node *from, int to) {
1169 if (dump_backedge_information_flag && is_backedge(from, to))
1170 fprintf (F, BACK_EDGE_ATTR);
1172 switch (get_irn_opcode(from)) {
1174 fprintf (F, CF_EDGE_ATTR);
1176 case iro_Start: break;
1179 if (get_irn_mode(get_End_keepalive(from, to)) == mode_BB)
1180 fprintf (F, CF_EDGE_ATTR);
1181 if (get_irn_mode(get_End_keepalive(from, to)) == mode_X)
1182 fprintf (F, INTER_MEM_EDGE_ATTR);
1190 print_data_edge_vcgattr(F, from, to);
1195 print_mem_edge_vcgattr(F, from, to);
1197 print_data_edge_vcgattr(F, from, to);
1201 print_data_edge_vcgattr(F, from, to);
1206 print_mem_edge_vcgattr(F, from, to);
1208 print_data_edge_vcgattr(F, from, to);
1215 print_data_edge_vcgattr(F, from, to);
1222 print_mem_edge_vcgattr(F, from, to);
1224 print_data_edge_vcgattr(F, from, to);
1236 print_data_edge_vcgattr(F, from, to);
1239 if (get_irn_modecode(from) == irm_M)
1240 fprintf (F, INTER_MEM_EDGE_ATTR);
1242 print_data_edge_vcgattr(F, from, to);
1249 print_mem_edge_vcgattr(F, from, to);
1251 print_data_edge_vcgattr(F, from, to);
1254 print_mem_edge_vcgattr(F, from, to);
1256 case iro_Tuple: break;
1259 switch (get_irn_modecode(from)) {
1261 fprintf (F, CF_EDGE_ATTR);
1264 fprintf (F, INTER_MEM_EDGE_ATTR);
1267 print_data_edge_vcgattr(F, from, to);
1271 case iro_Bad: break;
1272 case iro_Unknown: break;
1274 switch (get_irn_modecode(from)) {
1276 fprintf (F, INTRA_MEM_EDGE_ATTR);
1279 fprintf (F, CF_EDGE_ATTR);
1282 print_data_edge_vcgattr(F, from, to);
1290 /* dump edges to our inputs */
1292 dump_ir_data_edges(FILE *F, ir_node *n) {
1294 unsigned long visited = get_irn_visited(n);
1296 if ((get_irn_op(n) == op_End) && (!dump_keepalive))
1299 for (i = 0; i < get_irn_arity(n); i++) {
1300 ir_node * pred = get_irn_n(n, i);
1303 if ((get_interprocedural_view() && get_irn_visited(pred) < visited))
1304 continue; /* pred not dumped */
1306 if (dump_backedge_information_flag && is_backedge(n, i))
1307 fprintf (F, "backedge: {sourcename: \"");
1309 fprintf (F, "edge: {sourcename: \"");
1311 fprintf (F, "\" targetname: ");
1312 if ((get_opt_dump_const_local()) && is_constlike_node(pred)) {
1313 PRINT_CONSTID(n, pred);
1315 fprintf(F, "\""); PRINT_NODEID(pred); fprintf(F, "\"");
1317 fprintf (F, " label: \"%d\" ", i);
1318 print_edge_vcgattr(F, n, i);
1323 /** Dumps a node and its edges but not the block edge
1326 dump_node_wo_blockedge (ir_node *n, void *env) {
1329 dump_ir_data_edges(F, n);
1332 /** Dumps a node and its edges.
1335 dump_whole_node (ir_node *n, void *env) {
1337 dump_node_wo_blockedge(n, env);
1338 if (!node_floats(n)) dump_ir_block_edge(F, n);
1342 dump_const_node(ir_node *n, void *env) {
1343 if (is_Block(n)) return;
1344 dump_node_wo_blockedge(n, env);
1347 /***********************************************************************/
1348 /* the following routines dump the nodes/irgs bracketed to graphs. */
1349 /***********************************************************************/
1351 /** Dumps a constant expression as entity initializer, array bound ...
1353 static void dump_const_expression(FILE *F, ir_node *value) {
1354 ir_graph *rem = current_ir_graph;
1355 int rem_dump_const_local = dump_const_local;
1356 dump_const_local = 0;
1357 current_ir_graph = get_const_code_irg();
1358 irg_walk(value, dump_const_node, NULL, F);
1359 /* Decrease visited flag so that we walk with the same flag for the next
1360 expression. This guarantees that we don't dump the same node twice,
1361 as for const expressions cse is performed to save memory. */
1362 set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph) -1);
1363 current_ir_graph = rem;
1364 dump_const_local = rem_dump_const_local;
1367 /** Dump a block as graph containing its nodes.
1369 * Expects to find nodes belonging to the block as list in its
1371 * Dumps the edges of all nodes including itself. */
1373 dump_whole_block(FILE *F, ir_node *block) {
1375 assert(is_Block(block));
1377 fprintf(F, "graph: { title: \"");
1378 PRINT_NODEID(block);
1379 fprintf(F, "\" label: \"");
1380 dump_node_label(F, block);
1382 if (get_opt_dump_abstvals())
1383 fprintf (F, " seqno: %d", (int)get_Block_seqno(block));
1385 fprintf(F, "\" status:clustered color:%s \n",
1386 get_Block_matured(block) ? "yellow" : "red");
1388 /* dump the blocks edges */
1389 dump_ir_data_edges(F, block);
1391 /* dump the nodes that go into the block */
1392 for (node = ird_get_irn_link(block); node; node = ird_get_irn_link(node)) {
1394 dump_ir_data_edges(F, node);
1397 /* Close the vcg information for the block */
1399 dump_const_node_local(F, block);
1401 dump_irn_chi_term(F, block);
1406 /** dumps a graph block-wise. Expects all blockless nodes in arr in irgs link.
1407 * The outermost nodes: blocks and nodes not op_pin_state_pinned, Bad, Unknown. */
1409 dump_block_graph(FILE *F, ir_graph *irg) {
1411 ir_graph *rem = current_ir_graph;
1412 ir_node **arr = ird_get_irg_link(irg);
1413 current_ir_graph = irg;
1415 for (i = ARR_LEN(arr) - 1; i >= 0; --i) {
1416 ir_node * node = arr[i];
1417 if (is_Block(node)) {
1418 /* Dumps the block and all the nodes in the block, which are to
1419 be found in Block->link. */
1420 dump_whole_block(F, node);
1422 /* Nodes that are not in a Block. */
1424 if (!node_floats(node) && is_Bad(get_nodes_block(node))) {
1425 dump_const_block_local(F, node);
1427 dump_ir_data_edges(F, node);
1431 if (dump_loop_information_flag && (get_irg_loopinfo_state(irg) & loopinfo_valid))
1432 dump_loop_nodes_into_graph(F, irg);
1434 current_ir_graph = rem;
1437 /** Dumps an irg as a graph clustered by block nodes.
1438 * If interprocedural view edges can point to nodes out of this graph.
1440 static void dump_graph_from_list(FILE *F, ir_graph *irg) {
1442 fprintf(F, "graph: { title: \"");
1444 fprintf(F, "\" label: \"%s\" status:clustered color:white \n",
1445 get_ent_dump_name(get_irg_entity(irg)));
1447 dump_block_graph(F, irg);
1449 /* Close the vcg information for the irg */
1450 fprintf(F, "}\n\n");
1453 /** dumps a graph extended block-wise. Expects all blockless nodes in arr in irgs link.
1454 * The outermost nodes: blocks and nodes not op_pin_state_pinned, Bad, Unknown. */
1456 dump_extblock_graph(FILE *F, ir_graph *irg) {
1458 ir_graph *rem = current_ir_graph;
1459 ir_extblk **arr = ird_get_irg_link(irg);
1460 current_ir_graph = irg;
1463 for (i = ARR_LEN(arr) - 1; i >= 0; --i) {
1464 ir_extblk *extbb = arr[i];
1465 ir_node *leader = extbb->blks[0];
1468 fprintf(F, "graph: { title: \"");
1469 PRINT_EXTBBID(leader);
1470 fprintf(F, "\" label: \"ExtBB %ld\" status:clustered color:lightgreen\n",
1471 get_irn_node_nr(leader));
1473 for (j = ARR_LEN(extbb->blks) - 1; j >= 0; --j) {
1474 ir_node * node = extbb->blks[j];
1475 if (is_Block(node)) {
1476 /* Dumps the block and all the nodes in the block, which are to
1477 be found in Block->link. */
1478 dump_whole_block(F, node);
1480 /* Nodes that are not in a Block. */
1482 if (is_Bad(get_nodes_block(node)) && !node_floats(node)) {
1483 dump_const_block_local(F, node);
1485 dump_ir_data_edges(F, node);
1491 if (dump_loop_information_flag && (get_irg_loopinfo_state(irg) & loopinfo_valid))
1492 dump_loop_nodes_into_graph(F, irg);
1494 current_ir_graph = rem;
1499 /*******************************************************************/
1500 /* Basic type and entity nodes and edges. */
1501 /*******************************************************************/
1503 /** dumps the edges between nodes and their type or entity attributes. */
1504 static void dump_node2type_edges(ir_node *n, void *env)
1509 switch (get_irn_opcode(n)) {
1511 /* @@@ some consts have an entity */
1514 if ( (get_SymConst_kind(n) ==symconst_type_tag)
1515 || (get_SymConst_kind(n) ==symconst_size))
1517 print_node_type_edge(F,n,get_SymConst_type(n),NODE2TYPE_EDGE_ATTR);
1521 print_node_ent_edge(F,n,get_Sel_entity(n),NODE2TYPE_EDGE_ATTR);
1524 print_node_type_edge(F,n,get_Call_type(n),NODE2TYPE_EDGE_ATTR);
1527 print_node_type_edge(F,n,get_Alloc_type(n),NODE2TYPE_EDGE_ATTR);
1530 print_node_type_edge(F,n,get_Free_type(n),NODE2TYPE_EDGE_ATTR);
1533 print_node_type_edge(F,n,get_Cast_type(n),NODE2TYPE_EDGE_ATTR);
1541 static int print_type_info(FILE *F, type *tp) {
1544 if (get_type_state(tp) == layout_undefined) {
1545 fprintf(F, "state: layout_undefined\n");
1547 fprintf(F, "state: layout_fixed,\n");
1549 if (get_type_mode(tp))
1550 fprintf(F, "mode: %s,\n", get_mode_name_ex(get_type_mode(tp), &bad));
1551 fprintf(F, "size: %db,\n", get_type_size_bits(tp));
1556 static void print_typespecific_info(FILE *F, type *tp) {
1557 switch (get_type_tpop_code(tp)) {
1560 fprintf(F, "peculiarity: %s\n", get_peculiarity_string(get_class_peculiarity(tp)));
1567 fprintf(F, "variadicity: %s\n", get_variadicity_name(get_method_variadicity(tp)));
1568 fprintf(F, "params: %d\n", get_method_n_params(tp));
1569 fprintf(F, "results: %d\n", get_method_n_ress(tp));
1577 case tpo_enumeration:
1591 static void print_typespecific_vcgattr(FILE *F, type *tp) {
1592 switch (get_type_tpop_code(tp)) {
1595 if (peculiarity_existent == get_class_peculiarity(tp))
1596 fprintf (F, " " TYPE_CLASS_NODE_ATTR);
1598 fprintf (F, " " TYPE_DESCRIPTION_NODE_ATTR);
1602 fprintf (F, " " TYPE_METH_NODE_ATTR);
1613 case tpo_enumeration:
1627 int dump_type_node(FILE *F, type *tp)
1631 fprintf (F, "node: {title: ");
1633 fprintf (F, " label: \"%s %s\"", get_type_tpop_name(tp), get_type_name_ex(tp, &bad));
1634 fprintf (F, " info1: \"");
1636 bad |= print_type_info(F, tp);
1637 print_typespecific_info(F, tp);
1639 dump_type_to_file(F, tp, dump_verbosity_max);
1641 fprintf (F, "\"\n");
1642 print_node_dbg_info(F, get_type_dbg_info(tp));
1643 print_typespecific_vcgattr(F, tp);
1650 #define X(a) case a: fprintf(F, #a); break
1651 void dump_entity_node(FILE *F, entity *ent, int color)
1653 fprintf (F, "node: {title: \"");
1654 PRINT_ENTID(ent); fprintf(F, "\"");
1655 fprintf (F, DEFAULT_TYPE_ATTRIBUTE);
1656 fprintf (F, "label: ");
1657 fprintf (F, "\"ent %s\" ", get_ent_dump_name(ent));
1659 fprintf(F, "color: %d", color);
1661 fprintf (F, ENTITY_NODE_ATTR);
1662 fprintf (F, "\n info1: \"");
1664 dump_entity_to_file(F, ent, dump_verbosity_entattrs | dump_verbosity_entconsts);
1667 print_node_dbg_info(F, get_entity_dbg_info(ent));
1672 static void dump_enum_item(FILE *F, type *tp, int pos)
1675 ident *id = get_enumeration_nameid(tp, pos);
1676 tarval *tv = get_enumeration_enum(tp, pos);
1678 tarval_snprintf(buf, sizeof(buf), tv);
1679 fprintf (F, "node: {title: \"");
1680 PRINT_ITEMID(tp, pos); fprintf(F, "\"");
1681 fprintf (F, DEFAULT_ENUM_ITEM_ATTRIBUTE);
1682 fprintf (F, "label: ");
1683 fprintf (F, "\"enum item %s\" " ENUM_ITEM_NODE_ATTR, get_id_str(id));
1684 fprintf (F, "\n info1: \"value: %s\"}\n", buf);
1687 /* dumps a type or entity and it's edges. */
1689 dump_type_info(type_or_ent *tore, void *env) {
1691 int i = 0; /* to shutup gcc */
1693 /* dump this type or entity */
1695 switch (get_kind(tore)) {
1698 entity *ent = (entity *)tore;
1701 dump_entity_node(F, ent, 0);
1703 /* skip this to reduce graph. Member edge of type is parallel to this edge. *
1704 fprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
1705 ENT_OWN_EDGE_ATTR "}\n", ent, get_entity_owner(ent));*/
1706 print_ent_type_edge(F,ent, get_entity_type(ent), ENT_TYPE_EDGE_ATTR);
1707 if (is_Class_type(get_entity_owner(ent))) {
1708 for(i = 0; i < get_entity_n_overwrites(ent); i++)
1709 print_ent_ent_edge(F,ent, get_entity_overwrites(ent, i), 0, ENT_OVERWRITES_EDGE_ATTR);
1711 /* attached subgraphs */
1712 if (const_entities && (get_entity_variability(ent) != variability_uninitialized)) {
1713 if (is_atomic_entity(ent)) {
1714 value = get_atomic_ent_value(ent);
1716 print_ent_node_edge(F, ent, value, ENT_VALUE_EDGE_ATTR, i);
1717 /* DDMN(value); $$$ */
1718 dump_const_expression(F, value);
1721 if (is_compound_entity(ent)) {
1722 for (i = 0; i < get_compound_ent_n_values(ent); i++) {
1723 value = get_compound_ent_value(ent, i);
1725 print_ent_node_edge(F, ent, value, ENT_VALUE_EDGE_ATTR, i);
1726 dump_const_expression(F, value);
1727 print_ent_ent_edge(F, ent, get_compound_ent_value_member(ent, i), 0, ENT_CORR_EDGE_ATTR, i);
1729 fprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
1730 ENT_CORR_EDGE_ATTR "}\n", GET_ENTID(ent),
1731 get_compound_ent_value_member(ent, i), i);
1740 type *tp = (type *)tore;
1741 dump_type_node(F, tp);
1742 /* and now the edges */
1743 switch (get_type_tpop_code(tp)) {
1746 for (i=0; i < get_class_n_supertypes(tp); i++)
1747 print_type_type_edge(F, tp,get_class_supertype(tp, i),TYPE_SUPER_EDGE_ATTR);
1748 for (i=0; i < get_class_n_members(tp); i++)
1749 print_type_ent_edge(F,tp,get_class_member(tp, i),TYPE_MEMBER_EDGE_ATTR);
1753 for (i=0; i < get_struct_n_members(tp); i++)
1754 print_type_ent_edge(F,tp,get_struct_member(tp, i),TYPE_MEMBER_EDGE_ATTR);
1758 for (i = 0; i < get_method_n_params(tp); i++)
1759 print_type_type_edge(F,tp,get_method_param_type(tp, i),METH_PAR_EDGE_ATTR,i);
1760 for (i = 0; i < get_method_n_ress(tp); i++)
1761 print_type_type_edge(F,tp,get_method_res_type(tp, i),METH_RES_EDGE_ATTR,i);
1765 for (i = 0; i < get_union_n_members(tp); i++)
1766 print_type_ent_edge(F,tp,get_union_member(tp, i),UNION_EDGE_ATTR);
1770 print_type_type_edge(F,tp,get_array_element_type(tp),ARR_ELT_TYPE_EDGE_ATTR);
1771 print_type_ent_edge(F,tp,get_array_element_entity(tp),ARR_ENT_EDGE_ATTR);
1772 for (i = 0; i < get_array_n_dimensions(tp); i++) {
1773 ir_node *upper = get_array_upper_bound(tp, i);
1774 ir_node *lower = get_array_lower_bound(tp, i);
1775 print_node_type_edge(F, upper, tp, "label: \"upper %d\"", get_array_order(tp, i));
1776 print_node_type_edge(F, lower, tp, "label: \"lower %d\"", get_array_order(tp, i));
1777 dump_const_expression(F, upper);
1778 dump_const_expression(F, lower);
1782 case tpo_enumeration:
1784 for (i = 0; i < get_enumeration_n_enums(tp); ++i) {
1785 dump_enum_item(F, tp, i);
1786 print_enum_item_edge(F, tp, i, "label: \"item %d\"", i);
1791 print_type_type_edge(F,tp,get_pointer_points_to_type(tp), PTR_PTS_TO_EDGE_ATTR);
1799 break; /* case k_type */
1802 printf(" *** irdump, dump_type_info(l.%i), faulty type.\n", __LINE__);
1804 } /* switch kind_or_entity */
1807 typedef struct _h_env {
1812 /** For dumping class hierarchies.
1813 * Dumps a class type node and a superclass edge.
1814 * If env->dump_ent dumps entities of classes and overwrites edges.
1817 dump_class_hierarchy_node (type_or_ent *tore, void *ctx) {
1820 int i = 0; /* to shutup gcc */
1822 /* dump this type or entity */
1823 switch (get_kind(tore)) {
1825 entity *ent = (entity *)tore;
1826 if (get_entity_owner(ent) == get_glob_type()) break;
1827 if (!is_Method_type(get_entity_type(ent))) break; /* GL */
1828 if (env->dump_ent && is_Class_type(get_entity_owner(ent))) {
1830 dump_entity_node(F, ent, 0);
1832 print_type_ent_edge(F,get_entity_owner(ent),ent,TYPE_MEMBER_EDGE_ATTR);
1833 for(i = 0; i < get_entity_n_overwrites(ent); i++)
1834 print_ent_ent_edge(F, get_entity_overwrites(ent, i), ent, 0, ENT_OVERWRITES_EDGE_ATTR);
1836 } break; /* case k_entity */
1839 type *tp = (type *)tore;
1840 if (tp == get_glob_type()) break;
1841 switch (get_type_tpop_code(tp)) {
1843 dump_type_node(F, tp);
1844 /* and now the edges */
1845 for (i=0; i < get_class_n_supertypes(tp); i++)
1847 print_type_type_edge(F,tp,get_class_supertype(tp, i),TYPE_SUPER_EDGE_ATTR);
1853 break; /* case k_type */
1856 printf(" *** irdump, dump_class_hierarchy_node(l.%i), faulty type.\n", __LINE__);
1858 } /* switch kind_or_entity */
1861 /*******************************************************************/
1862 /* dump analysis information that is expressed in graph terms. */
1863 /*******************************************************************/
1865 /* dump out edges */
1867 dump_out_edge(ir_node *n, void *env) {
1870 for (i = 0; i < get_irn_n_outs(n); i++) {
1871 assert(get_irn_out(n, i));
1872 fprintf (F, "edge: {sourcename: \"");
1874 fprintf (F, "\" targetname: \"");
1875 PRINT_NODEID(get_irn_out(n, i));
1876 fprintf (F, "\" color: red linestyle: dashed");
1882 dump_loop_label(FILE *F, ir_loop *loop) {
1883 fprintf (F, "loop %d, %d sons, %d nodes",
1884 get_loop_depth(loop), get_loop_n_sons(loop), get_loop_n_nodes(loop));
1887 static INLINE void dump_loop_info(FILE *F, ir_loop *loop) {
1888 fprintf (F, " info1: \"");
1889 fprintf (F, " loop nr: %d", get_loop_loop_nr(loop));
1890 #if DEBUG_libfirm /* GL @@@ debug analyses */
1891 fprintf (F, "\n The loop was analyzed %d times.", (int)get_loop_link(loop));
1897 dump_loop_node(FILE *F, ir_loop *loop) {
1898 fprintf (F, "node: {title: \"");
1900 fprintf (F, "\" label: \"");
1901 dump_loop_label(F, loop);
1903 dump_loop_info(F, loop);
1909 dump_loop_node_edge(FILE *F, ir_loop *loop, int i) {
1911 fprintf (F, "edge: {sourcename: \"");
1913 fprintf (F, "\" targetname: \"");
1914 PRINT_NODEID(get_loop_node(loop, i));
1915 fprintf (F, "\" color: green");
1920 dump_loop_son_edge(FILE *F, ir_loop *loop, int i) {
1922 fprintf (F, "edge: {sourcename: \"");
1924 fprintf (F, "\" targetname: \"");
1925 PRINT_LOOPID(get_loop_son(loop, i));
1926 fprintf (F, "\" color: darkgreen label: \"%d\"}\n",
1927 get_loop_element_pos(loop, get_loop_son(loop, i)));
1931 void dump_loops(FILE *F, ir_loop *loop) {
1933 /* dump this loop node */
1934 dump_loop_node(F, loop);
1936 /* dump edges to nodes in loop -- only if it is a real loop */
1937 if (get_loop_depth(loop) != 0) {
1938 for (i = 0; i < get_loop_n_nodes(loop); i++) {
1939 dump_loop_node_edge(F, loop, i);
1942 for (i = 0; i < get_loop_n_sons(loop); i++) {
1943 dump_loops(F, get_loop_son(loop, i));
1944 dump_loop_son_edge(F, loop, i);
1949 void dump_loop_nodes_into_graph(FILE *F, ir_graph *irg) {
1950 ir_graph *rem = current_ir_graph;
1951 current_ir_graph = irg;
1953 if (get_irg_loop(irg)) dump_loops(F, get_irg_loop(irg));
1955 current_ir_graph = rem;
1960 * dumps the VCG header
1962 void dump_vcg_header(FILE *F, const char *name, const char *orientation) {
1971 if (!orientation) orientation = "bottom_to_top";
1975 "graph: { title: \"ir graph of %s\"\n"
1976 "display_edge_labels: %s\n"
1977 "layoutalgorithm: mindepth\n"
1978 "manhattan_edges: yes\n"
1979 "port_sharing: no\n"
1981 "classname 1: \"intrablock Data\"\n"
1982 "classname 16: \"interblock Data\"\n"
1983 "classname 2: \"Block\"\n"
1984 "classname 13: \"Control Flow\"\n"
1985 "classname 18: \"Exception Control Flow for Interval Analysis\"\n"
1986 "classname 14: \"intrablock Memory\"\n"
1987 "classname 17: \"interblock Memory\"\n"
1988 "classname 15: \"Dominators\"\n"
1989 "classname 3: \"Entity type\"\n"
1990 "classname 4: \"Entity owner\"\n"
1991 "classname 5: \"Method Param\"\n"
1992 "classname 6: \"Method Res\"\n"
1993 "classname 7: \"Super\"\n"
1994 "classname 8: \"Union\"\n"
1995 "classname 9: \"Points-to\"\n"
1996 "classname 10: \"Array Element Type\"\n"
1997 "classname 11: \"Overwrites\"\n"
1998 "classname 12: \"Member\"\n"
1999 "infoname 1: \"Attribute\"\n"
2000 "infoname 2: \"Verification errors\"\n"
2001 "infoname 3: \"Debug info\"\n",
2002 name, label, orientation);
2004 /* don't use all, the range is too whith/black. */
2008 "colorentry 100: 0 0 0\n"
2009 "colorentry 101: 20 0 0\n"
2010 "colorentry 102: 40 0 0\n"
2011 "colorentry 103: 60 0 0\n"
2012 "colorentry 104: 80 0 0\n"
2013 "colorentry 105: 100 0 0\n"
2014 "colorentry 106: 120 0 0\n"
2015 "colorentry 107: 140 0 0\n"
2016 "colorentry 108: 150 0 0\n"
2017 "colorentry 109: 180 0 0\n"
2018 "colorentry 110: 200 0 0\n"
2019 "colorentry 111: 220 0 0\n"
2020 "colorentry 112: 240 0 0\n"
2021 "colorentry 113: 255 0 0\n"
2022 "colorentry 113: 255 20 20\n"
2023 "colorentry 114: 255 40 40\n"
2024 "colorentry 115: 255 60 60\n"
2025 "colorentry 116: 255 80 80\n"
2026 "colorentry 117: 255 100 100\n"
2027 "colorentry 118: 255 120 120\n"
2028 "colorentry 119: 255 140 140\n"
2029 "colorentry 120: 255 150 150\n"
2030 "colorentry 121: 255 180 180\n"
2031 "colorentry 122: 255 200 200\n"
2032 "colorentry 123: 255 220 220\n"
2033 "colorentry 124: 255 240 240\n"
2034 "colorentry 125: 255 250 250\n"
2037 fprintf (F, "\n"); /* a separator */
2043 * @param irg The graph to be dumped
2044 * @param suffix1 first filename suffix
2045 * @param suffix2 second filename suffix
2047 FILE *vcg_open (ir_graph *irg, const char * suffix1, const char *suffix2) {
2049 const char *nm = get_irg_dump_name(irg);
2050 int len = strlen(nm), i, j;
2051 char *fname; /* filename to put the vcg information in */
2053 if (!suffix1) suffix1 = "";
2054 if (!suffix2) suffix2 = "";
2056 /* open file for vcg graph */
2057 fname = malloc (len * 2 + strlen(suffix1) + strlen(suffix2) + 5);
2059 /* strncpy (fname, nm, len); */ /* copy the filename */
2061 for (i = 0; i < len; ++i) { /* replace '/' in the name: escape by @. */
2063 fname[j] = '@'; j++; fname[j] = '1'; j++;
2064 } else if (nm[i] == '@') {
2065 fname[j] = '@'; j++; fname[j] = '2'; j++;
2067 fname[j] = nm[i]; j++;
2071 strcat (fname, suffix1); /* append file suffix */
2072 strcat (fname, suffix2); /* append file suffix */
2073 strcat (fname, ".vcg"); /* append the .vcg suffix */
2075 /* vcg really expect only a <CR> at end of line, so
2076 * the "b"inary mode is what you mean (and even needed for Win32)
2078 F = fopen (fname, "wb"); /* open file for writing */
2080 panic("cannot open %s for writing (%m)", fname); /* not reached */
2090 * @param name prefix file name
2091 * @param suffix filename suffix
2093 FILE *vcg_open_name (const char *name, const char *suffix) {
2095 char *fname; /* filename to put the vcg information in */
2096 int i, j, len = strlen(name);
2098 if (!suffix) suffix = "";
2100 /** open file for vcg graph */
2101 fname = xmalloc(len * 2 + 5 + strlen(suffix));
2102 /* strcpy (fname, name);*/ /* copy the filename */
2104 for (i = 0; i < len; ++i) { /* replace '/' in the name: escape by @. */
2105 if (name[i] == '/') {
2106 fname[j] = '@'; j++; fname[j] = '1'; j++;
2107 } else if (name[i] == '@') {
2108 fname[j] = '@'; j++; fname[j] = '2'; j++;
2110 fname[j] = name[i]; j++;
2114 strcat (fname, suffix);
2115 strcat (fname, ".vcg"); /* append the .vcg suffix */
2117 /* vcg really expect only a <CR> at end of line, so
2118 * the "b"inary mode is what you mean (and even needed for Win32)
2120 F = fopen (fname, "wb"); /* open file for writing */
2122 panic ("cannot open %s for writing (%m)", fname); /* not reached */
2130 * Dumps the vcg file footer
2132 static INLINE void dump_vcg_footer (FILE *F) {
2137 * close the vcg file
2139 void vcg_close (FILE *F) {
2140 dump_vcg_footer(F); /* print footer */
2141 fclose (F); /* close vcg file */
2144 /************************************************************************/
2145 /************************************************************************/
2146 /* Routines that dump all or parts of the firm representation to a file */
2147 /************************************************************************/
2148 /************************************************************************/
2150 /************************************************************************/
2151 /* Dump ir graphs, different formats and additional information. */
2152 /************************************************************************/
2154 /** Routine to dump a graph, blocks as conventional nodes. */
2156 dump_ir_graph (ir_graph *irg, const char *suffix )
2161 rem = current_ir_graph;
2163 if (!is_filtered_dump_name(get_entity_ident(get_irg_entity(irg)))) return;
2165 current_ir_graph = irg;
2166 if (get_interprocedural_view()) suffix1 = "-pure-ip";
2167 else suffix1 = "-pure";
2168 f = vcg_open(irg, suffix, suffix1);
2169 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
2171 /* walk over the graph */
2172 /* dump_whole_node must be called in post visiting predecessors */
2173 irg_walk(get_irg_end(irg), NULL, dump_whole_node, f);
2175 /* dump the out edges in a separate walk */
2176 if ((dump_out_edge_flag) && (get_irg_outs_state(irg) != outs_none)) {
2177 irg_out_walk(get_irg_start(irg), dump_out_edge, NULL, f);
2182 current_ir_graph = rem;
2185 /* Dump a firm graph without explicit block nodes. */
2186 void dump_ir_block_graph (ir_graph *irg, const char *suffix)
2192 if (!is_filtered_dump_name(get_entity_ident(get_irg_entity(irg))))
2195 if (get_interprocedural_view()) suffix1 = "-ip";
2197 f = vcg_open(irg, suffix, suffix1);
2198 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
2200 construct_block_lists(irg);
2203 * If we are in the interprocedural view, we dump not
2204 * only the requested irg but also all irgs that can be reached
2207 for (i = 0; i < get_irp_n_irgs(); i++) {
2208 ir_node **arr = ird_get_irg_link(get_irp_irg(i));
2210 dump_graph_from_list(f, get_irp_irg(i));
2218 /* Dump a firm graph without explicit block nodes but grouped in extended blocks. */
2219 void dump_ir_extblock_graph (ir_graph *irg, const char *suffix)
2225 if (!is_filtered_dump_name(get_entity_ident(get_irg_entity(irg))))
2230 if (get_interprocedural_view()) suffix1 = "-ip";
2232 F = vcg_open(irg, suffix, suffix1);
2233 dump_vcg_header(F, get_irg_dump_name(irg), NULL);
2235 construct_extblock_lists(irg);
2237 fprintf(F, "graph: { title: \"");
2239 fprintf(F, "\" label: \"%s\" status:clustered color:white \n",
2240 get_ent_dump_name(get_irg_entity(irg)));
2242 for (i = 0; i < get_irp_n_irgs(); i++) {
2243 ir_graph *irg = get_irp_irg(i);
2244 list_tuple *lists = ird_get_irg_link(irg);
2247 /* dump the extended blocks first */
2248 if (ARR_LEN(lists->extbb_list)) {
2249 ird_set_irg_link(irg, lists->extbb_list);
2250 dump_extblock_graph(F, irg);
2253 /* we may have blocks without extended blocks, bad for instance */
2254 if (ARR_LEN(lists->blk_list)) {
2255 ird_set_irg_link(irg, lists->blk_list);
2256 dump_block_graph(F, irg);
2259 DEL_ARR_F(lists->extbb_list);
2260 DEL_ARR_F(lists->blk_list);
2265 /* Close the vcg information for the irg */
2266 fprintf(F, "}\n\n");
2272 /* dumps a graph with type information */
2274 dump_ir_graph_w_types (ir_graph *irg, const char *suffix)
2277 ir_graph *rem = current_ir_graph;
2280 /* if a filter is set, dump only the irg's that match the filter */
2281 if (!is_filtered_dump_name(get_entity_ident(get_irg_entity(irg))))
2284 current_ir_graph = irg;
2286 if (get_interprocedural_view()) suffix1 = "-pure-wtypes-ip";
2287 else suffix1 = "-pure-wtypes";
2288 f = vcg_open(irg,suffix, suffix1);
2289 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
2291 /* dump common ir graph */
2292 irg_walk(get_irg_end(irg), NULL, dump_whole_node, f);
2293 /* dump type info */
2294 type_walk_irg(irg, dump_type_info, NULL, f);
2295 inc_irg_visited(get_const_code_irg());
2296 /* dump edges from graph to type info */
2297 irg_walk(get_irg_end(irg), dump_node2type_edges, NULL, f);
2300 current_ir_graph = rem;
2304 dump_ir_block_graph_w_types (ir_graph *irg, const char *suffix)
2309 ir_graph *rem = current_ir_graph;
2311 /* if a filter is set, dump only the irg's that match the filter */
2312 if (!is_filtered_dump_name(get_entity_ident(get_irg_entity(irg))))
2315 if (get_interprocedural_view()) suffix1 = "-wtypes-ip";
2316 else suffix1 = "-wtypes";
2317 f = vcg_open(irg, suffix, suffix1);
2318 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
2320 /* dump common blocked ir graph */
2321 construct_block_lists(irg);
2323 for (i = 0; i < get_irp_n_irgs(); i++) {
2324 ir_node **arr = ird_get_irg_link(get_irp_irg(i));
2326 dump_graph_from_list(f, get_irp_irg(i));
2331 /* dump type info */
2332 current_ir_graph = irg;
2333 type_walk_irg(irg, dump_type_info, NULL, f);
2334 inc_irg_visited(get_const_code_irg());
2336 /* dump edges from graph to type info */
2337 irg_walk(get_irg_end(irg), dump_node2type_edges, NULL, f);
2339 current_ir_graph = rem;
2343 /*---------------------------------------------------------------------*/
2344 /* The following routines dump a control flow graph. */
2345 /*---------------------------------------------------------------------*/
2348 dump_block_to_cfg(ir_node *block, void *env) {
2353 if (is_Block(block)) {
2354 /* This is a block. Dump a node for the block. */
2355 fprintf (F, "node: {title: \""); PRINT_NODEID(block);
2356 fprintf (F, "\" label: \"");
2357 if (block == get_irg_start_block(get_irn_irg(block)))
2358 fprintf(F, "Start ");
2359 if (block == get_irg_end_block(get_irn_irg(block)))
2362 fprintf (F, "%s ", get_op_name(get_irn_op(block)));
2363 PRINT_NODEID(block);
2365 fprintf(F, "info1:\"");
2368 if (dump_dominator_information_flag) {
2369 fprintf(F, "dom depth %d\n", get_Block_dom_depth(block));
2370 fprintf(F, "tree pre num %d\n", get_Block_dom_tree_pre_num(block));
2371 fprintf(F, "max subtree pre num %d\n", get_Block_dom_max_subtree_pre_num(block));
2374 /* show arity and possible Bad predecessors of the block */
2375 fprintf(F, "arity: %d\n", get_Block_n_cfgpreds(block));
2376 for (fl = i = 0; i < get_Block_n_cfgpreds(block); ++i) {
2377 ir_node *pred = get_Block_cfgpred(block, i);
2380 fprintf(F, "Bad pred at pos: ");
2381 fprintf(F, "%d ", i);
2388 /* the generic version. */
2389 dump_irnode_to_file(F, block);
2391 /* Check whether we have bad predecessors to color the block. */
2392 for (i = 0; i < get_Block_n_cfgpreds(block); ++i)
2393 if ((fl = is_Bad(get_Block_cfgpred(block, i))))
2397 fprintf (F, "\""); /* closing quote of info */
2399 if ((block == get_irg_start_block(get_irn_irg(block))) ||
2400 (block == get_irg_end_block(get_irn_irg(block))) )
2401 fprintf(F, " color:blue ");
2403 fprintf(F, " color:yellow ");
2406 /* Dump the edges */
2407 for ( i = 0; i < get_Block_n_cfgpreds(block); i++)
2408 if (get_irn_op(skip_Proj(get_Block_cfgpred(block, i))) != op_Bad) {
2409 pred = get_nodes_block(skip_Proj(get_Block_cfgpred(block, i)));
2410 fprintf (F, "edge: { sourcename: \"");
2411 PRINT_NODEID(block);
2412 fprintf (F, "\" targetname: \"");
2414 fprintf (F, "\"}\n");
2417 /* Dump dominator edge */
2418 if (dump_dominator_information_flag && get_Block_idom(block)) {
2419 pred = get_Block_idom(block);
2420 fprintf (F, "edge: { sourcename: \"");
2421 PRINT_NODEID(block);
2422 fprintf (F, "\" targetname: \"");
2424 fprintf (F, "\" " DOMINATOR_EDGE_ATTR "}\n");
2430 dump_cfg (ir_graph *irg, const char *suffix)
2433 ir_graph *rem = current_ir_graph;
2434 int ddif = dump_dominator_information_flag;
2435 int ipv = get_interprocedural_view();
2437 /* if a filter is set, dump only the irg's that match the filter */
2438 if (!is_filtered_dump_name(get_entity_ident(get_irg_entity(irg))))
2441 current_ir_graph = irg;
2443 f = vcg_open(irg, suffix, "-cfg");
2444 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
2447 printf("Warning: dumping cfg not in interprocedural view!\n");
2448 set_interprocedural_view(false);
2451 if (get_irg_dom_state(irg) != dom_consistent)
2452 dump_dominator_information_flag = 0;
2454 /* walk over the blocks in the graph */
2455 irg_block_walk(get_irg_end(irg), dump_block_to_cfg, NULL, f);
2456 dump_node(f, get_irg_bad(irg));
2458 dump_dominator_information_flag = ddif;
2459 set_interprocedural_view(ipv);
2461 current_ir_graph = rem;
2465 static void descend_and_dump(FILE *F, ir_node *n, int depth, pset *mark_set) {
2466 if (pset_find_ptr(mark_set, n)) return;
2468 pset_insert_ptr(mark_set, n);
2471 int i, start = is_Block(n) ? 0 : -1;
2472 dump_whole_node(n, F);
2473 for (i = start; i < get_irn_arity(n); ++i)
2474 descend_and_dump(F, get_irn_n(n, i), depth-1, mark_set);
2477 /* Don't dump edges to nodes further out. These might be edges to
2478 nodes we already dumped, if there is a shorter path to these. */
2482 static int subgraph_counter = 0;
2483 void dump_subgraph (ir_node *root, int depth, const char *suffix) {
2486 pset *mark_set = pset_new_ptr(1);
2487 sprintf(buf, "-subg_%03d", subgraph_counter++);
2488 F = vcg_open(get_irn_irg(root), suffix, buf);
2489 dump_vcg_header(F, get_irg_dump_name(get_irn_irg(root)), NULL);
2490 descend_and_dump(F, root, depth, mark_set);
2496 static int weight_overall(int rec, int loop) {
2497 return 2*rec + loop;
2500 static int compute_color (int my, int max) {
2507 /* if small, scale to the full color range. */
2509 my = my * (n_colors/max);
2511 step = 1 + (max / n_colors);
2515 return base_color + n_colors - color;
2518 static int get_entity_color(entity *ent) {
2519 ir_graph *irg = get_entity_irg(ent);
2523 int rec_depth = get_irg_recursion_depth(irg);
2524 int loop_depth = get_irg_loop_depth(irg);
2525 int overall_depth = weight_overall(rec_depth, loop_depth);
2527 int max_rec_depth = irp->max_callgraph_recursion_depth;
2528 int max_loop_depth = irp->max_callgraph_loop_depth;
2529 int max_overall_depth = weight_overall(max_rec_depth, max_loop_depth);
2531 /* int my_rec_color = compute_color(rec_depth, max_rec_depth); */
2532 /* int my_loop_color = compute_color(loop_depth, max_loop_depth); */
2533 int my_overall_color = compute_color(overall_depth, max_overall_depth);;
2535 return my_overall_color;
2539 void dump_callgraph(const char *suffix) {
2541 int i, n_irgs = get_irp_n_irgs();
2542 int rem = edge_label;
2544 //ident *prefix = new_id_from_str("java/");
2546 F = vcg_open_name("Callgraph", suffix);
2547 dump_vcg_header(F, "Callgraph", NULL);
2549 for (i = 0; i < n_irgs; ++i) {
2550 ir_graph *irg = get_irp_irg(i);
2551 entity *ent = get_irg_entity(irg);
2552 int j, n_callees = get_irg_n_callees(irg);
2554 /* Do not dump runtime system. */
2555 //if (id_is_prefix(prefix, get_entity_ld_ident(ent))) continue;
2557 dump_entity_node(F, ent, get_entity_color(ent));
2558 for (j = 0; j < n_callees; ++j) {
2559 entity *c = get_irg_entity(get_irg_callee(irg, j));
2560 //if (id_is_prefix(prefix, get_entity_ld_ident(c))) continue;
2561 int be = is_irg_callee_backedge(irg, j);
2564 "label:\"recursion %d\" color: %d" :
2565 "label:\"calls %d\" color: %d";
2566 print_ent_ent_edge(F, ent, c, be, attr, get_irg_callee_loop_depth(irg, j), get_entity_color(ent));
2574 /* Dump all irgs in interprocedural view to a single file. */
2575 void dump_all_cg_block_graph(const char *suffix) {
2578 int rem_view = get_interprocedural_view();
2579 set_interprocedural_view(true);
2581 f = vcg_open_name("All_graphs", suffix);
2582 dump_vcg_header(f, "All_graphs", NULL);
2584 /* collect nodes in all irgs reachable in call graph*/
2585 for (i = 0; i < get_irp_n_irgs(); i++)
2586 ird_set_irg_link(get_irp_irg(i), NULL);
2588 cg_walk(clear_link, collect_node, NULL);
2590 /* dump all graphs */
2591 for (i = 0; i < get_irp_n_irgs(); i++) {
2592 current_ir_graph = get_irp_irg(i);
2593 assert(ird_get_irg_link(current_ir_graph));
2594 dump_graph_from_list(f, current_ir_graph);
2595 DEL_ARR_F(ird_get_irg_link(current_ir_graph));
2599 set_interprocedural_view(rem_view);
2602 /*---------------------------------------------------------------------*/
2603 /* the following routines dumps type information without any ir nodes. */
2604 /*---------------------------------------------------------------------*/
2607 dump_type_graph (ir_graph *irg, const char *suffix)
2611 rem = current_ir_graph;
2613 /* if a filter is set, dump only the irg's that match the filter */
2614 if (!is_filtered_dump_name(get_entity_ident(get_irg_entity(irg)))) return;
2616 current_ir_graph = irg;
2618 f = vcg_open(irg, suffix, "-type");
2619 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
2621 /* walk over the blocks in the graph */
2622 type_walk_irg(irg, dump_type_info, NULL, f);
2623 /* The walker for the const code can be called several times for the
2624 same (sub) expression. So that no nodes are dumped several times
2625 we decrease the visited flag of the corresponding graph after each
2626 walk. So now increase it finally. */
2627 inc_irg_visited(get_const_code_irg());
2630 current_ir_graph = rem;
2634 dump_all_types (const char *suffix)
2636 FILE *f = vcg_open_name("All_types", suffix);
2637 dump_vcg_header(f, "All_types", NULL);
2638 type_walk(dump_type_info, NULL, f);
2639 inc_irg_visited(get_const_code_irg());
2644 dump_class_hierarchy (bool entities, const char *suffix)
2646 FILE *f = vcg_open_name("class_hierarchy", suffix);
2650 dump_vcg_header(f, "class_hierarchy", NULL);
2655 type_walk(dump_class_hierarchy_node, NULL, &env);
2659 /*---------------------------------------------------------------------*/
2660 /* dumps all graphs with the graph-dumper passed. Possible dumpers: */
2662 /* dump_ir_block_graph */
2664 /* dump_type_graph */
2665 /* dump_ir_graph_w_types */
2666 /*---------------------------------------------------------------------*/
2668 void dump_all_ir_graphs(dump_graph_func *dmp_grph, const char *suffix) {
2669 int i, n_irgs = get_irp_n_irgs();
2670 for (i = 0; i < n_irgs; ++i) {
2671 dmp_grph(get_irp_irg(i), suffix);
2676 /*--------------------------------------------------------------------------------*
2677 * Dumps a stand alone loop graph with firm nodes which belong to one loop node *
2678 * packed together in one subgraph/box *
2679 *--------------------------------------------------------------------------------*/
2681 void dump_loops_standalone(FILE *F, ir_loop *loop) {
2682 int i = 0, loop_node_started = 0, son_number = 0, first = 0;
2684 ir_loop *son = NULL;
2686 /* Dump a new loop node. */
2687 dump_loop_node(F, loop);
2689 /* Dump the loop elements. */
2691 for(i = 0; i < get_loop_n_elements(loop); i++) {
2692 le = get_loop_element(loop, i);
2694 if (get_kind(son) == k_ir_loop) {
2696 /* We are a loop son -> Recurse */
2698 if(loop_node_started) { /* Close the "firm-nodes" node first if we started one. */
2699 fprintf(F, "\" }\n");
2700 fprintf (F, "edge: {sourcename: \"");
2702 fprintf (F, "\" targetname: \"");
2704 fprintf (F, "-%d-nodes\" label:\"%d...%d\"}\n", first, first, i-1);
2705 loop_node_started = 0;
2707 dump_loop_son_edge(F, loop, son_number++);
2708 dump_loops_standalone(F, son);
2709 } else if (get_kind(son) == k_ir_node) {
2710 /* We are a loop node -> Collect firm nodes */
2712 ir_node *n = le.node;
2715 if (!loop_node_started) {
2716 /* Start a new node which contains all firm nodes of the current loop */
2717 fprintf (F, "node: { title: \"");
2719 fprintf (F, "-%d-nodes\" color: lightyellow label: \"", i);
2720 loop_node_started = 1;
2726 bad |= dump_node_label(F, n);
2727 /* Causes indeterministic output: if (is_Block(n)) fprintf (F, "\t ->%d", (int)get_irn_link(n)); */
2728 if (has_backedges(n)) fprintf(F, "\t loop head!");
2729 } else { /* for callgraph loop tree */
2731 assert(get_kind(son) == k_ir_graph);
2733 /* We are a loop node -> Collect firm graphs */
2734 n = (ir_graph *)le.node;
2735 if (!loop_node_started) {
2736 /* Start a new node which contains all firm nodes of the current loop */
2737 fprintf (F, "node: { title: \"");
2739 fprintf (F, "-%d-nodes\" color: lightyellow label: \"", i);
2740 loop_node_started = 1;
2745 fprintf (F, " %s", get_irg_dump_name(n));
2746 /* fprintf (F, " %s (depth %d)", get_irg_dump_name(n), n->callgraph_weighted_loop_depth); */
2750 if (loop_node_started) {
2751 fprintf(F, "\" }\n");
2752 fprintf (F, "edge: {sourcename: \"");
2754 fprintf (F, "\" targetname: \"");
2756 fprintf (F, "-%d-nodes\" label:\"%d...%d\"}\n", first, first, i-1);
2757 loop_node_started = 0;
2761 void dump_loop_tree(ir_graph *irg, const char *suffix)
2764 ir_graph *rem = current_ir_graph;
2765 int el_rem = edge_label;
2768 /* if a filter is set, dump only the irg's that match the filter */
2769 if (!is_filtered_dump_name(get_entity_ident(get_irg_entity(irg)))) return;
2771 current_ir_graph = irg;
2773 f = vcg_open(irg, suffix, "-looptree");
2774 dump_vcg_header(f, get_irg_dump_name(irg), "top_to_bottom");
2776 if (get_irg_loop(irg)) dump_loops_standalone(f, get_irg_loop(irg));
2780 edge_label = el_rem;
2781 current_ir_graph = rem;
2784 void dump_callgraph_loop_tree(const char *suffix) {
2786 F = vcg_open_name("Callgraph_looptree", suffix);
2787 dump_vcg_header(F, "callgraph looptree", "top_to_bottom");
2788 dump_loops_standalone(F, irp->outermost_cg_loop);
2793 /*-----------------------------------------------------------------------------*/
2794 /* Dumps the firm nodes in the loop tree to a graph along with the loop nodes. */
2795 /*-----------------------------------------------------------------------------*/
2797 void collect_nodeloop(FILE *F, ir_loop *loop, eset *loopnodes) {
2798 int i, son_number = 0, node_number = 0;
2800 if (dump_loop_information_flag) dump_loop_node(F, loop);
2802 for (i = 0; i < get_loop_n_elements(loop); i++) {
2803 loop_element le = get_loop_element(loop, i);
2804 if (*(le.kind) == k_ir_loop) {
2805 if (dump_loop_information_flag) dump_loop_son_edge(F, loop, son_number++);
2807 collect_nodeloop(F, le.son, loopnodes);
2809 if (dump_loop_information_flag) dump_loop_node_edge(F, loop, node_number++);
2810 eset_insert(loopnodes, le.node);
2815 void collect_nodeloop_external_nodes(ir_loop *loop, eset *loopnodes, eset *extnodes) {
2818 for(i = 0; i < get_loop_n_elements(loop); i++) {
2819 loop_element le = get_loop_element(loop, i);
2820 if (*(le.kind) == k_ir_loop) {
2822 collect_nodeloop_external_nodes(le.son, loopnodes, extnodes);
2824 if (is_Block(le.node)) start = 0; else start = -1;
2825 for (j = start; j < get_irn_arity(le.node); j++) {
2826 ir_node *pred = get_irn_n(le.node, j);
2827 if (!eset_contains(loopnodes, pred)) {
2828 eset_insert(extnodes, pred);
2829 if (!is_Block(pred)) {
2830 pred = get_nodes_block(pred);
2831 if (!eset_contains(loopnodes, pred)) eset_insert(extnodes, pred);
2839 void dump_loop(ir_loop *l, const char *suffix) {
2842 eset *loopnodes = eset_create();
2843 eset *extnodes = eset_create();
2846 snprintf(name, sizeof(name), "loop_%d", get_loop_loop_nr(l));
2847 F = vcg_open_name (name, suffix);
2848 dump_vcg_header(F, name, NULL);
2850 /* collect all nodes to dump */
2851 collect_nodeloop(F, l, loopnodes);
2852 collect_nodeloop_external_nodes(l, loopnodes, extnodes);
2854 /* build block lists */
2855 for (n = eset_first(loopnodes); n != NULL; n = eset_next(loopnodes))
2856 set_irn_link(n, NULL);
2857 for (n = eset_first(extnodes); n != NULL; n = eset_next(extnodes))
2858 set_irn_link(n, NULL);
2859 for (n = eset_first(loopnodes); n != NULL; n = eset_next(loopnodes))
2861 b = get_nodes_block(n);
2862 set_irn_link(n, get_irn_link(b));
2865 for (n = eset_first(extnodes); n != NULL; n = eset_next(extnodes))
2867 b = get_nodes_block(n);
2868 set_irn_link(n, get_irn_link(b));
2872 for (b = eset_first(loopnodes); b != NULL; b = eset_next(loopnodes))
2874 fprintf(F, "graph: { title: \"");
2876 fprintf(F, "\" label: \"");
2877 dump_node_opcode(F, b);
2878 fprintf (F, " %ld", get_irn_node_nr(b));
2879 fprintf(F, "\" status:clustered color:yellow\n");
2881 /* dump the blocks edges */
2882 dump_ir_data_edges(F, b);
2884 /* dump the nodes that go into the block */
2885 for (n = get_irn_link(b); n; n = get_irn_link(n)) {
2886 if (eset_contains(extnodes, n)) overrule_nodecolor = "lightblue";
2888 overrule_nodecolor = NULL;
2889 if (!eset_contains(extnodes, n)) dump_ir_data_edges(F, n);
2892 /* Close the vcg information for the block */
2894 dump_const_node_local(F, b);
2897 for (b = eset_first(extnodes); b != NULL; b = eset_next(extnodes))
2899 fprintf(F, "graph: { title: \"");
2901 fprintf(F, "\" label: \"");
2902 dump_node_opcode(F, b);
2903 fprintf (F, " %ld", get_irn_node_nr(b));
2904 fprintf(F, "\" status:clustered color:lightblue\n");
2906 /* dump the nodes that go into the block */
2907 for (n = get_irn_link(b); n; n = get_irn_link(n)) {
2908 if (!eset_contains(loopnodes, n)) overrule_nodecolor = "lightblue";
2910 overrule_nodecolor = NULL;
2911 if (eset_contains(loopnodes, n)) dump_ir_data_edges(F, n);
2914 /* Close the vcg information for the block */
2916 dump_const_node_local(F, b);
2920 eset_destroy(loopnodes);
2921 eset_destroy(extnodes);