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);
880 proj_nr = get_Filter_proj(n);
881 if (! get_interprocedural_view()) {
883 pred = get_Filter_pred(n);
887 fprintf (F, "%ld ", proj_nr);
890 fprintf (F, "%s ", get_ent_dump_name(get_Sel_entity(n)));
893 fprintf (F, "(%s) ", get_type_name_ex(get_Cast_type(n), &bad));
896 fprintf (F, "%s ", get_pnc_string(get_Confirm_cmp(n)));
907 #include "execution_frequency.h"
908 #include "callgraph.h"
910 void dump_node_ana_vals(FILE *F, ir_node *n) {
912 fprintf(F, " %lf*(%2.0lf + %2.0lf) = %2.0lf ",
913 get_irn_exec_freq(n),
914 get_irg_method_execution_frequency(get_irn_irg(n)),
915 pow(5, get_irg_recursion_depth(get_irn_irg(n))),
916 get_irn_exec_freq(n) * (get_irg_method_execution_frequency(get_irn_irg(n)) + pow(5, get_irg_recursion_depth(get_irn_irg(n))))
921 /* Dumps a node label without the enclosing ". */
922 int dump_node_label(FILE *F, ir_node *n) {
925 bad |= dump_node_opcode(F, n);
926 bad |= dump_node_mode(F, n);
928 bad |= dump_node_typeinfo(F, n);
929 bad |= dump_node_nodeattr(F, n);
930 fprintf(F, "%ld", get_irn_node_nr(n));
937 * Dumps the attributes of a node n into the file F.
938 * Currently this is only the color of a node.
940 static void dump_node_vcgattr(FILE *F, ir_node *node, ir_node *local, int bad)
945 fprintf(F, "color: red");
949 if (dump_node_vcgattr_hook)
950 if (dump_node_vcgattr_hook(F, node, local))
953 n = local ? local : node;
955 switch (get_irn_opcode(n)) {
962 fprintf (F, "color: blue");
965 if (is_Block_dead(n))
966 fprintf (F, "color: lightred");
968 fprintf (F, "color: lightyellow");
971 fprintf (F, "color: green");
977 fprintf (F, "color: yellow");
980 PRINT_DEFAULT_NODE_ATTR;
983 if (overrule_nodecolor) fprintf(F, " color: %s", overrule_nodecolor);
988 * Dump the node information of a node n to a file F.
990 static INLINE int dump_node_info(FILE *F, ir_node *n)
992 fprintf (F, " info1: \"");
993 bad = dump_irnode_to_file(F, n);
999 * checks whether a node is "constant-like" ie can be treated "block-less"
1002 bool is_constlike_node(ir_node *n) {
1003 ir_op *op = get_irn_op(n);
1004 return (op == op_Const || op == op_Bad || op == op_NoMem || op == op_SymConst || op == op_Unknown);
1008 /** outputs the predecessors of n, that are constants, local. I.e.,
1009 generates a copy of the constant predecessors for each node called with. */
1010 static void dump_const_node_local(FILE *F, ir_node *n) {
1012 if (!get_opt_dump_const_local()) return;
1014 /* Use visited flag to avoid outputting nodes twice.
1015 initialize it first. */
1016 for (i = 0; i < get_irn_arity(n); i++) {
1017 ir_node *con = get_irn_n(n, i);
1018 if (is_constlike_node(con)) {
1019 set_irn_visited(con, get_irg_visited(current_ir_graph) - 1);
1023 for (i = 0; i < get_irn_arity(n); i++) {
1024 ir_node *con = get_irn_n(n, i);
1025 if (is_constlike_node(con) && irn_not_visited(con)) {
1028 mark_irn_visited(con);
1029 /* Generate a new name for the node by appending the names of
1031 fprintf(F, "node: {title: "); PRINT_CONSTID(n, con);
1032 fprintf(F, " label: \"");
1033 bad |= dump_node_label(F, con);
1035 bad |= dump_node_info(F, con);
1036 dump_node_vcgattr(F, n, con, bad);
1042 /** If the block of an edge is a const_like node, dump it local with an edge */
1043 static void dump_const_block_local(FILE *F, ir_node *n) {
1046 if (!get_opt_dump_const_local()) return;
1048 blk = get_nodes_block(n);
1049 if (is_constlike_node(blk)) {
1052 /* Generate a new name for the node by appending the names of
1054 fprintf(F, "node: {title: \""); PRINT_CONSTBLKID(n, blk);
1055 fprintf(F, "\" label: \"");
1056 bad |= dump_node_label(F, blk);
1058 bad |= dump_node_info(F, blk);
1059 dump_node_vcgattr(F, n, blk, bad);
1062 fprintf (F, "edge: { sourcename: \"");
1064 fprintf (F, "\" targetname: \""); PRINT_CONSTBLKID(n,blk);
1065 fprintf (F, "\" " BLOCK_EDGE_ATTR "}\n");
1070 * prints the error message of a node to a file F as info2.
1072 static void INLINE print_node_error(FILE *F, const char *err_msg)
1077 fprintf (F, " info2: \"%s\"", err_msg);
1081 * prints debug messages of a node to file F as info3.
1083 static void print_node_dbg_info(FILE *F, dbg_info *dbg)
1087 if (__dbg_info_snprint) {
1089 if (__dbg_info_snprint(buf, sizeof(buf), dbg) > 0)
1090 fprintf (F, " info3: \"%s\"\n", buf);
1097 static void dump_node(FILE *F, ir_node *n)
1102 if (get_opt_dump_const_local() && is_constlike_node(n))
1105 /* dump this node */
1106 fprintf(F, "node: {title: \""); PRINT_NODEID(n); fprintf(F, "\" label: \"");
1108 bad = ! irn_vrfy_irg_dump(n, current_ir_graph, &p);
1109 bad |= dump_node_label(F, n);
1110 dump_node_ana_vals(F, n);
1111 //dump_node_ana_info(F, n);
1113 bad |= dump_node_info(F, n);
1114 print_node_error(F, p);
1115 print_node_dbg_info(F, get_irn_dbg_info(n));
1116 dump_node_vcgattr(F, n, NULL, bad);
1118 dump_const_node_local(F, n);
1120 if(dump_node_edge_hook)
1121 dump_node_edge_hook(F, n);
1123 dump_irn_chi_term(F, n);
1124 dump_irn_state(F, n);
1128 /** dump the edge to the block this node belongs to */
1130 dump_ir_block_edge(FILE *F, ir_node *n) {
1131 if (get_opt_dump_const_local() && is_constlike_node(n)) return;
1132 if (is_no_Block(n)) {
1133 ir_node *block = get_nodes_block(n);
1135 if (get_opt_dump_const_local() && is_constlike_node(block)) {
1136 dump_const_block_local(F, n);
1139 fprintf (F, "edge: { sourcename: \"");
1141 fprintf (F, "\" targetname: ");
1142 fprintf(F, "\""); PRINT_NODEID(block); fprintf(F, "\"");
1143 fprintf (F, " " BLOCK_EDGE_ATTR "}\n");
1149 print_data_edge_vcgattr(FILE *F, ir_node *from, int to) {
1151 * do not use get_nodes_block() here, will fail
1152 * if the irg is not pinned.
1154 if (get_irn_n(from, -1) == get_irn_n(get_irn_n(from, to), -1))
1155 fprintf (F, INTRA_DATA_EDGE_ATTR);
1157 fprintf (F, INTER_DATA_EDGE_ATTR);
1161 print_mem_edge_vcgattr(FILE *F, ir_node *from, int to) {
1163 * do not use get_nodes_block() here, will fail
1164 * if the irg is not pinned.
1166 if (get_irn_n(from, -1) == get_irn_n(get_irn_n(from, to), -1))
1167 fprintf (F, INTRA_MEM_EDGE_ATTR);
1169 fprintf (F, INTER_MEM_EDGE_ATTR);
1173 print_edge_vcgattr(FILE *F, ir_node *from, int to) {
1176 if (dump_backedge_information_flag && is_backedge(from, to))
1177 fprintf (F, BACK_EDGE_ATTR);
1179 switch (get_irn_opcode(from)) {
1181 fprintf (F, CF_EDGE_ATTR);
1183 case iro_Start: break;
1186 if (get_irn_mode(get_End_keepalive(from, to)) == mode_BB)
1187 fprintf (F, CF_EDGE_ATTR);
1188 if (get_irn_mode(get_End_keepalive(from, to)) == mode_X)
1189 fprintf (F, INTER_MEM_EDGE_ATTR);
1197 print_data_edge_vcgattr(F, from, to);
1202 print_mem_edge_vcgattr(F, from, to);
1204 print_data_edge_vcgattr(F, from, to);
1208 print_data_edge_vcgattr(F, from, to);
1213 print_mem_edge_vcgattr(F, from, to);
1215 print_data_edge_vcgattr(F, from, to);
1222 print_data_edge_vcgattr(F, from, to);
1229 print_mem_edge_vcgattr(F, from, to);
1231 print_data_edge_vcgattr(F, from, to);
1243 print_data_edge_vcgattr(F, from, to);
1246 if (get_irn_modecode(from) == irm_M)
1247 fprintf (F, INTER_MEM_EDGE_ATTR);
1249 print_data_edge_vcgattr(F, from, to);
1256 print_mem_edge_vcgattr(F, from, to);
1258 print_data_edge_vcgattr(F, from, to);
1261 print_mem_edge_vcgattr(F, from, to);
1263 case iro_Tuple: break;
1266 switch (get_irn_modecode(from)) {
1268 fprintf (F, CF_EDGE_ATTR);
1271 fprintf (F, INTER_MEM_EDGE_ATTR);
1274 print_data_edge_vcgattr(F, from, to);
1278 case iro_Bad: break;
1279 case iro_Unknown: break;
1281 switch (get_irn_modecode(from)) {
1283 fprintf (F, INTRA_MEM_EDGE_ATTR);
1286 fprintf (F, CF_EDGE_ATTR);
1289 print_data_edge_vcgattr(F, from, to);
1297 /* dump edges to our inputs */
1299 dump_ir_data_edges(FILE *F, ir_node *n) {
1301 unsigned long visited = get_irn_visited(n);
1303 if ((get_irn_op(n) == op_End) && (!dump_keepalive))
1306 for (i = 0; i < get_irn_arity(n); i++) {
1307 ir_node * pred = get_irn_n(n, i);
1310 if ((get_interprocedural_view() && get_irn_visited(pred) < visited))
1311 continue; /* pred not dumped */
1313 if (dump_backedge_information_flag && is_backedge(n, i))
1314 fprintf (F, "backedge: {sourcename: \"");
1316 fprintf (F, "edge: {sourcename: \"");
1318 fprintf (F, "\" targetname: ");
1319 if ((get_opt_dump_const_local()) && is_constlike_node(pred)) {
1320 PRINT_CONSTID(n, pred);
1322 fprintf(F, "\""); PRINT_NODEID(pred); fprintf(F, "\"");
1324 fprintf (F, " label: \"%d\" ", i);
1325 print_edge_vcgattr(F, n, i);
1330 /** Dumps a node and its edges but not the block edge
1333 dump_node_wo_blockedge (ir_node *n, void *env) {
1336 dump_ir_data_edges(F, n);
1339 /** Dumps a node and its edges.
1342 dump_whole_node (ir_node *n, void *env) {
1344 dump_node_wo_blockedge(n, env);
1345 if (!node_floats(n)) dump_ir_block_edge(F, n);
1349 dump_const_node(ir_node *n, void *env) {
1350 if (is_Block(n)) return;
1351 dump_node_wo_blockedge(n, env);
1354 /***********************************************************************/
1355 /* the following routines dump the nodes/irgs bracketed to graphs. */
1356 /***********************************************************************/
1358 /** Dumps a constant expression as entity initializer, array bound ...
1360 static void dump_const_expression(FILE *F, ir_node *value) {
1361 ir_graph *rem = current_ir_graph;
1362 int rem_dump_const_local = dump_const_local;
1363 dump_const_local = 0;
1364 current_ir_graph = get_const_code_irg();
1365 irg_walk(value, dump_const_node, NULL, F);
1366 /* Decrease visited flag so that we walk with the same flag for the next
1367 expression. This guarantees that we don't dump the same node twice,
1368 as for const expressions cse is performed to save memory. */
1369 set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph) -1);
1370 current_ir_graph = rem;
1371 dump_const_local = rem_dump_const_local;
1374 /** Dump a block as graph containing its nodes.
1376 * Expects to find nodes belonging to the block as list in its
1378 * Dumps the edges of all nodes including itself. */
1380 dump_whole_block(FILE *F, ir_node *block) {
1382 assert(is_Block(block));
1384 fprintf(F, "graph: { title: \"");
1385 PRINT_NODEID(block);
1386 fprintf(F, "\" label: \"");
1387 dump_node_label(F, block);
1389 if (get_opt_dump_abstvals())
1390 fprintf (F, " seqno: %d", (int)get_Block_seqno(block));
1392 fprintf(F, "\" status:clustered color:%s \n",
1393 get_Block_matured(block) ? "yellow" : "red");
1395 /* dump the blocks edges */
1396 dump_ir_data_edges(F, block);
1398 /* dump the nodes that go into the block */
1399 for (node = ird_get_irn_link(block); node; node = ird_get_irn_link(node)) {
1401 dump_ir_data_edges(F, node);
1404 /* Close the vcg information for the block */
1406 dump_const_node_local(F, block);
1408 dump_irn_chi_term(F, block);
1413 /** dumps a graph block-wise. Expects all blockless nodes in arr in irgs link.
1414 * The outermost nodes: blocks and nodes not op_pin_state_pinned, Bad, Unknown. */
1416 dump_block_graph(FILE *F, ir_graph *irg) {
1418 ir_graph *rem = current_ir_graph;
1419 ir_node **arr = ird_get_irg_link(irg);
1420 current_ir_graph = irg;
1422 for (i = ARR_LEN(arr) - 1; i >= 0; --i) {
1423 ir_node * node = arr[i];
1424 if (is_Block(node)) {
1425 /* Dumps the block and all the nodes in the block, which are to
1426 be found in Block->link. */
1427 dump_whole_block(F, node);
1429 /* Nodes that are not in a Block. */
1431 if (!node_floats(node) && is_Bad(get_nodes_block(node))) {
1432 dump_const_block_local(F, node);
1434 dump_ir_data_edges(F, node);
1438 if (dump_loop_information_flag && (get_irg_loopinfo_state(irg) & loopinfo_valid))
1439 dump_loop_nodes_into_graph(F, irg);
1441 current_ir_graph = rem;
1444 /** Dumps an irg as a graph clustered by block nodes.
1445 * If interprocedural view edges can point to nodes out of this graph.
1447 static void dump_graph_from_list(FILE *F, ir_graph *irg) {
1449 fprintf(F, "graph: { title: \"");
1451 fprintf(F, "\" label: \"%s\" status:clustered color:white \n",
1452 get_ent_dump_name(get_irg_entity(irg)));
1454 dump_block_graph(F, irg);
1456 /* Close the vcg information for the irg */
1457 fprintf(F, "}\n\n");
1460 /** dumps a graph extended block-wise. Expects all blockless nodes in arr in irgs link.
1461 * The outermost nodes: blocks and nodes not op_pin_state_pinned, Bad, Unknown. */
1463 dump_extblock_graph(FILE *F, ir_graph *irg) {
1465 ir_graph *rem = current_ir_graph;
1466 ir_extblk **arr = ird_get_irg_link(irg);
1467 current_ir_graph = irg;
1470 for (i = ARR_LEN(arr) - 1; i >= 0; --i) {
1471 ir_extblk *extbb = arr[i];
1472 ir_node *leader = get_extbb_leader(extbb);
1475 fprintf(F, "graph: { title: \"");
1476 PRINT_EXTBBID(leader);
1477 fprintf(F, "\" label: \"ExtBB %ld\" status:clustered color:lightgreen\n",
1478 get_irn_node_nr(leader));
1480 for (j = ARR_LEN(extbb->blks) - 1; j >= 0; --j) {
1481 ir_node * node = extbb->blks[j];
1482 if (is_Block(node)) {
1483 /* Dumps the block and all the nodes in the block, which are to
1484 be found in Block->link. */
1485 dump_whole_block(F, node);
1487 /* Nodes that are not in a Block. */
1489 if (is_Bad(get_nodes_block(node)) && !node_floats(node)) {
1490 dump_const_block_local(F, node);
1492 dump_ir_data_edges(F, node);
1498 if (dump_loop_information_flag && (get_irg_loopinfo_state(irg) & loopinfo_valid))
1499 dump_loop_nodes_into_graph(F, irg);
1501 current_ir_graph = rem;
1506 /*******************************************************************/
1507 /* Basic type and entity nodes and edges. */
1508 /*******************************************************************/
1510 /** dumps the edges between nodes and their type or entity attributes. */
1511 static void dump_node2type_edges(ir_node *n, void *env)
1516 switch (get_irn_opcode(n)) {
1518 /* @@@ some consts have an entity */
1521 if ( (get_SymConst_kind(n) ==symconst_type_tag)
1522 || (get_SymConst_kind(n) ==symconst_size))
1524 print_node_type_edge(F,n,get_SymConst_type(n),NODE2TYPE_EDGE_ATTR);
1528 print_node_ent_edge(F,n,get_Sel_entity(n),NODE2TYPE_EDGE_ATTR);
1531 print_node_type_edge(F,n,get_Call_type(n),NODE2TYPE_EDGE_ATTR);
1534 print_node_type_edge(F,n,get_Alloc_type(n),NODE2TYPE_EDGE_ATTR);
1537 print_node_type_edge(F,n,get_Free_type(n),NODE2TYPE_EDGE_ATTR);
1540 print_node_type_edge(F,n,get_Cast_type(n),NODE2TYPE_EDGE_ATTR);
1548 static int print_type_info(FILE *F, type *tp) {
1551 if (get_type_state(tp) == layout_undefined) {
1552 fprintf(F, "state: layout_undefined\n");
1554 fprintf(F, "state: layout_fixed,\n");
1556 if (get_type_mode(tp))
1557 fprintf(F, "mode: %s,\n", get_mode_name_ex(get_type_mode(tp), &bad));
1558 fprintf(F, "size: %db,\n", get_type_size_bits(tp));
1563 static void print_typespecific_info(FILE *F, type *tp) {
1564 switch (get_type_tpop_code(tp)) {
1567 fprintf(F, "peculiarity: %s\n", get_peculiarity_string(get_class_peculiarity(tp)));
1574 fprintf(F, "variadicity: %s\n", get_variadicity_name(get_method_variadicity(tp)));
1575 fprintf(F, "params: %d\n", get_method_n_params(tp));
1576 fprintf(F, "results: %d\n", get_method_n_ress(tp));
1584 case tpo_enumeration:
1598 static void print_typespecific_vcgattr(FILE *F, type *tp) {
1599 switch (get_type_tpop_code(tp)) {
1602 if (peculiarity_existent == get_class_peculiarity(tp))
1603 fprintf (F, " " TYPE_CLASS_NODE_ATTR);
1605 fprintf (F, " " TYPE_DESCRIPTION_NODE_ATTR);
1609 fprintf (F, " " TYPE_METH_NODE_ATTR);
1620 case tpo_enumeration:
1634 int dump_type_node(FILE *F, type *tp)
1638 fprintf (F, "node: {title: ");
1640 fprintf (F, " label: \"%s %s\"", get_type_tpop_name(tp), get_type_name_ex(tp, &bad));
1641 fprintf (F, " info1: \"");
1643 bad |= print_type_info(F, tp);
1644 print_typespecific_info(F, tp);
1646 dump_type_to_file(F, tp, dump_verbosity_max);
1648 fprintf (F, "\"\n");
1649 print_node_dbg_info(F, get_type_dbg_info(tp));
1650 print_typespecific_vcgattr(F, tp);
1657 #define X(a) case a: fprintf(F, #a); break
1658 void dump_entity_node(FILE *F, entity *ent, int color)
1660 fprintf (F, "node: {title: \"");
1661 PRINT_ENTID(ent); fprintf(F, "\"");
1662 fprintf (F, DEFAULT_TYPE_ATTRIBUTE);
1663 fprintf (F, "label: ");
1664 fprintf (F, "\"ent %s\" ", get_ent_dump_name(ent));
1666 fprintf(F, "color: %d", color);
1668 fprintf (F, ENTITY_NODE_ATTR);
1669 fprintf (F, "\n info1: \"");
1671 dump_entity_to_file(F, ent, dump_verbosity_entattrs | dump_verbosity_entconsts);
1674 print_node_dbg_info(F, get_entity_dbg_info(ent));
1679 static void dump_enum_item(FILE *F, type *tp, int pos)
1682 ident *id = get_enumeration_nameid(tp, pos);
1683 tarval *tv = get_enumeration_enum(tp, pos);
1685 tarval_snprintf(buf, sizeof(buf), tv);
1686 fprintf (F, "node: {title: \"");
1687 PRINT_ITEMID(tp, pos); fprintf(F, "\"");
1688 fprintf (F, DEFAULT_ENUM_ITEM_ATTRIBUTE);
1689 fprintf (F, "label: ");
1690 fprintf (F, "\"enum item %s\" " ENUM_ITEM_NODE_ATTR, get_id_str(id));
1691 fprintf (F, "\n info1: \"value: %s\"}\n", buf);
1694 /* dumps a type or entity and it's edges. */
1696 dump_type_info(type_or_ent *tore, void *env) {
1698 int i = 0; /* to shutup gcc */
1700 /* dump this type or entity */
1702 switch (get_kind(tore)) {
1705 entity *ent = (entity *)tore;
1708 dump_entity_node(F, ent, 0);
1710 /* skip this to reduce graph. Member edge of type is parallel to this edge. *
1711 fprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
1712 ENT_OWN_EDGE_ATTR "}\n", ent, get_entity_owner(ent));*/
1713 print_ent_type_edge(F,ent, get_entity_type(ent), ENT_TYPE_EDGE_ATTR);
1714 if (is_Class_type(get_entity_owner(ent))) {
1715 for(i = 0; i < get_entity_n_overwrites(ent); i++)
1716 print_ent_ent_edge(F,ent, get_entity_overwrites(ent, i), 0, ENT_OVERWRITES_EDGE_ATTR);
1718 /* attached subgraphs */
1719 if (const_entities && (get_entity_variability(ent) != variability_uninitialized)) {
1720 if (is_atomic_entity(ent)) {
1721 value = get_atomic_ent_value(ent);
1723 print_ent_node_edge(F, ent, value, ENT_VALUE_EDGE_ATTR, i);
1724 /* DDMN(value); $$$ */
1725 dump_const_expression(F, value);
1728 if (is_compound_entity(ent)) {
1729 for (i = 0; i < get_compound_ent_n_values(ent); i++) {
1730 value = get_compound_ent_value(ent, i);
1732 print_ent_node_edge(F, ent, value, ENT_VALUE_EDGE_ATTR, i);
1733 dump_const_expression(F, value);
1734 print_ent_ent_edge(F, ent, get_compound_ent_value_member(ent, i), 0, ENT_CORR_EDGE_ATTR, i);
1736 fprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
1737 ENT_CORR_EDGE_ATTR "}\n", GET_ENTID(ent),
1738 get_compound_ent_value_member(ent, i), i);
1747 type *tp = (type *)tore;
1748 dump_type_node(F, tp);
1749 /* and now the edges */
1750 switch (get_type_tpop_code(tp)) {
1753 for (i=0; i < get_class_n_supertypes(tp); i++)
1754 print_type_type_edge(F, tp,get_class_supertype(tp, i),TYPE_SUPER_EDGE_ATTR);
1755 for (i=0; i < get_class_n_members(tp); i++)
1756 print_type_ent_edge(F,tp,get_class_member(tp, i),TYPE_MEMBER_EDGE_ATTR);
1760 for (i=0; i < get_struct_n_members(tp); i++)
1761 print_type_ent_edge(F,tp,get_struct_member(tp, i),TYPE_MEMBER_EDGE_ATTR);
1765 for (i = 0; i < get_method_n_params(tp); i++)
1766 print_type_type_edge(F,tp,get_method_param_type(tp, i),METH_PAR_EDGE_ATTR,i);
1767 for (i = 0; i < get_method_n_ress(tp); i++)
1768 print_type_type_edge(F,tp,get_method_res_type(tp, i),METH_RES_EDGE_ATTR,i);
1772 for (i = 0; i < get_union_n_members(tp); i++)
1773 print_type_ent_edge(F,tp,get_union_member(tp, i),UNION_EDGE_ATTR);
1777 print_type_type_edge(F,tp,get_array_element_type(tp),ARR_ELT_TYPE_EDGE_ATTR);
1778 print_type_ent_edge(F,tp,get_array_element_entity(tp),ARR_ENT_EDGE_ATTR);
1779 for (i = 0; i < get_array_n_dimensions(tp); i++) {
1780 ir_node *upper = get_array_upper_bound(tp, i);
1781 ir_node *lower = get_array_lower_bound(tp, i);
1782 print_node_type_edge(F, upper, tp, "label: \"upper %d\"", get_array_order(tp, i));
1783 print_node_type_edge(F, lower, tp, "label: \"lower %d\"", get_array_order(tp, i));
1784 dump_const_expression(F, upper);
1785 dump_const_expression(F, lower);
1789 case tpo_enumeration:
1791 for (i = 0; i < get_enumeration_n_enums(tp); ++i) {
1792 dump_enum_item(F, tp, i);
1793 print_enum_item_edge(F, tp, i, "label: \"item %d\"", i);
1798 print_type_type_edge(F,tp,get_pointer_points_to_type(tp), PTR_PTS_TO_EDGE_ATTR);
1806 break; /* case k_type */
1809 printf(" *** irdump, dump_type_info(l.%i), faulty type.\n", __LINE__);
1811 } /* switch kind_or_entity */
1814 typedef struct _h_env {
1819 /** For dumping class hierarchies.
1820 * Dumps a class type node and a superclass edge.
1821 * If env->dump_ent dumps entities of classes and overwrites edges.
1824 dump_class_hierarchy_node (type_or_ent *tore, void *ctx) {
1827 int i = 0; /* to shutup gcc */
1829 /* dump this type or entity */
1830 switch (get_kind(tore)) {
1832 entity *ent = (entity *)tore;
1833 if (get_entity_owner(ent) == get_glob_type()) break;
1834 if (!is_Method_type(get_entity_type(ent))) break; /* GL */
1835 if (env->dump_ent && is_Class_type(get_entity_owner(ent))) {
1837 dump_entity_node(F, ent, 0);
1839 print_type_ent_edge(F,get_entity_owner(ent),ent,TYPE_MEMBER_EDGE_ATTR);
1840 for(i = 0; i < get_entity_n_overwrites(ent); i++)
1841 print_ent_ent_edge(F, get_entity_overwrites(ent, i), ent, 0, ENT_OVERWRITES_EDGE_ATTR);
1843 } break; /* case k_entity */
1846 type *tp = (type *)tore;
1847 if (tp == get_glob_type()) break;
1848 switch (get_type_tpop_code(tp)) {
1850 dump_type_node(F, tp);
1851 /* and now the edges */
1852 for (i=0; i < get_class_n_supertypes(tp); i++)
1854 print_type_type_edge(F,tp,get_class_supertype(tp, i),TYPE_SUPER_EDGE_ATTR);
1860 break; /* case k_type */
1863 printf(" *** irdump, dump_class_hierarchy_node(l.%i), faulty type.\n", __LINE__);
1865 } /* switch kind_or_entity */
1868 /*******************************************************************/
1869 /* dump analysis information that is expressed in graph terms. */
1870 /*******************************************************************/
1872 /* dump out edges */
1874 dump_out_edge(ir_node *n, void *env) {
1877 for (i = 0; i < get_irn_n_outs(n); i++) {
1878 assert(get_irn_out(n, i));
1879 fprintf (F, "edge: {sourcename: \"");
1881 fprintf (F, "\" targetname: \"");
1882 PRINT_NODEID(get_irn_out(n, i));
1883 fprintf (F, "\" color: red linestyle: dashed");
1889 dump_loop_label(FILE *F, ir_loop *loop) {
1890 fprintf (F, "loop %d, %d sons, %d nodes",
1891 get_loop_depth(loop), get_loop_n_sons(loop), get_loop_n_nodes(loop));
1894 static INLINE void dump_loop_info(FILE *F, ir_loop *loop) {
1895 fprintf (F, " info1: \"");
1896 fprintf (F, " loop nr: %d", get_loop_loop_nr(loop));
1897 #if DEBUG_libfirm /* GL @@@ debug analyses */
1898 fprintf (F, "\n The loop was analyzed %d times.", (int)get_loop_link(loop));
1904 dump_loop_node(FILE *F, ir_loop *loop) {
1905 fprintf (F, "node: {title: \"");
1907 fprintf (F, "\" label: \"");
1908 dump_loop_label(F, loop);
1910 dump_loop_info(F, loop);
1916 dump_loop_node_edge(FILE *F, ir_loop *loop, int i) {
1918 fprintf (F, "edge: {sourcename: \"");
1920 fprintf (F, "\" targetname: \"");
1921 PRINT_NODEID(get_loop_node(loop, i));
1922 fprintf (F, "\" color: green");
1927 dump_loop_son_edge(FILE *F, ir_loop *loop, int i) {
1929 fprintf (F, "edge: {sourcename: \"");
1931 fprintf (F, "\" targetname: \"");
1932 PRINT_LOOPID(get_loop_son(loop, i));
1933 fprintf (F, "\" color: darkgreen label: \"%d\"}\n",
1934 get_loop_element_pos(loop, get_loop_son(loop, i)));
1938 void dump_loops(FILE *F, ir_loop *loop) {
1940 /* dump this loop node */
1941 dump_loop_node(F, loop);
1943 /* dump edges to nodes in loop -- only if it is a real loop */
1944 if (get_loop_depth(loop) != 0) {
1945 for (i = 0; i < get_loop_n_nodes(loop); i++) {
1946 dump_loop_node_edge(F, loop, i);
1949 for (i = 0; i < get_loop_n_sons(loop); i++) {
1950 dump_loops(F, get_loop_son(loop, i));
1951 dump_loop_son_edge(F, loop, i);
1956 void dump_loop_nodes_into_graph(FILE *F, ir_graph *irg) {
1957 ir_graph *rem = current_ir_graph;
1958 current_ir_graph = irg;
1960 if (get_irg_loop(irg)) dump_loops(F, get_irg_loop(irg));
1962 current_ir_graph = rem;
1967 * dumps the VCG header
1969 void dump_vcg_header(FILE *F, const char *name, const char *orientation) {
1978 if (!orientation) orientation = "bottom_to_top";
1982 "graph: { title: \"ir graph of %s\"\n"
1983 "display_edge_labels: %s\n"
1984 "layoutalgorithm: mindepth\n"
1985 "manhattan_edges: yes\n"
1986 "port_sharing: no\n"
1988 "classname 1: \"intrablock Data\"\n"
1989 "classname 16: \"interblock Data\"\n"
1990 "classname 2: \"Block\"\n"
1991 "classname 13: \"Control Flow\"\n"
1992 "classname 18: \"Exception Control Flow for Interval Analysis\"\n"
1993 "classname 14: \"intrablock Memory\"\n"
1994 "classname 17: \"interblock Memory\"\n"
1995 "classname 15: \"Dominators\"\n"
1996 "classname 3: \"Entity type\"\n"
1997 "classname 4: \"Entity owner\"\n"
1998 "classname 5: \"Method Param\"\n"
1999 "classname 6: \"Method Res\"\n"
2000 "classname 7: \"Super\"\n"
2001 "classname 8: \"Union\"\n"
2002 "classname 9: \"Points-to\"\n"
2003 "classname 10: \"Array Element Type\"\n"
2004 "classname 11: \"Overwrites\"\n"
2005 "classname 12: \"Member\"\n"
2006 "infoname 1: \"Attribute\"\n"
2007 "infoname 2: \"Verification errors\"\n"
2008 "infoname 3: \"Debug info\"\n",
2009 name, label, orientation);
2011 /* don't use all, the range is too whith/black. */
2015 "colorentry 100: 0 0 0\n"
2016 "colorentry 101: 20 0 0\n"
2017 "colorentry 102: 40 0 0\n"
2018 "colorentry 103: 60 0 0\n"
2019 "colorentry 104: 80 0 0\n"
2020 "colorentry 105: 100 0 0\n"
2021 "colorentry 106: 120 0 0\n"
2022 "colorentry 107: 140 0 0\n"
2023 "colorentry 108: 150 0 0\n"
2024 "colorentry 109: 180 0 0\n"
2025 "colorentry 110: 200 0 0\n"
2026 "colorentry 111: 220 0 0\n"
2027 "colorentry 112: 240 0 0\n"
2028 "colorentry 113: 255 0 0\n"
2029 "colorentry 113: 255 20 20\n"
2030 "colorentry 114: 255 40 40\n"
2031 "colorentry 115: 255 60 60\n"
2032 "colorentry 116: 255 80 80\n"
2033 "colorentry 117: 255 100 100\n"
2034 "colorentry 118: 255 120 120\n"
2035 "colorentry 119: 255 140 140\n"
2036 "colorentry 120: 255 150 150\n"
2037 "colorentry 121: 255 180 180\n"
2038 "colorentry 122: 255 200 200\n"
2039 "colorentry 123: 255 220 220\n"
2040 "colorentry 124: 255 240 240\n"
2041 "colorentry 125: 255 250 250\n"
2044 fprintf (F, "\n"); /* a separator */
2050 * @param irg The graph to be dumped
2051 * @param suffix1 first filename suffix
2052 * @param suffix2 second filename suffix
2054 FILE *vcg_open (ir_graph *irg, const char * suffix1, const char *suffix2) {
2056 const char *nm = get_irg_dump_name(irg);
2057 int len = strlen(nm), i, j;
2058 char *fname; /* filename to put the vcg information in */
2060 if (!suffix1) suffix1 = "";
2061 if (!suffix2) suffix2 = "";
2063 /* open file for vcg graph */
2064 fname = malloc (len * 2 + strlen(suffix1) + strlen(suffix2) + 5);
2066 /* strncpy (fname, nm, len); */ /* copy the filename */
2068 for (i = 0; i < len; ++i) { /* replace '/' in the name: escape by @. */
2070 fname[j] = '@'; j++; fname[j] = '1'; j++;
2071 } else if (nm[i] == '@') {
2072 fname[j] = '@'; j++; fname[j] = '2'; j++;
2074 fname[j] = nm[i]; j++;
2078 strcat (fname, suffix1); /* append file suffix */
2079 strcat (fname, suffix2); /* append file suffix */
2080 strcat (fname, ".vcg"); /* append the .vcg suffix */
2082 /* vcg really expect only a <CR> at end of line, so
2083 * the "b"inary mode is what you mean (and even needed for Win32)
2085 F = fopen (fname, "wb"); /* open file for writing */
2087 panic("cannot open %s for writing (%m)", fname); /* not reached */
2097 * @param name prefix file name
2098 * @param suffix filename suffix
2100 FILE *vcg_open_name (const char *name, const char *suffix) {
2102 char *fname; /* filename to put the vcg information in */
2103 int i, j, len = strlen(name);
2105 if (!suffix) suffix = "";
2107 /** open file for vcg graph */
2108 fname = xmalloc(len * 2 + 5 + strlen(suffix));
2109 /* strcpy (fname, name);*/ /* copy the filename */
2111 for (i = 0; i < len; ++i) { /* replace '/' in the name: escape by @. */
2112 if (name[i] == '/') {
2113 fname[j] = '@'; j++; fname[j] = '1'; j++;
2114 } else if (name[i] == '@') {
2115 fname[j] = '@'; j++; fname[j] = '2'; j++;
2117 fname[j] = name[i]; j++;
2121 strcat (fname, suffix);
2122 strcat (fname, ".vcg"); /* append the .vcg suffix */
2124 /* vcg really expect only a <CR> at end of line, so
2125 * the "b"inary mode is what you mean (and even needed for Win32)
2127 F = fopen (fname, "wb"); /* open file for writing */
2129 panic ("cannot open %s for writing (%m)", fname); /* not reached */
2137 * Dumps the vcg file footer
2139 static INLINE void dump_vcg_footer (FILE *F) {
2144 * close the vcg file
2146 void vcg_close (FILE *F) {
2147 dump_vcg_footer(F); /* print footer */
2148 fclose (F); /* close vcg file */
2151 /************************************************************************/
2152 /************************************************************************/
2153 /* Routines that dump all or parts of the firm representation to a file */
2154 /************************************************************************/
2155 /************************************************************************/
2157 /************************************************************************/
2158 /* Dump ir graphs, different formats and additional information. */
2159 /************************************************************************/
2161 /** Routine to dump a graph, blocks as conventional nodes. */
2163 dump_ir_graph (ir_graph *irg, const char *suffix )
2168 rem = current_ir_graph;
2170 if (!is_filtered_dump_name(get_entity_ident(get_irg_entity(irg)))) return;
2172 current_ir_graph = irg;
2173 if (get_interprocedural_view()) suffix1 = "-pure-ip";
2174 else suffix1 = "-pure";
2175 f = vcg_open(irg, suffix, suffix1);
2176 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
2178 /* walk over the graph */
2179 /* dump_whole_node must be called in post visiting predecessors */
2180 irg_walk(get_irg_end(irg), NULL, dump_whole_node, f);
2182 /* dump the out edges in a separate walk */
2183 if ((dump_out_edge_flag) && (get_irg_outs_state(irg) != outs_none)) {
2184 irg_out_walk(get_irg_start(irg), dump_out_edge, NULL, f);
2189 current_ir_graph = rem;
2192 /* Dump a firm graph without explicit block nodes. */
2193 void dump_ir_block_graph (ir_graph *irg, const char *suffix)
2199 if (!is_filtered_dump_name(get_entity_ident(get_irg_entity(irg))))
2202 if (get_interprocedural_view()) suffix1 = "-ip";
2204 f = vcg_open(irg, suffix, suffix1);
2205 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
2207 construct_block_lists(irg);
2210 * If we are in the interprocedural view, we dump not
2211 * only the requested irg but also all irgs that can be reached
2214 for (i = 0; i < get_irp_n_irgs(); i++) {
2215 ir_node **arr = ird_get_irg_link(get_irp_irg(i));
2217 dump_graph_from_list(f, get_irp_irg(i));
2225 /* Dump a firm graph without explicit block nodes but grouped in extended blocks. */
2226 void dump_ir_extblock_graph (ir_graph *irg, const char *suffix)
2232 if (!is_filtered_dump_name(get_entity_ident(get_irg_entity(irg))))
2237 if (get_interprocedural_view()) suffix1 = "-ip";
2239 F = vcg_open(irg, suffix, suffix1);
2240 dump_vcg_header(F, get_irg_dump_name(irg), NULL);
2242 construct_extblock_lists(irg);
2244 fprintf(F, "graph: { title: \"");
2246 fprintf(F, "\" label: \"%s\" status:clustered color:white \n",
2247 get_ent_dump_name(get_irg_entity(irg)));
2249 for (i = 0; i < get_irp_n_irgs(); i++) {
2250 ir_graph *irg = get_irp_irg(i);
2251 list_tuple *lists = ird_get_irg_link(irg);
2254 /* dump the extended blocks first */
2255 if (ARR_LEN(lists->extbb_list)) {
2256 ird_set_irg_link(irg, lists->extbb_list);
2257 dump_extblock_graph(F, irg);
2260 /* we may have blocks without extended blocks, bad for instance */
2261 if (ARR_LEN(lists->blk_list)) {
2262 ird_set_irg_link(irg, lists->blk_list);
2263 dump_block_graph(F, irg);
2266 DEL_ARR_F(lists->extbb_list);
2267 DEL_ARR_F(lists->blk_list);
2272 /* Close the vcg information for the irg */
2273 fprintf(F, "}\n\n");
2279 /* dumps a graph with type information */
2281 dump_ir_graph_w_types (ir_graph *irg, const char *suffix)
2284 ir_graph *rem = current_ir_graph;
2286 int rem_dump_const_local;
2288 /* if a filter is set, dump only the irg's that match the filter */
2289 if (!is_filtered_dump_name(get_entity_ident(get_irg_entity(irg))))
2292 current_ir_graph = irg;
2293 rem_dump_const_local = dump_const_local;
2294 /* dumping types does not work with local nodes */
2295 dump_const_local = 0;
2297 if (get_interprocedural_view()) suffix1 = "-pure-wtypes-ip";
2298 else suffix1 = "-pure-wtypes";
2299 f = vcg_open(irg,suffix, suffix1);
2300 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
2302 /* dump common ir graph */
2303 irg_walk(get_irg_end(irg), NULL, dump_whole_node, f);
2304 /* dump type info */
2305 type_walk_irg(irg, dump_type_info, NULL, f);
2306 inc_irg_visited(get_const_code_irg());
2307 /* dump edges from graph to type info */
2308 irg_walk(get_irg_end(irg), dump_node2type_edges, NULL, f);
2311 dump_const_local = rem_dump_const_local;
2312 current_ir_graph = rem;
2316 dump_ir_block_graph_w_types (ir_graph *irg, const char *suffix)
2321 ir_graph *rem = current_ir_graph;
2322 int rem_dump_const_local;
2324 /* if a filter is set, dump only the irg's that match the filter */
2325 if (!is_filtered_dump_name(get_entity_ident(get_irg_entity(irg))))
2328 rem_dump_const_local = dump_const_local;
2329 /* dumping types does not work with local nodes */
2330 dump_const_local = 0;
2332 if (get_interprocedural_view()) suffix1 = "-wtypes-ip";
2333 else suffix1 = "-wtypes";
2334 f = vcg_open(irg, suffix, suffix1);
2335 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
2337 /* dump common blocked ir graph */
2338 construct_block_lists(irg);
2340 for (i = 0; i < get_irp_n_irgs(); i++) {
2341 ir_node **arr = ird_get_irg_link(get_irp_irg(i));
2343 dump_graph_from_list(f, get_irp_irg(i));
2348 /* dump type info */
2349 current_ir_graph = irg;
2350 type_walk_irg(irg, dump_type_info, NULL, f);
2351 inc_irg_visited(get_const_code_irg());
2353 /* dump edges from graph to type info */
2354 irg_walk(get_irg_end(irg), dump_node2type_edges, NULL, f);
2357 dump_const_local = rem_dump_const_local;
2358 current_ir_graph = rem;
2361 /*---------------------------------------------------------------------*/
2362 /* The following routines dump a control flow graph. */
2363 /*---------------------------------------------------------------------*/
2366 dump_block_to_cfg(ir_node *block, void *env) {
2371 if (is_Block(block)) {
2372 /* This is a block. Dump a node for the block. */
2373 fprintf (F, "node: {title: \""); PRINT_NODEID(block);
2374 fprintf (F, "\" label: \"");
2375 if (block == get_irg_start_block(get_irn_irg(block)))
2376 fprintf(F, "Start ");
2377 if (block == get_irg_end_block(get_irn_irg(block)))
2380 fprintf (F, "%s ", get_op_name(get_irn_op(block)));
2381 PRINT_NODEID(block);
2383 fprintf(F, "info1:\"");
2386 if (dump_dominator_information_flag) {
2387 fprintf(F, "dom depth %d\n", get_Block_dom_depth(block));
2388 fprintf(F, "tree pre num %d\n", get_Block_dom_tree_pre_num(block));
2389 fprintf(F, "max subtree pre num %d\n", get_Block_dom_max_subtree_pre_num(block));
2392 /* show arity and possible Bad predecessors of the block */
2393 fprintf(F, "arity: %d\n", get_Block_n_cfgpreds(block));
2394 for (fl = i = 0; i < get_Block_n_cfgpreds(block); ++i) {
2395 ir_node *pred = get_Block_cfgpred(block, i);
2398 fprintf(F, "Bad pred at pos: ");
2399 fprintf(F, "%d ", i);
2406 /* the generic version. */
2407 dump_irnode_to_file(F, block);
2409 /* Check whether we have bad predecessors to color the block. */
2410 for (i = 0; i < get_Block_n_cfgpreds(block); ++i)
2411 if ((fl = is_Bad(get_Block_cfgpred(block, i))))
2415 fprintf (F, "\""); /* closing quote of info */
2417 if ((block == get_irg_start_block(get_irn_irg(block))) ||
2418 (block == get_irg_end_block(get_irn_irg(block))) )
2419 fprintf(F, " color:blue ");
2421 fprintf(F, " color:yellow ");
2424 /* Dump the edges */
2425 for ( i = 0; i < get_Block_n_cfgpreds(block); i++)
2426 if (get_irn_op(skip_Proj(get_Block_cfgpred(block, i))) != op_Bad) {
2427 pred = get_nodes_block(skip_Proj(get_Block_cfgpred(block, i)));
2428 fprintf (F, "edge: { sourcename: \"");
2429 PRINT_NODEID(block);
2430 fprintf (F, "\" targetname: \"");
2432 fprintf (F, "\"}\n");
2435 /* Dump dominator edge */
2436 if (dump_dominator_information_flag && get_Block_idom(block)) {
2437 pred = get_Block_idom(block);
2438 fprintf (F, "edge: { sourcename: \"");
2439 PRINT_NODEID(block);
2440 fprintf (F, "\" targetname: \"");
2442 fprintf (F, "\" " DOMINATOR_EDGE_ATTR "}\n");
2448 dump_cfg (ir_graph *irg, const char *suffix)
2451 ir_graph *rem = current_ir_graph;
2452 int ddif = dump_dominator_information_flag;
2453 int ipv = get_interprocedural_view();
2455 /* if a filter is set, dump only the irg's that match the filter */
2456 if (!is_filtered_dump_name(get_entity_ident(get_irg_entity(irg))))
2459 current_ir_graph = irg;
2461 f = vcg_open(irg, suffix, "-cfg");
2462 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
2465 printf("Warning: dumping cfg not in interprocedural view!\n");
2466 set_interprocedural_view(false);
2469 if (get_irg_dom_state(irg) != dom_consistent)
2470 dump_dominator_information_flag = 0;
2472 /* walk over the blocks in the graph */
2473 irg_block_walk(get_irg_end(irg), dump_block_to_cfg, NULL, f);
2474 dump_node(f, get_irg_bad(irg));
2476 dump_dominator_information_flag = ddif;
2477 set_interprocedural_view(ipv);
2479 current_ir_graph = rem;
2483 static void descend_and_dump(FILE *F, ir_node *n, int depth, pset *mark_set) {
2484 if (pset_find_ptr(mark_set, n)) return;
2486 pset_insert_ptr(mark_set, n);
2489 int i, start = is_Block(n) ? 0 : -1;
2490 dump_whole_node(n, F);
2491 for (i = start; i < get_irn_arity(n); ++i)
2492 descend_and_dump(F, get_irn_n(n, i), depth-1, mark_set);
2495 /* Don't dump edges to nodes further out. These might be edges to
2496 nodes we already dumped, if there is a shorter path to these. */
2500 static int subgraph_counter = 0;
2501 void dump_subgraph (ir_node *root, int depth, const char *suffix) {
2504 pset *mark_set = pset_new_ptr(1);
2505 sprintf(buf, "-subg_%03d", subgraph_counter++);
2506 F = vcg_open(get_irn_irg(root), suffix, buf);
2507 dump_vcg_header(F, get_irg_dump_name(get_irn_irg(root)), NULL);
2508 descend_and_dump(F, root, depth, mark_set);
2514 static int weight_overall(int rec, int loop) {
2515 return 2*rec + loop;
2518 static int compute_color (int my, int max) {
2525 /* if small, scale to the full color range. */
2527 my = my * (n_colors/max);
2529 step = 1 + (max / n_colors);
2533 return base_color + n_colors - color;
2536 static int get_entity_color(entity *ent) {
2537 ir_graph *irg = get_entity_irg(ent);
2541 int rec_depth = get_irg_recursion_depth(irg);
2542 int loop_depth = get_irg_loop_depth(irg);
2543 int overall_depth = weight_overall(rec_depth, loop_depth);
2545 int max_rec_depth = irp->max_callgraph_recursion_depth;
2546 int max_loop_depth = irp->max_callgraph_loop_depth;
2547 int max_overall_depth = weight_overall(max_rec_depth, max_loop_depth);
2549 /* int my_rec_color = compute_color(rec_depth, max_rec_depth); */
2550 /* int my_loop_color = compute_color(loop_depth, max_loop_depth); */
2551 int my_overall_color = compute_color(overall_depth, max_overall_depth);;
2553 return my_overall_color;
2557 void dump_callgraph(const char *suffix) {
2559 int i, n_irgs = get_irp_n_irgs();
2560 int rem = edge_label;
2562 //ident *prefix = new_id_from_str("java/");
2564 F = vcg_open_name("Callgraph", suffix);
2565 dump_vcg_header(F, "Callgraph", NULL);
2567 for (i = 0; i < n_irgs; ++i) {
2568 ir_graph *irg = get_irp_irg(i);
2569 entity *ent = get_irg_entity(irg);
2570 int j, n_callees = get_irg_n_callees(irg);
2572 /* Do not dump runtime system. */
2573 //if (id_is_prefix(prefix, get_entity_ld_ident(ent))) continue;
2575 dump_entity_node(F, ent, get_entity_color(ent));
2576 for (j = 0; j < n_callees; ++j) {
2577 entity *c = get_irg_entity(get_irg_callee(irg, j));
2578 //if (id_is_prefix(prefix, get_entity_ld_ident(c))) continue;
2579 int be = is_irg_callee_backedge(irg, j);
2582 "label:\"recursion %d\" color: %d" :
2583 "label:\"calls %d\" color: %d";
2584 print_ent_ent_edge(F, ent, c, be, attr, get_irg_callee_loop_depth(irg, j), get_entity_color(ent));
2592 /* Dump all irgs in interprocedural view to a single file. */
2593 void dump_all_cg_block_graph(const char *suffix) {
2596 int rem_view = get_interprocedural_view();
2597 set_interprocedural_view(true);
2599 f = vcg_open_name("All_graphs", suffix);
2600 dump_vcg_header(f, "All_graphs", NULL);
2602 /* collect nodes in all irgs reachable in call graph*/
2603 for (i = 0; i < get_irp_n_irgs(); i++)
2604 ird_set_irg_link(get_irp_irg(i), NULL);
2606 cg_walk(clear_link, collect_node, NULL);
2608 /* dump all graphs */
2609 for (i = 0; i < get_irp_n_irgs(); i++) {
2610 current_ir_graph = get_irp_irg(i);
2611 assert(ird_get_irg_link(current_ir_graph));
2612 dump_graph_from_list(f, current_ir_graph);
2613 DEL_ARR_F(ird_get_irg_link(current_ir_graph));
2617 set_interprocedural_view(rem_view);
2620 /*---------------------------------------------------------------------*/
2621 /* the following routines dumps type information without any ir nodes. */
2622 /*---------------------------------------------------------------------*/
2625 dump_type_graph (ir_graph *irg, const char *suffix)
2629 rem = current_ir_graph;
2631 /* if a filter is set, dump only the irg's that match the filter */
2632 if (!is_filtered_dump_name(get_entity_ident(get_irg_entity(irg)))) return;
2634 current_ir_graph = irg;
2636 f = vcg_open(irg, suffix, "-type");
2637 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
2639 /* walk over the blocks in the graph */
2640 type_walk_irg(irg, dump_type_info, NULL, f);
2641 /* The walker for the const code can be called several times for the
2642 same (sub) expression. So that no nodes are dumped several times
2643 we decrease the visited flag of the corresponding graph after each
2644 walk. So now increase it finally. */
2645 inc_irg_visited(get_const_code_irg());
2648 current_ir_graph = rem;
2652 dump_all_types (const char *suffix)
2654 FILE *f = vcg_open_name("All_types", suffix);
2655 dump_vcg_header(f, "All_types", NULL);
2656 type_walk(dump_type_info, NULL, f);
2657 inc_irg_visited(get_const_code_irg());
2662 dump_class_hierarchy (bool entities, const char *suffix)
2664 FILE *f = vcg_open_name("class_hierarchy", suffix);
2668 dump_vcg_header(f, "class_hierarchy", NULL);
2673 type_walk(dump_class_hierarchy_node, NULL, &env);
2677 /*---------------------------------------------------------------------*/
2678 /* dumps all graphs with the graph-dumper passed. Possible dumpers: */
2680 /* dump_ir_block_graph */
2682 /* dump_type_graph */
2683 /* dump_ir_graph_w_types */
2684 /*---------------------------------------------------------------------*/
2686 void dump_all_ir_graphs(dump_graph_func *dmp_grph, const char *suffix) {
2687 int i, n_irgs = get_irp_n_irgs();
2688 for (i = 0; i < n_irgs; ++i) {
2689 dmp_grph(get_irp_irg(i), suffix);
2694 /*--------------------------------------------------------------------------------*
2695 * Dumps a stand alone loop graph with firm nodes which belong to one loop node *
2696 * packed together in one subgraph/box *
2697 *--------------------------------------------------------------------------------*/
2699 void dump_loops_standalone(FILE *F, ir_loop *loop) {
2700 int i = 0, loop_node_started = 0, son_number = 0, first = 0;
2702 ir_loop *son = NULL;
2704 /* Dump a new loop node. */
2705 dump_loop_node(F, loop);
2707 /* Dump the loop elements. */
2709 for(i = 0; i < get_loop_n_elements(loop); i++) {
2710 le = get_loop_element(loop, i);
2712 if (get_kind(son) == k_ir_loop) {
2714 /* We are a loop son -> Recurse */
2716 if(loop_node_started) { /* Close the "firm-nodes" node first if we started one. */
2717 fprintf(F, "\" }\n");
2718 fprintf (F, "edge: {sourcename: \"");
2720 fprintf (F, "\" targetname: \"");
2722 fprintf (F, "-%d-nodes\" label:\"%d...%d\"}\n", first, first, i-1);
2723 loop_node_started = 0;
2725 dump_loop_son_edge(F, loop, son_number++);
2726 dump_loops_standalone(F, son);
2727 } else if (get_kind(son) == k_ir_node) {
2728 /* We are a loop node -> Collect firm nodes */
2730 ir_node *n = le.node;
2733 if (!loop_node_started) {
2734 /* Start a new node which contains all firm nodes of the current loop */
2735 fprintf (F, "node: { title: \"");
2737 fprintf (F, "-%d-nodes\" color: lightyellow label: \"", i);
2738 loop_node_started = 1;
2744 bad |= dump_node_label(F, n);
2745 /* Causes indeterministic output: if (is_Block(n)) fprintf (F, "\t ->%d", (int)get_irn_link(n)); */
2746 if (has_backedges(n)) fprintf(F, "\t loop head!");
2747 } else { /* for callgraph loop tree */
2749 assert(get_kind(son) == k_ir_graph);
2751 /* We are a loop node -> Collect firm graphs */
2752 n = (ir_graph *)le.node;
2753 if (!loop_node_started) {
2754 /* Start a new node which contains all firm nodes of the current loop */
2755 fprintf (F, "node: { title: \"");
2757 fprintf (F, "-%d-nodes\" color: lightyellow label: \"", i);
2758 loop_node_started = 1;
2763 fprintf (F, " %s", get_irg_dump_name(n));
2764 /* fprintf (F, " %s (depth %d)", get_irg_dump_name(n), n->callgraph_weighted_loop_depth); */
2768 if (loop_node_started) {
2769 fprintf(F, "\" }\n");
2770 fprintf (F, "edge: {sourcename: \"");
2772 fprintf (F, "\" targetname: \"");
2774 fprintf (F, "-%d-nodes\" label:\"%d...%d\"}\n", first, first, i-1);
2775 loop_node_started = 0;
2779 void dump_loop_tree(ir_graph *irg, const char *suffix)
2782 ir_graph *rem = current_ir_graph;
2783 int el_rem = edge_label;
2786 /* if a filter is set, dump only the irg's that match the filter */
2787 if (!is_filtered_dump_name(get_entity_ident(get_irg_entity(irg)))) return;
2789 current_ir_graph = irg;
2791 f = vcg_open(irg, suffix, "-looptree");
2792 dump_vcg_header(f, get_irg_dump_name(irg), "top_to_bottom");
2794 if (get_irg_loop(irg)) dump_loops_standalone(f, get_irg_loop(irg));
2798 edge_label = el_rem;
2799 current_ir_graph = rem;
2802 void dump_callgraph_loop_tree(const char *suffix) {
2804 F = vcg_open_name("Callgraph_looptree", suffix);
2805 dump_vcg_header(F, "callgraph looptree", "top_to_bottom");
2806 dump_loops_standalone(F, irp->outermost_cg_loop);
2811 /*-----------------------------------------------------------------------------*/
2812 /* Dumps the firm nodes in the loop tree to a graph along with the loop nodes. */
2813 /*-----------------------------------------------------------------------------*/
2815 void collect_nodeloop(FILE *F, ir_loop *loop, eset *loopnodes) {
2816 int i, son_number = 0, node_number = 0;
2818 if (dump_loop_information_flag) dump_loop_node(F, loop);
2820 for (i = 0; i < get_loop_n_elements(loop); i++) {
2821 loop_element le = get_loop_element(loop, i);
2822 if (*(le.kind) == k_ir_loop) {
2823 if (dump_loop_information_flag) dump_loop_son_edge(F, loop, son_number++);
2825 collect_nodeloop(F, le.son, loopnodes);
2827 if (dump_loop_information_flag) dump_loop_node_edge(F, loop, node_number++);
2828 eset_insert(loopnodes, le.node);
2833 void collect_nodeloop_external_nodes(ir_loop *loop, eset *loopnodes, eset *extnodes) {
2836 for(i = 0; i < get_loop_n_elements(loop); i++) {
2837 loop_element le = get_loop_element(loop, i);
2838 if (*(le.kind) == k_ir_loop) {
2840 collect_nodeloop_external_nodes(le.son, loopnodes, extnodes);
2842 if (is_Block(le.node)) start = 0; else start = -1;
2843 for (j = start; j < get_irn_arity(le.node); j++) {
2844 ir_node *pred = get_irn_n(le.node, j);
2845 if (!eset_contains(loopnodes, pred)) {
2846 eset_insert(extnodes, pred);
2847 if (!is_Block(pred)) {
2848 pred = get_nodes_block(pred);
2849 if (!eset_contains(loopnodes, pred)) eset_insert(extnodes, pred);
2857 void dump_loop(ir_loop *l, const char *suffix) {
2860 eset *loopnodes = eset_create();
2861 eset *extnodes = eset_create();
2864 snprintf(name, sizeof(name), "loop_%d", get_loop_loop_nr(l));
2865 F = vcg_open_name (name, suffix);
2866 dump_vcg_header(F, name, NULL);
2868 /* collect all nodes to dump */
2869 collect_nodeloop(F, l, loopnodes);
2870 collect_nodeloop_external_nodes(l, loopnodes, extnodes);
2872 /* build block lists */
2873 for (n = eset_first(loopnodes); n != NULL; n = eset_next(loopnodes))
2874 set_irn_link(n, NULL);
2875 for (n = eset_first(extnodes); n != NULL; n = eset_next(extnodes))
2876 set_irn_link(n, NULL);
2877 for (n = eset_first(loopnodes); n != NULL; n = eset_next(loopnodes))
2879 b = get_nodes_block(n);
2880 set_irn_link(n, get_irn_link(b));
2883 for (n = eset_first(extnodes); n != NULL; n = eset_next(extnodes))
2885 b = get_nodes_block(n);
2886 set_irn_link(n, get_irn_link(b));
2890 for (b = eset_first(loopnodes); b != NULL; b = eset_next(loopnodes))
2892 fprintf(F, "graph: { title: \"");
2894 fprintf(F, "\" label: \"");
2895 dump_node_opcode(F, b);
2896 fprintf (F, " %ld", get_irn_node_nr(b));
2897 fprintf(F, "\" status:clustered color:yellow\n");
2899 /* dump the blocks edges */
2900 dump_ir_data_edges(F, b);
2902 /* dump the nodes that go into the block */
2903 for (n = get_irn_link(b); n; n = get_irn_link(n)) {
2904 if (eset_contains(extnodes, n)) overrule_nodecolor = "lightblue";
2906 overrule_nodecolor = NULL;
2907 if (!eset_contains(extnodes, n)) dump_ir_data_edges(F, n);
2910 /* Close the vcg information for the block */
2912 dump_const_node_local(F, b);
2915 for (b = eset_first(extnodes); b != NULL; b = eset_next(extnodes))
2917 fprintf(F, "graph: { title: \"");
2919 fprintf(F, "\" label: \"");
2920 dump_node_opcode(F, b);
2921 fprintf (F, " %ld", get_irn_node_nr(b));
2922 fprintf(F, "\" status:clustered color:lightblue\n");
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(loopnodes, n)) overrule_nodecolor = "lightblue";
2928 overrule_nodecolor = NULL;
2929 if (eset_contains(loopnodes, n)) dump_ir_data_edges(F, n);
2932 /* Close the vcg information for the block */
2934 dump_const_node_local(F, b);
2938 eset_destroy(loopnodes);
2939 eset_destroy(extnodes);