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"
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 const char *overrule_nodecolor = NULL;
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 * prints the edge from a type S to a type T with additional info fmt, ...
234 static void print_type_type_edge(FILE *F, type *S, type *T, const char *fmt, ...)
239 fprintf(F, "edge: { sourcename: "); PRINT_TYPEID(S);
240 fprintf(F, " targetname: "); PRINT_TYPEID(T);
241 vfprintf(F, fmt, ap);
247 * prints the edge from a type T to an entity E with additional info fmt, ...
250 static void print_type_ent_edge(FILE *F, type *T, entity *E, const char *fmt, ...)
255 fprintf(F, "edge: { sourcename: "); PRINT_TYPEID(T);
256 fprintf(F, " targetname: \""); PRINT_ENTID(E); fprintf(F, "\"");
257 vfprintf(F, fmt, ap);
263 * prints the edge from an entity E to an entity T with additional info fmt, ...
266 static void print_ent_ent_edge(FILE *F, entity *E, entity *T, int backedge, const char *fmt, ...)
272 fprintf(F, "backedge: { sourcename: \"");
274 fprintf(F, "edge: { sourcename: \"");
276 fprintf(F, "\" targetname: \""); PRINT_ENTID(T); fprintf(F, "\"");
277 vfprintf(F, fmt, ap);
283 * prints the edge from an entity E to a type T with additional info fmt, ...
286 static void print_ent_type_edge(FILE *F, entity *E, type *T, const char *fmt, ...)
291 fprintf(F, "edge: { sourcename: \""); PRINT_ENTID(E);
292 fprintf(F, "\" targetname: "); PRINT_TYPEID(T);
293 vfprintf(F, fmt, ap);
299 * prints the edge from a node N to a type T with additional info fmt, ...
302 static void print_node_type_edge(FILE *F, const ir_node *N, type *T, const char *fmt, ...)
307 fprintf(F, "edge: { sourcename: \""); PRINT_NODEID(N);
308 fprintf(F, "\" targetname: "); PRINT_TYPEID(T);
309 vfprintf(F, fmt, ap);
315 * prints the edge from a node N to an entity E with additional info fmt, ...
318 static void print_node_ent_edge(FILE *F, const ir_node *N, entity *E, const char *fmt, ...)
323 fprintf(F, "edge: { sourcename: \""); PRINT_NODEID(N);
324 fprintf(F, "\" targetname: \""); PRINT_ENTID(E);
326 vfprintf(F, fmt, ap);
332 * prints the edge from an entity E to a node N with additional info fmt, ...
335 static void print_ent_node_edge(FILE *F, entity *E, const ir_node *N, const char *fmt, ...)
340 fprintf(F, "edge: { sourcename: \""); PRINT_ENTID(E);
341 fprintf(F, "\" targetname: \""); PRINT_NODEID(N); fprintf(F, "\"");
342 vfprintf(F, fmt, ap);
348 * prints the edge from a type E to an enumeration item item with additional info fmt, ...
351 static void print_enum_item_edge(FILE *F, type *E, int item, const char *fmt, ...)
356 fprintf(F, "edge: { sourcename: "); PRINT_TYPEID(E);
357 fprintf(F, " targetname: \""); PRINT_ITEMID(E, item); fprintf(F, "\" ");
358 vfprintf(F, fmt, ap);
363 /*-----------------------------------------------------------------*/
364 /* global and ahead declarations */
365 /*-----------------------------------------------------------------*/
367 static void dump_whole_node(ir_node *n, void *env);
368 static INLINE void dump_loop_nodes_into_graph(FILE *F, ir_graph *irg);
370 /*-----------------------------------------------------------------*/
371 /* Helper functions. */
372 /*-----------------------------------------------------------------*/
375 * This map is used as a private link attr to be able to call dumper
376 * anywhere without destroying link fields.
378 static pmap *irdump_link_map = NULL;
380 /** NOT A STANDARD LIBFIRM INIT METHOD
382 * We do not want to integrate dumping into libfirm, i.e., if the dumpers
383 * are off, we want to have as few interferences as possible. Therefore the
384 * initialization is performed lazily and not called from within init_firm.
386 * Creates the link attribute map. */
387 static void init_irdump(void) {
388 /* We need a new, empty map. */
389 if (irdump_link_map) pmap_destroy(irdump_link_map);
390 irdump_link_map = pmap_create();
391 if (!dump_file_filter_id)
392 dump_file_filter_id = new_id_from_str("");
395 * Returns the private link field.
397 static void *ird_get_irn_link(ir_node *n) {
399 if (!irdump_link_map) return NULL;
401 if (pmap_contains(irdump_link_map, (void *)n))
402 res = pmap_get(irdump_link_map, (void *)n);
407 * Sets the private link field.
409 static void ird_set_irn_link(ir_node *n, void *x) {
410 if (!irdump_link_map)
412 pmap_insert(irdump_link_map, (void *)n, x);
416 * Gets the private link field of an irg.
418 static void *ird_get_irg_link(ir_graph *irg) {
420 if (!irdump_link_map) return NULL;
422 if (pmap_contains(irdump_link_map, (void *)irg))
423 res = pmap_get(irdump_link_map, (void *)irg);
428 * Sets the private link field of an irg.
430 static void ird_set_irg_link(ir_graph *irg, void *x) {
431 if (!irdump_link_map) init_irdump();
432 pmap_insert(irdump_link_map, (void *)irg, x);
436 * Walker, clears the private link field.
438 static void clear_link(ir_node * node, void * env) {
439 ird_set_irn_link(node, NULL);
443 * If the entity has a ld_name, returns it if the dump_ld_name is set,
444 * else returns the name of the entity.
446 static const char *_get_ent_dump_name(entity *ent, int dump_ld_name) {
448 return "<NULL entity>";
450 /* Don't use get_entity_ld_ident (ent) as it computes the mangled name! */
451 if (ent->ld_name) return get_id_str(ent->ld_name);
453 return get_id_str(ent->name);
457 * If the entity has a ld_name, returns it if the option dump_ld_name is set,
458 * else returns the name of the entity.
460 const char *get_ent_dump_name(entity *ent) {
461 return _get_ent_dump_name(ent, dump_ld_name);
464 /* Returns the name of an IRG. */
465 const char *get_irg_dump_name(ir_graph *irg) {
466 /* Don't use get_entity_ld_ident (ent) as it computes the mangled name! */
467 return _get_ent_dump_name(get_irg_entity(irg), 1);
471 * Returns non-zero if a node is in floating state.
473 static int node_floats(ir_node *n) {
474 return ((get_irn_pinned(n) == op_pin_state_floats) &&
475 (get_irg_pinned(current_ir_graph) == op_pin_state_floats));
479 * Walker, allocates an array for all blocks and puts it's nodes non-floating nodes into this array.
481 static void collect_node(ir_node * node, void *env) {
484 || get_irn_op(node) == op_Bad
485 || get_irn_op(node) == op_Unknown
486 || get_irn_op(node) == op_NoMem) {
487 ir_node ** arr = (ir_node **) ird_get_irg_link(get_irn_irg(node));
488 if (!arr) arr = NEW_ARR_F(ir_node *, 0);
489 ARR_APP1(ir_node *, arr, node);
490 ird_set_irg_link(get_irn_irg(node), arr); /* arr is an l-value, APP_ARR might change it! */
492 ir_node * block = get_nodes_block(node);
495 /* this node is in a Bad block, so we must place it into the graph's list */
496 ir_node ** arr = (ir_node **) ird_get_irg_link(get_irn_irg(node));
497 if (!arr) arr = NEW_ARR_F(ir_node *, 0);
498 ARR_APP1(ir_node *, arr, node);
499 ird_set_irg_link(get_irn_irg(node), arr); /* arr is an l-value, APP_ARR might change it! */
502 ird_set_irn_link(node, ird_get_irn_link(block));
503 ird_set_irn_link(block, node);
508 /** Construct lists to walk ir block-wise.
510 * Collects all blocks, nodes not op_pin_state_pinned,
511 * Bad, NoMem and Unknown into a flexible array in link field of
512 * irg they belong to. Sets the irg link field to NULL in all
513 * graphs not visited.
514 * Free the list with DEL_ARR_F().
516 static ir_node **construct_block_lists(ir_graph *irg) {
517 int i, rem_view = get_interprocedural_view();
518 ir_graph *rem = current_ir_graph;
519 current_ir_graph = irg;
521 for (i = 0; i < get_irp_n_irgs(); i++)
522 ird_set_irg_link(get_irp_irg(i), NULL);
524 irg_walk_graph(current_ir_graph, clear_link, collect_node, current_ir_graph);
526 /* Collect also EndReg and EndExcept. We do not want to change the walker. */
527 set_interprocedural_view(false);
529 set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph)-1);
530 irg_walk(get_irg_end_reg(current_ir_graph), clear_link, collect_node, current_ir_graph);
531 set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph)-1);
532 irg_walk(get_irg_end_except(current_ir_graph), clear_link, collect_node, current_ir_graph);
534 set_interprocedural_view(rem_view);
536 current_ir_graph = rem;
537 return ird_get_irg_link(irg);
540 typedef struct _list_tuple {
542 ir_extblk **extbb_list;
545 /** Construct lists to walk ir extended block-wise.
546 * Free the lists in the tuple with DEL_ARR_F().
548 static list_tuple *construct_extblock_lists(ir_graph *irg) {
549 ir_node **blk_list = construct_block_lists(irg);
551 ir_graph *rem = current_ir_graph;
552 list_tuple *lists = xmalloc(sizeof(*lists));
554 current_ir_graph = irg;
556 lists->blk_list = NEW_ARR_F(ir_node *, 0);
557 lists->extbb_list = NEW_ARR_F(ir_extblk *, 0);
559 for (i = ARR_LEN(blk_list) - 1; i >= 0; --i) {
562 if (is_Block(blk_list[i])) {
563 ext = get_Block_extbb(blk_list[i]);
565 if (extbb_not_visited(ext)) {
566 ARR_APP1(ir_extblk *, lists->extbb_list, ext);
567 mark_extbb_visited(ext);
571 ARR_APP1(ir_node *, lists->blk_list, blk_list[i]);
574 current_ir_graph = rem;
576 ird_set_irg_link(irg, lists);
580 /*-----------------------------------------------------------------*/
581 /* Routines to dump information about a single ir node. */
582 /*-----------------------------------------------------------------*/
585 * dump the name of a node n to the File F.
588 dump_node_opcode(FILE *F, ir_node *n)
592 switch(get_irn_opcode(n)) {
597 res = tarval_snprintf(buf, sizeof(buf), get_Const_tarval(n));
598 assert(res < sizeof(buf) && "buffer to small for tarval_snprintf");
603 if (get_SymConst_kind(n) == symconst_addr_name) {
604 /* don't use get_SymConst_ptr_info as it mangles the name. */
605 fprintf (F, "SymC %s", get_id_str(get_SymConst_name(n)));
606 } else if (get_SymConst_kind(n) == symconst_addr_ent) {
607 assert(get_SymConst_entity(n));
608 assert(is_entity(get_SymConst_entity(n)));
609 fprintf (F, "SymC &%s", get_entity_name(get_SymConst_entity(n)));
611 assert(get_kind(get_SymConst_type(n)) == k_type);
612 assert(get_type_ident(get_SymConst_type(n)));
613 fprintf (F, "SymC %s ", get_type_name_ex(get_SymConst_type(n), &bad));
614 if (get_SymConst_kind(n) == symconst_type_tag)
622 if (!get_interprocedural_view())
629 ir_node *pred = get_Proj_pred(n);
631 if (get_irn_opcode(pred) == iro_Cond
632 && get_Proj_proj(n) == get_Cond_defaultProj(pred)
633 && get_irn_mode(get_Cond_selector(pred)) != mode_b)
634 fprintf (F, "defProj");
642 if (get_interprocedural_view()) {
643 fprintf(F, "%s %s", get_irn_opname(n), get_ent_dump_name(get_irg_entity(get_irn_irg(n))));
648 case iro_CallBegin: {
649 ir_node *addr = get_CallBegin_ptr(n);
651 if (get_irn_op(addr) == op_Sel)
652 ent = get_Sel_entity(addr);
653 else if ((get_irn_op(addr) == op_SymConst) && (get_SymConst_kind(addr) == symconst_addr_ent))
654 ent = get_SymConst_entity(addr);
655 fprintf (F, "%s", get_irn_opname(n));
656 if (ent) fprintf (F, " %s", get_entity_name(ent));
660 fprintf (F, "%s[%s]", get_irn_opname(n), get_mode_name_ex(get_Load_mode(n), &bad));
663 fprintf (F, "%s%s", is_Block_dead(n) ? "Dead " : "", get_irn_opname(n));
668 fprintf (F, "%s", get_irn_opname(n));
676 * Dump the mode of a node n to a file F.
677 * Ignore modes that are "always known".
680 dump_node_mode(FILE *F, ir_node *n)
683 opcode iro = get_irn_opcode(n);
696 ir_mode *mode = get_irn_mode(n);
698 if (mode && mode != mode_BB && mode != mode_ANY && mode != mode_BAD &&
699 (mode != mode_T || iro == iro_Proj))
700 fprintf(F, "%s", get_mode_name_ex(mode, &bad));
708 * Dump the type of a node n to a file F if it's known.
710 static int dump_node_typeinfo(FILE *F, ir_node *n) {
713 if (opt_dump_analysed_type_info) {
714 if (get_irg_typeinfo_state(current_ir_graph) == ir_typeinfo_consistent ||
715 get_irg_typeinfo_state(current_ir_graph) == ir_typeinfo_inconsistent) {
716 type *tp = get_irn_typeinfo_type(n);
717 if (tp != firm_none_type)
718 fprintf(F, "[%s] ", get_type_name_ex(tp, &bad));
726 typedef struct _pns_lookup {
727 long nr; /**< the proj number */
728 const char *name; /**< the name of the Proj */
731 typedef struct _proj_lookup {
732 opcode code; /**< the opcode of the Proj predecessor */
733 unsigned num_data; /**< number of data entries */
734 const pns_lookup_t *data; /**< the data */
737 #define ARR_SIZE(a) (sizeof(a)/sizeof(a[0]))
739 /** the lookup table for Proj(Start) names */
740 static const pns_lookup_t start_lut[] = {
741 #define X(a) { pn_Start_##a, #a }
750 /** the lookup table for Proj(Cond) names */
751 static const pns_lookup_t cond_lut[] = {
752 #define X(a) { pn_Cond_##a, #a }
758 /** the lookup table for Proj(Call) names */
759 static const pns_lookup_t call_lut[] = {
760 #define X(a) { pn_Call_##a, #a }
769 /** the lookup table for Proj(Quot) names */
770 static const pns_lookup_t quot_lut[] = {
771 #define X(a) { pn_Quot_##a, #a }
778 /** the lookup table for Proj(DivMod) names */
779 static const pns_lookup_t divmod_lut[] = {
780 #define X(a) { pn_DivMod_##a, #a }
788 /** the lookup table for Proj(Div) names */
789 static const pns_lookup_t div_lut[] = {
790 #define X(a) { pn_Div_##a, #a }
797 /** the lookup table for Proj(Mod) names */
798 static const pns_lookup_t mod_lut[] = {
799 #define X(a) { pn_Mod_##a, #a }
806 /** the lookup table for Proj(Load) names */
807 static const pns_lookup_t load_lut[] = {
808 #define X(a) { pn_Load_##a, #a }
815 /** the lookup table for Proj(Store) names */
816 static const pns_lookup_t store_lut[] = {
817 #define X(a) { pn_Store_##a, #a }
823 /** the lookup table for Proj(Alloc) names */
824 static const pns_lookup_t alloc_lut[] = {
825 #define X(a) { pn_Alloc_##a, #a }
833 /** the Proj lookup table */
834 static const proj_lookup_t proj_lut[] = {
835 #define E(a) ARR_SIZE(a), a
836 { iro_Start, E(start_lut) },
837 { iro_Cond, E(cond_lut) },
838 { iro_Call, E(call_lut) },
839 { iro_Quot, E(quot_lut) },
840 { iro_DivMod, E(divmod_lut) },
841 { iro_Div, E(div_lut) },
842 { iro_Mod, E(mod_lut) },
843 { iro_Load, E(load_lut) },
844 { iro_Store, E(store_lut) },
845 { iro_Alloc, E(alloc_lut) }
850 * Dump additional node attributes of some nodes to a file F.
853 dump_node_nodeattr(FILE *F, ir_node *n)
860 switch (get_irn_opcode(n)) {
862 if (false && get_interprocedural_view()) {
863 fprintf (F, "%s ", get_ent_dump_name(get_irg_entity(current_ir_graph)));
868 pred = get_Proj_pred(n);
869 proj_nr = get_Proj_proj(n);
871 code = get_irn_opcode(pred);
874 fprintf (F, "%s ", get_pnc_string(get_Proj_proj(n)));
875 else if (code == iro_Proj && get_irn_opcode(get_Proj_pred(pred)) == iro_Start)
876 fprintf (F, "Arg %ld ", proj_nr);
878 unsigned i, j, f = 0;
880 for (i = 0; i < ARR_SIZE(proj_lut); ++i) {
881 if (code == proj_lut[i].code) {
882 for (j = 0; j < proj_lut[i].num_data; ++j) {
883 if (proj_nr == proj_lut[i].data[j].nr) {
884 fprintf (F, "%s ", proj_lut[i].data[j].name);
893 fprintf (F, "%ld ", proj_nr);
894 if (code == iro_Cond && get_Cond_jmp_pred(pred) != COND_JMP_PRED_NONE) {
895 if (proj_nr == pn_Cond_false && get_Cond_jmp_pred(pred) == COND_JMP_PRED_FALSE)
897 if (proj_nr == pn_Cond_true && get_Cond_jmp_pred(pred) == COND_JMP_PRED_TRUE)
903 proj_nr = get_Filter_proj(n);
904 if (! get_interprocedural_view()) {
906 pred = get_Filter_pred(n);
910 fprintf (F, "%ld ", proj_nr);
913 fprintf (F, "%s ", get_ent_dump_name(get_Sel_entity(n)));
916 fprintf (F, "(%s) ", get_type_name_ex(get_Cast_type(n), &bad));
919 fprintf (F, "%s ", get_pnc_string(get_Confirm_cmp(n)));
930 #include "execution_frequency.h"
931 #include "callgraph.h"
933 void dump_node_ana_vals(FILE *F, ir_node *n) {
935 fprintf(F, " %lf*(%2.0lf + %2.0lf) = %2.0lf ",
936 get_irn_exec_freq(n),
937 get_irg_method_execution_frequency(get_irn_irg(n)),
938 pow(5, get_irg_recursion_depth(get_irn_irg(n))),
939 get_irn_exec_freq(n) * (get_irg_method_execution_frequency(get_irn_irg(n)) + pow(5, get_irg_recursion_depth(get_irn_irg(n))))
944 /* Dumps a node label without the enclosing ". */
945 int dump_node_label(FILE *F, ir_node *n) {
948 bad |= dump_node_opcode(F, n);
949 bad |= dump_node_mode(F, n);
951 bad |= dump_node_typeinfo(F, n);
952 bad |= dump_node_nodeattr(F, n);
953 fprintf(F, "%ld", get_irn_node_nr(n));
960 * Dumps the attributes of a node n into the file F.
961 * Currently this is only the color of a node.
963 static void dump_node_vcgattr(FILE *F, ir_node *node, ir_node *local, int bad)
968 fprintf(F, "color: red");
972 if (dump_node_vcgattr_hook)
973 if (dump_node_vcgattr_hook(F, node, local))
976 n = local ? local : node;
978 switch (get_irn_opcode(n)) {
985 fprintf (F, "color: blue");
988 if (is_Block_dead(n))
989 fprintf (F, "color: lightred");
991 fprintf (F, "color: lightyellow");
994 fprintf (F, "color: green");
1000 fprintf (F, "color: yellow");
1003 PRINT_DEFAULT_NODE_ATTR;
1006 if (overrule_nodecolor) fprintf(F, " color: %s", overrule_nodecolor);
1011 * Dump the node information of a node n to a file F.
1013 static INLINE int dump_node_info(FILE *F, ir_node *n)
1015 fprintf (F, " info1: \"");
1016 bad = dump_irnode_to_file(F, n);
1022 * checks whether a node is "constant-like" ie can be treated "block-less"
1025 bool is_constlike_node(ir_node *n) {
1026 ir_op *op = get_irn_op(n);
1027 return (op == op_Const || op == op_Bad || op == op_NoMem || op == op_SymConst || op == op_Unknown);
1031 /** outputs the predecessors of n, that are constants, local. I.e.,
1032 generates a copy of the constant predecessors for each node called with. */
1033 static void dump_const_node_local(FILE *F, ir_node *n) {
1035 if (!get_opt_dump_const_local()) return;
1037 /* Use visited flag to avoid outputting nodes twice.
1038 initialize it first. */
1039 for (i = 0; i < get_irn_arity(n); i++) {
1040 ir_node *con = get_irn_n(n, i);
1041 if (is_constlike_node(con)) {
1042 set_irn_visited(con, get_irg_visited(current_ir_graph) - 1);
1046 for (i = 0; i < get_irn_arity(n); i++) {
1047 ir_node *con = get_irn_n(n, i);
1048 if (is_constlike_node(con) && irn_not_visited(con)) {
1051 mark_irn_visited(con);
1052 /* Generate a new name for the node by appending the names of
1054 fprintf(F, "node: {title: "); PRINT_CONSTID(n, con);
1055 fprintf(F, " label: \"");
1056 bad |= dump_node_label(F, con);
1058 bad |= dump_node_info(F, con);
1059 dump_node_vcgattr(F, n, con, bad);
1065 /** If the block of an edge is a const_like node, dump it local with an edge */
1066 static void dump_const_block_local(FILE *F, ir_node *n) {
1069 if (!get_opt_dump_const_local()) return;
1071 blk = get_nodes_block(n);
1072 if (is_constlike_node(blk)) {
1075 /* Generate a new name for the node by appending the names of
1077 fprintf(F, "node: {title: \""); PRINT_CONSTBLKID(n, blk);
1078 fprintf(F, "\" label: \"");
1079 bad |= dump_node_label(F, blk);
1081 bad |= dump_node_info(F, blk);
1082 dump_node_vcgattr(F, n, blk, bad);
1085 fprintf (F, "edge: { sourcename: \"");
1087 fprintf (F, "\" targetname: \""); PRINT_CONSTBLKID(n,blk);
1089 if (dump_edge_vcgattr_hook) {
1091 if (dump_edge_vcgattr_hook(F, n, -1)) {
1096 fprintf (F, " " BLOCK_EDGE_ATTR "}\n");
1101 fprintf (F, "\" " BLOCK_EDGE_ATTR "}\n");
1106 * prints the error message of a node to a file F as info2.
1108 static void INLINE print_node_error(FILE *F, const char *err_msg)
1113 fprintf (F, " info2: \"%s\"", err_msg);
1117 * prints debug messages of a node to file F as info3.
1119 static void print_node_dbg_info(FILE *F, dbg_info *dbg)
1123 if (__dbg_info_snprint) {
1125 if (__dbg_info_snprint(buf, sizeof(buf), dbg) > 0)
1126 fprintf (F, " info3: \"%s\"\n", buf);
1133 static void dump_node(FILE *F, ir_node *n)
1138 if (get_opt_dump_const_local() && is_constlike_node(n))
1141 /* dump this node */
1142 fprintf(F, "node: {title: \""); PRINT_NODEID(n); fprintf(F, "\" label: \"");
1144 bad = ! irn_vrfy_irg_dump(n, current_ir_graph, &p);
1145 bad |= dump_node_label(F, n);
1146 dump_node_ana_vals(F, n);
1147 //dump_node_ana_info(F, n);
1149 bad |= dump_node_info(F, n);
1150 print_node_error(F, p);
1151 print_node_dbg_info(F, get_irn_dbg_info(n));
1152 dump_node_vcgattr(F, n, NULL, bad);
1154 dump_const_node_local(F, n);
1156 if(dump_node_edge_hook)
1157 dump_node_edge_hook(F, n);
1159 dump_irn_chi_term(F, n);
1160 dump_irn_state(F, n);
1164 /** dump the edge to the block this node belongs to */
1166 dump_ir_block_edge(FILE *F, ir_node *n) {
1167 if (get_opt_dump_const_local() && is_constlike_node(n)) return;
1168 if (is_no_Block(n)) {
1169 ir_node *block = get_nodes_block(n);
1171 if (get_opt_dump_const_local() && is_constlike_node(block)) {
1172 dump_const_block_local(F, n);
1175 fprintf (F, "edge: { sourcename: \"");
1177 fprintf (F, "\" targetname: ");
1178 fprintf(F, "\""); PRINT_NODEID(block); fprintf(F, "\"");
1180 if (dump_edge_vcgattr_hook) {
1182 if (dump_edge_vcgattr_hook(F, n, -1)) {
1187 fprintf (F, " " BLOCK_EDGE_ATTR "}\n");
1192 fprintf (F, " " BLOCK_EDGE_ATTR "}\n");
1198 print_data_edge_vcgattr(FILE *F, ir_node *from, int to) {
1200 * do not use get_nodes_block() here, will fail
1201 * if the irg is not pinned.
1203 if (get_irn_n(from, -1) == get_irn_n(get_irn_n(from, to), -1))
1204 fprintf (F, INTRA_DATA_EDGE_ATTR);
1206 fprintf (F, INTER_DATA_EDGE_ATTR);
1210 print_mem_edge_vcgattr(FILE *F, ir_node *from, int to) {
1212 * do not use get_nodes_block() here, will fail
1213 * if the irg is not pinned.
1215 if (get_irn_n(from, -1) == get_irn_n(get_irn_n(from, to), -1))
1216 fprintf (F, INTRA_MEM_EDGE_ATTR);
1218 fprintf (F, INTER_MEM_EDGE_ATTR);
1222 print_edge_vcgattr(FILE *F, ir_node *from, int to) {
1225 if (dump_edge_vcgattr_hook)
1226 if (dump_edge_vcgattr_hook(F, from, to))
1229 if (dump_backedge_information_flag && is_backedge(from, to))
1230 fprintf (F, BACK_EDGE_ATTR);
1232 switch (get_irn_opcode(from)) {
1234 fprintf (F, CF_EDGE_ATTR);
1236 case iro_Start: break;
1239 if (get_irn_mode(get_End_keepalive(from, to)) == mode_BB)
1240 fprintf (F, CF_EDGE_ATTR);
1241 if (get_irn_mode(get_End_keepalive(from, to)) == mode_X)
1242 fprintf (F, INTER_MEM_EDGE_ATTR);
1250 print_data_edge_vcgattr(F, from, to);
1255 print_mem_edge_vcgattr(F, from, to);
1257 print_data_edge_vcgattr(F, from, to);
1261 print_data_edge_vcgattr(F, from, to);
1266 print_mem_edge_vcgattr(F, from, to);
1268 print_data_edge_vcgattr(F, from, to);
1275 print_data_edge_vcgattr(F, from, to);
1282 print_mem_edge_vcgattr(F, from, to);
1284 print_data_edge_vcgattr(F, from, to);
1296 print_data_edge_vcgattr(F, from, to);
1299 if (get_irn_modecode(from) == irm_M)
1300 fprintf (F, INTER_MEM_EDGE_ATTR);
1302 print_data_edge_vcgattr(F, from, to);
1309 print_mem_edge_vcgattr(F, from, to);
1311 print_data_edge_vcgattr(F, from, to);
1314 print_mem_edge_vcgattr(F, from, to);
1316 case iro_Tuple: break;
1319 switch (get_irn_modecode(from)) {
1321 fprintf (F, CF_EDGE_ATTR);
1324 fprintf (F, INTER_MEM_EDGE_ATTR);
1327 print_data_edge_vcgattr(F, from, to);
1331 case iro_Bad: break;
1332 case iro_Unknown: break;
1334 switch (get_irn_modecode(from)) {
1336 fprintf (F, INTRA_MEM_EDGE_ATTR);
1339 fprintf (F, CF_EDGE_ATTR);
1342 print_data_edge_vcgattr(F, from, to);
1350 /* dump edges to our inputs */
1352 dump_ir_data_edges(FILE *F, ir_node *n) {
1354 unsigned long visited = get_irn_visited(n);
1356 if ((get_irn_op(n) == op_End) && (!dump_keepalive))
1359 for (i = 0; i < get_irn_arity(n); i++) {
1360 ir_node * pred = get_irn_n(n, i);
1363 if ((get_interprocedural_view() && get_irn_visited(pred) < visited))
1364 continue; /* pred not dumped */
1366 if (dump_backedge_information_flag && is_backedge(n, i))
1367 fprintf (F, "backedge: {sourcename: \"");
1369 fprintf (F, "edge: {sourcename: \"");
1371 fprintf (F, "\" targetname: ");
1372 if ((get_opt_dump_const_local()) && is_constlike_node(pred)) {
1373 PRINT_CONSTID(n, pred);
1375 fprintf(F, "\""); PRINT_NODEID(pred); fprintf(F, "\"");
1377 fprintf (F, " label: \"%d\" ", i);
1378 print_edge_vcgattr(F, n, i);
1383 /** Dumps a node and its edges but not the block edge
1386 dump_node_wo_blockedge (ir_node *n, void *env) {
1389 dump_ir_data_edges(F, n);
1392 /** Dumps a node and its edges.
1395 dump_whole_node (ir_node *n, void *env) {
1397 dump_node_wo_blockedge(n, env);
1398 if (!node_floats(n)) dump_ir_block_edge(F, n);
1402 dump_const_node(ir_node *n, void *env) {
1403 if (is_Block(n)) return;
1404 dump_node_wo_blockedge(n, env);
1407 /***********************************************************************/
1408 /* the following routines dump the nodes/irgs bracketed to graphs. */
1409 /***********************************************************************/
1411 /** Dumps a constant expression as entity initializer, array bound ...
1413 static void dump_const_expression(FILE *F, ir_node *value) {
1414 ir_graph *rem = current_ir_graph;
1415 int rem_dump_const_local = dump_const_local;
1416 dump_const_local = 0;
1417 current_ir_graph = get_const_code_irg();
1418 irg_walk(value, dump_const_node, NULL, F);
1419 /* Decrease visited flag so that we walk with the same flag for the next
1420 expression. This guarantees that we don't dump the same node twice,
1421 as for const expressions cse is performed to save memory. */
1422 set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph) -1);
1423 current_ir_graph = rem;
1424 dump_const_local = rem_dump_const_local;
1427 /** Dump a block as graph containing its nodes.
1429 * Expects to find nodes belonging to the block as list in its
1431 * Dumps the edges of all nodes including itself. */
1433 dump_whole_block(FILE *F, ir_node *block) {
1435 const char *color = "yellow";
1437 assert(is_Block(block));
1439 fprintf(F, "graph: { title: \"");
1440 PRINT_NODEID(block);
1441 fprintf(F, "\" label: \"");
1442 dump_node_label(F, block);
1444 if (get_opt_dump_abstvals())
1445 fprintf (F, " seqno: %d", (int)get_Block_seqno(block));
1448 /* colorize blocks */
1449 if (! get_Block_matured(block))
1451 if (is_Block_dead(block))
1454 fprintf(F, "\" status:clustered color:%s \n", color);
1456 /* ycomp can show attributs for blocks, VCG parses but ignores them */
1457 dump_node_info(F, block);
1459 /* dump the blocks edges */
1460 dump_ir_data_edges(F, block);
1462 /* dump the nodes that go into the block */
1463 for (node = ird_get_irn_link(block); node; node = ird_get_irn_link(node)) {
1465 dump_ir_data_edges(F, node);
1468 /* Close the vcg information for the block */
1470 dump_const_node_local(F, block);
1472 dump_irn_chi_term(F, block);
1477 /** dumps a graph block-wise. Expects all blockless nodes in arr in irgs link.
1478 * The outermost nodes: blocks and nodes not op_pin_state_pinned, Bad, Unknown. */
1480 dump_block_graph(FILE *F, ir_graph *irg) {
1482 ir_graph *rem = current_ir_graph;
1483 ir_node **arr = ird_get_irg_link(irg);
1484 current_ir_graph = irg;
1486 for (i = ARR_LEN(arr) - 1; i >= 0; --i) {
1487 ir_node * node = arr[i];
1488 if (is_Block(node)) {
1489 /* Dumps the block and all the nodes in the block, which are to
1490 be found in Block->link. */
1491 dump_whole_block(F, node);
1493 /* Nodes that are not in a Block. */
1495 if (!node_floats(node) && is_Bad(get_nodes_block(node))) {
1496 dump_const_block_local(F, node);
1498 dump_ir_data_edges(F, node);
1502 if (dump_loop_information_flag && (get_irg_loopinfo_state(irg) & loopinfo_valid))
1503 dump_loop_nodes_into_graph(F, irg);
1505 current_ir_graph = rem;
1508 /** Dumps an irg as a graph clustered by block nodes.
1509 * If interprocedural view edges can point to nodes out of this graph.
1511 static void dump_graph_from_list(FILE *F, ir_graph *irg) {
1513 fprintf(F, "graph: { title: \"");
1515 fprintf(F, "\" label: \"%s\" status:clustered color:white \n",
1516 get_ent_dump_name(get_irg_entity(irg)));
1518 dump_block_graph(F, irg);
1520 /* Close the vcg information for the irg */
1521 fprintf(F, "}\n\n");
1524 /** dumps a graph extended block-wise. Expects all blockless nodes in arr in irgs link.
1525 * The outermost nodes: blocks and nodes not op_pin_state_pinned, Bad, Unknown. */
1527 dump_extblock_graph(FILE *F, ir_graph *irg) {
1529 ir_graph *rem = current_ir_graph;
1530 ir_extblk **arr = ird_get_irg_link(irg);
1531 current_ir_graph = irg;
1534 for (i = ARR_LEN(arr) - 1; i >= 0; --i) {
1535 ir_extblk *extbb = arr[i];
1536 ir_node *leader = get_extbb_leader(extbb);
1539 fprintf(F, "graph: { title: \"");
1540 PRINT_EXTBBID(leader);
1541 fprintf(F, "\" label: \"ExtBB %ld\" status:clustered color:lightgreen\n",
1542 get_irn_node_nr(leader));
1544 for (j = ARR_LEN(extbb->blks) - 1; j >= 0; --j) {
1545 ir_node * node = extbb->blks[j];
1546 if (is_Block(node)) {
1547 /* Dumps the block and all the nodes in the block, which are to
1548 be found in Block->link. */
1549 dump_whole_block(F, node);
1551 /* Nodes that are not in a Block. */
1553 if (is_Bad(get_nodes_block(node)) && !node_floats(node)) {
1554 dump_const_block_local(F, node);
1556 dump_ir_data_edges(F, node);
1562 if (dump_loop_information_flag && (get_irg_loopinfo_state(irg) & loopinfo_valid))
1563 dump_loop_nodes_into_graph(F, irg);
1565 current_ir_graph = rem;
1570 /*******************************************************************/
1571 /* Basic type and entity nodes and edges. */
1572 /*******************************************************************/
1574 /** dumps the edges between nodes and their type or entity attributes. */
1575 static void dump_node2type_edges(ir_node *n, void *env)
1580 switch (get_irn_opcode(n)) {
1582 /* @@@ some consts have an entity */
1585 if ( (get_SymConst_kind(n) ==symconst_type_tag)
1586 || (get_SymConst_kind(n) ==symconst_size))
1588 print_node_type_edge(F,n,get_SymConst_type(n),NODE2TYPE_EDGE_ATTR);
1592 print_node_ent_edge(F,n,get_Sel_entity(n),NODE2TYPE_EDGE_ATTR);
1595 print_node_type_edge(F,n,get_Call_type(n),NODE2TYPE_EDGE_ATTR);
1598 print_node_type_edge(F,n,get_Alloc_type(n),NODE2TYPE_EDGE_ATTR);
1601 print_node_type_edge(F,n,get_Free_type(n),NODE2TYPE_EDGE_ATTR);
1604 print_node_type_edge(F,n,get_Cast_type(n),NODE2TYPE_EDGE_ATTR);
1612 static int print_type_info(FILE *F, type *tp) {
1615 if (get_type_state(tp) == layout_undefined) {
1616 fprintf(F, "state: layout_undefined\n");
1618 fprintf(F, "state: layout_fixed,\n");
1620 if (get_type_mode(tp))
1621 fprintf(F, "mode: %s,\n", get_mode_name_ex(get_type_mode(tp), &bad));
1622 fprintf(F, "size: %db,\n", get_type_size_bits(tp));
1627 static void print_typespecific_info(FILE *F, type *tp) {
1628 switch (get_type_tpop_code(tp)) {
1631 fprintf(F, "peculiarity: %s\n", get_peculiarity_string(get_class_peculiarity(tp)));
1638 fprintf(F, "variadicity: %s\n", get_variadicity_name(get_method_variadicity(tp)));
1639 fprintf(F, "params: %d\n", get_method_n_params(tp));
1640 fprintf(F, "results: %d\n", get_method_n_ress(tp));
1648 case tpo_enumeration:
1662 static void print_typespecific_vcgattr(FILE *F, type *tp) {
1663 switch (get_type_tpop_code(tp)) {
1666 if (peculiarity_existent == get_class_peculiarity(tp))
1667 fprintf (F, " " TYPE_CLASS_NODE_ATTR);
1669 fprintf (F, " " TYPE_DESCRIPTION_NODE_ATTR);
1673 fprintf (F, " " TYPE_METH_NODE_ATTR);
1684 case tpo_enumeration:
1698 int dump_type_node(FILE *F, type *tp)
1702 fprintf (F, "node: {title: ");
1704 fprintf (F, " label: \"%s %s\"", get_type_tpop_name(tp), get_type_name_ex(tp, &bad));
1705 fprintf (F, " info1: \"");
1707 bad |= print_type_info(F, tp);
1708 print_typespecific_info(F, tp);
1710 dump_type_to_file(F, tp, dump_verbosity_max);
1712 fprintf (F, "\"\n");
1713 print_node_dbg_info(F, get_type_dbg_info(tp));
1714 print_typespecific_vcgattr(F, tp);
1721 #define X(a) case a: fprintf(F, #a); break
1722 void dump_entity_node(FILE *F, entity *ent, int color)
1724 fprintf (F, "node: {title: \"");
1725 PRINT_ENTID(ent); fprintf(F, "\"");
1726 fprintf (F, DEFAULT_TYPE_ATTRIBUTE);
1727 fprintf (F, "label: ");
1728 fprintf (F, "\"ent %s\" ", get_ent_dump_name(ent));
1730 fprintf(F, "color: %d", color);
1732 fprintf (F, ENTITY_NODE_ATTR);
1733 fprintf (F, "\n info1: \"");
1735 dump_entity_to_file(F, ent, dump_verbosity_entattrs | dump_verbosity_entconsts);
1738 print_node_dbg_info(F, get_entity_dbg_info(ent));
1743 static void dump_enum_item(FILE *F, type *tp, int pos)
1746 ident *id = get_enumeration_nameid(tp, pos);
1747 tarval *tv = get_enumeration_enum(tp, pos);
1749 tarval_snprintf(buf, sizeof(buf), tv);
1750 fprintf (F, "node: {title: \"");
1751 PRINT_ITEMID(tp, pos); fprintf(F, "\"");
1752 fprintf (F, DEFAULT_ENUM_ITEM_ATTRIBUTE);
1753 fprintf (F, "label: ");
1754 fprintf (F, "\"enum item %s\" " ENUM_ITEM_NODE_ATTR, get_id_str(id));
1755 fprintf (F, "\n info1: \"value: %s\"}\n", buf);
1758 /* dumps a type or entity and it's edges. */
1760 dump_type_info(type_or_ent *tore, void *env) {
1762 int i = 0; /* to shutup gcc */
1764 /* dump this type or entity */
1766 switch (get_kind(tore)) {
1769 entity *ent = (entity *)tore;
1772 dump_entity_node(F, ent, 0);
1774 /* skip this to reduce graph. Member edge of type is parallel to this edge. *
1775 fprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
1776 ENT_OWN_EDGE_ATTR "}\n", ent, get_entity_owner(ent));*/
1777 print_ent_type_edge(F,ent, get_entity_type(ent), ENT_TYPE_EDGE_ATTR);
1778 if (is_Class_type(get_entity_owner(ent))) {
1779 for(i = 0; i < get_entity_n_overwrites(ent); i++)
1780 print_ent_ent_edge(F,ent, get_entity_overwrites(ent, i), 0, ENT_OVERWRITES_EDGE_ATTR);
1782 /* attached subgraphs */
1783 if (const_entities && (get_entity_variability(ent) != variability_uninitialized)) {
1784 if (is_atomic_entity(ent)) {
1785 value = get_atomic_ent_value(ent);
1787 print_ent_node_edge(F, ent, value, ENT_VALUE_EDGE_ATTR, i);
1788 /* DDMN(value); $$$ */
1789 dump_const_expression(F, value);
1792 if (is_compound_entity(ent)) {
1793 for (i = 0; i < get_compound_ent_n_values(ent); i++) {
1794 value = get_compound_ent_value(ent, i);
1796 print_ent_node_edge(F, ent, value, ENT_VALUE_EDGE_ATTR, i);
1797 dump_const_expression(F, value);
1798 print_ent_ent_edge(F, ent, get_compound_ent_value_member(ent, i), 0, ENT_CORR_EDGE_ATTR, i);
1800 fprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
1801 ENT_CORR_EDGE_ATTR "}\n", GET_ENTID(ent),
1802 get_compound_ent_value_member(ent, i), i);
1811 type *tp = (type *)tore;
1812 dump_type_node(F, tp);
1813 /* and now the edges */
1814 switch (get_type_tpop_code(tp)) {
1817 for (i=0; i < get_class_n_supertypes(tp); i++)
1818 print_type_type_edge(F, tp,get_class_supertype(tp, i),TYPE_SUPER_EDGE_ATTR);
1819 for (i=0; i < get_class_n_members(tp); i++)
1820 print_type_ent_edge(F,tp,get_class_member(tp, i),TYPE_MEMBER_EDGE_ATTR);
1824 for (i=0; i < get_struct_n_members(tp); i++)
1825 print_type_ent_edge(F,tp,get_struct_member(tp, i),TYPE_MEMBER_EDGE_ATTR);
1829 for (i = 0; i < get_method_n_params(tp); i++)
1830 print_type_type_edge(F,tp,get_method_param_type(tp, i),METH_PAR_EDGE_ATTR,i);
1831 for (i = 0; i < get_method_n_ress(tp); i++)
1832 print_type_type_edge(F,tp,get_method_res_type(tp, i),METH_RES_EDGE_ATTR,i);
1836 for (i = 0; i < get_union_n_members(tp); i++)
1837 print_type_ent_edge(F,tp,get_union_member(tp, i),UNION_EDGE_ATTR);
1841 print_type_type_edge(F,tp,get_array_element_type(tp),ARR_ELT_TYPE_EDGE_ATTR);
1842 print_type_ent_edge(F,tp,get_array_element_entity(tp),ARR_ENT_EDGE_ATTR);
1843 for (i = 0; i < get_array_n_dimensions(tp); i++) {
1844 ir_node *upper = get_array_upper_bound(tp, i);
1845 ir_node *lower = get_array_lower_bound(tp, i);
1846 print_node_type_edge(F, upper, tp, "label: \"upper %d\"", get_array_order(tp, i));
1847 print_node_type_edge(F, lower, tp, "label: \"lower %d\"", get_array_order(tp, i));
1848 dump_const_expression(F, upper);
1849 dump_const_expression(F, lower);
1853 case tpo_enumeration:
1855 for (i = 0; i < get_enumeration_n_enums(tp); ++i) {
1856 dump_enum_item(F, tp, i);
1857 print_enum_item_edge(F, tp, i, "label: \"item %d\"", i);
1862 print_type_type_edge(F,tp,get_pointer_points_to_type(tp), PTR_PTS_TO_EDGE_ATTR);
1870 break; /* case k_type */
1873 printf(" *** irdump, dump_type_info(l.%i), faulty type.\n", __LINE__);
1875 } /* switch kind_or_entity */
1878 typedef struct _h_env {
1883 /** For dumping class hierarchies.
1884 * Dumps a class type node and a superclass edge.
1885 * If env->dump_ent dumps entities of classes and overwrites edges.
1888 dump_class_hierarchy_node (type_or_ent *tore, void *ctx) {
1891 int i = 0; /* to shutup gcc */
1893 /* dump this type or entity */
1894 switch (get_kind(tore)) {
1896 entity *ent = (entity *)tore;
1897 if (get_entity_owner(ent) == get_glob_type()) break;
1898 if (!is_Method_type(get_entity_type(ent))) break; /* GL */
1899 if (env->dump_ent && is_Class_type(get_entity_owner(ent))) {
1901 dump_entity_node(F, ent, 0);
1903 print_type_ent_edge(F,get_entity_owner(ent),ent,TYPE_MEMBER_EDGE_ATTR);
1904 for(i = 0; i < get_entity_n_overwrites(ent); i++)
1905 print_ent_ent_edge(F, get_entity_overwrites(ent, i), ent, 0, ENT_OVERWRITES_EDGE_ATTR);
1907 } break; /* case k_entity */
1910 type *tp = (type *)tore;
1911 if (tp == get_glob_type()) break;
1912 switch (get_type_tpop_code(tp)) {
1914 dump_type_node(F, tp);
1915 /* and now the edges */
1916 for (i=0; i < get_class_n_supertypes(tp); i++)
1918 print_type_type_edge(F,tp,get_class_supertype(tp, i),TYPE_SUPER_EDGE_ATTR);
1924 break; /* case k_type */
1927 printf(" *** irdump, dump_class_hierarchy_node(l.%i), faulty type.\n", __LINE__);
1929 } /* switch kind_or_entity */
1932 /*******************************************************************/
1933 /* dump analysis information that is expressed in graph terms. */
1934 /*******************************************************************/
1936 /* dump out edges */
1938 dump_out_edge(ir_node *n, void *env) {
1941 for (i = 0; i < get_irn_n_outs(n); i++) {
1942 assert(get_irn_out(n, i));
1943 fprintf (F, "edge: {sourcename: \"");
1945 fprintf (F, "\" targetname: \"");
1946 PRINT_NODEID(get_irn_out(n, i));
1947 fprintf (F, "\" color: red linestyle: dashed");
1953 dump_loop_label(FILE *F, ir_loop *loop) {
1954 fprintf (F, "loop %d, %d sons, %d nodes",
1955 get_loop_depth(loop), get_loop_n_sons(loop), get_loop_n_nodes(loop));
1958 static INLINE void dump_loop_info(FILE *F, ir_loop *loop) {
1959 fprintf (F, " info1: \"");
1960 fprintf (F, " loop nr: %d", get_loop_loop_nr(loop));
1961 #if DEBUG_libfirm /* GL @@@ debug analyses */
1962 fprintf (F, "\n The loop was analyzed %d times.", PTR_TO_INT(get_loop_link(loop)));
1968 dump_loop_node(FILE *F, ir_loop *loop) {
1969 fprintf (F, "node: {title: \"");
1971 fprintf (F, "\" label: \"");
1972 dump_loop_label(F, loop);
1974 dump_loop_info(F, loop);
1980 dump_loop_node_edge(FILE *F, ir_loop *loop, int i) {
1982 fprintf (F, "edge: {sourcename: \"");
1984 fprintf (F, "\" targetname: \"");
1985 PRINT_NODEID(get_loop_node(loop, i));
1986 fprintf (F, "\" color: green");
1991 dump_loop_son_edge(FILE *F, ir_loop *loop, int i) {
1993 fprintf (F, "edge: {sourcename: \"");
1995 fprintf (F, "\" targetname: \"");
1996 PRINT_LOOPID(get_loop_son(loop, i));
1997 fprintf (F, "\" color: darkgreen label: \"%d\"}\n",
1998 get_loop_element_pos(loop, get_loop_son(loop, i)));
2002 void dump_loops(FILE *F, ir_loop *loop) {
2004 /* dump this loop node */
2005 dump_loop_node(F, loop);
2007 /* dump edges to nodes in loop -- only if it is a real loop */
2008 if (get_loop_depth(loop) != 0) {
2009 for (i = 0; i < get_loop_n_nodes(loop); i++) {
2010 dump_loop_node_edge(F, loop, i);
2013 for (i = 0; i < get_loop_n_sons(loop); i++) {
2014 dump_loops(F, get_loop_son(loop, i));
2015 dump_loop_son_edge(F, loop, i);
2020 void dump_loop_nodes_into_graph(FILE *F, ir_graph *irg) {
2021 ir_graph *rem = current_ir_graph;
2022 current_ir_graph = irg;
2024 if (get_irg_loop(irg)) dump_loops(F, get_irg_loop(irg));
2026 current_ir_graph = rem;
2031 * dumps the VCG header
2033 void dump_vcg_header(FILE *F, const char *name, const char *orientation) {
2042 if (!orientation) orientation = "bottom_to_top";
2046 "graph: { title: \"ir graph of %s\"\n"
2047 "display_edge_labels: %s\n"
2048 "layoutalgorithm: mindepth\n"
2049 "manhattan_edges: yes\n"
2050 "port_sharing: no\n"
2052 "classname 1: \"intrablock Data\"\n"
2053 "classname 16: \"interblock Data\"\n"
2054 "classname 2: \"Block\"\n"
2055 "classname 13: \"Control Flow\"\n"
2056 "classname 18: \"Exception Control Flow for Interval Analysis\"\n"
2057 "classname 14: \"intrablock Memory\"\n"
2058 "classname 17: \"interblock Memory\"\n"
2059 "classname 15: \"Dominators\"\n"
2060 "classname 3: \"Entity type\"\n"
2061 "classname 4: \"Entity owner\"\n"
2062 "classname 5: \"Method Param\"\n"
2063 "classname 6: \"Method Res\"\n"
2064 "classname 7: \"Super\"\n"
2065 "classname 8: \"Union\"\n"
2066 "classname 9: \"Points-to\"\n"
2067 "classname 10: \"Array Element Type\"\n"
2068 "classname 11: \"Overwrites\"\n"
2069 "classname 12: \"Member\"\n"
2070 "infoname 1: \"Attribute\"\n"
2071 "infoname 2: \"Verification errors\"\n"
2072 "infoname 3: \"Debug info\"\n",
2073 name, label, orientation);
2075 /* don't use all, the range is too whith/black. */
2079 "colorentry 100: 0 0 0\n"
2080 "colorentry 101: 20 0 0\n"
2081 "colorentry 102: 40 0 0\n"
2082 "colorentry 103: 60 0 0\n"
2083 "colorentry 104: 80 0 0\n"
2084 "colorentry 105: 100 0 0\n"
2085 "colorentry 106: 120 0 0\n"
2086 "colorentry 107: 140 0 0\n"
2087 "colorentry 108: 150 0 0\n"
2088 "colorentry 109: 180 0 0\n"
2089 "colorentry 110: 200 0 0\n"
2090 "colorentry 111: 220 0 0\n"
2091 "colorentry 112: 240 0 0\n"
2092 "colorentry 113: 255 0 0\n"
2093 "colorentry 113: 255 20 20\n"
2094 "colorentry 114: 255 40 40\n"
2095 "colorentry 115: 255 60 60\n"
2096 "colorentry 116: 255 80 80\n"
2097 "colorentry 117: 255 100 100\n"
2098 "colorentry 118: 255 120 120\n"
2099 "colorentry 119: 255 140 140\n"
2100 "colorentry 120: 255 150 150\n"
2101 "colorentry 121: 255 180 180\n"
2102 "colorentry 122: 255 200 200\n"
2103 "colorentry 123: 255 220 220\n"
2104 "colorentry 124: 255 240 240\n"
2105 "colorentry 125: 255 250 250\n"
2108 fprintf (F, "\n"); /* a separator */
2114 * @param irg The graph to be dumped
2115 * @param suffix1 first filename suffix
2116 * @param suffix2 second filename suffix
2118 FILE *vcg_open (ir_graph *irg, const char * suffix1, const char *suffix2) {
2120 const char *nm = get_irg_dump_name(irg);
2121 int len = strlen(nm), i, j;
2122 char *fname; /* filename to put the vcg information in */
2124 if (!suffix1) suffix1 = "";
2125 if (!suffix2) suffix2 = "";
2127 /* open file for vcg graph */
2128 fname = malloc (len * 2 + strlen(suffix1) + strlen(suffix2) + 5);
2130 /* strncpy (fname, nm, len); */ /* copy the filename */
2132 for (i = 0; i < len; ++i) { /* replace '/' in the name: escape by @. */
2134 fname[j] = '@'; j++; fname[j] = '1'; j++;
2135 } else if (nm[i] == '@') {
2136 fname[j] = '@'; j++; fname[j] = '2'; j++;
2138 fname[j] = nm[i]; j++;
2142 strcat (fname, suffix1); /* append file suffix */
2143 strcat (fname, suffix2); /* append file suffix */
2144 strcat (fname, ".vcg"); /* append the .vcg suffix */
2146 /* vcg really expect only a <CR> at end of line, so
2147 * the "b"inary mode is what you mean (and even needed for Win32)
2149 F = fopen (fname, "wb"); /* open file for writing */
2151 panic("cannot open %s for writing (%m)", fname); /* not reached */
2161 * @param name prefix file name
2162 * @param suffix filename suffix
2164 FILE *vcg_open_name (const char *name, const char *suffix) {
2166 char *fname; /* filename to put the vcg information in */
2167 int i, j, len = strlen(name);
2169 if (!suffix) suffix = "";
2171 /** open file for vcg graph */
2172 fname = xmalloc(len * 2 + 5 + strlen(suffix));
2173 /* strcpy (fname, name);*/ /* copy the filename */
2175 for (i = 0; i < len; ++i) { /* replace '/' in the name: escape by @. */
2176 if (name[i] == '/') {
2177 fname[j] = '@'; j++; fname[j] = '1'; j++;
2178 } else if (name[i] == '@') {
2179 fname[j] = '@'; j++; fname[j] = '2'; j++;
2181 fname[j] = name[i]; j++;
2185 strcat (fname, suffix);
2186 strcat (fname, ".vcg"); /* append the .vcg suffix */
2188 /* vcg really expect only a <CR> at end of line, so
2189 * the "b"inary mode is what you mean (and even needed for Win32)
2191 F = fopen (fname, "wb"); /* open file for writing */
2193 panic ("cannot open %s for writing (%m)", fname); /* not reached */
2201 * Dumps the vcg file footer
2203 static INLINE void dump_vcg_footer (FILE *F) {
2208 * close the vcg file
2210 void vcg_close (FILE *F) {
2211 dump_vcg_footer(F); /* print footer */
2212 fclose (F); /* close vcg file */
2215 /************************************************************************/
2216 /************************************************************************/
2217 /* Routines that dump all or parts of the firm representation to a file */
2218 /************************************************************************/
2219 /************************************************************************/
2221 /************************************************************************/
2222 /* Dump ir graphs, different formats and additional information. */
2223 /************************************************************************/
2225 /** Routine to dump a graph, blocks as conventional nodes. */
2227 dump_ir_graph (ir_graph *irg, const char *suffix )
2232 rem = current_ir_graph;
2234 if (!is_filtered_dump_name(get_entity_ident(get_irg_entity(irg)))) return;
2236 current_ir_graph = irg;
2237 if (get_interprocedural_view()) suffix1 = "-pure-ip";
2238 else suffix1 = "-pure";
2239 f = vcg_open(irg, suffix, suffix1);
2240 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
2242 /* call the dump graph hook */
2243 if (dump_ir_graph_hook)
2244 if (dump_ir_graph_hook(f, irg))
2247 /* walk over the graph */
2248 /* dump_whole_node must be called in post visiting predecessors */
2249 irg_walk(get_irg_end(irg), NULL, dump_whole_node, f);
2251 /* dump the out edges in a separate walk */
2252 if ((dump_out_edge_flag) && (get_irg_outs_state(irg) != outs_none)) {
2253 irg_out_walk(get_irg_start(irg), dump_out_edge, NULL, f);
2258 current_ir_graph = rem;
2261 /* Dump a firm graph without explicit block nodes. */
2262 void dump_ir_block_graph (ir_graph *irg, const char *suffix)
2268 if (!is_filtered_dump_name(get_entity_ident(get_irg_entity(irg))))
2271 if (get_interprocedural_view()) suffix1 = "-ip";
2273 f = vcg_open(irg, suffix, suffix1);
2274 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
2276 construct_block_lists(irg);
2279 * If we are in the interprocedural view, we dump not
2280 * only the requested irg but also all irgs that can be reached
2283 for (i = 0; i < get_irp_n_irgs(); i++) {
2284 ir_node **arr = ird_get_irg_link(get_irp_irg(i));
2286 dump_graph_from_list(f, get_irp_irg(i));
2294 /* Dump a firm graph without explicit block nodes but grouped in extended blocks. */
2295 void dump_ir_extblock_graph (ir_graph *irg, const char *suffix)
2301 if (!is_filtered_dump_name(get_entity_ident(get_irg_entity(irg))))
2306 if (get_interprocedural_view()) suffix1 = "-ip";
2308 F = vcg_open(irg, suffix, suffix1);
2309 dump_vcg_header(F, get_irg_dump_name(irg), NULL);
2311 construct_extblock_lists(irg);
2313 fprintf(F, "graph: { title: \"");
2315 fprintf(F, "\" label: \"%s\" status:clustered color:white \n",
2316 get_ent_dump_name(get_irg_entity(irg)));
2318 for (i = 0; i < get_irp_n_irgs(); i++) {
2319 ir_graph *irg = get_irp_irg(i);
2320 list_tuple *lists = ird_get_irg_link(irg);
2323 /* dump the extended blocks first */
2324 if (ARR_LEN(lists->extbb_list)) {
2325 ird_set_irg_link(irg, lists->extbb_list);
2326 dump_extblock_graph(F, irg);
2329 /* we may have blocks without extended blocks, bad for instance */
2330 if (ARR_LEN(lists->blk_list)) {
2331 ird_set_irg_link(irg, lists->blk_list);
2332 dump_block_graph(F, irg);
2335 DEL_ARR_F(lists->extbb_list);
2336 DEL_ARR_F(lists->blk_list);
2341 /* Close the vcg information for the irg */
2342 fprintf(F, "}\n\n");
2348 /* dumps a graph with type information */
2350 dump_ir_graph_w_types (ir_graph *irg, const char *suffix)
2353 ir_graph *rem = current_ir_graph;
2355 int rem_dump_const_local;
2357 /* if a filter is set, dump only the irg's that match the filter */
2358 if (!is_filtered_dump_name(get_entity_ident(get_irg_entity(irg))))
2361 current_ir_graph = irg;
2362 rem_dump_const_local = dump_const_local;
2363 /* dumping types does not work with local nodes */
2364 dump_const_local = 0;
2366 if (get_interprocedural_view()) suffix1 = "-pure-wtypes-ip";
2367 else suffix1 = "-pure-wtypes";
2368 f = vcg_open(irg,suffix, suffix1);
2369 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
2371 /* dump common ir graph */
2372 irg_walk(get_irg_end(irg), NULL, dump_whole_node, f);
2373 /* dump type info */
2374 type_walk_irg(irg, dump_type_info, NULL, f);
2375 inc_irg_visited(get_const_code_irg());
2376 /* dump edges from graph to type info */
2377 irg_walk(get_irg_end(irg), dump_node2type_edges, NULL, f);
2380 dump_const_local = rem_dump_const_local;
2381 current_ir_graph = rem;
2385 dump_ir_block_graph_w_types (ir_graph *irg, const char *suffix)
2390 ir_graph *rem = current_ir_graph;
2391 int rem_dump_const_local;
2393 /* if a filter is set, dump only the irg's that match the filter */
2394 if (!is_filtered_dump_name(get_entity_ident(get_irg_entity(irg))))
2397 rem_dump_const_local = dump_const_local;
2398 /* dumping types does not work with local nodes */
2399 dump_const_local = 0;
2401 if (get_interprocedural_view()) suffix1 = "-wtypes-ip";
2402 else suffix1 = "-wtypes";
2403 f = vcg_open(irg, suffix, suffix1);
2404 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
2406 /* dump common blocked ir graph */
2407 construct_block_lists(irg);
2409 for (i = 0; i < get_irp_n_irgs(); i++) {
2410 ir_node **arr = ird_get_irg_link(get_irp_irg(i));
2412 dump_graph_from_list(f, get_irp_irg(i));
2417 /* dump type info */
2418 current_ir_graph = irg;
2419 type_walk_irg(irg, dump_type_info, NULL, f);
2420 inc_irg_visited(get_const_code_irg());
2422 /* dump edges from graph to type info */
2423 irg_walk(get_irg_end(irg), dump_node2type_edges, NULL, f);
2426 dump_const_local = rem_dump_const_local;
2427 current_ir_graph = rem;
2430 /*---------------------------------------------------------------------*/
2431 /* The following routines dump a control flow graph. */
2432 /*---------------------------------------------------------------------*/
2435 dump_block_to_cfg(ir_node *block, void *env) {
2440 if (is_Block(block)) {
2441 /* This is a block. Dump a node for the block. */
2442 fprintf (F, "node: {title: \""); PRINT_NODEID(block);
2443 fprintf (F, "\" label: \"");
2444 if (block == get_irg_start_block(get_irn_irg(block)))
2445 fprintf(F, "Start ");
2446 if (block == get_irg_end_block(get_irn_irg(block)))
2449 fprintf (F, "%s ", get_op_name(get_irn_op(block)));
2450 PRINT_NODEID(block);
2452 fprintf(F, "info1:\"");
2455 if (dump_dominator_information_flag) {
2456 fprintf(F, "dom depth %d\n", get_Block_dom_depth(block));
2457 fprintf(F, "tree pre num %d\n", get_Block_dom_tree_pre_num(block));
2458 fprintf(F, "max subtree pre num %d\n", get_Block_dom_max_subtree_pre_num(block));
2461 /* show arity and possible Bad predecessors of the block */
2462 fprintf(F, "arity: %d\n", get_Block_n_cfgpreds(block));
2463 for (fl = i = 0; i < get_Block_n_cfgpreds(block); ++i) {
2464 ir_node *pred = get_Block_cfgpred(block, i);
2467 fprintf(F, "Bad pred at pos: ");
2468 fprintf(F, "%d ", i);
2475 /* the generic version. */
2476 dump_irnode_to_file(F, block);
2478 /* Check whether we have bad predecessors to color the block. */
2479 for (i = 0; i < get_Block_n_cfgpreds(block); ++i)
2480 if ((fl = is_Bad(get_Block_cfgpred(block, i))))
2484 fprintf (F, "\""); /* closing quote of info */
2486 if ((block == get_irg_start_block(get_irn_irg(block))) ||
2487 (block == get_irg_end_block(get_irn_irg(block))) )
2488 fprintf(F, " color:blue ");
2490 fprintf(F, " color:yellow ");
2493 /* Dump the edges */
2494 for ( i = 0; i < get_Block_n_cfgpreds(block); i++)
2495 if (get_irn_op(skip_Proj(get_Block_cfgpred(block, i))) != op_Bad) {
2496 pred = get_nodes_block(skip_Proj(get_Block_cfgpred(block, i)));
2497 fprintf (F, "edge: { sourcename: \"");
2498 PRINT_NODEID(block);
2499 fprintf (F, "\" targetname: \"");
2501 fprintf (F, "\"}\n");
2504 /* Dump dominator edge */
2505 if (dump_dominator_information_flag && get_Block_idom(block)) {
2506 pred = get_Block_idom(block);
2507 fprintf (F, "edge: { sourcename: \"");
2508 PRINT_NODEID(block);
2509 fprintf (F, "\" targetname: \"");
2511 fprintf (F, "\" " DOMINATOR_EDGE_ATTR "}\n");
2517 dump_cfg (ir_graph *irg, const char *suffix)
2520 ir_graph *rem = current_ir_graph;
2521 int ddif = dump_dominator_information_flag;
2522 int ipv = get_interprocedural_view();
2524 /* if a filter is set, dump only the irg's that match the filter */
2525 if (!is_filtered_dump_name(get_entity_ident(get_irg_entity(irg))))
2528 current_ir_graph = irg;
2530 f = vcg_open(irg, suffix, "-cfg");
2531 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
2534 printf("Warning: dumping cfg not in interprocedural view!\n");
2535 set_interprocedural_view(false);
2538 if (get_irg_dom_state(irg) != dom_consistent)
2539 dump_dominator_information_flag = 0;
2541 /* walk over the blocks in the graph */
2542 irg_block_walk(get_irg_end(irg), dump_block_to_cfg, NULL, f);
2543 dump_node(f, get_irg_bad(irg));
2545 dump_dominator_information_flag = ddif;
2546 set_interprocedural_view(ipv);
2548 current_ir_graph = rem;
2552 static void descend_and_dump(FILE *F, ir_node *n, int depth, pset *mark_set) {
2553 if (pset_find_ptr(mark_set, n)) return;
2555 pset_insert_ptr(mark_set, n);
2558 int i, start = is_Block(n) ? 0 : -1;
2559 dump_whole_node(n, F);
2560 for (i = start; i < get_irn_arity(n); ++i)
2561 descend_and_dump(F, get_irn_n(n, i), depth-1, mark_set);
2564 /* Don't dump edges to nodes further out. These might be edges to
2565 nodes we already dumped, if there is a shorter path to these. */
2569 static int subgraph_counter = 0;
2570 void dump_subgraph (ir_node *root, int depth, const char *suffix) {
2573 pset *mark_set = pset_new_ptr(1);
2574 sprintf(buf, "-subg_%03d", subgraph_counter++);
2575 F = vcg_open(get_irn_irg(root), suffix, buf);
2576 dump_vcg_header(F, get_irg_dump_name(get_irn_irg(root)), NULL);
2577 descend_and_dump(F, root, depth, mark_set);
2583 static int weight_overall(int rec, int loop) {
2584 return 2*rec + loop;
2587 static int compute_color (int my, int max) {
2594 /* if small, scale to the full color range. */
2596 my = my * (n_colors/max);
2598 step = 1 + (max / n_colors);
2602 return base_color + n_colors - color;
2605 static int get_entity_color(entity *ent) {
2606 ir_graph *irg = get_entity_irg(ent);
2610 int rec_depth = get_irg_recursion_depth(irg);
2611 int loop_depth = get_irg_loop_depth(irg);
2612 int overall_depth = weight_overall(rec_depth, loop_depth);
2614 int max_rec_depth = irp->max_callgraph_recursion_depth;
2615 int max_loop_depth = irp->max_callgraph_loop_depth;
2616 int max_overall_depth = weight_overall(max_rec_depth, max_loop_depth);
2618 /* int my_rec_color = compute_color(rec_depth, max_rec_depth); */
2619 /* int my_loop_color = compute_color(loop_depth, max_loop_depth); */
2620 int my_overall_color = compute_color(overall_depth, max_overall_depth);;
2622 return my_overall_color;
2626 void dump_callgraph(const char *suffix) {
2628 int i, n_irgs = get_irp_n_irgs();
2629 int rem = edge_label;
2631 //ident *prefix = new_id_from_str("java/");
2633 F = vcg_open_name("Callgraph", suffix);
2634 dump_vcg_header(F, "Callgraph", NULL);
2636 for (i = 0; i < n_irgs; ++i) {
2637 ir_graph *irg = get_irp_irg(i);
2638 entity *ent = get_irg_entity(irg);
2639 int j, n_callees = get_irg_n_callees(irg);
2641 /* Do not dump runtime system. */
2642 //if (id_is_prefix(prefix, get_entity_ld_ident(ent))) continue;
2644 dump_entity_node(F, ent, get_entity_color(ent));
2645 for (j = 0; j < n_callees; ++j) {
2646 entity *c = get_irg_entity(get_irg_callee(irg, j));
2647 //if (id_is_prefix(prefix, get_entity_ld_ident(c))) continue;
2648 int be = is_irg_callee_backedge(irg, j);
2651 "label:\"recursion %d\" color: %d" :
2652 "label:\"calls %d\" color: %d";
2653 print_ent_ent_edge(F, ent, c, be, attr, get_irg_callee_loop_depth(irg, j), get_entity_color(ent));
2661 /* Dump all irgs in interprocedural view to a single file. */
2662 void dump_all_cg_block_graph(const char *suffix) {
2665 int rem_view = get_interprocedural_view();
2666 set_interprocedural_view(true);
2668 f = vcg_open_name("All_graphs", suffix);
2669 dump_vcg_header(f, "All_graphs", NULL);
2671 /* collect nodes in all irgs reachable in call graph*/
2672 for (i = 0; i < get_irp_n_irgs(); i++)
2673 ird_set_irg_link(get_irp_irg(i), NULL);
2675 cg_walk(clear_link, collect_node, NULL);
2677 /* dump all graphs */
2678 for (i = 0; i < get_irp_n_irgs(); i++) {
2679 current_ir_graph = get_irp_irg(i);
2680 assert(ird_get_irg_link(current_ir_graph));
2681 dump_graph_from_list(f, current_ir_graph);
2682 DEL_ARR_F(ird_get_irg_link(current_ir_graph));
2686 set_interprocedural_view(rem_view);
2689 /*---------------------------------------------------------------------*/
2690 /* the following routines dumps type information without any ir nodes. */
2691 /*---------------------------------------------------------------------*/
2694 dump_type_graph (ir_graph *irg, const char *suffix)
2698 rem = current_ir_graph;
2700 /* if a filter is set, dump only the irg's that match the filter */
2701 if (!is_filtered_dump_name(get_entity_ident(get_irg_entity(irg)))) return;
2703 current_ir_graph = irg;
2705 f = vcg_open(irg, suffix, "-type");
2706 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
2708 /* walk over the blocks in the graph */
2709 type_walk_irg(irg, dump_type_info, NULL, f);
2710 /* The walker for the const code can be called several times for the
2711 same (sub) expression. So that no nodes are dumped several times
2712 we decrease the visited flag of the corresponding graph after each
2713 walk. So now increase it finally. */
2714 inc_irg_visited(get_const_code_irg());
2717 current_ir_graph = rem;
2721 dump_all_types (const char *suffix)
2723 FILE *f = vcg_open_name("All_types", suffix);
2724 dump_vcg_header(f, "All_types", NULL);
2725 type_walk(dump_type_info, NULL, f);
2726 inc_irg_visited(get_const_code_irg());
2731 dump_class_hierarchy (bool entities, const char *suffix)
2733 FILE *f = vcg_open_name("class_hierarchy", suffix);
2737 dump_vcg_header(f, "class_hierarchy", NULL);
2742 type_walk(dump_class_hierarchy_node, NULL, &env);
2746 /*---------------------------------------------------------------------*/
2747 /* dumps all graphs with the graph-dumper passed. Possible dumpers: */
2749 /* dump_ir_block_graph */
2751 /* dump_type_graph */
2752 /* dump_ir_graph_w_types */
2753 /*---------------------------------------------------------------------*/
2755 void dump_all_ir_graphs(dump_graph_func *dmp_grph, const char *suffix) {
2756 int i, n_irgs = get_irp_n_irgs();
2757 for (i = 0; i < n_irgs; ++i) {
2758 dmp_grph(get_irp_irg(i), suffix);
2763 /*--------------------------------------------------------------------------------*
2764 * Dumps a stand alone loop graph with firm nodes which belong to one loop node *
2765 * packed together in one subgraph/box *
2766 *--------------------------------------------------------------------------------*/
2768 void dump_loops_standalone(FILE *F, ir_loop *loop) {
2769 int i = 0, loop_node_started = 0, son_number = 0, first = 0;
2771 ir_loop *son = NULL;
2773 /* Dump a new loop node. */
2774 dump_loop_node(F, loop);
2776 /* Dump the loop elements. */
2778 for(i = 0; i < get_loop_n_elements(loop); i++) {
2779 le = get_loop_element(loop, i);
2781 if (get_kind(son) == k_ir_loop) {
2783 /* We are a loop son -> Recurse */
2785 if(loop_node_started) { /* Close the "firm-nodes" node first if we started one. */
2786 fprintf(F, "\" }\n");
2787 fprintf (F, "edge: {sourcename: \"");
2789 fprintf (F, "\" targetname: \"");
2791 fprintf (F, "-%d-nodes\" label:\"%d...%d\"}\n", first, first, i-1);
2792 loop_node_started = 0;
2794 dump_loop_son_edge(F, loop, son_number++);
2795 dump_loops_standalone(F, son);
2796 } else if (get_kind(son) == k_ir_node) {
2797 /* We are a loop node -> Collect firm nodes */
2799 ir_node *n = le.node;
2802 if (!loop_node_started) {
2803 /* Start a new node which contains all firm nodes of the current loop */
2804 fprintf (F, "node: { title: \"");
2806 fprintf (F, "-%d-nodes\" color: lightyellow label: \"", i);
2807 loop_node_started = 1;
2813 bad |= dump_node_label(F, n);
2814 /* Causes indeterministic output: if (is_Block(n)) fprintf (F, "\t ->%d", (int)get_irn_link(n)); */
2815 if (has_backedges(n)) fprintf(F, "\t loop head!");
2816 } else { /* for callgraph loop tree */
2818 assert(get_kind(son) == k_ir_graph);
2820 /* We are a loop node -> Collect firm graphs */
2821 n = (ir_graph *)le.node;
2822 if (!loop_node_started) {
2823 /* Start a new node which contains all firm nodes of the current loop */
2824 fprintf (F, "node: { title: \"");
2826 fprintf (F, "-%d-nodes\" color: lightyellow label: \"", i);
2827 loop_node_started = 1;
2832 fprintf (F, " %s", get_irg_dump_name(n));
2833 /* fprintf (F, " %s (depth %d)", get_irg_dump_name(n), n->callgraph_weighted_loop_depth); */
2837 if (loop_node_started) {
2838 fprintf(F, "\" }\n");
2839 fprintf (F, "edge: {sourcename: \"");
2841 fprintf (F, "\" targetname: \"");
2843 fprintf (F, "-%d-nodes\" label:\"%d...%d\"}\n", first, first, i-1);
2844 loop_node_started = 0;
2848 void dump_loop_tree(ir_graph *irg, const char *suffix)
2851 ir_graph *rem = current_ir_graph;
2852 int el_rem = edge_label;
2855 /* if a filter is set, dump only the irg's that match the filter */
2856 if (!is_filtered_dump_name(get_entity_ident(get_irg_entity(irg)))) return;
2858 current_ir_graph = irg;
2860 f = vcg_open(irg, suffix, "-looptree");
2861 dump_vcg_header(f, get_irg_dump_name(irg), "top_to_bottom");
2863 if (get_irg_loop(irg)) dump_loops_standalone(f, get_irg_loop(irg));
2867 edge_label = el_rem;
2868 current_ir_graph = rem;
2871 void dump_callgraph_loop_tree(const char *suffix) {
2873 F = vcg_open_name("Callgraph_looptree", suffix);
2874 dump_vcg_header(F, "callgraph looptree", "top_to_bottom");
2875 dump_loops_standalone(F, irp->outermost_cg_loop);
2880 /*-----------------------------------------------------------------------------*/
2881 /* Dumps the firm nodes in the loop tree to a graph along with the loop nodes. */
2882 /*-----------------------------------------------------------------------------*/
2884 void collect_nodeloop(FILE *F, ir_loop *loop, eset *loopnodes) {
2885 int i, son_number = 0, node_number = 0;
2887 if (dump_loop_information_flag) dump_loop_node(F, loop);
2889 for (i = 0; i < get_loop_n_elements(loop); i++) {
2890 loop_element le = get_loop_element(loop, i);
2891 if (*(le.kind) == k_ir_loop) {
2892 if (dump_loop_information_flag) dump_loop_son_edge(F, loop, son_number++);
2894 collect_nodeloop(F, le.son, loopnodes);
2896 if (dump_loop_information_flag) dump_loop_node_edge(F, loop, node_number++);
2897 eset_insert(loopnodes, le.node);
2902 void collect_nodeloop_external_nodes(ir_loop *loop, eset *loopnodes, eset *extnodes) {
2905 for(i = 0; i < get_loop_n_elements(loop); i++) {
2906 loop_element le = get_loop_element(loop, i);
2907 if (*(le.kind) == k_ir_loop) {
2909 collect_nodeloop_external_nodes(le.son, loopnodes, extnodes);
2911 if (is_Block(le.node)) start = 0; else start = -1;
2912 for (j = start; j < get_irn_arity(le.node); j++) {
2913 ir_node *pred = get_irn_n(le.node, j);
2914 if (!eset_contains(loopnodes, pred)) {
2915 eset_insert(extnodes, pred);
2916 if (!is_Block(pred)) {
2917 pred = get_nodes_block(pred);
2918 if (!eset_contains(loopnodes, pred)) eset_insert(extnodes, pred);
2926 void dump_loop(ir_loop *l, const char *suffix) {
2929 eset *loopnodes = eset_create();
2930 eset *extnodes = eset_create();
2933 snprintf(name, sizeof(name), "loop_%d", get_loop_loop_nr(l));
2934 F = vcg_open_name (name, suffix);
2935 dump_vcg_header(F, name, NULL);
2937 /* collect all nodes to dump */
2938 collect_nodeloop(F, l, loopnodes);
2939 collect_nodeloop_external_nodes(l, loopnodes, extnodes);
2941 /* build block lists */
2942 for (n = eset_first(loopnodes); n != NULL; n = eset_next(loopnodes))
2943 set_irn_link(n, NULL);
2944 for (n = eset_first(extnodes); n != NULL; n = eset_next(extnodes))
2945 set_irn_link(n, NULL);
2946 for (n = eset_first(loopnodes); n != NULL; n = eset_next(loopnodes))
2948 b = get_nodes_block(n);
2949 set_irn_link(n, get_irn_link(b));
2952 for (n = eset_first(extnodes); n != NULL; n = eset_next(extnodes))
2954 b = get_nodes_block(n);
2955 set_irn_link(n, get_irn_link(b));
2959 for (b = eset_first(loopnodes); b != NULL; b = eset_next(loopnodes))
2961 fprintf(F, "graph: { title: \"");
2963 fprintf(F, "\" label: \"");
2964 dump_node_opcode(F, b);
2965 fprintf (F, " %ld", get_irn_node_nr(b));
2966 fprintf(F, "\" status:clustered color:yellow\n");
2968 /* dump the blocks edges */
2969 dump_ir_data_edges(F, b);
2971 /* dump the nodes that go into the block */
2972 for (n = get_irn_link(b); n; n = get_irn_link(n)) {
2973 if (eset_contains(extnodes, n)) overrule_nodecolor = "lightblue";
2975 overrule_nodecolor = NULL;
2976 if (!eset_contains(extnodes, n)) dump_ir_data_edges(F, n);
2979 /* Close the vcg information for the block */
2981 dump_const_node_local(F, b);
2984 for (b = eset_first(extnodes); b != NULL; b = eset_next(extnodes))
2986 fprintf(F, "graph: { title: \"");
2988 fprintf(F, "\" label: \"");
2989 dump_node_opcode(F, b);
2990 fprintf (F, " %ld", get_irn_node_nr(b));
2991 fprintf(F, "\" status:clustered color:lightblue\n");
2993 /* dump the nodes that go into the block */
2994 for (n = get_irn_link(b); n; n = get_irn_link(n)) {
2995 if (!eset_contains(loopnodes, n)) overrule_nodecolor = "lightblue";
2997 overrule_nodecolor = NULL;
2998 if (eset_contains(loopnodes, n)) dump_ir_data_edges(F, n);
3001 /* Close the vcg information for the block */
3003 dump_const_node_local(F, b);
3007 eset_destroy(loopnodes);
3008 eset_destroy(extnodes);