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 attribute hook. */
109 static DUMP_NODE_VCGATTR_FUNC dump_node_vcgattr_hook = NULL;
112 void set_dump_node_vcgattr_hook(DUMP_NODE_VCGATTR_FUNC hook) {
113 dump_node_vcgattr_hook = hook;
116 INLINE bool get_opt_dump_const_local(void) {
117 if (!dump_out_edge_flag && !dump_loop_information_flag)
118 return dump_const_local;
123 void only_dump_method_with_name(ident *name) {
124 dump_file_filter_id = name;
127 ident *get_dump_file_filter_ident(void) {
128 return dump_file_filter_id;
131 /** Returns true if dump file filter is not set, or if it is a
133 int is_filtered_dump_name(ident *name) {
134 if (!dump_file_filter_id) return 1;
135 return id_is_prefix(dump_file_filter_id, name);
138 /* To turn off display of edge labels. Edge labels often cause xvcg to
139 abort with a segmentation fault. */
140 void turn_off_edge_labels(void) {
144 void dump_consts_local(bool b) {
145 dump_const_local = b;
148 void dump_constant_entity_values(bool b) {
152 void dump_keepalive_edges(bool b) {
156 bool get_opt_dump_keepalive_edges(void) {
157 return dump_keepalive;
160 void dump_out_edges(bool b) {
161 dump_out_edge_flag = b;
164 void dump_dominator_information(bool b) {
165 dump_dominator_information_flag = b;
168 void dump_loop_information(bool b) {
169 dump_loop_information_flag = b;
172 void dump_backedge_information(bool b) {
173 dump_backedge_information_flag = b;
176 /* Dump the information of type field specified in ana/irtypeinfo.h.
177 * If the flag is set, the type name is output in [] in the node label,
178 * else it is output as info.
180 void set_opt_dump_analysed_type_info(bool b) {
181 opt_dump_analysed_type_info = b;
184 void dump_pointer_values_to_info(bool b) {
185 opt_dump_pointer_values_to_info = b;
188 void dump_ld_names(bool b) {
192 /* -------------- some extended helper functions ----------------- */
195 * returns the name of a mode or <ERROR> if mode is NOT a mode object.
196 * in the later case, sets bad
198 const char *get_mode_name_ex(ir_mode *mode, int *bad)
201 return get_mode_name(mode);
207 * returns the name of a type or <ERROR> if mode is NOT a mode object.
208 * in the later case, sets bad
210 const char *get_type_name_ex(type *tp, int *bad)
213 return get_type_name(tp);
219 * prints the edge from a type S to a type T with additional info fmt, ...
222 static void print_type_type_edge(FILE *F, type *S, type *T, const char *fmt, ...)
227 fprintf(F, "edge: { sourcename: "); PRINT_TYPEID(S);
228 fprintf(F, " targetname: "); PRINT_TYPEID(T);
229 vfprintf(F, fmt, ap);
235 * prints the edge from a type T to an entity E with additional info fmt, ...
238 static void print_type_ent_edge(FILE *F, type *T, entity *E, const char *fmt, ...)
243 fprintf(F, "edge: { sourcename: "); PRINT_TYPEID(T);
244 fprintf(F, " targetname: \""); PRINT_ENTID(E); fprintf(F, "\"");
245 vfprintf(F, fmt, ap);
251 * prints the edge from an entity E to an entity T with additional info fmt, ...
254 static void print_ent_ent_edge(FILE *F, entity *E, entity *T, int backedge, const char *fmt, ...)
260 fprintf(F, "backedge: { sourcename: \"");
262 fprintf(F, "edge: { sourcename: \"");
264 fprintf(F, "\" targetname: \""); PRINT_ENTID(T); fprintf(F, "\"");
265 vfprintf(F, fmt, ap);
271 * prints the edge from an entity E to a type T with additional info fmt, ...
274 static void print_ent_type_edge(FILE *F, entity *E, type *T, const char *fmt, ...)
279 fprintf(F, "edge: { sourcename: \""); PRINT_ENTID(E);
280 fprintf(F, "\" targetname: "); PRINT_TYPEID(T);
281 vfprintf(F, fmt, ap);
287 * prints the edge from a node N to a type T with additional info fmt, ...
290 static void print_node_type_edge(FILE *F, const ir_node *N, type *T, const char *fmt, ...)
295 fprintf(F, "edge: { sourcename: \""); PRINT_NODEID(N);
296 fprintf(F, "\" targetname: "); PRINT_TYPEID(T);
297 vfprintf(F, fmt, ap);
303 * prints the edge from a node N to an entity E with additional info fmt, ...
306 static void print_node_ent_edge(FILE *F, const ir_node *N, entity *E, const char *fmt, ...)
311 fprintf(F, "edge: { sourcename: \""); PRINT_NODEID(N);
312 fprintf(F, "\" targetname: \""); PRINT_ENTID(E);
314 vfprintf(F, fmt, ap);
320 * prints the edge from an entity E to a node N with additional info fmt, ...
323 static void print_ent_node_edge(FILE *F, entity *E, const ir_node *N, const char *fmt, ...)
328 fprintf(F, "edge: { sourcename: \""); PRINT_ENTID(E);
329 fprintf(F, "\" targetname: \""); PRINT_NODEID(N); fprintf(F, "\"");
330 vfprintf(F, fmt, ap);
336 * prints the edge from a type E to an enumeration item item with additional info fmt, ...
339 static void print_enum_item_edge(FILE *F, type *E, int item, const char *fmt, ...)
344 fprintf(F, "edge: { sourcename: "); PRINT_TYPEID(E);
345 fprintf(F, " targetname: \""); PRINT_ITEMID(E, item); fprintf(F, "\" ");
346 vfprintf(F, fmt, ap);
351 /*-----------------------------------------------------------------*/
352 /* global and ahead declarations */
353 /*-----------------------------------------------------------------*/
355 static void dump_whole_node(ir_node *n, void *env);
356 static INLINE void dump_loop_nodes_into_graph(FILE *F, ir_graph *irg);
358 /*-----------------------------------------------------------------*/
359 /* Helper functions. */
360 /*-----------------------------------------------------------------*/
363 * This map is used as a private link attr to be able to call dumper
364 * anywhere without destroying link fields.
366 static pmap *irdump_link_map = NULL;
368 /** NOT A STANDARD LIBFIRM INIT METHOD
370 * We do not want to integrate dumping into libfirm, i.e., if the dumpers
371 * are off, we want to have as few interferences as possible. Therefore the
372 * initialization is performed lazily and not called from within init_firm.
374 * Creates the link attribute map. */
375 static void init_irdump(void) {
376 /* We need a new, empty map. */
377 if (irdump_link_map) pmap_destroy(irdump_link_map);
378 irdump_link_map = pmap_create();
379 if (!dump_file_filter_id)
380 dump_file_filter_id = new_id_from_str("");
383 * Returns the private link field.
385 static void *ird_get_irn_link(ir_node *n) {
387 if (!irdump_link_map) return NULL;
389 if (pmap_contains(irdump_link_map, (void *)n))
390 res = pmap_get(irdump_link_map, (void *)n);
395 * Sets the private link field.
397 static void ird_set_irn_link(ir_node *n, void *x) {
398 if (!irdump_link_map)
400 pmap_insert(irdump_link_map, (void *)n, x);
404 * Gets the private link field of an irg.
406 static void *ird_get_irg_link(ir_graph *irg) {
408 if (!irdump_link_map) return NULL;
410 if (pmap_contains(irdump_link_map, (void *)irg))
411 res = pmap_get(irdump_link_map, (void *)irg);
416 * Sets the private link field of an irg.
418 static void ird_set_irg_link(ir_graph *irg, void *x) {
419 if (!irdump_link_map) init_irdump();
420 pmap_insert(irdump_link_map, (void *)irg, x);
424 * Walker, clears the private link field.
426 static void clear_link(ir_node * node, void * env) {
427 ird_set_irn_link(node, NULL);
431 * If the entity has a ld_name, returns it if the dump_ld_name is set,
432 * else returns the name of the entity.
434 static const char *_get_ent_dump_name(entity *ent, int dump_ld_name) {
436 return "<NULL entity>";
438 /* Don't use get_entity_ld_ident (ent) as it computes the mangled name! */
439 if (ent->ld_name) return get_id_str(ent->ld_name);
441 return get_id_str(ent->name);
445 * If the entity has a ld_name, returns it if the option dump_ld_name is set,
446 * else returns the name of the entity.
448 const char *get_ent_dump_name(entity *ent) {
449 return _get_ent_dump_name(ent, dump_ld_name);
452 /* Returns the name of an IRG. */
453 const char *get_irg_dump_name(ir_graph *irg) {
454 /* Don't use get_entity_ld_ident (ent) as it computes the mangled name! */
455 return _get_ent_dump_name(get_irg_entity(irg), 1);
459 * Returns non-zero if a node is in floating state.
461 static int node_floats(ir_node *n) {
462 return ((get_irn_pinned(n) == op_pin_state_floats) &&
463 (get_irg_pinned(current_ir_graph) == op_pin_state_floats));
467 * Walker, allocates an array for all blocks and puts it's nodes non-floating nodes into this array.
469 static void collect_node(ir_node * node, void *env) {
472 || get_irn_op(node) == op_Bad
473 || get_irn_op(node) == op_Unknown
474 || get_irn_op(node) == op_NoMem) {
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! */
480 ir_node * block = get_nodes_block(node);
483 /* this node is in a Bad block, so we must place it into the graph's list */
484 ir_node ** arr = (ir_node **) ird_get_irg_link(get_irn_irg(node));
485 if (!arr) arr = NEW_ARR_F(ir_node *, 0);
486 ARR_APP1(ir_node *, arr, node);
487 ird_set_irg_link(get_irn_irg(node), arr); /* arr is an l-value, APP_ARR might change it! */
490 ird_set_irn_link(node, ird_get_irn_link(block));
491 ird_set_irn_link(block, node);
496 /** Construct lists to walk ir block-wise.
498 * Collects all blocks, nodes not op_pin_state_pinned,
499 * Bad, NoMem and Unknown into a flexible array in link field of
500 * irg they belong to. Sets the irg link field to NULL in all
501 * graphs not visited.
502 * Free the list with DEL_ARR_F().
504 static ir_node **construct_block_lists(ir_graph *irg) {
505 int i, rem_view = get_interprocedural_view();
506 ir_graph *rem = current_ir_graph;
507 current_ir_graph = irg;
509 for (i = 0; i < get_irp_n_irgs(); i++)
510 ird_set_irg_link(get_irp_irg(i), NULL);
512 irg_walk_graph(current_ir_graph, clear_link, collect_node, current_ir_graph);
514 /* Collect also EndReg and EndExcept. We do not want to change the walker. */
515 set_interprocedural_view(false);
517 set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph)-1);
518 irg_walk(get_irg_end_reg(current_ir_graph), clear_link, collect_node, current_ir_graph);
519 set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph)-1);
520 irg_walk(get_irg_end_except(current_ir_graph), clear_link, collect_node, current_ir_graph);
522 set_interprocedural_view(rem_view);
524 current_ir_graph = rem;
525 return ird_get_irg_link(irg);
528 typedef struct _list_tuple {
530 ir_extblk **extbb_list;
533 /** Construct lists to walk ir extended block-wise.
534 * Free the lists in the tuple with DEL_ARR_F().
536 static list_tuple *construct_extblock_lists(ir_graph *irg) {
537 ir_node **blk_list = construct_block_lists(irg);
539 ir_graph *rem = current_ir_graph;
540 list_tuple *lists = xmalloc(sizeof(*lists));
542 current_ir_graph = irg;
544 lists->blk_list = NEW_ARR_F(ir_node *, 0);
545 lists->extbb_list = NEW_ARR_F(ir_extblk *, 0);
547 for (i = ARR_LEN(blk_list) - 1; i >= 0; --i) {
550 if (is_Block(blk_list[i])) {
551 ext = get_Block_extbb(blk_list[i]);
553 if (extbb_not_visited(ext)) {
554 ARR_APP1(ir_extblk *, lists->extbb_list, ext);
555 mark_extbb_visited(ext);
559 ARR_APP1(ir_node *, lists->blk_list, blk_list[i]);
562 current_ir_graph = rem;
564 ird_set_irg_link(irg, lists);
568 /*-----------------------------------------------------------------*/
569 /* Routines to dump information about a single ir node. */
570 /*-----------------------------------------------------------------*/
573 * dump the name of a node n to the File F.
576 dump_node_opcode(FILE *F, ir_node *n)
580 switch(get_irn_opcode(n)) {
585 res = tarval_snprintf(buf, sizeof(buf), get_Const_tarval(n));
586 assert(res < sizeof(buf) && "buffer to small for tarval_snprintf");
591 if (get_SymConst_kind(n) == symconst_addr_name) {
592 /* don't use get_SymConst_ptr_info as it mangles the name. */
593 fprintf (F, "SymC %s", get_id_str(get_SymConst_name(n)));
594 } else if (get_SymConst_kind(n) == symconst_addr_ent) {
595 assert(get_SymConst_entity(n));
596 assert(is_entity(get_SymConst_entity(n)));
597 fprintf (F, "SymC &%s", get_entity_name(get_SymConst_entity(n)));
599 assert(get_kind(get_SymConst_type(n)) == k_type);
600 assert(get_type_ident(get_SymConst_type(n)));
601 fprintf (F, "SymC %s ", get_type_name_ex(get_SymConst_type(n), &bad));
602 if (get_SymConst_kind(n) == symconst_type_tag)
610 if (!get_interprocedural_view())
617 ir_node *pred = get_Proj_pred(n);
619 if (get_irn_opcode(pred) == iro_Cond
620 && get_Proj_proj(n) == get_Cond_defaultProj(pred)
621 && get_irn_mode(get_Cond_selector(pred)) != mode_b)
622 fprintf (F, "defProj");
630 if (get_interprocedural_view()) {
631 fprintf(F, "%s %s", get_irn_opname(n), get_ent_dump_name(get_irg_entity(get_irn_irg(n))));
636 case iro_CallBegin: {
637 ir_node *addr = get_CallBegin_ptr(n);
639 if (get_irn_op(addr) == op_Sel)
640 ent = get_Sel_entity(addr);
641 else if ((get_irn_op(addr) == op_SymConst) && (get_SymConst_kind(addr) == symconst_addr_ent))
642 ent = get_SymConst_entity(addr);
643 fprintf (F, "%s", get_irn_opname(n));
644 if (ent) fprintf (F, " %s", get_entity_name(ent));
648 fprintf (F, "%s[%s]", get_irn_opname(n), get_mode_name_ex(get_Load_mode(n), &bad));
651 fprintf (F, "%s%s", is_Block_dead(n) ? "Dead " : "", get_irn_opname(n));
656 fprintf (F, "%s", get_irn_opname(n));
664 * Dump the mode of a node n to a file F.
665 * Ignore modes that are "always known".
668 dump_node_mode(FILE *F, ir_node *n)
671 opcode iro = get_irn_opcode(n);
684 ir_mode *mode = get_irn_mode(n);
686 if (mode && mode != mode_BB && mode != mode_ANY && mode != mode_BAD &&
687 (mode != mode_T || iro == iro_Proj))
688 fprintf(F, "%s", get_mode_name_ex(mode, &bad));
696 * Dump the type of a node n to a file F if it's known.
698 static int dump_node_typeinfo(FILE *F, ir_node *n) {
701 if (opt_dump_analysed_type_info) {
702 if (get_irg_typeinfo_state(current_ir_graph) == ir_typeinfo_consistent ||
703 get_irg_typeinfo_state(current_ir_graph) == ir_typeinfo_inconsistent) {
704 type *tp = get_irn_typeinfo_type(n);
705 if (tp != firm_none_type)
706 fprintf(F, "[%s] ", get_type_name_ex(tp, &bad));
714 typedef struct _pns_lookup {
715 long nr; /**< the proj number */
716 const char *name; /**< the name of the Proj */
719 typedef struct _proj_lookup {
720 opcode code; /**< the opcode of the Proj predecessor */
721 unsigned num_data; /**< number of data entries */
722 const pns_lookup_t *data; /**< the data */
725 #define ARR_SIZE(a) (sizeof(a)/sizeof(a[0]))
727 /** the lookup table for Proj(Start) names */
728 static const pns_lookup_t start_lut[] = {
729 #define X(a) { pn_Start_##a, #a }
738 /** the lookup table for Proj(Cond) names */
739 static const pns_lookup_t cond_lut[] = {
740 #define X(a) { pn_Cond_##a, #a }
746 /** the lookup table for Proj(Call) names */
747 static const pns_lookup_t call_lut[] = {
748 #define X(a) { pn_Call_##a, #a }
757 /** the lookup table for Proj(Quot) names */
758 static const pns_lookup_t quot_lut[] = {
759 #define X(a) { pn_Quot_##a, #a }
766 /** the lookup table for Proj(DivMod) names */
767 static const pns_lookup_t divmod_lut[] = {
768 #define X(a) { pn_DivMod_##a, #a }
776 /** the lookup table for Proj(Div) names */
777 static const pns_lookup_t div_lut[] = {
778 #define X(a) { pn_Div_##a, #a }
785 /** the lookup table for Proj(Mod) names */
786 static const pns_lookup_t mod_lut[] = {
787 #define X(a) { pn_Mod_##a, #a }
794 /** the lookup table for Proj(Load) names */
795 static const pns_lookup_t load_lut[] = {
796 #define X(a) { pn_Load_##a, #a }
803 /** the lookup table for Proj(Store) names */
804 static const pns_lookup_t store_lut[] = {
805 #define X(a) { pn_Store_##a, #a }
811 /** the lookup table for Proj(Alloc) names */
812 static const pns_lookup_t alloc_lut[] = {
813 #define X(a) { pn_Alloc_##a, #a }
821 /** the Proj lookup table */
822 static const proj_lookup_t proj_lut[] = {
823 #define E(a) ARR_SIZE(a), a
824 { iro_Start, E(start_lut) },
825 { iro_Cond, E(cond_lut) },
826 { iro_Call, E(call_lut) },
827 { iro_Quot, E(quot_lut) },
828 { iro_DivMod, E(divmod_lut) },
829 { iro_Div, E(div_lut) },
830 { iro_Mod, E(mod_lut) },
831 { iro_Load, E(load_lut) },
832 { iro_Store, E(store_lut) },
833 { iro_Alloc, E(alloc_lut) }
838 * Dump additional node attributes of some nodes to a file F.
841 dump_node_nodeattr(FILE *F, ir_node *n)
848 switch (get_irn_opcode(n)) {
850 if (false && get_interprocedural_view()) {
851 fprintf (F, "%s ", get_ent_dump_name(get_irg_entity(current_ir_graph)));
856 pred = get_Proj_pred(n);
857 proj_nr = get_Proj_proj(n);
859 code = get_irn_opcode(pred);
862 fprintf (F, "%s ", get_pnc_string(get_Proj_proj(n)));
863 else if (code == iro_Proj && get_irn_opcode(get_Proj_pred(pred)) == iro_Start)
864 fprintf (F, "Arg %ld ", proj_nr);
866 unsigned i, j, f = 0;
868 for (i = 0; i < ARR_SIZE(proj_lut); ++i) {
869 if (code == proj_lut[i].code) {
870 for (j = 0; j < proj_lut[i].num_data; ++j) {
871 if (proj_nr == proj_lut[i].data[j].nr) {
872 fprintf (F, "%s ", proj_lut[i].data[j].name);
881 fprintf (F, "%ld ", proj_nr);
882 if (code == iro_Cond && get_Cond_jmp_pred(pred) != COND_JMP_PRED_NONE) {
883 if (proj_nr == pn_Cond_false && get_Cond_jmp_pred(pred) == COND_JMP_PRED_FALSE)
885 if (proj_nr == pn_Cond_true && get_Cond_jmp_pred(pred) == COND_JMP_PRED_TRUE)
891 proj_nr = get_Filter_proj(n);
892 if (! get_interprocedural_view()) {
894 pred = get_Filter_pred(n);
898 fprintf (F, "%ld ", proj_nr);
901 fprintf (F, "%s ", get_ent_dump_name(get_Sel_entity(n)));
904 fprintf (F, "(%s) ", get_type_name_ex(get_Cast_type(n), &bad));
907 fprintf (F, "%s ", get_pnc_string(get_Confirm_cmp(n)));
918 #include "execution_frequency.h"
919 #include "callgraph.h"
921 void dump_node_ana_vals(FILE *F, ir_node *n) {
923 fprintf(F, " %lf*(%2.0lf + %2.0lf) = %2.0lf ",
924 get_irn_exec_freq(n),
925 get_irg_method_execution_frequency(get_irn_irg(n)),
926 pow(5, get_irg_recursion_depth(get_irn_irg(n))),
927 get_irn_exec_freq(n) * (get_irg_method_execution_frequency(get_irn_irg(n)) + pow(5, get_irg_recursion_depth(get_irn_irg(n))))
932 /* Dumps a node label without the enclosing ". */
933 int dump_node_label(FILE *F, ir_node *n) {
936 bad |= dump_node_opcode(F, n);
937 bad |= dump_node_mode(F, n);
939 bad |= dump_node_typeinfo(F, n);
940 bad |= dump_node_nodeattr(F, n);
941 fprintf(F, "%ld", get_irn_node_nr(n));
948 * Dumps the attributes of a node n into the file F.
949 * Currently this is only the color of a node.
951 static void dump_node_vcgattr(FILE *F, ir_node *node, ir_node *local, int bad)
956 fprintf(F, "color: red");
960 if (dump_node_vcgattr_hook)
961 if (dump_node_vcgattr_hook(F, node, local))
964 n = local ? local : node;
966 switch (get_irn_opcode(n)) {
973 fprintf (F, "color: blue");
976 if (is_Block_dead(n))
977 fprintf (F, "color: lightred");
979 fprintf (F, "color: lightyellow");
982 fprintf (F, "color: green");
988 fprintf (F, "color: yellow");
991 PRINT_DEFAULT_NODE_ATTR;
994 if (overrule_nodecolor) fprintf(F, " color: %s", overrule_nodecolor);
999 * Dump the node information of a node n to a file F.
1001 static INLINE int dump_node_info(FILE *F, ir_node *n)
1003 fprintf (F, " info1: \"");
1004 bad = dump_irnode_to_file(F, n);
1010 * checks whether a node is "constant-like" ie can be treated "block-less"
1013 bool is_constlike_node(ir_node *n) {
1014 ir_op *op = get_irn_op(n);
1015 return (op == op_Const || op == op_Bad || op == op_NoMem || op == op_SymConst || op == op_Unknown);
1019 /** outputs the predecessors of n, that are constants, local. I.e.,
1020 generates a copy of the constant predecessors for each node called with. */
1021 static void dump_const_node_local(FILE *F, ir_node *n) {
1023 if (!get_opt_dump_const_local()) return;
1025 /* Use visited flag to avoid outputting nodes twice.
1026 initialize it first. */
1027 for (i = 0; i < get_irn_arity(n); i++) {
1028 ir_node *con = get_irn_n(n, i);
1029 if (is_constlike_node(con)) {
1030 set_irn_visited(con, get_irg_visited(current_ir_graph) - 1);
1034 for (i = 0; i < get_irn_arity(n); i++) {
1035 ir_node *con = get_irn_n(n, i);
1036 if (is_constlike_node(con) && irn_not_visited(con)) {
1039 mark_irn_visited(con);
1040 /* Generate a new name for the node by appending the names of
1042 fprintf(F, "node: {title: "); PRINT_CONSTID(n, con);
1043 fprintf(F, " label: \"");
1044 bad |= dump_node_label(F, con);
1046 bad |= dump_node_info(F, con);
1047 dump_node_vcgattr(F, n, con, bad);
1053 /** If the block of an edge is a const_like node, dump it local with an edge */
1054 static void dump_const_block_local(FILE *F, ir_node *n) {
1057 if (!get_opt_dump_const_local()) return;
1059 blk = get_nodes_block(n);
1060 if (is_constlike_node(blk)) {
1063 /* Generate a new name for the node by appending the names of
1065 fprintf(F, "node: {title: \""); PRINT_CONSTBLKID(n, blk);
1066 fprintf(F, "\" label: \"");
1067 bad |= dump_node_label(F, blk);
1069 bad |= dump_node_info(F, blk);
1070 dump_node_vcgattr(F, n, blk, bad);
1073 fprintf (F, "edge: { sourcename: \"");
1075 fprintf (F, "\" targetname: \""); PRINT_CONSTBLKID(n,blk);
1076 fprintf (F, "\" " BLOCK_EDGE_ATTR "}\n");
1081 * prints the error message of a node to a file F as info2.
1083 static void INLINE print_node_error(FILE *F, const char *err_msg)
1088 fprintf (F, " info2: \"%s\"", err_msg);
1092 * prints debug messages of a node to file F as info3.
1094 static void print_node_dbg_info(FILE *F, dbg_info *dbg)
1098 if (__dbg_info_snprint) {
1100 if (__dbg_info_snprint(buf, sizeof(buf), dbg) > 0)
1101 fprintf (F, " info3: \"%s\"\n", buf);
1108 static void dump_node(FILE *F, ir_node *n)
1113 if (get_opt_dump_const_local() && is_constlike_node(n))
1116 /* dump this node */
1117 fprintf(F, "node: {title: \""); PRINT_NODEID(n); fprintf(F, "\" label: \"");
1119 bad = ! irn_vrfy_irg_dump(n, current_ir_graph, &p);
1120 bad |= dump_node_label(F, n);
1121 dump_node_ana_vals(F, n);
1122 //dump_node_ana_info(F, n);
1124 bad |= dump_node_info(F, n);
1125 print_node_error(F, p);
1126 print_node_dbg_info(F, get_irn_dbg_info(n));
1127 dump_node_vcgattr(F, n, NULL, bad);
1129 dump_const_node_local(F, n);
1131 if(dump_node_edge_hook)
1132 dump_node_edge_hook(F, n);
1134 dump_irn_chi_term(F, n);
1135 dump_irn_state(F, n);
1139 /** dump the edge to the block this node belongs to */
1141 dump_ir_block_edge(FILE *F, ir_node *n) {
1142 if (get_opt_dump_const_local() && is_constlike_node(n)) return;
1143 if (is_no_Block(n)) {
1144 ir_node *block = get_nodes_block(n);
1146 if (get_opt_dump_const_local() && is_constlike_node(block)) {
1147 dump_const_block_local(F, n);
1150 fprintf (F, "edge: { sourcename: \"");
1152 fprintf (F, "\" targetname: ");
1153 fprintf(F, "\""); PRINT_NODEID(block); fprintf(F, "\"");
1154 fprintf (F, " " BLOCK_EDGE_ATTR "}\n");
1160 print_data_edge_vcgattr(FILE *F, ir_node *from, int to) {
1162 * do not use get_nodes_block() here, will fail
1163 * if the irg is not pinned.
1165 if (get_irn_n(from, -1) == get_irn_n(get_irn_n(from, to), -1))
1166 fprintf (F, INTRA_DATA_EDGE_ATTR);
1168 fprintf (F, INTER_DATA_EDGE_ATTR);
1172 print_mem_edge_vcgattr(FILE *F, ir_node *from, int to) {
1174 * do not use get_nodes_block() here, will fail
1175 * if the irg is not pinned.
1177 if (get_irn_n(from, -1) == get_irn_n(get_irn_n(from, to), -1))
1178 fprintf (F, INTRA_MEM_EDGE_ATTR);
1180 fprintf (F, INTER_MEM_EDGE_ATTR);
1184 print_edge_vcgattr(FILE *F, ir_node *from, int to) {
1187 if (dump_backedge_information_flag && is_backedge(from, to))
1188 fprintf (F, BACK_EDGE_ATTR);
1190 switch (get_irn_opcode(from)) {
1192 fprintf (F, CF_EDGE_ATTR);
1194 case iro_Start: break;
1197 if (get_irn_mode(get_End_keepalive(from, to)) == mode_BB)
1198 fprintf (F, CF_EDGE_ATTR);
1199 if (get_irn_mode(get_End_keepalive(from, to)) == mode_X)
1200 fprintf (F, INTER_MEM_EDGE_ATTR);
1208 print_data_edge_vcgattr(F, from, to);
1213 print_mem_edge_vcgattr(F, from, to);
1215 print_data_edge_vcgattr(F, from, to);
1219 print_data_edge_vcgattr(F, from, to);
1224 print_mem_edge_vcgattr(F, from, to);
1226 print_data_edge_vcgattr(F, from, to);
1233 print_data_edge_vcgattr(F, from, to);
1240 print_mem_edge_vcgattr(F, from, to);
1242 print_data_edge_vcgattr(F, from, to);
1254 print_data_edge_vcgattr(F, from, to);
1257 if (get_irn_modecode(from) == irm_M)
1258 fprintf (F, INTER_MEM_EDGE_ATTR);
1260 print_data_edge_vcgattr(F, from, to);
1267 print_mem_edge_vcgattr(F, from, to);
1269 print_data_edge_vcgattr(F, from, to);
1272 print_mem_edge_vcgattr(F, from, to);
1274 case iro_Tuple: break;
1277 switch (get_irn_modecode(from)) {
1279 fprintf (F, CF_EDGE_ATTR);
1282 fprintf (F, INTER_MEM_EDGE_ATTR);
1285 print_data_edge_vcgattr(F, from, to);
1289 case iro_Bad: break;
1290 case iro_Unknown: break;
1292 switch (get_irn_modecode(from)) {
1294 fprintf (F, INTRA_MEM_EDGE_ATTR);
1297 fprintf (F, CF_EDGE_ATTR);
1300 print_data_edge_vcgattr(F, from, to);
1308 /* dump edges to our inputs */
1310 dump_ir_data_edges(FILE *F, ir_node *n) {
1312 unsigned long visited = get_irn_visited(n);
1314 if ((get_irn_op(n) == op_End) && (!dump_keepalive))
1317 for (i = 0; i < get_irn_arity(n); i++) {
1318 ir_node * pred = get_irn_n(n, i);
1321 if ((get_interprocedural_view() && get_irn_visited(pred) < visited))
1322 continue; /* pred not dumped */
1324 if (dump_backedge_information_flag && is_backedge(n, i))
1325 fprintf (F, "backedge: {sourcename: \"");
1327 fprintf (F, "edge: {sourcename: \"");
1329 fprintf (F, "\" targetname: ");
1330 if ((get_opt_dump_const_local()) && is_constlike_node(pred)) {
1331 PRINT_CONSTID(n, pred);
1333 fprintf(F, "\""); PRINT_NODEID(pred); fprintf(F, "\"");
1335 fprintf (F, " label: \"%d\" ", i);
1336 print_edge_vcgattr(F, n, i);
1341 /** Dumps a node and its edges but not the block edge
1344 dump_node_wo_blockedge (ir_node *n, void *env) {
1347 dump_ir_data_edges(F, n);
1350 /** Dumps a node and its edges.
1353 dump_whole_node (ir_node *n, void *env) {
1355 dump_node_wo_blockedge(n, env);
1356 if (!node_floats(n)) dump_ir_block_edge(F, n);
1360 dump_const_node(ir_node *n, void *env) {
1361 if (is_Block(n)) return;
1362 dump_node_wo_blockedge(n, env);
1365 /***********************************************************************/
1366 /* the following routines dump the nodes/irgs bracketed to graphs. */
1367 /***********************************************************************/
1369 /** Dumps a constant expression as entity initializer, array bound ...
1371 static void dump_const_expression(FILE *F, ir_node *value) {
1372 ir_graph *rem = current_ir_graph;
1373 int rem_dump_const_local = dump_const_local;
1374 dump_const_local = 0;
1375 current_ir_graph = get_const_code_irg();
1376 irg_walk(value, dump_const_node, NULL, F);
1377 /* Decrease visited flag so that we walk with the same flag for the next
1378 expression. This guarantees that we don't dump the same node twice,
1379 as for const expressions cse is performed to save memory. */
1380 set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph) -1);
1381 current_ir_graph = rem;
1382 dump_const_local = rem_dump_const_local;
1385 /** Dump a block as graph containing its nodes.
1387 * Expects to find nodes belonging to the block as list in its
1389 * Dumps the edges of all nodes including itself. */
1391 dump_whole_block(FILE *F, ir_node *block) {
1393 const char *color = "yellow";
1395 assert(is_Block(block));
1397 fprintf(F, "graph: { title: \"");
1398 PRINT_NODEID(block);
1399 fprintf(F, "\" label: \"");
1400 dump_node_label(F, block);
1402 if (get_opt_dump_abstvals())
1403 fprintf (F, " seqno: %d", (int)get_Block_seqno(block));
1406 /* colorize blocks */
1407 if (! get_Block_matured(block))
1409 if (is_Block_dead(block))
1412 fprintf(F, "\" status:clustered color:%s \n", color);
1414 /* ycomp can show attributs for blocks, VCG parses but ignores them */
1415 dump_node_info(F, block);
1417 /* dump the blocks edges */
1418 dump_ir_data_edges(F, block);
1420 /* dump the nodes that go into the block */
1421 for (node = ird_get_irn_link(block); node; node = ird_get_irn_link(node)) {
1423 dump_ir_data_edges(F, node);
1426 /* Close the vcg information for the block */
1428 dump_const_node_local(F, block);
1430 dump_irn_chi_term(F, block);
1435 /** dumps a graph block-wise. Expects all blockless nodes in arr in irgs link.
1436 * The outermost nodes: blocks and nodes not op_pin_state_pinned, Bad, Unknown. */
1438 dump_block_graph(FILE *F, ir_graph *irg) {
1440 ir_graph *rem = current_ir_graph;
1441 ir_node **arr = ird_get_irg_link(irg);
1442 current_ir_graph = irg;
1444 for (i = ARR_LEN(arr) - 1; i >= 0; --i) {
1445 ir_node * node = arr[i];
1446 if (is_Block(node)) {
1447 /* Dumps the block and all the nodes in the block, which are to
1448 be found in Block->link. */
1449 dump_whole_block(F, node);
1451 /* Nodes that are not in a Block. */
1453 if (!node_floats(node) && is_Bad(get_nodes_block(node))) {
1454 dump_const_block_local(F, node);
1456 dump_ir_data_edges(F, node);
1460 if (dump_loop_information_flag && (get_irg_loopinfo_state(irg) & loopinfo_valid))
1461 dump_loop_nodes_into_graph(F, irg);
1463 current_ir_graph = rem;
1466 /** Dumps an irg as a graph clustered by block nodes.
1467 * If interprocedural view edges can point to nodes out of this graph.
1469 static void dump_graph_from_list(FILE *F, ir_graph *irg) {
1471 fprintf(F, "graph: { title: \"");
1473 fprintf(F, "\" label: \"%s\" status:clustered color:white \n",
1474 get_ent_dump_name(get_irg_entity(irg)));
1476 dump_block_graph(F, irg);
1478 /* Close the vcg information for the irg */
1479 fprintf(F, "}\n\n");
1482 /** dumps a graph extended block-wise. Expects all blockless nodes in arr in irgs link.
1483 * The outermost nodes: blocks and nodes not op_pin_state_pinned, Bad, Unknown. */
1485 dump_extblock_graph(FILE *F, ir_graph *irg) {
1487 ir_graph *rem = current_ir_graph;
1488 ir_extblk **arr = ird_get_irg_link(irg);
1489 current_ir_graph = irg;
1492 for (i = ARR_LEN(arr) - 1; i >= 0; --i) {
1493 ir_extblk *extbb = arr[i];
1494 ir_node *leader = get_extbb_leader(extbb);
1497 fprintf(F, "graph: { title: \"");
1498 PRINT_EXTBBID(leader);
1499 fprintf(F, "\" label: \"ExtBB %ld\" status:clustered color:lightgreen\n",
1500 get_irn_node_nr(leader));
1502 for (j = ARR_LEN(extbb->blks) - 1; j >= 0; --j) {
1503 ir_node * node = extbb->blks[j];
1504 if (is_Block(node)) {
1505 /* Dumps the block and all the nodes in the block, which are to
1506 be found in Block->link. */
1507 dump_whole_block(F, node);
1509 /* Nodes that are not in a Block. */
1511 if (is_Bad(get_nodes_block(node)) && !node_floats(node)) {
1512 dump_const_block_local(F, node);
1514 dump_ir_data_edges(F, node);
1520 if (dump_loop_information_flag && (get_irg_loopinfo_state(irg) & loopinfo_valid))
1521 dump_loop_nodes_into_graph(F, irg);
1523 current_ir_graph = rem;
1528 /*******************************************************************/
1529 /* Basic type and entity nodes and edges. */
1530 /*******************************************************************/
1532 /** dumps the edges between nodes and their type or entity attributes. */
1533 static void dump_node2type_edges(ir_node *n, void *env)
1538 switch (get_irn_opcode(n)) {
1540 /* @@@ some consts have an entity */
1543 if ( (get_SymConst_kind(n) ==symconst_type_tag)
1544 || (get_SymConst_kind(n) ==symconst_size))
1546 print_node_type_edge(F,n,get_SymConst_type(n),NODE2TYPE_EDGE_ATTR);
1550 print_node_ent_edge(F,n,get_Sel_entity(n),NODE2TYPE_EDGE_ATTR);
1553 print_node_type_edge(F,n,get_Call_type(n),NODE2TYPE_EDGE_ATTR);
1556 print_node_type_edge(F,n,get_Alloc_type(n),NODE2TYPE_EDGE_ATTR);
1559 print_node_type_edge(F,n,get_Free_type(n),NODE2TYPE_EDGE_ATTR);
1562 print_node_type_edge(F,n,get_Cast_type(n),NODE2TYPE_EDGE_ATTR);
1570 static int print_type_info(FILE *F, type *tp) {
1573 if (get_type_state(tp) == layout_undefined) {
1574 fprintf(F, "state: layout_undefined\n");
1576 fprintf(F, "state: layout_fixed,\n");
1578 if (get_type_mode(tp))
1579 fprintf(F, "mode: %s,\n", get_mode_name_ex(get_type_mode(tp), &bad));
1580 fprintf(F, "size: %db,\n", get_type_size_bits(tp));
1585 static void print_typespecific_info(FILE *F, type *tp) {
1586 switch (get_type_tpop_code(tp)) {
1589 fprintf(F, "peculiarity: %s\n", get_peculiarity_string(get_class_peculiarity(tp)));
1596 fprintf(F, "variadicity: %s\n", get_variadicity_name(get_method_variadicity(tp)));
1597 fprintf(F, "params: %d\n", get_method_n_params(tp));
1598 fprintf(F, "results: %d\n", get_method_n_ress(tp));
1606 case tpo_enumeration:
1620 static void print_typespecific_vcgattr(FILE *F, type *tp) {
1621 switch (get_type_tpop_code(tp)) {
1624 if (peculiarity_existent == get_class_peculiarity(tp))
1625 fprintf (F, " " TYPE_CLASS_NODE_ATTR);
1627 fprintf (F, " " TYPE_DESCRIPTION_NODE_ATTR);
1631 fprintf (F, " " TYPE_METH_NODE_ATTR);
1642 case tpo_enumeration:
1656 int dump_type_node(FILE *F, type *tp)
1660 fprintf (F, "node: {title: ");
1662 fprintf (F, " label: \"%s %s\"", get_type_tpop_name(tp), get_type_name_ex(tp, &bad));
1663 fprintf (F, " info1: \"");
1665 bad |= print_type_info(F, tp);
1666 print_typespecific_info(F, tp);
1668 dump_type_to_file(F, tp, dump_verbosity_max);
1670 fprintf (F, "\"\n");
1671 print_node_dbg_info(F, get_type_dbg_info(tp));
1672 print_typespecific_vcgattr(F, tp);
1679 #define X(a) case a: fprintf(F, #a); break
1680 void dump_entity_node(FILE *F, entity *ent, int color)
1682 fprintf (F, "node: {title: \"");
1683 PRINT_ENTID(ent); fprintf(F, "\"");
1684 fprintf (F, DEFAULT_TYPE_ATTRIBUTE);
1685 fprintf (F, "label: ");
1686 fprintf (F, "\"ent %s\" ", get_ent_dump_name(ent));
1688 fprintf(F, "color: %d", color);
1690 fprintf (F, ENTITY_NODE_ATTR);
1691 fprintf (F, "\n info1: \"");
1693 dump_entity_to_file(F, ent, dump_verbosity_entattrs | dump_verbosity_entconsts);
1696 print_node_dbg_info(F, get_entity_dbg_info(ent));
1701 static void dump_enum_item(FILE *F, type *tp, int pos)
1704 ident *id = get_enumeration_nameid(tp, pos);
1705 tarval *tv = get_enumeration_enum(tp, pos);
1707 tarval_snprintf(buf, sizeof(buf), tv);
1708 fprintf (F, "node: {title: \"");
1709 PRINT_ITEMID(tp, pos); fprintf(F, "\"");
1710 fprintf (F, DEFAULT_ENUM_ITEM_ATTRIBUTE);
1711 fprintf (F, "label: ");
1712 fprintf (F, "\"enum item %s\" " ENUM_ITEM_NODE_ATTR, get_id_str(id));
1713 fprintf (F, "\n info1: \"value: %s\"}\n", buf);
1716 /* dumps a type or entity and it's edges. */
1718 dump_type_info(type_or_ent *tore, void *env) {
1720 int i = 0; /* to shutup gcc */
1722 /* dump this type or entity */
1724 switch (get_kind(tore)) {
1727 entity *ent = (entity *)tore;
1730 dump_entity_node(F, ent, 0);
1732 /* skip this to reduce graph. Member edge of type is parallel to this edge. *
1733 fprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
1734 ENT_OWN_EDGE_ATTR "}\n", ent, get_entity_owner(ent));*/
1735 print_ent_type_edge(F,ent, get_entity_type(ent), ENT_TYPE_EDGE_ATTR);
1736 if (is_Class_type(get_entity_owner(ent))) {
1737 for(i = 0; i < get_entity_n_overwrites(ent); i++)
1738 print_ent_ent_edge(F,ent, get_entity_overwrites(ent, i), 0, ENT_OVERWRITES_EDGE_ATTR);
1740 /* attached subgraphs */
1741 if (const_entities && (get_entity_variability(ent) != variability_uninitialized)) {
1742 if (is_atomic_entity(ent)) {
1743 value = get_atomic_ent_value(ent);
1745 print_ent_node_edge(F, ent, value, ENT_VALUE_EDGE_ATTR, i);
1746 /* DDMN(value); $$$ */
1747 dump_const_expression(F, value);
1750 if (is_compound_entity(ent)) {
1751 for (i = 0; i < get_compound_ent_n_values(ent); i++) {
1752 value = get_compound_ent_value(ent, i);
1754 print_ent_node_edge(F, ent, value, ENT_VALUE_EDGE_ATTR, i);
1755 dump_const_expression(F, value);
1756 print_ent_ent_edge(F, ent, get_compound_ent_value_member(ent, i), 0, ENT_CORR_EDGE_ATTR, i);
1758 fprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
1759 ENT_CORR_EDGE_ATTR "}\n", GET_ENTID(ent),
1760 get_compound_ent_value_member(ent, i), i);
1769 type *tp = (type *)tore;
1770 dump_type_node(F, tp);
1771 /* and now the edges */
1772 switch (get_type_tpop_code(tp)) {
1775 for (i=0; i < get_class_n_supertypes(tp); i++)
1776 print_type_type_edge(F, tp,get_class_supertype(tp, i),TYPE_SUPER_EDGE_ATTR);
1777 for (i=0; i < get_class_n_members(tp); i++)
1778 print_type_ent_edge(F,tp,get_class_member(tp, i),TYPE_MEMBER_EDGE_ATTR);
1782 for (i=0; i < get_struct_n_members(tp); i++)
1783 print_type_ent_edge(F,tp,get_struct_member(tp, i),TYPE_MEMBER_EDGE_ATTR);
1787 for (i = 0; i < get_method_n_params(tp); i++)
1788 print_type_type_edge(F,tp,get_method_param_type(tp, i),METH_PAR_EDGE_ATTR,i);
1789 for (i = 0; i < get_method_n_ress(tp); i++)
1790 print_type_type_edge(F,tp,get_method_res_type(tp, i),METH_RES_EDGE_ATTR,i);
1794 for (i = 0; i < get_union_n_members(tp); i++)
1795 print_type_ent_edge(F,tp,get_union_member(tp, i),UNION_EDGE_ATTR);
1799 print_type_type_edge(F,tp,get_array_element_type(tp),ARR_ELT_TYPE_EDGE_ATTR);
1800 print_type_ent_edge(F,tp,get_array_element_entity(tp),ARR_ENT_EDGE_ATTR);
1801 for (i = 0; i < get_array_n_dimensions(tp); i++) {
1802 ir_node *upper = get_array_upper_bound(tp, i);
1803 ir_node *lower = get_array_lower_bound(tp, i);
1804 print_node_type_edge(F, upper, tp, "label: \"upper %d\"", get_array_order(tp, i));
1805 print_node_type_edge(F, lower, tp, "label: \"lower %d\"", get_array_order(tp, i));
1806 dump_const_expression(F, upper);
1807 dump_const_expression(F, lower);
1811 case tpo_enumeration:
1813 for (i = 0; i < get_enumeration_n_enums(tp); ++i) {
1814 dump_enum_item(F, tp, i);
1815 print_enum_item_edge(F, tp, i, "label: \"item %d\"", i);
1820 print_type_type_edge(F,tp,get_pointer_points_to_type(tp), PTR_PTS_TO_EDGE_ATTR);
1828 break; /* case k_type */
1831 printf(" *** irdump, dump_type_info(l.%i), faulty type.\n", __LINE__);
1833 } /* switch kind_or_entity */
1836 typedef struct _h_env {
1841 /** For dumping class hierarchies.
1842 * Dumps a class type node and a superclass edge.
1843 * If env->dump_ent dumps entities of classes and overwrites edges.
1846 dump_class_hierarchy_node (type_or_ent *tore, void *ctx) {
1849 int i = 0; /* to shutup gcc */
1851 /* dump this type or entity */
1852 switch (get_kind(tore)) {
1854 entity *ent = (entity *)tore;
1855 if (get_entity_owner(ent) == get_glob_type()) break;
1856 if (!is_Method_type(get_entity_type(ent))) break; /* GL */
1857 if (env->dump_ent && is_Class_type(get_entity_owner(ent))) {
1859 dump_entity_node(F, ent, 0);
1861 print_type_ent_edge(F,get_entity_owner(ent),ent,TYPE_MEMBER_EDGE_ATTR);
1862 for(i = 0; i < get_entity_n_overwrites(ent); i++)
1863 print_ent_ent_edge(F, get_entity_overwrites(ent, i), ent, 0, ENT_OVERWRITES_EDGE_ATTR);
1865 } break; /* case k_entity */
1868 type *tp = (type *)tore;
1869 if (tp == get_glob_type()) break;
1870 switch (get_type_tpop_code(tp)) {
1872 dump_type_node(F, tp);
1873 /* and now the edges */
1874 for (i=0; i < get_class_n_supertypes(tp); i++)
1876 print_type_type_edge(F,tp,get_class_supertype(tp, i),TYPE_SUPER_EDGE_ATTR);
1882 break; /* case k_type */
1885 printf(" *** irdump, dump_class_hierarchy_node(l.%i), faulty type.\n", __LINE__);
1887 } /* switch kind_or_entity */
1890 /*******************************************************************/
1891 /* dump analysis information that is expressed in graph terms. */
1892 /*******************************************************************/
1894 /* dump out edges */
1896 dump_out_edge(ir_node *n, void *env) {
1899 for (i = 0; i < get_irn_n_outs(n); i++) {
1900 assert(get_irn_out(n, i));
1901 fprintf (F, "edge: {sourcename: \"");
1903 fprintf (F, "\" targetname: \"");
1904 PRINT_NODEID(get_irn_out(n, i));
1905 fprintf (F, "\" color: red linestyle: dashed");
1911 dump_loop_label(FILE *F, ir_loop *loop) {
1912 fprintf (F, "loop %d, %d sons, %d nodes",
1913 get_loop_depth(loop), get_loop_n_sons(loop), get_loop_n_nodes(loop));
1916 static INLINE void dump_loop_info(FILE *F, ir_loop *loop) {
1917 fprintf (F, " info1: \"");
1918 fprintf (F, " loop nr: %d", get_loop_loop_nr(loop));
1919 #if DEBUG_libfirm /* GL @@@ debug analyses */
1920 fprintf (F, "\n The loop was analyzed %d times.", PTR_TO_INT(get_loop_link(loop)));
1926 dump_loop_node(FILE *F, ir_loop *loop) {
1927 fprintf (F, "node: {title: \"");
1929 fprintf (F, "\" label: \"");
1930 dump_loop_label(F, loop);
1932 dump_loop_info(F, loop);
1938 dump_loop_node_edge(FILE *F, ir_loop *loop, int i) {
1940 fprintf (F, "edge: {sourcename: \"");
1942 fprintf (F, "\" targetname: \"");
1943 PRINT_NODEID(get_loop_node(loop, i));
1944 fprintf (F, "\" color: green");
1949 dump_loop_son_edge(FILE *F, ir_loop *loop, int i) {
1951 fprintf (F, "edge: {sourcename: \"");
1953 fprintf (F, "\" targetname: \"");
1954 PRINT_LOOPID(get_loop_son(loop, i));
1955 fprintf (F, "\" color: darkgreen label: \"%d\"}\n",
1956 get_loop_element_pos(loop, get_loop_son(loop, i)));
1960 void dump_loops(FILE *F, ir_loop *loop) {
1962 /* dump this loop node */
1963 dump_loop_node(F, loop);
1965 /* dump edges to nodes in loop -- only if it is a real loop */
1966 if (get_loop_depth(loop) != 0) {
1967 for (i = 0; i < get_loop_n_nodes(loop); i++) {
1968 dump_loop_node_edge(F, loop, i);
1971 for (i = 0; i < get_loop_n_sons(loop); i++) {
1972 dump_loops(F, get_loop_son(loop, i));
1973 dump_loop_son_edge(F, loop, i);
1978 void dump_loop_nodes_into_graph(FILE *F, ir_graph *irg) {
1979 ir_graph *rem = current_ir_graph;
1980 current_ir_graph = irg;
1982 if (get_irg_loop(irg)) dump_loops(F, get_irg_loop(irg));
1984 current_ir_graph = rem;
1989 * dumps the VCG header
1991 void dump_vcg_header(FILE *F, const char *name, const char *orientation) {
2000 if (!orientation) orientation = "bottom_to_top";
2004 "graph: { title: \"ir graph of %s\"\n"
2005 "display_edge_labels: %s\n"
2006 "layoutalgorithm: mindepth\n"
2007 "manhattan_edges: yes\n"
2008 "port_sharing: no\n"
2010 "classname 1: \"intrablock Data\"\n"
2011 "classname 16: \"interblock Data\"\n"
2012 "classname 2: \"Block\"\n"
2013 "classname 13: \"Control Flow\"\n"
2014 "classname 18: \"Exception Control Flow for Interval Analysis\"\n"
2015 "classname 14: \"intrablock Memory\"\n"
2016 "classname 17: \"interblock Memory\"\n"
2017 "classname 15: \"Dominators\"\n"
2018 "classname 3: \"Entity type\"\n"
2019 "classname 4: \"Entity owner\"\n"
2020 "classname 5: \"Method Param\"\n"
2021 "classname 6: \"Method Res\"\n"
2022 "classname 7: \"Super\"\n"
2023 "classname 8: \"Union\"\n"
2024 "classname 9: \"Points-to\"\n"
2025 "classname 10: \"Array Element Type\"\n"
2026 "classname 11: \"Overwrites\"\n"
2027 "classname 12: \"Member\"\n"
2028 "infoname 1: \"Attribute\"\n"
2029 "infoname 2: \"Verification errors\"\n"
2030 "infoname 3: \"Debug info\"\n",
2031 name, label, orientation);
2033 /* don't use all, the range is too whith/black. */
2037 "colorentry 100: 0 0 0\n"
2038 "colorentry 101: 20 0 0\n"
2039 "colorentry 102: 40 0 0\n"
2040 "colorentry 103: 60 0 0\n"
2041 "colorentry 104: 80 0 0\n"
2042 "colorentry 105: 100 0 0\n"
2043 "colorentry 106: 120 0 0\n"
2044 "colorentry 107: 140 0 0\n"
2045 "colorentry 108: 150 0 0\n"
2046 "colorentry 109: 180 0 0\n"
2047 "colorentry 110: 200 0 0\n"
2048 "colorentry 111: 220 0 0\n"
2049 "colorentry 112: 240 0 0\n"
2050 "colorentry 113: 255 0 0\n"
2051 "colorentry 113: 255 20 20\n"
2052 "colorentry 114: 255 40 40\n"
2053 "colorentry 115: 255 60 60\n"
2054 "colorentry 116: 255 80 80\n"
2055 "colorentry 117: 255 100 100\n"
2056 "colorentry 118: 255 120 120\n"
2057 "colorentry 119: 255 140 140\n"
2058 "colorentry 120: 255 150 150\n"
2059 "colorentry 121: 255 180 180\n"
2060 "colorentry 122: 255 200 200\n"
2061 "colorentry 123: 255 220 220\n"
2062 "colorentry 124: 255 240 240\n"
2063 "colorentry 125: 255 250 250\n"
2066 fprintf (F, "\n"); /* a separator */
2072 * @param irg The graph to be dumped
2073 * @param suffix1 first filename suffix
2074 * @param suffix2 second filename suffix
2076 FILE *vcg_open (ir_graph *irg, const char * suffix1, const char *suffix2) {
2078 const char *nm = get_irg_dump_name(irg);
2079 int len = strlen(nm), i, j;
2080 char *fname; /* filename to put the vcg information in */
2082 if (!suffix1) suffix1 = "";
2083 if (!suffix2) suffix2 = "";
2085 /* open file for vcg graph */
2086 fname = malloc (len * 2 + strlen(suffix1) + strlen(suffix2) + 5);
2088 /* strncpy (fname, nm, len); */ /* copy the filename */
2090 for (i = 0; i < len; ++i) { /* replace '/' in the name: escape by @. */
2092 fname[j] = '@'; j++; fname[j] = '1'; j++;
2093 } else if (nm[i] == '@') {
2094 fname[j] = '@'; j++; fname[j] = '2'; j++;
2096 fname[j] = nm[i]; j++;
2100 strcat (fname, suffix1); /* append file suffix */
2101 strcat (fname, suffix2); /* append file suffix */
2102 strcat (fname, ".vcg"); /* append the .vcg suffix */
2104 /* vcg really expect only a <CR> at end of line, so
2105 * the "b"inary mode is what you mean (and even needed for Win32)
2107 F = fopen (fname, "wb"); /* open file for writing */
2109 panic("cannot open %s for writing (%m)", fname); /* not reached */
2119 * @param name prefix file name
2120 * @param suffix filename suffix
2122 FILE *vcg_open_name (const char *name, const char *suffix) {
2124 char *fname; /* filename to put the vcg information in */
2125 int i, j, len = strlen(name);
2127 if (!suffix) suffix = "";
2129 /** open file for vcg graph */
2130 fname = xmalloc(len * 2 + 5 + strlen(suffix));
2131 /* strcpy (fname, name);*/ /* copy the filename */
2133 for (i = 0; i < len; ++i) { /* replace '/' in the name: escape by @. */
2134 if (name[i] == '/') {
2135 fname[j] = '@'; j++; fname[j] = '1'; j++;
2136 } else if (name[i] == '@') {
2137 fname[j] = '@'; j++; fname[j] = '2'; j++;
2139 fname[j] = name[i]; j++;
2143 strcat (fname, 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 */
2159 * Dumps the vcg file footer
2161 static INLINE void dump_vcg_footer (FILE *F) {
2166 * close the vcg file
2168 void vcg_close (FILE *F) {
2169 dump_vcg_footer(F); /* print footer */
2170 fclose (F); /* close vcg file */
2173 /************************************************************************/
2174 /************************************************************************/
2175 /* Routines that dump all or parts of the firm representation to a file */
2176 /************************************************************************/
2177 /************************************************************************/
2179 /************************************************************************/
2180 /* Dump ir graphs, different formats and additional information. */
2181 /************************************************************************/
2183 /** Routine to dump a graph, blocks as conventional nodes. */
2185 dump_ir_graph (ir_graph *irg, const char *suffix )
2190 rem = current_ir_graph;
2192 if (!is_filtered_dump_name(get_entity_ident(get_irg_entity(irg)))) return;
2194 current_ir_graph = irg;
2195 if (get_interprocedural_view()) suffix1 = "-pure-ip";
2196 else suffix1 = "-pure";
2197 f = vcg_open(irg, suffix, suffix1);
2198 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
2200 /* walk over the graph */
2201 /* dump_whole_node must be called in post visiting predecessors */
2202 irg_walk(get_irg_end(irg), NULL, dump_whole_node, f);
2204 /* dump the out edges in a separate walk */
2205 if ((dump_out_edge_flag) && (get_irg_outs_state(irg) != outs_none)) {
2206 irg_out_walk(get_irg_start(irg), dump_out_edge, NULL, f);
2211 current_ir_graph = rem;
2214 /* Dump a firm graph without explicit block nodes. */
2215 void dump_ir_block_graph (ir_graph *irg, const char *suffix)
2221 if (!is_filtered_dump_name(get_entity_ident(get_irg_entity(irg))))
2224 if (get_interprocedural_view()) suffix1 = "-ip";
2226 f = vcg_open(irg, suffix, suffix1);
2227 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
2229 construct_block_lists(irg);
2232 * If we are in the interprocedural view, we dump not
2233 * only the requested irg but also all irgs that can be reached
2236 for (i = 0; i < get_irp_n_irgs(); i++) {
2237 ir_node **arr = ird_get_irg_link(get_irp_irg(i));
2239 dump_graph_from_list(f, get_irp_irg(i));
2247 /* Dump a firm graph without explicit block nodes but grouped in extended blocks. */
2248 void dump_ir_extblock_graph (ir_graph *irg, const char *suffix)
2254 if (!is_filtered_dump_name(get_entity_ident(get_irg_entity(irg))))
2259 if (get_interprocedural_view()) suffix1 = "-ip";
2261 F = vcg_open(irg, suffix, suffix1);
2262 dump_vcg_header(F, get_irg_dump_name(irg), NULL);
2264 construct_extblock_lists(irg);
2266 fprintf(F, "graph: { title: \"");
2268 fprintf(F, "\" label: \"%s\" status:clustered color:white \n",
2269 get_ent_dump_name(get_irg_entity(irg)));
2271 for (i = 0; i < get_irp_n_irgs(); i++) {
2272 ir_graph *irg = get_irp_irg(i);
2273 list_tuple *lists = ird_get_irg_link(irg);
2276 /* dump the extended blocks first */
2277 if (ARR_LEN(lists->extbb_list)) {
2278 ird_set_irg_link(irg, lists->extbb_list);
2279 dump_extblock_graph(F, irg);
2282 /* we may have blocks without extended blocks, bad for instance */
2283 if (ARR_LEN(lists->blk_list)) {
2284 ird_set_irg_link(irg, lists->blk_list);
2285 dump_block_graph(F, irg);
2288 DEL_ARR_F(lists->extbb_list);
2289 DEL_ARR_F(lists->blk_list);
2294 /* Close the vcg information for the irg */
2295 fprintf(F, "}\n\n");
2301 /* dumps a graph with type information */
2303 dump_ir_graph_w_types (ir_graph *irg, const char *suffix)
2306 ir_graph *rem = current_ir_graph;
2308 int rem_dump_const_local;
2310 /* if a filter is set, dump only the irg's that match the filter */
2311 if (!is_filtered_dump_name(get_entity_ident(get_irg_entity(irg))))
2314 current_ir_graph = irg;
2315 rem_dump_const_local = dump_const_local;
2316 /* dumping types does not work with local nodes */
2317 dump_const_local = 0;
2319 if (get_interprocedural_view()) suffix1 = "-pure-wtypes-ip";
2320 else suffix1 = "-pure-wtypes";
2321 f = vcg_open(irg,suffix, suffix1);
2322 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
2324 /* dump common ir graph */
2325 irg_walk(get_irg_end(irg), NULL, dump_whole_node, f);
2326 /* dump type info */
2327 type_walk_irg(irg, dump_type_info, NULL, f);
2328 inc_irg_visited(get_const_code_irg());
2329 /* dump edges from graph to type info */
2330 irg_walk(get_irg_end(irg), dump_node2type_edges, NULL, f);
2333 dump_const_local = rem_dump_const_local;
2334 current_ir_graph = rem;
2338 dump_ir_block_graph_w_types (ir_graph *irg, const char *suffix)
2343 ir_graph *rem = current_ir_graph;
2344 int rem_dump_const_local;
2346 /* if a filter is set, dump only the irg's that match the filter */
2347 if (!is_filtered_dump_name(get_entity_ident(get_irg_entity(irg))))
2350 rem_dump_const_local = dump_const_local;
2351 /* dumping types does not work with local nodes */
2352 dump_const_local = 0;
2354 if (get_interprocedural_view()) suffix1 = "-wtypes-ip";
2355 else suffix1 = "-wtypes";
2356 f = vcg_open(irg, suffix, suffix1);
2357 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
2359 /* dump common blocked ir graph */
2360 construct_block_lists(irg);
2362 for (i = 0; i < get_irp_n_irgs(); i++) {
2363 ir_node **arr = ird_get_irg_link(get_irp_irg(i));
2365 dump_graph_from_list(f, get_irp_irg(i));
2370 /* dump type info */
2371 current_ir_graph = irg;
2372 type_walk_irg(irg, dump_type_info, NULL, f);
2373 inc_irg_visited(get_const_code_irg());
2375 /* dump edges from graph to type info */
2376 irg_walk(get_irg_end(irg), dump_node2type_edges, NULL, f);
2379 dump_const_local = rem_dump_const_local;
2380 current_ir_graph = rem;
2383 /*---------------------------------------------------------------------*/
2384 /* The following routines dump a control flow graph. */
2385 /*---------------------------------------------------------------------*/
2388 dump_block_to_cfg(ir_node *block, void *env) {
2393 if (is_Block(block)) {
2394 /* This is a block. Dump a node for the block. */
2395 fprintf (F, "node: {title: \""); PRINT_NODEID(block);
2396 fprintf (F, "\" label: \"");
2397 if (block == get_irg_start_block(get_irn_irg(block)))
2398 fprintf(F, "Start ");
2399 if (block == get_irg_end_block(get_irn_irg(block)))
2402 fprintf (F, "%s ", get_op_name(get_irn_op(block)));
2403 PRINT_NODEID(block);
2405 fprintf(F, "info1:\"");
2408 if (dump_dominator_information_flag) {
2409 fprintf(F, "dom depth %d\n", get_Block_dom_depth(block));
2410 fprintf(F, "tree pre num %d\n", get_Block_dom_tree_pre_num(block));
2411 fprintf(F, "max subtree pre num %d\n", get_Block_dom_max_subtree_pre_num(block));
2414 /* show arity and possible Bad predecessors of the block */
2415 fprintf(F, "arity: %d\n", get_Block_n_cfgpreds(block));
2416 for (fl = i = 0; i < get_Block_n_cfgpreds(block); ++i) {
2417 ir_node *pred = get_Block_cfgpred(block, i);
2420 fprintf(F, "Bad pred at pos: ");
2421 fprintf(F, "%d ", i);
2428 /* the generic version. */
2429 dump_irnode_to_file(F, block);
2431 /* Check whether we have bad predecessors to color the block. */
2432 for (i = 0; i < get_Block_n_cfgpreds(block); ++i)
2433 if ((fl = is_Bad(get_Block_cfgpred(block, i))))
2437 fprintf (F, "\""); /* closing quote of info */
2439 if ((block == get_irg_start_block(get_irn_irg(block))) ||
2440 (block == get_irg_end_block(get_irn_irg(block))) )
2441 fprintf(F, " color:blue ");
2443 fprintf(F, " color:yellow ");
2446 /* Dump the edges */
2447 for ( i = 0; i < get_Block_n_cfgpreds(block); i++)
2448 if (get_irn_op(skip_Proj(get_Block_cfgpred(block, i))) != op_Bad) {
2449 pred = get_nodes_block(skip_Proj(get_Block_cfgpred(block, i)));
2450 fprintf (F, "edge: { sourcename: \"");
2451 PRINT_NODEID(block);
2452 fprintf (F, "\" targetname: \"");
2454 fprintf (F, "\"}\n");
2457 /* Dump dominator edge */
2458 if (dump_dominator_information_flag && get_Block_idom(block)) {
2459 pred = get_Block_idom(block);
2460 fprintf (F, "edge: { sourcename: \"");
2461 PRINT_NODEID(block);
2462 fprintf (F, "\" targetname: \"");
2464 fprintf (F, "\" " DOMINATOR_EDGE_ATTR "}\n");
2470 dump_cfg (ir_graph *irg, const char *suffix)
2473 ir_graph *rem = current_ir_graph;
2474 int ddif = dump_dominator_information_flag;
2475 int ipv = get_interprocedural_view();
2477 /* if a filter is set, dump only the irg's that match the filter */
2478 if (!is_filtered_dump_name(get_entity_ident(get_irg_entity(irg))))
2481 current_ir_graph = irg;
2483 f = vcg_open(irg, suffix, "-cfg");
2484 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
2487 printf("Warning: dumping cfg not in interprocedural view!\n");
2488 set_interprocedural_view(false);
2491 if (get_irg_dom_state(irg) != dom_consistent)
2492 dump_dominator_information_flag = 0;
2494 /* walk over the blocks in the graph */
2495 irg_block_walk(get_irg_end(irg), dump_block_to_cfg, NULL, f);
2496 dump_node(f, get_irg_bad(irg));
2498 dump_dominator_information_flag = ddif;
2499 set_interprocedural_view(ipv);
2501 current_ir_graph = rem;
2505 static void descend_and_dump(FILE *F, ir_node *n, int depth, pset *mark_set) {
2506 if (pset_find_ptr(mark_set, n)) return;
2508 pset_insert_ptr(mark_set, n);
2511 int i, start = is_Block(n) ? 0 : -1;
2512 dump_whole_node(n, F);
2513 for (i = start; i < get_irn_arity(n); ++i)
2514 descend_and_dump(F, get_irn_n(n, i), depth-1, mark_set);
2517 /* Don't dump edges to nodes further out. These might be edges to
2518 nodes we already dumped, if there is a shorter path to these. */
2522 static int subgraph_counter = 0;
2523 void dump_subgraph (ir_node *root, int depth, const char *suffix) {
2526 pset *mark_set = pset_new_ptr(1);
2527 sprintf(buf, "-subg_%03d", subgraph_counter++);
2528 F = vcg_open(get_irn_irg(root), suffix, buf);
2529 dump_vcg_header(F, get_irg_dump_name(get_irn_irg(root)), NULL);
2530 descend_and_dump(F, root, depth, mark_set);
2536 static int weight_overall(int rec, int loop) {
2537 return 2*rec + loop;
2540 static int compute_color (int my, int max) {
2547 /* if small, scale to the full color range. */
2549 my = my * (n_colors/max);
2551 step = 1 + (max / n_colors);
2555 return base_color + n_colors - color;
2558 static int get_entity_color(entity *ent) {
2559 ir_graph *irg = get_entity_irg(ent);
2563 int rec_depth = get_irg_recursion_depth(irg);
2564 int loop_depth = get_irg_loop_depth(irg);
2565 int overall_depth = weight_overall(rec_depth, loop_depth);
2567 int max_rec_depth = irp->max_callgraph_recursion_depth;
2568 int max_loop_depth = irp->max_callgraph_loop_depth;
2569 int max_overall_depth = weight_overall(max_rec_depth, max_loop_depth);
2571 /* int my_rec_color = compute_color(rec_depth, max_rec_depth); */
2572 /* int my_loop_color = compute_color(loop_depth, max_loop_depth); */
2573 int my_overall_color = compute_color(overall_depth, max_overall_depth);;
2575 return my_overall_color;
2579 void dump_callgraph(const char *suffix) {
2581 int i, n_irgs = get_irp_n_irgs();
2582 int rem = edge_label;
2584 //ident *prefix = new_id_from_str("java/");
2586 F = vcg_open_name("Callgraph", suffix);
2587 dump_vcg_header(F, "Callgraph", NULL);
2589 for (i = 0; i < n_irgs; ++i) {
2590 ir_graph *irg = get_irp_irg(i);
2591 entity *ent = get_irg_entity(irg);
2592 int j, n_callees = get_irg_n_callees(irg);
2594 /* Do not dump runtime system. */
2595 //if (id_is_prefix(prefix, get_entity_ld_ident(ent))) continue;
2597 dump_entity_node(F, ent, get_entity_color(ent));
2598 for (j = 0; j < n_callees; ++j) {
2599 entity *c = get_irg_entity(get_irg_callee(irg, j));
2600 //if (id_is_prefix(prefix, get_entity_ld_ident(c))) continue;
2601 int be = is_irg_callee_backedge(irg, j);
2604 "label:\"recursion %d\" color: %d" :
2605 "label:\"calls %d\" color: %d";
2606 print_ent_ent_edge(F, ent, c, be, attr, get_irg_callee_loop_depth(irg, j), get_entity_color(ent));
2614 /* Dump all irgs in interprocedural view to a single file. */
2615 void dump_all_cg_block_graph(const char *suffix) {
2618 int rem_view = get_interprocedural_view();
2619 set_interprocedural_view(true);
2621 f = vcg_open_name("All_graphs", suffix);
2622 dump_vcg_header(f, "All_graphs", NULL);
2624 /* collect nodes in all irgs reachable in call graph*/
2625 for (i = 0; i < get_irp_n_irgs(); i++)
2626 ird_set_irg_link(get_irp_irg(i), NULL);
2628 cg_walk(clear_link, collect_node, NULL);
2630 /* dump all graphs */
2631 for (i = 0; i < get_irp_n_irgs(); i++) {
2632 current_ir_graph = get_irp_irg(i);
2633 assert(ird_get_irg_link(current_ir_graph));
2634 dump_graph_from_list(f, current_ir_graph);
2635 DEL_ARR_F(ird_get_irg_link(current_ir_graph));
2639 set_interprocedural_view(rem_view);
2642 /*---------------------------------------------------------------------*/
2643 /* the following routines dumps type information without any ir nodes. */
2644 /*---------------------------------------------------------------------*/
2647 dump_type_graph (ir_graph *irg, const char *suffix)
2651 rem = current_ir_graph;
2653 /* if a filter is set, dump only the irg's that match the filter */
2654 if (!is_filtered_dump_name(get_entity_ident(get_irg_entity(irg)))) return;
2656 current_ir_graph = irg;
2658 f = vcg_open(irg, suffix, "-type");
2659 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
2661 /* walk over the blocks in the graph */
2662 type_walk_irg(irg, dump_type_info, NULL, f);
2663 /* The walker for the const code can be called several times for the
2664 same (sub) expression. So that no nodes are dumped several times
2665 we decrease the visited flag of the corresponding graph after each
2666 walk. So now increase it finally. */
2667 inc_irg_visited(get_const_code_irg());
2670 current_ir_graph = rem;
2674 dump_all_types (const char *suffix)
2676 FILE *f = vcg_open_name("All_types", suffix);
2677 dump_vcg_header(f, "All_types", NULL);
2678 type_walk(dump_type_info, NULL, f);
2679 inc_irg_visited(get_const_code_irg());
2684 dump_class_hierarchy (bool entities, const char *suffix)
2686 FILE *f = vcg_open_name("class_hierarchy", suffix);
2690 dump_vcg_header(f, "class_hierarchy", NULL);
2695 type_walk(dump_class_hierarchy_node, NULL, &env);
2699 /*---------------------------------------------------------------------*/
2700 /* dumps all graphs with the graph-dumper passed. Possible dumpers: */
2702 /* dump_ir_block_graph */
2704 /* dump_type_graph */
2705 /* dump_ir_graph_w_types */
2706 /*---------------------------------------------------------------------*/
2708 void dump_all_ir_graphs(dump_graph_func *dmp_grph, const char *suffix) {
2709 int i, n_irgs = get_irp_n_irgs();
2710 for (i = 0; i < n_irgs; ++i) {
2711 dmp_grph(get_irp_irg(i), suffix);
2716 /*--------------------------------------------------------------------------------*
2717 * Dumps a stand alone loop graph with firm nodes which belong to one loop node *
2718 * packed together in one subgraph/box *
2719 *--------------------------------------------------------------------------------*/
2721 void dump_loops_standalone(FILE *F, ir_loop *loop) {
2722 int i = 0, loop_node_started = 0, son_number = 0, first = 0;
2724 ir_loop *son = NULL;
2726 /* Dump a new loop node. */
2727 dump_loop_node(F, loop);
2729 /* Dump the loop elements. */
2731 for(i = 0; i < get_loop_n_elements(loop); i++) {
2732 le = get_loop_element(loop, i);
2734 if (get_kind(son) == k_ir_loop) {
2736 /* We are a loop son -> Recurse */
2738 if(loop_node_started) { /* Close the "firm-nodes" node first if we started one. */
2739 fprintf(F, "\" }\n");
2740 fprintf (F, "edge: {sourcename: \"");
2742 fprintf (F, "\" targetname: \"");
2744 fprintf (F, "-%d-nodes\" label:\"%d...%d\"}\n", first, first, i-1);
2745 loop_node_started = 0;
2747 dump_loop_son_edge(F, loop, son_number++);
2748 dump_loops_standalone(F, son);
2749 } else if (get_kind(son) == k_ir_node) {
2750 /* We are a loop node -> Collect firm nodes */
2752 ir_node *n = le.node;
2755 if (!loop_node_started) {
2756 /* Start a new node which contains all firm nodes of the current loop */
2757 fprintf (F, "node: { title: \"");
2759 fprintf (F, "-%d-nodes\" color: lightyellow label: \"", i);
2760 loop_node_started = 1;
2766 bad |= dump_node_label(F, n);
2767 /* Causes indeterministic output: if (is_Block(n)) fprintf (F, "\t ->%d", (int)get_irn_link(n)); */
2768 if (has_backedges(n)) fprintf(F, "\t loop head!");
2769 } else { /* for callgraph loop tree */
2771 assert(get_kind(son) == k_ir_graph);
2773 /* We are a loop node -> Collect firm graphs */
2774 n = (ir_graph *)le.node;
2775 if (!loop_node_started) {
2776 /* Start a new node which contains all firm nodes of the current loop */
2777 fprintf (F, "node: { title: \"");
2779 fprintf (F, "-%d-nodes\" color: lightyellow label: \"", i);
2780 loop_node_started = 1;
2785 fprintf (F, " %s", get_irg_dump_name(n));
2786 /* fprintf (F, " %s (depth %d)", get_irg_dump_name(n), n->callgraph_weighted_loop_depth); */
2790 if (loop_node_started) {
2791 fprintf(F, "\" }\n");
2792 fprintf (F, "edge: {sourcename: \"");
2794 fprintf (F, "\" targetname: \"");
2796 fprintf (F, "-%d-nodes\" label:\"%d...%d\"}\n", first, first, i-1);
2797 loop_node_started = 0;
2801 void dump_loop_tree(ir_graph *irg, const char *suffix)
2804 ir_graph *rem = current_ir_graph;
2805 int el_rem = edge_label;
2808 /* if a filter is set, dump only the irg's that match the filter */
2809 if (!is_filtered_dump_name(get_entity_ident(get_irg_entity(irg)))) return;
2811 current_ir_graph = irg;
2813 f = vcg_open(irg, suffix, "-looptree");
2814 dump_vcg_header(f, get_irg_dump_name(irg), "top_to_bottom");
2816 if (get_irg_loop(irg)) dump_loops_standalone(f, get_irg_loop(irg));
2820 edge_label = el_rem;
2821 current_ir_graph = rem;
2824 void dump_callgraph_loop_tree(const char *suffix) {
2826 F = vcg_open_name("Callgraph_looptree", suffix);
2827 dump_vcg_header(F, "callgraph looptree", "top_to_bottom");
2828 dump_loops_standalone(F, irp->outermost_cg_loop);
2833 /*-----------------------------------------------------------------------------*/
2834 /* Dumps the firm nodes in the loop tree to a graph along with the loop nodes. */
2835 /*-----------------------------------------------------------------------------*/
2837 void collect_nodeloop(FILE *F, ir_loop *loop, eset *loopnodes) {
2838 int i, son_number = 0, node_number = 0;
2840 if (dump_loop_information_flag) dump_loop_node(F, loop);
2842 for (i = 0; i < get_loop_n_elements(loop); i++) {
2843 loop_element le = get_loop_element(loop, i);
2844 if (*(le.kind) == k_ir_loop) {
2845 if (dump_loop_information_flag) dump_loop_son_edge(F, loop, son_number++);
2847 collect_nodeloop(F, le.son, loopnodes);
2849 if (dump_loop_information_flag) dump_loop_node_edge(F, loop, node_number++);
2850 eset_insert(loopnodes, le.node);
2855 void collect_nodeloop_external_nodes(ir_loop *loop, eset *loopnodes, eset *extnodes) {
2858 for(i = 0; i < get_loop_n_elements(loop); i++) {
2859 loop_element le = get_loop_element(loop, i);
2860 if (*(le.kind) == k_ir_loop) {
2862 collect_nodeloop_external_nodes(le.son, loopnodes, extnodes);
2864 if (is_Block(le.node)) start = 0; else start = -1;
2865 for (j = start; j < get_irn_arity(le.node); j++) {
2866 ir_node *pred = get_irn_n(le.node, j);
2867 if (!eset_contains(loopnodes, pred)) {
2868 eset_insert(extnodes, pred);
2869 if (!is_Block(pred)) {
2870 pred = get_nodes_block(pred);
2871 if (!eset_contains(loopnodes, pred)) eset_insert(extnodes, pred);
2879 void dump_loop(ir_loop *l, const char *suffix) {
2882 eset *loopnodes = eset_create();
2883 eset *extnodes = eset_create();
2886 snprintf(name, sizeof(name), "loop_%d", get_loop_loop_nr(l));
2887 F = vcg_open_name (name, suffix);
2888 dump_vcg_header(F, name, NULL);
2890 /* collect all nodes to dump */
2891 collect_nodeloop(F, l, loopnodes);
2892 collect_nodeloop_external_nodes(l, loopnodes, extnodes);
2894 /* build block lists */
2895 for (n = eset_first(loopnodes); n != NULL; n = eset_next(loopnodes))
2896 set_irn_link(n, NULL);
2897 for (n = eset_first(extnodes); n != NULL; n = eset_next(extnodes))
2898 set_irn_link(n, NULL);
2899 for (n = eset_first(loopnodes); n != NULL; n = eset_next(loopnodes))
2901 b = get_nodes_block(n);
2902 set_irn_link(n, get_irn_link(b));
2905 for (n = eset_first(extnodes); n != NULL; n = eset_next(extnodes))
2907 b = get_nodes_block(n);
2908 set_irn_link(n, get_irn_link(b));
2912 for (b = eset_first(loopnodes); b != NULL; b = eset_next(loopnodes))
2914 fprintf(F, "graph: { title: \"");
2916 fprintf(F, "\" label: \"");
2917 dump_node_opcode(F, b);
2918 fprintf (F, " %ld", get_irn_node_nr(b));
2919 fprintf(F, "\" status:clustered color:yellow\n");
2921 /* dump the blocks edges */
2922 dump_ir_data_edges(F, b);
2924 /* dump the nodes that go into the block */
2925 for (n = get_irn_link(b); n; n = get_irn_link(n)) {
2926 if (eset_contains(extnodes, n)) overrule_nodecolor = "lightblue";
2928 overrule_nodecolor = NULL;
2929 if (!eset_contains(extnodes, n)) dump_ir_data_edges(F, n);
2932 /* Close the vcg information for the block */
2934 dump_const_node_local(F, b);
2937 for (b = eset_first(extnodes); b != NULL; b = eset_next(extnodes))
2939 fprintf(F, "graph: { title: \"");
2941 fprintf(F, "\" label: \"");
2942 dump_node_opcode(F, b);
2943 fprintf (F, " %ld", get_irn_node_nr(b));
2944 fprintf(F, "\" status:clustered color:lightblue\n");
2946 /* dump the nodes that go into the block */
2947 for (n = get_irn_link(b); n; n = get_irn_link(n)) {
2948 if (!eset_contains(loopnodes, n)) overrule_nodecolor = "lightblue";
2950 overrule_nodecolor = NULL;
2951 if (eset_contains(loopnodes, n)) dump_ir_data_edges(F, n);
2954 /* Close the vcg information for the block */
2956 dump_const_node_local(F, b);
2960 eset_destroy(loopnodes);
2961 eset_destroy(extnodes);