3 * File name: ir/ir/irdump.c
4 * Purpose: Write vcg representation of firm to file.
5 * Author: Martin Trapp, Christian Schaefer
6 * Modified by: Goetz Lindenmaier, Hubert Schmidt
9 * Copyright: (c) 1998-2003 Universit�t Karlsruhe
10 * Licence: This file protected by GPL - GNU GENERAL PUBLIC LICENSE.
24 #include "firm_common_t.h"
27 #include "irgraph_t.h"
37 #include "type_or_entity.h"
41 #include "callgraph.h"
42 #include "irextbb_t.h"
43 #include "dbginfo_t.h"
54 extern void dump_irn_chi_term(FILE *FL, ir_node *n);
55 extern void dump_irn_state(FILE *FL, ir_node *n);
56 extern int get_opt_dump_abstvals(void);
57 typedef unsigned long SeqNo;
58 extern SeqNo get_Block_seqno(ir_node *n);
61 /* basis for a color range for vcg */
62 static int n_colors = 0;
63 static int base_color = 0;
65 /** Dump only irgs with names that start with this string */
66 static ident *dump_file_filter_id = NULL;
68 #define ERROR_TXT "<ERROR>"
70 /*******************************************************************/
71 /* flags to steer output */
72 /*******************************************************************/
74 /** An option to turn off edge labels */
75 static int edge_label = 1;
76 /** An option to turn off dumping values of constant entities */
77 static int const_entities = 1;
78 /** An option to dump the keep alive edges */
79 static int dump_keepalive = 0;
80 /** An option to dump ld_names instead of names. */
81 static int dump_ld_name = 1;
82 /** Compiler options to dump analysis information in dump_ir_graph */
83 int dump_out_edge_flag = 0;
84 int dump_dominator_information_flag = 0;
85 int dump_loop_information_flag = 0;
86 int dump_backedge_information_flag = 1;
87 int dump_const_local = 0;
88 bool opt_dump_analysed_type_info = 1;
89 bool opt_dump_pointer_values_to_info = 0; /* default off: for test compares!! */
91 static const char *overrule_nodecolor = NULL;
93 /** An additional edge hook. */
94 static DUMP_NODE_EDGE_FUNC dump_node_edge_hook = NULL;
96 void set_dump_node_edge_hook(DUMP_NODE_EDGE_FUNC func)
98 dump_node_edge_hook = func;
101 DUMP_NODE_EDGE_FUNC get_dump_node_edge_hook(void)
103 return dump_node_edge_hook;
107 /** The vcg attribute hook. */
108 static DUMP_NODE_VCGATTR_FUNC dump_node_vcgattr_hook = NULL;
111 void set_dump_node_vcgattr_hook(DUMP_NODE_VCGATTR_FUNC hook) {
112 dump_node_vcgattr_hook = hook;
115 INLINE bool get_opt_dump_const_local(void) {
116 if (!dump_out_edge_flag && !dump_loop_information_flag)
117 return dump_const_local;
122 void only_dump_method_with_name(ident *name) {
123 dump_file_filter_id = name;
126 ident *get_dump_file_filter_ident(void) {
127 return dump_file_filter_id;
130 /** Returns true if dump file filter is not set, or if it is a
132 int is_filtered_dump_name(ident *name) {
133 if (!dump_file_filter_id) return 1;
134 return id_is_prefix(dump_file_filter_id, name);
137 /* To turn off display of edge labels. Edge labels offen cause xvcg to
138 abort with a segmentation fault. */
139 void turn_off_edge_labels(void) {
143 void dump_consts_local(bool b) {
144 dump_const_local = b;
147 void dump_constant_entity_values(bool b) {
151 void dump_keepalive_edges(bool b) {
155 bool get_opt_dump_keepalive_edges(void) {
156 return dump_keepalive;
159 void dump_out_edges(bool b) {
160 dump_out_edge_flag = b;
163 void dump_dominator_information(bool b) {
164 dump_dominator_information_flag = b;
167 void dump_loop_information(bool b) {
168 dump_loop_information_flag = b;
171 void dump_backedge_information(bool b) {
172 dump_backedge_information_flag = b;
175 /* Dump the information of type field specified in ana/irtypeinfo.h.
176 * If the flag is set, the type name is output in [] in the node label,
177 * else it is output as info.
179 void set_opt_dump_analysed_type_info(bool b) {
180 opt_dump_analysed_type_info = b;
183 void dump_pointer_values_to_info(bool b) {
184 opt_dump_pointer_values_to_info = b;
187 void dump_ld_names(bool b) {
191 /* -------------- some extended helper functions ----------------- */
194 * returns the name of a mode or <ERROR> if mode is NOT a mode object.
195 * in the later case, sets bad
197 const char *get_mode_name_ex(ir_mode *mode, int *bad)
200 return get_mode_name(mode);
206 * returns the name of a type or <ERROR> if mode is NOT a mode object.
207 * in the later case, sets bad
209 const char *get_type_name_ex(type *tp, int *bad)
212 return get_type_name(tp);
218 * prints the edge from a type S to a type T with additional info fmt, ...
221 static void print_type_type_edge(FILE *F, type *S, type *T, const char *fmt, ...)
226 fprintf(F, "edge: { sourcename: "); PRINT_TYPEID(S);
227 fprintf(F, " targetname: "); PRINT_TYPEID(T);
228 vfprintf(F, fmt, ap);
234 * prints the edge from a type T to an entity E with additional info fmt, ...
237 static void print_type_ent_edge(FILE *F, type *T, entity *E, const char *fmt, ...)
242 fprintf(F, "edge: { sourcename: "); PRINT_TYPEID(T);
243 fprintf(F, " targetname: \""); PRINT_ENTID(E); fprintf(F, "\"");
244 vfprintf(F, fmt, ap);
250 * prints the edge from an entity E to an entity T with additional info fmt, ...
253 static void print_ent_ent_edge(FILE *F, entity *E, entity *T, int backedge, const char *fmt, ...)
259 fprintf(F, "backedge: { sourcename: \"");
261 fprintf(F, "edge: { sourcename: \"");
263 fprintf(F, "\" targetname: \""); PRINT_ENTID(T); fprintf(F, "\"");
264 vfprintf(F, fmt, ap);
270 * prints the edge from an entity E to a type T with additional info fmt, ...
273 static void print_ent_type_edge(FILE *F, entity *E, type *T, const char *fmt, ...)
278 fprintf(F, "edge: { sourcename: \""); PRINT_ENTID(E);
279 fprintf(F, "\" targetname: "); PRINT_TYPEID(T);
280 vfprintf(F, fmt, ap);
286 * prints the edge from a node N to a type T with additional info fmt, ...
289 static void print_node_type_edge(FILE *F, const ir_node *N, type *T, const char *fmt, ...)
294 fprintf(F, "edge: { sourcename: \""); PRINT_NODEID(N);
295 fprintf(F, "\" targetname: "); PRINT_TYPEID(T);
296 vfprintf(F, fmt, ap);
302 * prints the edge from a node N to an entity E with additional info fmt, ...
305 static void print_node_ent_edge(FILE *F, const ir_node *N, entity *E, const char *fmt, ...)
310 fprintf(F, "edge: { sourcename: \""); PRINT_NODEID(N);
311 fprintf(F, "\" targetname: \""); PRINT_ENTID(E);
313 vfprintf(F, fmt, ap);
319 * prints the edge from an entity E to a node N with additional info fmt, ...
322 static void print_ent_node_edge(FILE *F, entity *E, const ir_node *N, const char *fmt, ...)
327 fprintf(F, "edge: { sourcename: \""); PRINT_ENTID(E);
328 fprintf(F, "\" targetname: \""); PRINT_NODEID(N); fprintf(F, "\"");
329 vfprintf(F, fmt, ap);
335 * prints the edge from a type E to an enumeration item item with additional info fmt, ...
338 static void print_enum_item_edge(FILE *F, type *E, int item, const char *fmt, ...)
343 fprintf(F, "edge: { sourcename: "); PRINT_TYPEID(E);
344 fprintf(F, " targetname: \""); PRINT_ITEMID(E, item); fprintf(F, "\" ");
345 vfprintf(F, fmt, ap);
350 /*-----------------------------------------------------------------*/
351 /* global and ahead declarations */
352 /*-----------------------------------------------------------------*/
354 static void dump_whole_node(ir_node *n, void *env);
355 static INLINE void dump_loop_nodes_into_graph(FILE *F, ir_graph *irg);
357 /*-----------------------------------------------------------------*/
358 /* Helper functions. */
359 /*-----------------------------------------------------------------*/
362 * This map is used as a private link attr to be able to call dumper
363 * anywhere without destroying link fields.
365 static pmap *irdump_link_map = NULL;
367 /** NOT A STANDARD LIBFIRM INIT METHOD
369 * We do not want to integrate dumping into libfirm, i.e., if the dumpers
370 * are off, we want to have as few interferences as possible. Therefore the
371 * initialization is performed lazily and not called from within init_firm.
373 * Creates the link attribute map. */
374 static void init_irdump(void) {
375 /* We need a new, empty map. */
376 if (irdump_link_map) pmap_destroy(irdump_link_map);
377 irdump_link_map = pmap_create();
378 if (!dump_file_filter_id)
379 dump_file_filter_id = new_id_from_str("");
382 * Returns the private link field.
384 static void *ird_get_irn_link(ir_node *n) {
386 if (!irdump_link_map) return NULL;
388 if (pmap_contains(irdump_link_map, (void *)n))
389 res = pmap_get(irdump_link_map, (void *)n);
394 * Sets the private link field.
396 static void ird_set_irn_link(ir_node *n, void *x) {
397 if (!irdump_link_map) init_irdump();
398 pmap_insert(irdump_link_map, (void *)n, x);
402 * Gets the private link field of an irg.
404 static void *ird_get_irg_link(ir_graph *irg) {
406 if (!irdump_link_map) return NULL;
408 if (pmap_contains(irdump_link_map, (void *)irg))
409 res = pmap_get(irdump_link_map, (void *)irg);
414 * Sets the private link field of an irg.
416 static void ird_set_irg_link(ir_graph *irg, void *x) {
417 if (!irdump_link_map) init_irdump();
418 pmap_insert(irdump_link_map, (void *)irg, x);
422 * Walker, clears the private link field.
424 static void clear_link(ir_node * node, void * env) {
425 ird_set_irn_link(node, NULL);
429 * If the entity has a ld_name, returns it if the dump_ld_name is set,
430 * else returns the name of the entity.
432 static const char *_get_ent_dump_name(entity *ent, int dump_ld_name) {
434 return "<NULL entity>";
436 /* Don't use get_entity_ld_ident (ent) as it computes the mangled name! */
437 if (ent->ld_name) return get_id_str(ent->ld_name);
439 return get_id_str(ent->name);
443 * If the entity has a ld_name, returns it if the option dump_ld_name is set,
444 * else returns the name of the entity.
446 const char *get_ent_dump_name(entity *ent) {
447 return _get_ent_dump_name(ent, dump_ld_name);
450 /* Returns the name of an IRG. */
451 const char *get_irg_dump_name(ir_graph *irg) {
452 /* Don't use get_entity_ld_ident (ent) as it computes the mangled name! */
453 return _get_ent_dump_name(get_irg_entity(irg), 1);
457 * Returns non-zero if a node is in floating state.
459 static int node_floats(ir_node *n) {
460 return ((get_irn_pinned(n) == op_pin_state_floats) &&
461 (get_irg_pinned(current_ir_graph) == op_pin_state_floats));
465 * Walker, allocates an array for all blocks and puts it's nodes non-floating nodes into this array.
467 static void collect_node(ir_node * node, void *env) {
470 || get_irn_op(node) == op_Bad
471 || get_irn_op(node) == op_Unknown
472 || get_irn_op(node) == op_NoMem) {
473 ir_node ** arr = (ir_node **) ird_get_irg_link(get_irn_irg(node));
474 if (!arr) arr = NEW_ARR_F(ir_node *, 0);
475 ARR_APP1(ir_node *, arr, node);
476 ird_set_irg_link(get_irn_irg(node), arr); /* arr is an l-value, APP_ARR might change it! */
478 ir_node * block = get_nodes_block(node);
481 /* this node is in a Bad block, so we must place it into the graph's list */
482 ir_node ** arr = (ir_node **) ird_get_irg_link(get_irn_irg(node));
483 if (!arr) arr = NEW_ARR_F(ir_node *, 0);
484 ARR_APP1(ir_node *, arr, node);
485 ird_set_irg_link(get_irn_irg(node), arr); /* arr is an l-value, APP_ARR might change it! */
488 ird_set_irn_link(node, ird_get_irn_link(block));
489 ird_set_irn_link(block, node);
494 /** Construct lists to walk ir block-wise.
496 * Collects all blocks, nodes not op_pin_state_pinned,
497 * Bad, NoMem and Unknown into a flexible array in link field of
498 * irg they belong to. Sets the irg link field to NULL in all
499 * graphs not visited.
500 * Free the list with DEL_ARR_F().
502 static ir_node **construct_block_lists(ir_graph *irg) {
503 int i, rem_view = get_interprocedural_view();
504 ir_graph *rem = current_ir_graph;
505 current_ir_graph = irg;
507 for (i = 0; i < get_irp_n_irgs(); i++)
508 ird_set_irg_link(get_irp_irg(i), NULL);
510 irg_walk_graph(current_ir_graph, clear_link, collect_node, current_ir_graph);
512 /* Collect also EndReg and EndExcept. We do not want to change the walker. */
513 set_interprocedural_view(false);
515 set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph)-1);
516 irg_walk(get_irg_end_reg(current_ir_graph), clear_link, collect_node, current_ir_graph);
517 set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph)-1);
518 irg_walk(get_irg_end_except(current_ir_graph), clear_link, collect_node, current_ir_graph);
520 set_interprocedural_view(rem_view);
522 current_ir_graph = rem;
523 return ird_get_irg_link(irg);
526 typedef struct _list_tuple {
528 ir_extblk **extbb_list;
531 /** Construct lists to walk ir extended block-wise.
532 * Free the lists in the tuple with DEL_ARR_F().
534 static list_tuple *construct_extblock_lists(ir_graph *irg) {
535 ir_node **blk_list = construct_block_lists(irg);
537 ir_graph *rem = current_ir_graph;
538 list_tuple *lists = xmalloc(sizeof(*lists));
540 current_ir_graph = irg;
542 lists->blk_list = NEW_ARR_F(ir_node *, 0);
543 lists->extbb_list = NEW_ARR_F(ir_extblk *, 0);
545 for (i = ARR_LEN(blk_list) - 1; i >= 0; --i) {
548 if (is_Block(blk_list[i])) {
549 ext = get_Block_extbb(blk_list[i]);
551 if (extbb_not_visited(ext)) {
552 ARR_APP1(ir_extblk *, lists->extbb_list, ext);
553 mark_extbb_visited(ext);
557 ARR_APP1(ir_node *, lists->blk_list, blk_list[i]);
560 current_ir_graph = rem;
562 ird_set_irg_link(irg, lists);
566 /*-----------------------------------------------------------------*/
567 /* Routines to dump information about a single ir node. */
568 /*-----------------------------------------------------------------*/
571 * dump the name of a node n to the File F.
574 dump_node_opcode(FILE *F, ir_node *n)
578 switch(get_irn_opcode(n)) {
583 res = tarval_snprintf(buf, sizeof(buf), get_Const_tarval(n));
584 assert(res < sizeof(buf) && "buffer to small for tarval_snprintf");
589 if (get_SymConst_kind(n) == symconst_addr_name) {
590 /* don't use get_SymConst_ptr_info as it mangles the name. */
591 fprintf (F, "SymC %s", get_id_str(get_SymConst_name(n)));
592 } else if (get_SymConst_kind(n) == symconst_addr_ent) {
593 assert(get_SymConst_entity(n));
594 assert(is_entity(get_SymConst_entity(n)));
595 fprintf (F, "SymC &%s", get_entity_name(get_SymConst_entity(n)));
597 assert(get_kind(get_SymConst_type(n)) == k_type);
598 assert(get_type_ident(get_SymConst_type(n)));
599 fprintf (F, "SymC %s ", get_type_name_ex(get_SymConst_type(n), &bad));
600 if (get_SymConst_kind(n) == symconst_type_tag)
608 if (!get_interprocedural_view())
615 ir_node *pred = get_Proj_pred(n);
617 if (get_irn_opcode(pred) == iro_Cond
618 && get_Proj_proj(n) == get_Cond_defaultProj(pred)
619 && get_irn_mode(get_Cond_selector(pred)) != mode_b)
620 fprintf (F, "defProj");
628 if (get_interprocedural_view()) {
629 fprintf(F, "%s %s", get_irn_opname(n), get_ent_dump_name(get_irg_entity(get_irn_irg(n))));
634 case iro_CallBegin: {
635 ir_node *addr = get_CallBegin_ptr(n);
637 if (get_irn_op(addr) == op_Sel)
638 ent = get_Sel_entity(addr);
639 else if ((get_irn_op(addr) == op_SymConst) && (get_SymConst_kind(addr) == symconst_addr_ent))
640 ent = get_SymConst_entity(addr);
641 fprintf (F, "%s", get_irn_opname(n));
642 if (ent) fprintf (F, " %s", get_entity_name(ent));
646 fprintf (F, "%s[%s]", get_irn_opname(n), get_mode_name_ex(get_Load_mode(n), &bad));
651 fprintf (F, "%s", get_irn_opname(n));
659 * Dump the mode of a node n to a file F.
660 * Ignore modes that are "always known".
663 dump_node_mode(FILE *F, ir_node *n)
666 opcode iro = get_irn_opcode(n);
679 ir_mode *mode = get_irn_mode(n);
681 if (mode && mode != mode_BB && mode != mode_ANY && mode != mode_BAD &&
682 (mode != mode_T || iro == iro_Proj))
683 fprintf(F, "%s", get_mode_name_ex(mode, &bad));
691 * Dump the type of a node n to a file F if it's known.
693 static int dump_node_typeinfo(FILE *F, ir_node *n) {
696 if (opt_dump_analysed_type_info) {
697 if (get_irg_typeinfo_state(current_ir_graph) == ir_typeinfo_consistent ||
698 get_irg_typeinfo_state(current_ir_graph) == ir_typeinfo_inconsistent) {
699 type *tp = get_irn_typeinfo_type(n);
700 if (tp != firm_none_type)
701 fprintf(F, "[%s] ", get_type_name_ex(tp, &bad));
709 typedef struct _pns_lookup {
710 long nr; /**< the proj number */
711 const char *name; /**< the name of the Proj */
714 typedef struct _proj_lookup {
715 opcode code; /**< the opcode of the Proj predecessor */
716 unsigned num_data; /**< number of data entries */
717 const pns_lookup_t *data; /**< the data */
720 #define ARR_SIZE(a) (sizeof(a)/sizeof(a[0]))
722 /** the lookup table for Proj(Start) names */
723 static const pns_lookup_t start_lut[] = {
724 #define X(a) { pn_Start_##a, #a }
733 /** the lookup table for Proj(Cond) names */
734 static const pns_lookup_t cond_lut[] = {
735 #define X(a) { pn_Cond_##a, #a }
741 /** the lookup table for Proj(Call) names */
742 static const pns_lookup_t call_lut[] = {
743 #define X(a) { pn_Call_##a, #a }
752 /** the lookup table for Proj(Quot) names */
753 static const pns_lookup_t quot_lut[] = {
754 #define X(a) { pn_Quot_##a, #a }
761 /** the lookup table for Proj(DivMod) names */
762 static const pns_lookup_t divmod_lut[] = {
763 #define X(a) { pn_DivMod_##a, #a }
771 /** the lookup table for Proj(Div) names */
772 static const pns_lookup_t div_lut[] = {
773 #define X(a) { pn_Div_##a, #a }
780 /** the lookup table for Proj(Mod) names */
781 static const pns_lookup_t mod_lut[] = {
782 #define X(a) { pn_Mod_##a, #a }
789 /** the lookup table for Proj(Load) names */
790 static const pns_lookup_t load_lut[] = {
791 #define X(a) { pn_Load_##a, #a }
798 /** the lookup table for Proj(Store) names */
799 static const pns_lookup_t store_lut[] = {
800 #define X(a) { pn_Store_##a, #a }
806 /** the lookup table for Proj(Alloc) names */
807 static const pns_lookup_t alloc_lut[] = {
808 #define X(a) { pn_Alloc_##a, #a }
816 /** the Proj lookup table */
817 static const proj_lookup_t proj_lut[] = {
818 #define E(a) ARR_SIZE(a), a
819 { iro_Start, E(start_lut) },
820 { iro_Cond, E(cond_lut) },
821 { iro_Call, E(call_lut) },
822 { iro_Quot, E(quot_lut) },
823 { iro_DivMod, E(divmod_lut) },
824 { iro_Div, E(div_lut) },
825 { iro_Mod, E(mod_lut) },
826 { iro_Load, E(load_lut) },
827 { iro_Store, E(store_lut) },
828 { iro_Alloc, E(alloc_lut) }
833 * Dump additional node attributes of some nodes to a file F.
836 dump_node_nodeattr(FILE *F, ir_node *n)
843 switch (get_irn_opcode(n)) {
845 if (false && get_interprocedural_view()) {
846 fprintf (F, "%s ", get_ent_dump_name(get_irg_entity(current_ir_graph)));
851 pred = get_Proj_pred(n);
852 proj_nr = get_Proj_proj(n);
854 code = get_irn_opcode(pred);
857 fprintf (F, "%s ", get_pnc_string(get_Proj_proj(n)));
858 else if (code == iro_Proj && get_irn_opcode(get_Proj_pred(pred)) == iro_Start)
859 fprintf (F, "Arg %ld ", proj_nr);
861 unsigned i, j, f = 0;
863 for (i = 0; i < ARR_SIZE(proj_lut); ++i) {
864 if (code == proj_lut[i].code) {
865 for (j = 0; j < proj_lut[i].num_data; ++j) {
866 if (proj_nr == proj_lut[i].data[j].nr) {
867 fprintf (F, "%s ", proj_lut[i].data[j].name);
876 fprintf (F, "%ld ", proj_nr);
877 if (code == iro_Cond && get_Cond_jmp_pred(pred) != COND_JMP_PRED_NONE) {
878 if (proj_nr == pn_Cond_false && get_Cond_jmp_pred(pred) == COND_JMP_PRED_FALSE)
880 if (proj_nr == pn_Cond_true && get_Cond_jmp_pred(pred) == COND_JMP_PRED_TRUE)
886 proj_nr = get_Filter_proj(n);
887 if (! get_interprocedural_view()) {
889 pred = get_Filter_pred(n);
893 fprintf (F, "%ld ", proj_nr);
896 fprintf (F, "%s ", get_ent_dump_name(get_Sel_entity(n)));
899 fprintf (F, "(%s) ", get_type_name_ex(get_Cast_type(n), &bad));
902 fprintf (F, "%s ", get_pnc_string(get_Confirm_cmp(n)));
913 #include "execution_frequency.h"
914 #include "callgraph.h"
916 void dump_node_ana_vals(FILE *F, ir_node *n) {
918 fprintf(F, " %lf*(%2.0lf + %2.0lf) = %2.0lf ",
919 get_irn_exec_freq(n),
920 get_irg_method_execution_frequency(get_irn_irg(n)),
921 pow(5, get_irg_recursion_depth(get_irn_irg(n))),
922 get_irn_exec_freq(n) * (get_irg_method_execution_frequency(get_irn_irg(n)) + pow(5, get_irg_recursion_depth(get_irn_irg(n))))
927 /* Dumps a node label without the enclosing ". */
928 int dump_node_label(FILE *F, ir_node *n) {
931 bad |= dump_node_opcode(F, n);
932 bad |= dump_node_mode(F, n);
934 bad |= dump_node_typeinfo(F, n);
935 bad |= dump_node_nodeattr(F, n);
936 fprintf(F, "%ld", get_irn_node_nr(n));
943 * Dumps the attributes of a node n into the file F.
944 * Currently this is only the color of a node.
946 static void dump_node_vcgattr(FILE *F, ir_node *node, ir_node *local, int bad)
951 fprintf(F, "color: red");
955 if (dump_node_vcgattr_hook)
956 if (dump_node_vcgattr_hook(F, node, local))
959 n = local ? local : node;
961 switch (get_irn_opcode(n)) {
968 fprintf (F, "color: blue");
971 if (is_Block_dead(n))
972 fprintf (F, "color: lightred");
974 fprintf (F, "color: lightyellow");
977 fprintf (F, "color: green");
983 fprintf (F, "color: yellow");
986 PRINT_DEFAULT_NODE_ATTR;
989 if (overrule_nodecolor) fprintf(F, " color: %s", overrule_nodecolor);
994 * Dump the node information of a node n to a file F.
996 static INLINE int dump_node_info(FILE *F, ir_node *n)
998 fprintf (F, " info1: \"");
999 bad = dump_irnode_to_file(F, n);
1005 * checks whether a node is "constant-like" ie can be treated "block-less"
1008 bool is_constlike_node(ir_node *n) {
1009 ir_op *op = get_irn_op(n);
1010 return (op == op_Const || op == op_Bad || op == op_NoMem || op == op_SymConst || op == op_Unknown);
1014 /** outputs the predecessors of n, that are constants, local. I.e.,
1015 generates a copy of the constant predecessors for each node called with. */
1016 static void dump_const_node_local(FILE *F, ir_node *n) {
1018 if (!get_opt_dump_const_local()) return;
1020 /* Use visited flag to avoid outputting nodes twice.
1021 initialize it first. */
1022 for (i = 0; i < get_irn_arity(n); i++) {
1023 ir_node *con = get_irn_n(n, i);
1024 if (is_constlike_node(con)) {
1025 set_irn_visited(con, get_irg_visited(current_ir_graph) - 1);
1029 for (i = 0; i < get_irn_arity(n); i++) {
1030 ir_node *con = get_irn_n(n, i);
1031 if (is_constlike_node(con) && irn_not_visited(con)) {
1034 mark_irn_visited(con);
1035 /* Generate a new name for the node by appending the names of
1037 fprintf(F, "node: {title: "); PRINT_CONSTID(n, con);
1038 fprintf(F, " label: \"");
1039 bad |= dump_node_label(F, con);
1041 bad |= dump_node_info(F, con);
1042 dump_node_vcgattr(F, n, con, bad);
1048 /** If the block of an edge is a const_like node, dump it local with an edge */
1049 static void dump_const_block_local(FILE *F, ir_node *n) {
1052 if (!get_opt_dump_const_local()) return;
1054 blk = get_nodes_block(n);
1055 if (is_constlike_node(blk)) {
1058 /* Generate a new name for the node by appending the names of
1060 fprintf(F, "node: {title: \""); PRINT_CONSTBLKID(n, blk);
1061 fprintf(F, "\" label: \"");
1062 bad |= dump_node_label(F, blk);
1064 bad |= dump_node_info(F, blk);
1065 dump_node_vcgattr(F, n, blk, bad);
1068 fprintf (F, "edge: { sourcename: \"");
1070 fprintf (F, "\" targetname: \""); PRINT_CONSTBLKID(n,blk);
1071 fprintf (F, "\" " BLOCK_EDGE_ATTR "}\n");
1076 * prints the error message of a node to a file F as info2.
1078 static void INLINE print_node_error(FILE *F, const char *err_msg)
1083 fprintf (F, " info2: \"%s\"", err_msg);
1087 * prints debug messages of a node to file F as info3.
1089 static void print_node_dbg_info(FILE *F, dbg_info *dbg)
1093 if (__dbg_info_snprint) {
1095 if (__dbg_info_snprint(buf, sizeof(buf), dbg) > 0)
1096 fprintf (F, " info3: \"%s\"\n", buf);
1103 static void dump_node(FILE *F, ir_node *n)
1108 if (get_opt_dump_const_local() && is_constlike_node(n))
1111 /* dump this node */
1112 fprintf(F, "node: {title: \""); PRINT_NODEID(n); fprintf(F, "\" label: \"");
1114 bad = ! irn_vrfy_irg_dump(n, current_ir_graph, &p);
1115 bad |= dump_node_label(F, n);
1116 dump_node_ana_vals(F, n);
1117 //dump_node_ana_info(F, n);
1119 bad |= dump_node_info(F, n);
1120 print_node_error(F, p);
1121 print_node_dbg_info(F, get_irn_dbg_info(n));
1122 dump_node_vcgattr(F, n, NULL, bad);
1124 dump_const_node_local(F, n);
1126 if(dump_node_edge_hook)
1127 dump_node_edge_hook(F, n);
1129 dump_irn_chi_term(F, n);
1130 dump_irn_state(F, n);
1134 /** dump the edge to the block this node belongs to */
1136 dump_ir_block_edge(FILE *F, ir_node *n) {
1137 if (get_opt_dump_const_local() && is_constlike_node(n)) return;
1138 if (is_no_Block(n)) {
1139 ir_node *block = get_nodes_block(n);
1141 if (get_opt_dump_const_local() && is_constlike_node(block)) {
1142 dump_const_block_local(F, n);
1145 fprintf (F, "edge: { sourcename: \"");
1147 fprintf (F, "\" targetname: ");
1148 fprintf(F, "\""); PRINT_NODEID(block); fprintf(F, "\"");
1149 fprintf (F, " " BLOCK_EDGE_ATTR "}\n");
1155 print_data_edge_vcgattr(FILE *F, ir_node *from, int to) {
1157 * do not use get_nodes_block() here, will fail
1158 * if the irg is not pinned.
1160 if (get_irn_n(from, -1) == get_irn_n(get_irn_n(from, to), -1))
1161 fprintf (F, INTRA_DATA_EDGE_ATTR);
1163 fprintf (F, INTER_DATA_EDGE_ATTR);
1167 print_mem_edge_vcgattr(FILE *F, ir_node *from, int to) {
1169 * do not use get_nodes_block() here, will fail
1170 * if the irg is not pinned.
1172 if (get_irn_n(from, -1) == get_irn_n(get_irn_n(from, to), -1))
1173 fprintf (F, INTRA_MEM_EDGE_ATTR);
1175 fprintf (F, INTER_MEM_EDGE_ATTR);
1179 print_edge_vcgattr(FILE *F, ir_node *from, int to) {
1182 if (dump_backedge_information_flag && is_backedge(from, to))
1183 fprintf (F, BACK_EDGE_ATTR);
1185 switch (get_irn_opcode(from)) {
1187 fprintf (F, CF_EDGE_ATTR);
1189 case iro_Start: break;
1192 if (get_irn_mode(get_End_keepalive(from, to)) == mode_BB)
1193 fprintf (F, CF_EDGE_ATTR);
1194 if (get_irn_mode(get_End_keepalive(from, to)) == mode_X)
1195 fprintf (F, INTER_MEM_EDGE_ATTR);
1203 print_data_edge_vcgattr(F, from, to);
1208 print_mem_edge_vcgattr(F, from, to);
1210 print_data_edge_vcgattr(F, from, to);
1214 print_data_edge_vcgattr(F, from, to);
1219 print_mem_edge_vcgattr(F, from, to);
1221 print_data_edge_vcgattr(F, from, to);
1228 print_data_edge_vcgattr(F, from, to);
1235 print_mem_edge_vcgattr(F, from, to);
1237 print_data_edge_vcgattr(F, from, to);
1249 print_data_edge_vcgattr(F, from, to);
1252 if (get_irn_modecode(from) == irm_M)
1253 fprintf (F, INTER_MEM_EDGE_ATTR);
1255 print_data_edge_vcgattr(F, from, to);
1262 print_mem_edge_vcgattr(F, from, to);
1264 print_data_edge_vcgattr(F, from, to);
1267 print_mem_edge_vcgattr(F, from, to);
1269 case iro_Tuple: break;
1272 switch (get_irn_modecode(from)) {
1274 fprintf (F, CF_EDGE_ATTR);
1277 fprintf (F, INTER_MEM_EDGE_ATTR);
1280 print_data_edge_vcgattr(F, from, to);
1284 case iro_Bad: break;
1285 case iro_Unknown: break;
1287 switch (get_irn_modecode(from)) {
1289 fprintf (F, INTRA_MEM_EDGE_ATTR);
1292 fprintf (F, CF_EDGE_ATTR);
1295 print_data_edge_vcgattr(F, from, to);
1303 /* dump edges to our inputs */
1305 dump_ir_data_edges(FILE *F, ir_node *n) {
1307 unsigned long visited = get_irn_visited(n);
1309 if ((get_irn_op(n) == op_End) && (!dump_keepalive))
1312 for (i = 0; i < get_irn_arity(n); i++) {
1313 ir_node * pred = get_irn_n(n, i);
1316 if ((get_interprocedural_view() && get_irn_visited(pred) < visited))
1317 continue; /* pred not dumped */
1319 if (dump_backedge_information_flag && is_backedge(n, i))
1320 fprintf (F, "backedge: {sourcename: \"");
1322 fprintf (F, "edge: {sourcename: \"");
1324 fprintf (F, "\" targetname: ");
1325 if ((get_opt_dump_const_local()) && is_constlike_node(pred)) {
1326 PRINT_CONSTID(n, pred);
1328 fprintf(F, "\""); PRINT_NODEID(pred); fprintf(F, "\"");
1330 fprintf (F, " label: \"%d\" ", i);
1331 print_edge_vcgattr(F, n, i);
1336 /** Dumps a node and its edges but not the block edge
1339 dump_node_wo_blockedge (ir_node *n, void *env) {
1342 dump_ir_data_edges(F, n);
1345 /** Dumps a node and its edges.
1348 dump_whole_node (ir_node *n, void *env) {
1350 dump_node_wo_blockedge(n, env);
1351 if (!node_floats(n)) dump_ir_block_edge(F, n);
1355 dump_const_node(ir_node *n, void *env) {
1356 if (is_Block(n)) return;
1357 dump_node_wo_blockedge(n, env);
1360 /***********************************************************************/
1361 /* the following routines dump the nodes/irgs bracketed to graphs. */
1362 /***********************************************************************/
1364 /** Dumps a constant expression as entity initializer, array bound ...
1366 static void dump_const_expression(FILE *F, ir_node *value) {
1367 ir_graph *rem = current_ir_graph;
1368 int rem_dump_const_local = dump_const_local;
1369 dump_const_local = 0;
1370 current_ir_graph = get_const_code_irg();
1371 irg_walk(value, dump_const_node, NULL, F);
1372 /* Decrease visited flag so that we walk with the same flag for the next
1373 expression. This guarantees that we don't dump the same node twice,
1374 as for const expressions cse is performed to save memory. */
1375 set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph) -1);
1376 current_ir_graph = rem;
1377 dump_const_local = rem_dump_const_local;
1380 /** Dump a block as graph containing its nodes.
1382 * Expects to find nodes belonging to the block as list in its
1384 * Dumps the edges of all nodes including itself. */
1386 dump_whole_block(FILE *F, ir_node *block) {
1388 assert(is_Block(block));
1390 fprintf(F, "graph: { title: \"");
1391 PRINT_NODEID(block);
1392 fprintf(F, "\" label: \"");
1393 dump_node_label(F, block);
1395 if (get_opt_dump_abstvals())
1396 fprintf (F, " seqno: %d", (int)get_Block_seqno(block));
1398 fprintf(F, "\" status:clustered color:%s \n",
1399 get_Block_matured(block) ? "yellow" : "red");
1401 /* dump the blocks edges */
1402 dump_ir_data_edges(F, block);
1404 /* dump the nodes that go into the block */
1405 for (node = ird_get_irn_link(block); node; node = ird_get_irn_link(node)) {
1407 dump_ir_data_edges(F, node);
1410 /* Close the vcg information for the block */
1412 dump_const_node_local(F, block);
1414 dump_irn_chi_term(F, block);
1419 /** dumps a graph block-wise. Expects all blockless nodes in arr in irgs link.
1420 * The outermost nodes: blocks and nodes not op_pin_state_pinned, Bad, Unknown. */
1422 dump_block_graph(FILE *F, ir_graph *irg) {
1424 ir_graph *rem = current_ir_graph;
1425 ir_node **arr = ird_get_irg_link(irg);
1426 current_ir_graph = irg;
1428 for (i = ARR_LEN(arr) - 1; i >= 0; --i) {
1429 ir_node * node = arr[i];
1430 if (is_Block(node)) {
1431 /* Dumps the block and all the nodes in the block, which are to
1432 be found in Block->link. */
1433 dump_whole_block(F, node);
1435 /* Nodes that are not in a Block. */
1437 if (!node_floats(node) && is_Bad(get_nodes_block(node))) {
1438 dump_const_block_local(F, node);
1440 dump_ir_data_edges(F, node);
1444 if (dump_loop_information_flag && (get_irg_loopinfo_state(irg) & loopinfo_valid))
1445 dump_loop_nodes_into_graph(F, irg);
1447 current_ir_graph = rem;
1450 /** Dumps an irg as a graph clustered by block nodes.
1451 * If interprocedural view edges can point to nodes out of this graph.
1453 static void dump_graph_from_list(FILE *F, ir_graph *irg) {
1455 fprintf(F, "graph: { title: \"");
1457 fprintf(F, "\" label: \"%s\" status:clustered color:white \n",
1458 get_ent_dump_name(get_irg_entity(irg)));
1460 dump_block_graph(F, irg);
1462 /* Close the vcg information for the irg */
1463 fprintf(F, "}\n\n");
1466 /** dumps a graph extended block-wise. Expects all blockless nodes in arr in irgs link.
1467 * The outermost nodes: blocks and nodes not op_pin_state_pinned, Bad, Unknown. */
1469 dump_extblock_graph(FILE *F, ir_graph *irg) {
1471 ir_graph *rem = current_ir_graph;
1472 ir_extblk **arr = ird_get_irg_link(irg);
1473 current_ir_graph = irg;
1476 for (i = ARR_LEN(arr) - 1; i >= 0; --i) {
1477 ir_extblk *extbb = arr[i];
1478 ir_node *leader = get_extbb_leader(extbb);
1481 fprintf(F, "graph: { title: \"");
1482 PRINT_EXTBBID(leader);
1483 fprintf(F, "\" label: \"ExtBB %ld\" status:clustered color:lightgreen\n",
1484 get_irn_node_nr(leader));
1486 for (j = ARR_LEN(extbb->blks) - 1; j >= 0; --j) {
1487 ir_node * node = extbb->blks[j];
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 (is_Bad(get_nodes_block(node)) && !node_floats(node)) {
1496 dump_const_block_local(F, node);
1498 dump_ir_data_edges(F, node);
1504 if (dump_loop_information_flag && (get_irg_loopinfo_state(irg) & loopinfo_valid))
1505 dump_loop_nodes_into_graph(F, irg);
1507 current_ir_graph = rem;
1512 /*******************************************************************/
1513 /* Basic type and entity nodes and edges. */
1514 /*******************************************************************/
1516 /** dumps the edges between nodes and their type or entity attributes. */
1517 static void dump_node2type_edges(ir_node *n, void *env)
1522 switch (get_irn_opcode(n)) {
1524 /* @@@ some consts have an entity */
1527 if ( (get_SymConst_kind(n) ==symconst_type_tag)
1528 || (get_SymConst_kind(n) ==symconst_size))
1530 print_node_type_edge(F,n,get_SymConst_type(n),NODE2TYPE_EDGE_ATTR);
1534 print_node_ent_edge(F,n,get_Sel_entity(n),NODE2TYPE_EDGE_ATTR);
1537 print_node_type_edge(F,n,get_Call_type(n),NODE2TYPE_EDGE_ATTR);
1540 print_node_type_edge(F,n,get_Alloc_type(n),NODE2TYPE_EDGE_ATTR);
1543 print_node_type_edge(F,n,get_Free_type(n),NODE2TYPE_EDGE_ATTR);
1546 print_node_type_edge(F,n,get_Cast_type(n),NODE2TYPE_EDGE_ATTR);
1554 static int print_type_info(FILE *F, type *tp) {
1557 if (get_type_state(tp) == layout_undefined) {
1558 fprintf(F, "state: layout_undefined\n");
1560 fprintf(F, "state: layout_fixed,\n");
1562 if (get_type_mode(tp))
1563 fprintf(F, "mode: %s,\n", get_mode_name_ex(get_type_mode(tp), &bad));
1564 fprintf(F, "size: %db,\n", get_type_size_bits(tp));
1569 static void print_typespecific_info(FILE *F, type *tp) {
1570 switch (get_type_tpop_code(tp)) {
1573 fprintf(F, "peculiarity: %s\n", get_peculiarity_string(get_class_peculiarity(tp)));
1580 fprintf(F, "variadicity: %s\n", get_variadicity_name(get_method_variadicity(tp)));
1581 fprintf(F, "params: %d\n", get_method_n_params(tp));
1582 fprintf(F, "results: %d\n", get_method_n_ress(tp));
1590 case tpo_enumeration:
1604 static void print_typespecific_vcgattr(FILE *F, type *tp) {
1605 switch (get_type_tpop_code(tp)) {
1608 if (peculiarity_existent == get_class_peculiarity(tp))
1609 fprintf (F, " " TYPE_CLASS_NODE_ATTR);
1611 fprintf (F, " " TYPE_DESCRIPTION_NODE_ATTR);
1615 fprintf (F, " " TYPE_METH_NODE_ATTR);
1626 case tpo_enumeration:
1640 int dump_type_node(FILE *F, type *tp)
1644 fprintf (F, "node: {title: ");
1646 fprintf (F, " label: \"%s %s\"", get_type_tpop_name(tp), get_type_name_ex(tp, &bad));
1647 fprintf (F, " info1: \"");
1649 bad |= print_type_info(F, tp);
1650 print_typespecific_info(F, tp);
1652 dump_type_to_file(F, tp, dump_verbosity_max);
1654 fprintf (F, "\"\n");
1655 print_node_dbg_info(F, get_type_dbg_info(tp));
1656 print_typespecific_vcgattr(F, tp);
1663 #define X(a) case a: fprintf(F, #a); break
1664 void dump_entity_node(FILE *F, entity *ent, int color)
1666 fprintf (F, "node: {title: \"");
1667 PRINT_ENTID(ent); fprintf(F, "\"");
1668 fprintf (F, DEFAULT_TYPE_ATTRIBUTE);
1669 fprintf (F, "label: ");
1670 fprintf (F, "\"ent %s\" ", get_ent_dump_name(ent));
1672 fprintf(F, "color: %d", color);
1674 fprintf (F, ENTITY_NODE_ATTR);
1675 fprintf (F, "\n info1: \"");
1677 dump_entity_to_file(F, ent, dump_verbosity_entattrs | dump_verbosity_entconsts);
1680 print_node_dbg_info(F, get_entity_dbg_info(ent));
1685 static void dump_enum_item(FILE *F, type *tp, int pos)
1688 ident *id = get_enumeration_nameid(tp, pos);
1689 tarval *tv = get_enumeration_enum(tp, pos);
1691 tarval_snprintf(buf, sizeof(buf), tv);
1692 fprintf (F, "node: {title: \"");
1693 PRINT_ITEMID(tp, pos); fprintf(F, "\"");
1694 fprintf (F, DEFAULT_ENUM_ITEM_ATTRIBUTE);
1695 fprintf (F, "label: ");
1696 fprintf (F, "\"enum item %s\" " ENUM_ITEM_NODE_ATTR, get_id_str(id));
1697 fprintf (F, "\n info1: \"value: %s\"}\n", buf);
1700 /* dumps a type or entity and it's edges. */
1702 dump_type_info(type_or_ent *tore, void *env) {
1704 int i = 0; /* to shutup gcc */
1706 /* dump this type or entity */
1708 switch (get_kind(tore)) {
1711 entity *ent = (entity *)tore;
1714 dump_entity_node(F, ent, 0);
1716 /* skip this to reduce graph. Member edge of type is parallel to this edge. *
1717 fprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
1718 ENT_OWN_EDGE_ATTR "}\n", ent, get_entity_owner(ent));*/
1719 print_ent_type_edge(F,ent, get_entity_type(ent), ENT_TYPE_EDGE_ATTR);
1720 if (is_Class_type(get_entity_owner(ent))) {
1721 for(i = 0; i < get_entity_n_overwrites(ent); i++)
1722 print_ent_ent_edge(F,ent, get_entity_overwrites(ent, i), 0, ENT_OVERWRITES_EDGE_ATTR);
1724 /* attached subgraphs */
1725 if (const_entities && (get_entity_variability(ent) != variability_uninitialized)) {
1726 if (is_atomic_entity(ent)) {
1727 value = get_atomic_ent_value(ent);
1729 print_ent_node_edge(F, ent, value, ENT_VALUE_EDGE_ATTR, i);
1730 /* DDMN(value); $$$ */
1731 dump_const_expression(F, value);
1734 if (is_compound_entity(ent)) {
1735 for (i = 0; i < get_compound_ent_n_values(ent); i++) {
1736 value = get_compound_ent_value(ent, i);
1738 print_ent_node_edge(F, ent, value, ENT_VALUE_EDGE_ATTR, i);
1739 dump_const_expression(F, value);
1740 print_ent_ent_edge(F, ent, get_compound_ent_value_member(ent, i), 0, ENT_CORR_EDGE_ATTR, i);
1742 fprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
1743 ENT_CORR_EDGE_ATTR "}\n", GET_ENTID(ent),
1744 get_compound_ent_value_member(ent, i), i);
1753 type *tp = (type *)tore;
1754 dump_type_node(F, tp);
1755 /* and now the edges */
1756 switch (get_type_tpop_code(tp)) {
1759 for (i=0; i < get_class_n_supertypes(tp); i++)
1760 print_type_type_edge(F, tp,get_class_supertype(tp, i),TYPE_SUPER_EDGE_ATTR);
1761 for (i=0; i < get_class_n_members(tp); i++)
1762 print_type_ent_edge(F,tp,get_class_member(tp, i),TYPE_MEMBER_EDGE_ATTR);
1766 for (i=0; i < get_struct_n_members(tp); i++)
1767 print_type_ent_edge(F,tp,get_struct_member(tp, i),TYPE_MEMBER_EDGE_ATTR);
1771 for (i = 0; i < get_method_n_params(tp); i++)
1772 print_type_type_edge(F,tp,get_method_param_type(tp, i),METH_PAR_EDGE_ATTR,i);
1773 for (i = 0; i < get_method_n_ress(tp); i++)
1774 print_type_type_edge(F,tp,get_method_res_type(tp, i),METH_RES_EDGE_ATTR,i);
1778 for (i = 0; i < get_union_n_members(tp); i++)
1779 print_type_ent_edge(F,tp,get_union_member(tp, i),UNION_EDGE_ATTR);
1783 print_type_type_edge(F,tp,get_array_element_type(tp),ARR_ELT_TYPE_EDGE_ATTR);
1784 print_type_ent_edge(F,tp,get_array_element_entity(tp),ARR_ENT_EDGE_ATTR);
1785 for (i = 0; i < get_array_n_dimensions(tp); i++) {
1786 ir_node *upper = get_array_upper_bound(tp, i);
1787 ir_node *lower = get_array_lower_bound(tp, i);
1788 print_node_type_edge(F, upper, tp, "label: \"upper %d\"", get_array_order(tp, i));
1789 print_node_type_edge(F, lower, tp, "label: \"lower %d\"", get_array_order(tp, i));
1790 dump_const_expression(F, upper);
1791 dump_const_expression(F, lower);
1795 case tpo_enumeration:
1797 for (i = 0; i < get_enumeration_n_enums(tp); ++i) {
1798 dump_enum_item(F, tp, i);
1799 print_enum_item_edge(F, tp, i, "label: \"item %d\"", i);
1804 print_type_type_edge(F,tp,get_pointer_points_to_type(tp), PTR_PTS_TO_EDGE_ATTR);
1812 break; /* case k_type */
1815 printf(" *** irdump, dump_type_info(l.%i), faulty type.\n", __LINE__);
1817 } /* switch kind_or_entity */
1820 typedef struct _h_env {
1825 /** For dumping class hierarchies.
1826 * Dumps a class type node and a superclass edge.
1827 * If env->dump_ent dumps entities of classes and overwrites edges.
1830 dump_class_hierarchy_node (type_or_ent *tore, void *ctx) {
1833 int i = 0; /* to shutup gcc */
1835 /* dump this type or entity */
1836 switch (get_kind(tore)) {
1838 entity *ent = (entity *)tore;
1839 if (get_entity_owner(ent) == get_glob_type()) break;
1840 if (!is_Method_type(get_entity_type(ent))) break; /* GL */
1841 if (env->dump_ent && is_Class_type(get_entity_owner(ent))) {
1843 dump_entity_node(F, ent, 0);
1845 print_type_ent_edge(F,get_entity_owner(ent),ent,TYPE_MEMBER_EDGE_ATTR);
1846 for(i = 0; i < get_entity_n_overwrites(ent); i++)
1847 print_ent_ent_edge(F, get_entity_overwrites(ent, i), ent, 0, ENT_OVERWRITES_EDGE_ATTR);
1849 } break; /* case k_entity */
1852 type *tp = (type *)tore;
1853 if (tp == get_glob_type()) break;
1854 switch (get_type_tpop_code(tp)) {
1856 dump_type_node(F, tp);
1857 /* and now the edges */
1858 for (i=0; i < get_class_n_supertypes(tp); i++)
1860 print_type_type_edge(F,tp,get_class_supertype(tp, i),TYPE_SUPER_EDGE_ATTR);
1866 break; /* case k_type */
1869 printf(" *** irdump, dump_class_hierarchy_node(l.%i), faulty type.\n", __LINE__);
1871 } /* switch kind_or_entity */
1874 /*******************************************************************/
1875 /* dump analysis information that is expressed in graph terms. */
1876 /*******************************************************************/
1878 /* dump out edges */
1880 dump_out_edge(ir_node *n, void *env) {
1883 for (i = 0; i < get_irn_n_outs(n); i++) {
1884 assert(get_irn_out(n, i));
1885 fprintf (F, "edge: {sourcename: \"");
1887 fprintf (F, "\" targetname: \"");
1888 PRINT_NODEID(get_irn_out(n, i));
1889 fprintf (F, "\" color: red linestyle: dashed");
1895 dump_loop_label(FILE *F, ir_loop *loop) {
1896 fprintf (F, "loop %d, %d sons, %d nodes",
1897 get_loop_depth(loop), get_loop_n_sons(loop), get_loop_n_nodes(loop));
1900 static INLINE void dump_loop_info(FILE *F, ir_loop *loop) {
1901 fprintf (F, " info1: \"");
1902 fprintf (F, " loop nr: %d", get_loop_loop_nr(loop));
1903 #if DEBUG_libfirm /* GL @@@ debug analyses */
1904 fprintf (F, "\n The loop was analyzed %d times.", (int)get_loop_link(loop));
1910 dump_loop_node(FILE *F, ir_loop *loop) {
1911 fprintf (F, "node: {title: \"");
1913 fprintf (F, "\" label: \"");
1914 dump_loop_label(F, loop);
1916 dump_loop_info(F, loop);
1922 dump_loop_node_edge(FILE *F, ir_loop *loop, int i) {
1924 fprintf (F, "edge: {sourcename: \"");
1926 fprintf (F, "\" targetname: \"");
1927 PRINT_NODEID(get_loop_node(loop, i));
1928 fprintf (F, "\" color: green");
1933 dump_loop_son_edge(FILE *F, ir_loop *loop, int i) {
1935 fprintf (F, "edge: {sourcename: \"");
1937 fprintf (F, "\" targetname: \"");
1938 PRINT_LOOPID(get_loop_son(loop, i));
1939 fprintf (F, "\" color: darkgreen label: \"%d\"}\n",
1940 get_loop_element_pos(loop, get_loop_son(loop, i)));
1944 void dump_loops(FILE *F, ir_loop *loop) {
1946 /* dump this loop node */
1947 dump_loop_node(F, loop);
1949 /* dump edges to nodes in loop -- only if it is a real loop */
1950 if (get_loop_depth(loop) != 0) {
1951 for (i = 0; i < get_loop_n_nodes(loop); i++) {
1952 dump_loop_node_edge(F, loop, i);
1955 for (i = 0; i < get_loop_n_sons(loop); i++) {
1956 dump_loops(F, get_loop_son(loop, i));
1957 dump_loop_son_edge(F, loop, i);
1962 void dump_loop_nodes_into_graph(FILE *F, ir_graph *irg) {
1963 ir_graph *rem = current_ir_graph;
1964 current_ir_graph = irg;
1966 if (get_irg_loop(irg)) dump_loops(F, get_irg_loop(irg));
1968 current_ir_graph = rem;
1973 * dumps the VCG header
1975 void dump_vcg_header(FILE *F, const char *name, const char *orientation) {
1984 if (!orientation) orientation = "bottom_to_top";
1988 "graph: { title: \"ir graph of %s\"\n"
1989 "display_edge_labels: %s\n"
1990 "layoutalgorithm: mindepth\n"
1991 "manhattan_edges: yes\n"
1992 "port_sharing: no\n"
1994 "classname 1: \"intrablock Data\"\n"
1995 "classname 16: \"interblock Data\"\n"
1996 "classname 2: \"Block\"\n"
1997 "classname 13: \"Control Flow\"\n"
1998 "classname 18: \"Exception Control Flow for Interval Analysis\"\n"
1999 "classname 14: \"intrablock Memory\"\n"
2000 "classname 17: \"interblock Memory\"\n"
2001 "classname 15: \"Dominators\"\n"
2002 "classname 3: \"Entity type\"\n"
2003 "classname 4: \"Entity owner\"\n"
2004 "classname 5: \"Method Param\"\n"
2005 "classname 6: \"Method Res\"\n"
2006 "classname 7: \"Super\"\n"
2007 "classname 8: \"Union\"\n"
2008 "classname 9: \"Points-to\"\n"
2009 "classname 10: \"Array Element Type\"\n"
2010 "classname 11: \"Overwrites\"\n"
2011 "classname 12: \"Member\"\n"
2012 "infoname 1: \"Attribute\"\n"
2013 "infoname 2: \"Verification errors\"\n"
2014 "infoname 3: \"Debug info\"\n",
2015 name, label, orientation);
2017 /* don't use all, the range is too whith/black. */
2021 "colorentry 100: 0 0 0\n"
2022 "colorentry 101: 20 0 0\n"
2023 "colorentry 102: 40 0 0\n"
2024 "colorentry 103: 60 0 0\n"
2025 "colorentry 104: 80 0 0\n"
2026 "colorentry 105: 100 0 0\n"
2027 "colorentry 106: 120 0 0\n"
2028 "colorentry 107: 140 0 0\n"
2029 "colorentry 108: 150 0 0\n"
2030 "colorentry 109: 180 0 0\n"
2031 "colorentry 110: 200 0 0\n"
2032 "colorentry 111: 220 0 0\n"
2033 "colorentry 112: 240 0 0\n"
2034 "colorentry 113: 255 0 0\n"
2035 "colorentry 113: 255 20 20\n"
2036 "colorentry 114: 255 40 40\n"
2037 "colorentry 115: 255 60 60\n"
2038 "colorentry 116: 255 80 80\n"
2039 "colorentry 117: 255 100 100\n"
2040 "colorentry 118: 255 120 120\n"
2041 "colorentry 119: 255 140 140\n"
2042 "colorentry 120: 255 150 150\n"
2043 "colorentry 121: 255 180 180\n"
2044 "colorentry 122: 255 200 200\n"
2045 "colorentry 123: 255 220 220\n"
2046 "colorentry 124: 255 240 240\n"
2047 "colorentry 125: 255 250 250\n"
2050 fprintf (F, "\n"); /* a separator */
2056 * @param irg The graph to be dumped
2057 * @param suffix1 first filename suffix
2058 * @param suffix2 second filename suffix
2060 FILE *vcg_open (ir_graph *irg, const char * suffix1, const char *suffix2) {
2062 const char *nm = get_irg_dump_name(irg);
2063 int len = strlen(nm), i, j;
2064 char *fname; /* filename to put the vcg information in */
2066 if (!suffix1) suffix1 = "";
2067 if (!suffix2) suffix2 = "";
2069 /* open file for vcg graph */
2070 fname = malloc (len * 2 + strlen(suffix1) + strlen(suffix2) + 5);
2072 /* strncpy (fname, nm, len); */ /* copy the filename */
2074 for (i = 0; i < len; ++i) { /* replace '/' in the name: escape by @. */
2076 fname[j] = '@'; j++; fname[j] = '1'; j++;
2077 } else if (nm[i] == '@') {
2078 fname[j] = '@'; j++; fname[j] = '2'; j++;
2080 fname[j] = nm[i]; j++;
2084 strcat (fname, suffix1); /* append file suffix */
2085 strcat (fname, suffix2); /* append file suffix */
2086 strcat (fname, ".vcg"); /* append the .vcg suffix */
2088 /* vcg really expect only a <CR> at end of line, so
2089 * the "b"inary mode is what you mean (and even needed for Win32)
2091 F = fopen (fname, "wb"); /* open file for writing */
2093 panic("cannot open %s for writing (%m)", fname); /* not reached */
2103 * @param name prefix file name
2104 * @param suffix filename suffix
2106 FILE *vcg_open_name (const char *name, const char *suffix) {
2108 char *fname; /* filename to put the vcg information in */
2109 int i, j, len = strlen(name);
2111 if (!suffix) suffix = "";
2113 /** open file for vcg graph */
2114 fname = xmalloc(len * 2 + 5 + strlen(suffix));
2115 /* strcpy (fname, name);*/ /* copy the filename */
2117 for (i = 0; i < len; ++i) { /* replace '/' in the name: escape by @. */
2118 if (name[i] == '/') {
2119 fname[j] = '@'; j++; fname[j] = '1'; j++;
2120 } else if (name[i] == '@') {
2121 fname[j] = '@'; j++; fname[j] = '2'; j++;
2123 fname[j] = name[i]; j++;
2127 strcat (fname, suffix);
2128 strcat (fname, ".vcg"); /* append the .vcg suffix */
2130 /* vcg really expect only a <CR> at end of line, so
2131 * the "b"inary mode is what you mean (and even needed for Win32)
2133 F = fopen (fname, "wb"); /* open file for writing */
2135 panic ("cannot open %s for writing (%m)", fname); /* not reached */
2143 * Dumps the vcg file footer
2145 static INLINE void dump_vcg_footer (FILE *F) {
2150 * close the vcg file
2152 void vcg_close (FILE *F) {
2153 dump_vcg_footer(F); /* print footer */
2154 fclose (F); /* close vcg file */
2157 /************************************************************************/
2158 /************************************************************************/
2159 /* Routines that dump all or parts of the firm representation to a file */
2160 /************************************************************************/
2161 /************************************************************************/
2163 /************************************************************************/
2164 /* Dump ir graphs, different formats and additional information. */
2165 /************************************************************************/
2167 /** Routine to dump a graph, blocks as conventional nodes. */
2169 dump_ir_graph (ir_graph *irg, const char *suffix )
2174 rem = current_ir_graph;
2176 if (!is_filtered_dump_name(get_entity_ident(get_irg_entity(irg)))) return;
2178 current_ir_graph = irg;
2179 if (get_interprocedural_view()) suffix1 = "-pure-ip";
2180 else suffix1 = "-pure";
2181 f = vcg_open(irg, suffix, suffix1);
2182 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
2184 /* walk over the graph */
2185 /* dump_whole_node must be called in post visiting predecessors */
2186 irg_walk(get_irg_end(irg), NULL, dump_whole_node, f);
2188 /* dump the out edges in a separate walk */
2189 if ((dump_out_edge_flag) && (get_irg_outs_state(irg) != outs_none)) {
2190 irg_out_walk(get_irg_start(irg), dump_out_edge, NULL, f);
2195 current_ir_graph = rem;
2198 /* Dump a firm graph without explicit block nodes. */
2199 void dump_ir_block_graph (ir_graph *irg, const char *suffix)
2205 if (!is_filtered_dump_name(get_entity_ident(get_irg_entity(irg))))
2208 if (get_interprocedural_view()) suffix1 = "-ip";
2210 f = vcg_open(irg, suffix, suffix1);
2211 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
2213 construct_block_lists(irg);
2216 * If we are in the interprocedural view, we dump not
2217 * only the requested irg but also all irgs that can be reached
2220 for (i = 0; i < get_irp_n_irgs(); i++) {
2221 ir_node **arr = ird_get_irg_link(get_irp_irg(i));
2223 dump_graph_from_list(f, get_irp_irg(i));
2231 /* Dump a firm graph without explicit block nodes but grouped in extended blocks. */
2232 void dump_ir_extblock_graph (ir_graph *irg, const char *suffix)
2238 if (!is_filtered_dump_name(get_entity_ident(get_irg_entity(irg))))
2243 if (get_interprocedural_view()) suffix1 = "-ip";
2245 F = vcg_open(irg, suffix, suffix1);
2246 dump_vcg_header(F, get_irg_dump_name(irg), NULL);
2248 construct_extblock_lists(irg);
2250 fprintf(F, "graph: { title: \"");
2252 fprintf(F, "\" label: \"%s\" status:clustered color:white \n",
2253 get_ent_dump_name(get_irg_entity(irg)));
2255 for (i = 0; i < get_irp_n_irgs(); i++) {
2256 ir_graph *irg = get_irp_irg(i);
2257 list_tuple *lists = ird_get_irg_link(irg);
2260 /* dump the extended blocks first */
2261 if (ARR_LEN(lists->extbb_list)) {
2262 ird_set_irg_link(irg, lists->extbb_list);
2263 dump_extblock_graph(F, irg);
2266 /* we may have blocks without extended blocks, bad for instance */
2267 if (ARR_LEN(lists->blk_list)) {
2268 ird_set_irg_link(irg, lists->blk_list);
2269 dump_block_graph(F, irg);
2272 DEL_ARR_F(lists->extbb_list);
2273 DEL_ARR_F(lists->blk_list);
2278 /* Close the vcg information for the irg */
2279 fprintf(F, "}\n\n");
2285 /* dumps a graph with type information */
2287 dump_ir_graph_w_types (ir_graph *irg, const char *suffix)
2290 ir_graph *rem = current_ir_graph;
2292 int rem_dump_const_local;
2294 /* if a filter is set, dump only the irg's that match the filter */
2295 if (!is_filtered_dump_name(get_entity_ident(get_irg_entity(irg))))
2298 current_ir_graph = irg;
2299 rem_dump_const_local = dump_const_local;
2300 /* dumping types does not work with local nodes */
2301 dump_const_local = 0;
2303 if (get_interprocedural_view()) suffix1 = "-pure-wtypes-ip";
2304 else suffix1 = "-pure-wtypes";
2305 f = vcg_open(irg,suffix, suffix1);
2306 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
2308 /* dump common ir graph */
2309 irg_walk(get_irg_end(irg), NULL, dump_whole_node, f);
2310 /* dump type info */
2311 type_walk_irg(irg, dump_type_info, NULL, f);
2312 inc_irg_visited(get_const_code_irg());
2313 /* dump edges from graph to type info */
2314 irg_walk(get_irg_end(irg), dump_node2type_edges, NULL, f);
2317 dump_const_local = rem_dump_const_local;
2318 current_ir_graph = rem;
2322 dump_ir_block_graph_w_types (ir_graph *irg, const char *suffix)
2327 ir_graph *rem = current_ir_graph;
2328 int rem_dump_const_local;
2330 /* if a filter is set, dump only the irg's that match the filter */
2331 if (!is_filtered_dump_name(get_entity_ident(get_irg_entity(irg))))
2334 rem_dump_const_local = dump_const_local;
2335 /* dumping types does not work with local nodes */
2336 dump_const_local = 0;
2338 if (get_interprocedural_view()) suffix1 = "-wtypes-ip";
2339 else suffix1 = "-wtypes";
2340 f = vcg_open(irg, suffix, suffix1);
2341 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
2343 /* dump common blocked ir graph */
2344 construct_block_lists(irg);
2346 for (i = 0; i < get_irp_n_irgs(); i++) {
2347 ir_node **arr = ird_get_irg_link(get_irp_irg(i));
2349 dump_graph_from_list(f, get_irp_irg(i));
2354 /* dump type info */
2355 current_ir_graph = irg;
2356 type_walk_irg(irg, dump_type_info, NULL, f);
2357 inc_irg_visited(get_const_code_irg());
2359 /* dump edges from graph to type info */
2360 irg_walk(get_irg_end(irg), dump_node2type_edges, NULL, f);
2363 dump_const_local = rem_dump_const_local;
2364 current_ir_graph = rem;
2367 /*---------------------------------------------------------------------*/
2368 /* The following routines dump a control flow graph. */
2369 /*---------------------------------------------------------------------*/
2372 dump_block_to_cfg(ir_node *block, void *env) {
2377 if (is_Block(block)) {
2378 /* This is a block. Dump a node for the block. */
2379 fprintf (F, "node: {title: \""); PRINT_NODEID(block);
2380 fprintf (F, "\" label: \"");
2381 if (block == get_irg_start_block(get_irn_irg(block)))
2382 fprintf(F, "Start ");
2383 if (block == get_irg_end_block(get_irn_irg(block)))
2386 fprintf (F, "%s ", get_op_name(get_irn_op(block)));
2387 PRINT_NODEID(block);
2389 fprintf(F, "info1:\"");
2392 if (dump_dominator_information_flag) {
2393 fprintf(F, "dom depth %d\n", get_Block_dom_depth(block));
2394 fprintf(F, "tree pre num %d\n", get_Block_dom_tree_pre_num(block));
2395 fprintf(F, "max subtree pre num %d\n", get_Block_dom_max_subtree_pre_num(block));
2398 /* show arity and possible Bad predecessors of the block */
2399 fprintf(F, "arity: %d\n", get_Block_n_cfgpreds(block));
2400 for (fl = i = 0; i < get_Block_n_cfgpreds(block); ++i) {
2401 ir_node *pred = get_Block_cfgpred(block, i);
2404 fprintf(F, "Bad pred at pos: ");
2405 fprintf(F, "%d ", i);
2412 /* the generic version. */
2413 dump_irnode_to_file(F, block);
2415 /* Check whether we have bad predecessors to color the block. */
2416 for (i = 0; i < get_Block_n_cfgpreds(block); ++i)
2417 if ((fl = is_Bad(get_Block_cfgpred(block, i))))
2421 fprintf (F, "\""); /* closing quote of info */
2423 if ((block == get_irg_start_block(get_irn_irg(block))) ||
2424 (block == get_irg_end_block(get_irn_irg(block))) )
2425 fprintf(F, " color:blue ");
2427 fprintf(F, " color:yellow ");
2430 /* Dump the edges */
2431 for ( i = 0; i < get_Block_n_cfgpreds(block); i++)
2432 if (get_irn_op(skip_Proj(get_Block_cfgpred(block, i))) != op_Bad) {
2433 pred = get_nodes_block(skip_Proj(get_Block_cfgpred(block, i)));
2434 fprintf (F, "edge: { sourcename: \"");
2435 PRINT_NODEID(block);
2436 fprintf (F, "\" targetname: \"");
2438 fprintf (F, "\"}\n");
2441 /* Dump dominator edge */
2442 if (dump_dominator_information_flag && get_Block_idom(block)) {
2443 pred = get_Block_idom(block);
2444 fprintf (F, "edge: { sourcename: \"");
2445 PRINT_NODEID(block);
2446 fprintf (F, "\" targetname: \"");
2448 fprintf (F, "\" " DOMINATOR_EDGE_ATTR "}\n");
2454 dump_cfg (ir_graph *irg, const char *suffix)
2457 ir_graph *rem = current_ir_graph;
2458 int ddif = dump_dominator_information_flag;
2459 int ipv = get_interprocedural_view();
2461 /* if a filter is set, dump only the irg's that match the filter */
2462 if (!is_filtered_dump_name(get_entity_ident(get_irg_entity(irg))))
2465 current_ir_graph = irg;
2467 f = vcg_open(irg, suffix, "-cfg");
2468 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
2471 printf("Warning: dumping cfg not in interprocedural view!\n");
2472 set_interprocedural_view(false);
2475 if (get_irg_dom_state(irg) != dom_consistent)
2476 dump_dominator_information_flag = 0;
2478 /* walk over the blocks in the graph */
2479 irg_block_walk(get_irg_end(irg), dump_block_to_cfg, NULL, f);
2480 dump_node(f, get_irg_bad(irg));
2482 dump_dominator_information_flag = ddif;
2483 set_interprocedural_view(ipv);
2485 current_ir_graph = rem;
2489 static void descend_and_dump(FILE *F, ir_node *n, int depth, pset *mark_set) {
2490 if (pset_find_ptr(mark_set, n)) return;
2492 pset_insert_ptr(mark_set, n);
2495 int i, start = is_Block(n) ? 0 : -1;
2496 dump_whole_node(n, F);
2497 for (i = start; i < get_irn_arity(n); ++i)
2498 descend_and_dump(F, get_irn_n(n, i), depth-1, mark_set);
2501 /* Don't dump edges to nodes further out. These might be edges to
2502 nodes we already dumped, if there is a shorter path to these. */
2506 static int subgraph_counter = 0;
2507 void dump_subgraph (ir_node *root, int depth, const char *suffix) {
2510 pset *mark_set = pset_new_ptr(1);
2511 sprintf(buf, "-subg_%03d", subgraph_counter++);
2512 F = vcg_open(get_irn_irg(root), suffix, buf);
2513 dump_vcg_header(F, get_irg_dump_name(get_irn_irg(root)), NULL);
2514 descend_and_dump(F, root, depth, mark_set);
2520 static int weight_overall(int rec, int loop) {
2521 return 2*rec + loop;
2524 static int compute_color (int my, int max) {
2531 /* if small, scale to the full color range. */
2533 my = my * (n_colors/max);
2535 step = 1 + (max / n_colors);
2539 return base_color + n_colors - color;
2542 static int get_entity_color(entity *ent) {
2543 ir_graph *irg = get_entity_irg(ent);
2547 int rec_depth = get_irg_recursion_depth(irg);
2548 int loop_depth = get_irg_loop_depth(irg);
2549 int overall_depth = weight_overall(rec_depth, loop_depth);
2551 int max_rec_depth = irp->max_callgraph_recursion_depth;
2552 int max_loop_depth = irp->max_callgraph_loop_depth;
2553 int max_overall_depth = weight_overall(max_rec_depth, max_loop_depth);
2555 /* int my_rec_color = compute_color(rec_depth, max_rec_depth); */
2556 /* int my_loop_color = compute_color(loop_depth, max_loop_depth); */
2557 int my_overall_color = compute_color(overall_depth, max_overall_depth);;
2559 return my_overall_color;
2563 void dump_callgraph(const char *suffix) {
2565 int i, n_irgs = get_irp_n_irgs();
2566 int rem = edge_label;
2568 //ident *prefix = new_id_from_str("java/");
2570 F = vcg_open_name("Callgraph", suffix);
2571 dump_vcg_header(F, "Callgraph", NULL);
2573 for (i = 0; i < n_irgs; ++i) {
2574 ir_graph *irg = get_irp_irg(i);
2575 entity *ent = get_irg_entity(irg);
2576 int j, n_callees = get_irg_n_callees(irg);
2578 /* Do not dump runtime system. */
2579 //if (id_is_prefix(prefix, get_entity_ld_ident(ent))) continue;
2581 dump_entity_node(F, ent, get_entity_color(ent));
2582 for (j = 0; j < n_callees; ++j) {
2583 entity *c = get_irg_entity(get_irg_callee(irg, j));
2584 //if (id_is_prefix(prefix, get_entity_ld_ident(c))) continue;
2585 int be = is_irg_callee_backedge(irg, j);
2588 "label:\"recursion %d\" color: %d" :
2589 "label:\"calls %d\" color: %d";
2590 print_ent_ent_edge(F, ent, c, be, attr, get_irg_callee_loop_depth(irg, j), get_entity_color(ent));
2598 /* Dump all irgs in interprocedural view to a single file. */
2599 void dump_all_cg_block_graph(const char *suffix) {
2602 int rem_view = get_interprocedural_view();
2603 set_interprocedural_view(true);
2605 f = vcg_open_name("All_graphs", suffix);
2606 dump_vcg_header(f, "All_graphs", NULL);
2608 /* collect nodes in all irgs reachable in call graph*/
2609 for (i = 0; i < get_irp_n_irgs(); i++)
2610 ird_set_irg_link(get_irp_irg(i), NULL);
2612 cg_walk(clear_link, collect_node, NULL);
2614 /* dump all graphs */
2615 for (i = 0; i < get_irp_n_irgs(); i++) {
2616 current_ir_graph = get_irp_irg(i);
2617 assert(ird_get_irg_link(current_ir_graph));
2618 dump_graph_from_list(f, current_ir_graph);
2619 DEL_ARR_F(ird_get_irg_link(current_ir_graph));
2623 set_interprocedural_view(rem_view);
2626 /*---------------------------------------------------------------------*/
2627 /* the following routines dumps type information without any ir nodes. */
2628 /*---------------------------------------------------------------------*/
2631 dump_type_graph (ir_graph *irg, const char *suffix)
2635 rem = current_ir_graph;
2637 /* if a filter is set, dump only the irg's that match the filter */
2638 if (!is_filtered_dump_name(get_entity_ident(get_irg_entity(irg)))) return;
2640 current_ir_graph = irg;
2642 f = vcg_open(irg, suffix, "-type");
2643 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
2645 /* walk over the blocks in the graph */
2646 type_walk_irg(irg, dump_type_info, NULL, f);
2647 /* The walker for the const code can be called several times for the
2648 same (sub) expression. So that no nodes are dumped several times
2649 we decrease the visited flag of the corresponding graph after each
2650 walk. So now increase it finally. */
2651 inc_irg_visited(get_const_code_irg());
2654 current_ir_graph = rem;
2658 dump_all_types (const char *suffix)
2660 FILE *f = vcg_open_name("All_types", suffix);
2661 dump_vcg_header(f, "All_types", NULL);
2662 type_walk(dump_type_info, NULL, f);
2663 inc_irg_visited(get_const_code_irg());
2668 dump_class_hierarchy (bool entities, const char *suffix)
2670 FILE *f = vcg_open_name("class_hierarchy", suffix);
2674 dump_vcg_header(f, "class_hierarchy", NULL);
2679 type_walk(dump_class_hierarchy_node, NULL, &env);
2683 /*---------------------------------------------------------------------*/
2684 /* dumps all graphs with the graph-dumper passed. Possible dumpers: */
2686 /* dump_ir_block_graph */
2688 /* dump_type_graph */
2689 /* dump_ir_graph_w_types */
2690 /*---------------------------------------------------------------------*/
2692 void dump_all_ir_graphs(dump_graph_func *dmp_grph, const char *suffix) {
2693 int i, n_irgs = get_irp_n_irgs();
2694 for (i = 0; i < n_irgs; ++i) {
2695 dmp_grph(get_irp_irg(i), suffix);
2700 /*--------------------------------------------------------------------------------*
2701 * Dumps a stand alone loop graph with firm nodes which belong to one loop node *
2702 * packed together in one subgraph/box *
2703 *--------------------------------------------------------------------------------*/
2705 void dump_loops_standalone(FILE *F, ir_loop *loop) {
2706 int i = 0, loop_node_started = 0, son_number = 0, first = 0;
2708 ir_loop *son = NULL;
2710 /* Dump a new loop node. */
2711 dump_loop_node(F, loop);
2713 /* Dump the loop elements. */
2715 for(i = 0; i < get_loop_n_elements(loop); i++) {
2716 le = get_loop_element(loop, i);
2718 if (get_kind(son) == k_ir_loop) {
2720 /* We are a loop son -> Recurse */
2722 if(loop_node_started) { /* Close the "firm-nodes" node first if we started one. */
2723 fprintf(F, "\" }\n");
2724 fprintf (F, "edge: {sourcename: \"");
2726 fprintf (F, "\" targetname: \"");
2728 fprintf (F, "-%d-nodes\" label:\"%d...%d\"}\n", first, first, i-1);
2729 loop_node_started = 0;
2731 dump_loop_son_edge(F, loop, son_number++);
2732 dump_loops_standalone(F, son);
2733 } else if (get_kind(son) == k_ir_node) {
2734 /* We are a loop node -> Collect firm nodes */
2736 ir_node *n = le.node;
2739 if (!loop_node_started) {
2740 /* Start a new node which contains all firm nodes of the current loop */
2741 fprintf (F, "node: { title: \"");
2743 fprintf (F, "-%d-nodes\" color: lightyellow label: \"", i);
2744 loop_node_started = 1;
2750 bad |= dump_node_label(F, n);
2751 /* Causes indeterministic output: if (is_Block(n)) fprintf (F, "\t ->%d", (int)get_irn_link(n)); */
2752 if (has_backedges(n)) fprintf(F, "\t loop head!");
2753 } else { /* for callgraph loop tree */
2755 assert(get_kind(son) == k_ir_graph);
2757 /* We are a loop node -> Collect firm graphs */
2758 n = (ir_graph *)le.node;
2759 if (!loop_node_started) {
2760 /* Start a new node which contains all firm nodes of the current loop */
2761 fprintf (F, "node: { title: \"");
2763 fprintf (F, "-%d-nodes\" color: lightyellow label: \"", i);
2764 loop_node_started = 1;
2769 fprintf (F, " %s", get_irg_dump_name(n));
2770 /* fprintf (F, " %s (depth %d)", get_irg_dump_name(n), n->callgraph_weighted_loop_depth); */
2774 if (loop_node_started) {
2775 fprintf(F, "\" }\n");
2776 fprintf (F, "edge: {sourcename: \"");
2778 fprintf (F, "\" targetname: \"");
2780 fprintf (F, "-%d-nodes\" label:\"%d...%d\"}\n", first, first, i-1);
2781 loop_node_started = 0;
2785 void dump_loop_tree(ir_graph *irg, const char *suffix)
2788 ir_graph *rem = current_ir_graph;
2789 int el_rem = edge_label;
2792 /* if a filter is set, dump only the irg's that match the filter */
2793 if (!is_filtered_dump_name(get_entity_ident(get_irg_entity(irg)))) return;
2795 current_ir_graph = irg;
2797 f = vcg_open(irg, suffix, "-looptree");
2798 dump_vcg_header(f, get_irg_dump_name(irg), "top_to_bottom");
2800 if (get_irg_loop(irg)) dump_loops_standalone(f, get_irg_loop(irg));
2804 edge_label = el_rem;
2805 current_ir_graph = rem;
2808 void dump_callgraph_loop_tree(const char *suffix) {
2810 F = vcg_open_name("Callgraph_looptree", suffix);
2811 dump_vcg_header(F, "callgraph looptree", "top_to_bottom");
2812 dump_loops_standalone(F, irp->outermost_cg_loop);
2817 /*-----------------------------------------------------------------------------*/
2818 /* Dumps the firm nodes in the loop tree to a graph along with the loop nodes. */
2819 /*-----------------------------------------------------------------------------*/
2821 void collect_nodeloop(FILE *F, ir_loop *loop, eset *loopnodes) {
2822 int i, son_number = 0, node_number = 0;
2824 if (dump_loop_information_flag) dump_loop_node(F, loop);
2826 for (i = 0; i < get_loop_n_elements(loop); i++) {
2827 loop_element le = get_loop_element(loop, i);
2828 if (*(le.kind) == k_ir_loop) {
2829 if (dump_loop_information_flag) dump_loop_son_edge(F, loop, son_number++);
2831 collect_nodeloop(F, le.son, loopnodes);
2833 if (dump_loop_information_flag) dump_loop_node_edge(F, loop, node_number++);
2834 eset_insert(loopnodes, le.node);
2839 void collect_nodeloop_external_nodes(ir_loop *loop, eset *loopnodes, eset *extnodes) {
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) {
2846 collect_nodeloop_external_nodes(le.son, loopnodes, extnodes);
2848 if (is_Block(le.node)) start = 0; else start = -1;
2849 for (j = start; j < get_irn_arity(le.node); j++) {
2850 ir_node *pred = get_irn_n(le.node, j);
2851 if (!eset_contains(loopnodes, pred)) {
2852 eset_insert(extnodes, pred);
2853 if (!is_Block(pred)) {
2854 pred = get_nodes_block(pred);
2855 if (!eset_contains(loopnodes, pred)) eset_insert(extnodes, pred);
2863 void dump_loop(ir_loop *l, const char *suffix) {
2866 eset *loopnodes = eset_create();
2867 eset *extnodes = eset_create();
2870 snprintf(name, sizeof(name), "loop_%d", get_loop_loop_nr(l));
2871 F = vcg_open_name (name, suffix);
2872 dump_vcg_header(F, name, NULL);
2874 /* collect all nodes to dump */
2875 collect_nodeloop(F, l, loopnodes);
2876 collect_nodeloop_external_nodes(l, loopnodes, extnodes);
2878 /* build block lists */
2879 for (n = eset_first(loopnodes); n != NULL; n = eset_next(loopnodes))
2880 set_irn_link(n, NULL);
2881 for (n = eset_first(extnodes); n != NULL; n = eset_next(extnodes))
2882 set_irn_link(n, NULL);
2883 for (n = eset_first(loopnodes); n != NULL; n = eset_next(loopnodes))
2885 b = get_nodes_block(n);
2886 set_irn_link(n, get_irn_link(b));
2889 for (n = eset_first(extnodes); n != NULL; n = eset_next(extnodes))
2891 b = get_nodes_block(n);
2892 set_irn_link(n, get_irn_link(b));
2896 for (b = eset_first(loopnodes); b != NULL; b = eset_next(loopnodes))
2898 fprintf(F, "graph: { title: \"");
2900 fprintf(F, "\" label: \"");
2901 dump_node_opcode(F, b);
2902 fprintf (F, " %ld", get_irn_node_nr(b));
2903 fprintf(F, "\" status:clustered color:yellow\n");
2905 /* dump the blocks edges */
2906 dump_ir_data_edges(F, b);
2908 /* dump the nodes that go into the block */
2909 for (n = get_irn_link(b); n; n = get_irn_link(n)) {
2910 if (eset_contains(extnodes, n)) overrule_nodecolor = "lightblue";
2912 overrule_nodecolor = NULL;
2913 if (!eset_contains(extnodes, n)) dump_ir_data_edges(F, n);
2916 /* Close the vcg information for the block */
2918 dump_const_node_local(F, b);
2921 for (b = eset_first(extnodes); b != NULL; b = eset_next(extnodes))
2923 fprintf(F, "graph: { title: \"");
2925 fprintf(F, "\" label: \"");
2926 dump_node_opcode(F, b);
2927 fprintf (F, " %ld", get_irn_node_nr(b));
2928 fprintf(F, "\" status:clustered color:lightblue\n");
2930 /* dump the nodes that go into the block */
2931 for (n = get_irn_link(b); n; n = get_irn_link(n)) {
2932 if (!eset_contains(loopnodes, n)) overrule_nodecolor = "lightblue";
2934 overrule_nodecolor = NULL;
2935 if (eset_contains(loopnodes, n)) dump_ir_data_edges(F, n);
2938 /* Close the vcg information for the block */
2940 dump_const_node_local(F, b);
2944 eset_destroy(loopnodes);
2945 eset_destroy(extnodes);