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"
37 #include "type_or_entity.h"
41 #include "callgraph.h"
42 #include "irextbb_t.h"
43 #include "dbginfo_t.h"
55 extern void dump_irn_chi_term(FILE *FL, ir_node *n);
56 extern void dump_irn_state(FILE *FL, ir_node *n);
57 extern int get_opt_dump_abstvals(void);
58 typedef unsigned long SeqNo;
59 extern SeqNo get_Block_seqno(ir_node *n);
62 /* basis for a color range for vcg */
63 static int n_colors = 0;
64 static int base_color = 0;
66 /** Dump only irgs with names that start with this string */
67 static ident *dump_file_filter_id = NULL;
69 #define ERROR_TXT "<ERROR>"
71 /*******************************************************************/
72 /* flags to steer output */
73 /*******************************************************************/
75 /** An option to turn off edge labels */
76 static int edge_label = 1;
77 /** An option to turn off dumping values of constant entities */
78 static int const_entities = 1;
79 /** An option to dump the keep alive edges */
80 static int dump_keepalive = 0;
81 /** An option to dump ld_names instead of names. */
82 static int dump_ld_name = 1;
83 /** Compiler options to dump analysis information in dump_ir_graph */
84 static int dump_out_edge_flag = 0;
85 static int dump_loop_information_flag = 0;
86 static int dump_backedge_information_flag = 1;
87 static int dump_const_local = 0;
88 /** An option to dump all graph anchors */
89 static int dump_anchors = 0;
91 int dump_dominator_information_flag = 0;
92 int opt_dump_analysed_type_info = 1;
93 int opt_dump_pointer_values_to_info = 0; /* default off: for test compares!! */
95 static dumper_colors overrule_nodecolor = ird_color_default;
97 /** An additional edge hook. */
98 static DUMP_NODE_EDGE_FUNC dump_node_edge_hook = NULL;
100 void set_dump_node_edge_hook(DUMP_NODE_EDGE_FUNC func)
102 dump_node_edge_hook = func;
105 DUMP_NODE_EDGE_FUNC get_dump_node_edge_hook(void)
107 return dump_node_edge_hook;
111 /** The vcg node attribute hook. */
112 static DUMP_IR_GRAPH_FUNC dump_ir_graph_hook = NULL;
113 /** The vcg node attribute hook. */
114 static DUMP_NODE_VCGATTR_FUNC dump_node_vcgattr_hook = NULL;
115 /** The vcg edge attribute hook. */
116 static DUMP_EDGE_VCGATTR_FUNC dump_edge_vcgattr_hook = NULL;
118 /* set the ir graph hook */
119 void set_dump_ir_graph_hook(DUMP_IR_GRAPH_FUNC hook) {
120 dump_ir_graph_hook = hook;
122 /* set the node attribute hook */
123 void set_dump_node_vcgattr_hook(DUMP_NODE_VCGATTR_FUNC hook) {
124 dump_node_vcgattr_hook = hook;
126 /* set the edge attribute hook */
127 void set_dump_edge_vcgattr_hook(DUMP_EDGE_VCGATTR_FUNC hook) {
128 dump_edge_vcgattr_hook = hook;
131 int get_opt_dump_const_local(void) {
132 if (!dump_out_edge_flag && !dump_loop_information_flag)
133 return dump_const_local;
138 void only_dump_method_with_name(ident *name) {
139 dump_file_filter_id = name;
142 ident *get_dump_file_filter_ident(void) {
143 return dump_file_filter_id;
146 /** Returns non-zero if dump file filter is not set, or if it is a
148 int is_filtered_dump_name(ident *name) {
149 if (!dump_file_filter_id) return 1;
150 return id_is_prefix(dump_file_filter_id, name);
153 /* To turn off display of edge labels. Edge labels often cause xvcg to
154 abort with a segmentation fault. */
155 void turn_off_edge_labels(void) {
159 void dump_consts_local(int flag) {
160 dump_const_local = flag;
163 void dump_constant_entity_values(int flag) {
164 const_entities = flag;
167 void dump_keepalive_edges(int flag) {
168 dump_keepalive = flag;
171 int get_opt_dump_keepalive_edges(void) {
172 return dump_keepalive;
175 void dump_out_edges(int flag) {
176 dump_out_edge_flag = flag;
179 void dump_dominator_information(int flag) {
180 dump_dominator_information_flag = flag;
183 void dump_loop_information(int flag) {
184 dump_loop_information_flag = flag;
187 void dump_backedge_information(int flag) {
188 dump_backedge_information_flag = flag;
191 /* Dump the information of type field specified in ana/irtypeinfo.h.
192 * If the flag is set, the type name is output in [] in the node label,
193 * else it is output as info.
195 void set_opt_dump_analysed_type_info(int flag) {
196 opt_dump_analysed_type_info = flag;
199 void dump_pointer_values_to_info(int flag) {
200 opt_dump_pointer_values_to_info = flag;
203 void dump_ld_names(int flag) {
207 void dump_all_anchors(int flag) {
211 /* -------------- some extended helper functions ----------------- */
214 * returns the name of a mode or <ERROR> if mode is NOT a mode object.
215 * in the later case, sets bad
217 const char *get_mode_name_ex(ir_mode *mode, int *bad)
220 return get_mode_name(mode);
226 * returns the name of a type or <ERROR> if mode is NOT a mode object.
227 * in the later case, sets bad
229 const char *get_type_name_ex(ir_type *tp, int *bad)
232 return get_type_name(tp);
238 * printf the VCG color
240 static void print_vcg_color(FILE *F, dumper_colors color) {
241 static const char *color_names[32] = {
242 "white", "blue", "red", "green",
243 "yellow", "magenta", "cyan", "darkgray",
244 "darkblue", "darkred", "darkgreen", "darkyellow",
245 "darkmagenta", "darkcyan", "gold", "lightgray",
246 "lightblue", "lightred", "lightgreen", "lightyellow",
247 "lightmagenta", "lightcyan", "lilac", "turquoise",
248 "aquamarine", "khaki", "purple", "yellowgreen",
249 "pink", "orange", "orchid", "black"
252 if (color != ird_color_default)
253 fprintf(F, "color:%s", color_names[color]);
257 * prints the edge from a type S to a type T with additional info fmt, ...
260 static void print_type_type_edge(FILE *F, ir_type *S, ir_type *T, const char *fmt, ...)
265 fprintf(F, "edge: { sourcename: "); PRINT_TYPEID(S);
266 fprintf(F, " targetname: "); PRINT_TYPEID(T);
267 vfprintf(F, fmt, ap);
273 * prints the edge from a type T to an entity E with additional info fmt, ...
276 static void print_type_ent_edge(FILE *F, ir_type *T, entity *E, const char *fmt, ...)
281 fprintf(F, "edge: { sourcename: "); PRINT_TYPEID(T);
282 fprintf(F, " targetname: \""); PRINT_ENTID(E); fprintf(F, "\"");
283 vfprintf(F, fmt, ap);
289 * prints the edge from an entity E to an entity T with additional info fmt, ...
292 static void print_ent_ent_edge(FILE *F, entity *E, entity *T, int backedge, const char *fmt, ...)
298 fprintf(F, "backedge: { sourcename: \"");
300 fprintf(F, "edge: { sourcename: \"");
302 fprintf(F, "\" targetname: \""); PRINT_ENTID(T); fprintf(F, "\"");
303 vfprintf(F, fmt, ap);
309 * prints the edge from an entity E to a type T with additional info fmt, ...
312 static void print_ent_type_edge(FILE *F, entity *E, ir_type *T, const char *fmt, ...)
317 fprintf(F, "edge: { sourcename: \""); PRINT_ENTID(E);
318 fprintf(F, "\" targetname: "); PRINT_TYPEID(T);
319 vfprintf(F, fmt, ap);
325 * prints the edge from a node N to a type T with additional info fmt, ...
328 static void print_node_type_edge(FILE *F, const ir_node *N, ir_type *T, const char *fmt, ...)
333 fprintf(F, "edge: { sourcename: \""); PRINT_NODEID(N);
334 fprintf(F, "\" targetname: "); PRINT_TYPEID(T);
335 vfprintf(F, fmt, ap);
341 * prints the edge from a node N to an entity E with additional info fmt, ...
344 static void print_node_ent_edge(FILE *F, const ir_node *N, entity *E, const char *fmt, ...)
349 fprintf(F, "edge: { sourcename: \""); PRINT_NODEID(N);
350 fprintf(F, "\" targetname: \""); PRINT_ENTID(E);
352 vfprintf(F, fmt, ap);
358 * prints the edge from an entity E to a node N with additional info fmt, ...
361 static void print_ent_node_edge(FILE *F, entity *E, const ir_node *N, const char *fmt, ...)
366 fprintf(F, "edge: { sourcename: \""); PRINT_ENTID(E);
367 fprintf(F, "\" targetname: \""); PRINT_NODEID(N); fprintf(F, "\"");
368 vfprintf(F, fmt, ap);
374 * prints the edge from a type E to an enumeration item item with additional info fmt, ...
377 static void print_enum_item_edge(FILE *F, ir_type *E, int item, const char *fmt, ...)
382 fprintf(F, "edge: { sourcename: "); PRINT_TYPEID(E);
383 fprintf(F, " targetname: \""); PRINT_ITEMID(E, item); fprintf(F, "\" ");
384 vfprintf(F, fmt, ap);
389 /*-----------------------------------------------------------------*/
390 /* global and ahead declarations */
391 /*-----------------------------------------------------------------*/
393 static void dump_whole_node(ir_node *n, void *env);
394 static INLINE void dump_loop_nodes_into_graph(FILE *F, ir_graph *irg);
396 /*-----------------------------------------------------------------*/
397 /* Helper functions. */
398 /*-----------------------------------------------------------------*/
401 * This map is used as a private link attr to be able to call dumper
402 * anywhere without destroying link fields.
404 static pmap *irdump_link_map = NULL;
406 /** NOT A STANDARD LIBFIRM INIT METHOD
408 * We do not want to integrate dumping into libfirm, i.e., if the dumpers
409 * are off, we want to have as few interferences as possible. Therefore the
410 * initialization is performed lazily and not called from within init_firm.
412 * Creates the link attribute map. */
413 static void init_irdump(void) {
414 /* We need a new, empty map. */
415 if (irdump_link_map) pmap_destroy(irdump_link_map);
416 irdump_link_map = pmap_create();
417 if (!dump_file_filter_id)
418 dump_file_filter_id = new_id_from_str("");
421 * Returns the private link field.
423 static void *ird_get_irn_link(ir_node *n) {
425 if (!irdump_link_map) return NULL;
427 if (pmap_contains(irdump_link_map, (void *)n))
428 res = pmap_get(irdump_link_map, (void *)n);
433 * Sets the private link field.
435 static void ird_set_irn_link(ir_node *n, void *x) {
436 if (!irdump_link_map)
438 pmap_insert(irdump_link_map, (void *)n, x);
442 * Gets the private link field of an irg.
444 static void *ird_get_irg_link(ir_graph *irg) {
446 if (!irdump_link_map) return NULL;
448 if (pmap_contains(irdump_link_map, (void *)irg))
449 res = pmap_get(irdump_link_map, (void *)irg);
454 * Sets the private link field of an irg.
456 static void ird_set_irg_link(ir_graph *irg, void *x) {
457 if (!irdump_link_map) init_irdump();
458 pmap_insert(irdump_link_map, (void *)irg, x);
462 * Walker, clears the private link field.
464 static void clear_link(ir_node * node, void * env) {
465 ird_set_irn_link(node, NULL);
469 * If the entity has a ld_name, returns it if the dump_ld_name is set,
470 * else returns the name of the entity.
472 static const char *_get_ent_dump_name(entity *ent, int dump_ld_name) {
474 return "<NULL entity>";
476 /* Don't use get_entity_ld_ident (ent) as it computes the mangled name! */
477 if (ent->ld_name) return get_id_str(ent->ld_name);
479 return get_id_str(ent->name);
483 * If the entity has a ld_name, returns it if the option dump_ld_name is set,
484 * else returns the name of the entity.
486 const char *get_ent_dump_name(entity *ent) {
487 return _get_ent_dump_name(ent, dump_ld_name);
490 /* Returns the name of an IRG. */
491 const char *get_irg_dump_name(ir_graph *irg) {
492 /* Don't use get_entity_ld_ident (ent) as it computes the mangled name! */
493 return _get_ent_dump_name(get_irg_entity(irg), 1);
497 * Returns non-zero if a node is in floating state.
499 static int node_floats(ir_node *n) {
500 return ((get_irn_pinned(n) == op_pin_state_floats) &&
501 (get_irg_pinned(current_ir_graph) == op_pin_state_floats));
505 * Walker that visits the anchors
507 static void ird_walk_graph(ir_graph *irg, irg_walk_func *pre, irg_walk_func *post, void *env) {
508 irg_walk_graph(irg, pre, post, env);
513 for (i = anchor_max - 1; i >= 0; --i) {
514 ir_node *n = irg->anchors[i];
517 /* reset the visit flag: will be increase in the walker */
518 set_irg_visited(irg, get_irg_visited(irg) - 1);
519 irg_walk(n, pre, post, env);
526 * Walker, allocates an array for all blocks and puts it's nodes non-floating nodes into this array.
528 static void collect_node(ir_node * node, void *env) {
531 || get_irn_op(node) == op_Bad
532 || get_irn_op(node) == op_Unknown
533 || get_irn_op(node) == op_NoMem) {
534 ir_node ** arr = (ir_node **) ird_get_irg_link(get_irn_irg(node));
535 if (!arr) arr = NEW_ARR_F(ir_node *, 0);
536 ARR_APP1(ir_node *, arr, node);
537 ird_set_irg_link(get_irn_irg(node), arr); /* arr is an l-value, APP_ARR might change it! */
539 ir_node * block = get_nodes_block(node);
542 /* this node is in a Bad block, so we must place it into the graph's list */
543 ir_node ** arr = (ir_node **) ird_get_irg_link(get_irn_irg(node));
544 if (!arr) arr = NEW_ARR_F(ir_node *, 0);
545 ARR_APP1(ir_node *, arr, node);
546 ird_set_irg_link(get_irn_irg(node), arr); /* arr is an l-value, APP_ARR might change it! */
549 ird_set_irn_link(node, ird_get_irn_link(block));
550 ird_set_irn_link(block, node);
555 /** Construct lists to walk ir block-wise.
557 * Collects all blocks, nodes not op_pin_state_pinned,
558 * Bad, NoMem and Unknown into a flexible array in link field of
559 * irg they belong to. Sets the irg link field to NULL in all
560 * graphs not visited.
561 * Free the list with DEL_ARR_F().
563 static ir_node **construct_block_lists(ir_graph *irg) {
564 int i, rem_view = get_interprocedural_view();
565 ir_graph *rem = current_ir_graph;
566 current_ir_graph = irg;
568 for (i = get_irp_n_irgs() - 1; i >= 0; --i)
569 ird_set_irg_link(get_irp_irg(i), NULL);
571 ird_walk_graph(current_ir_graph, clear_link, collect_node, current_ir_graph);
573 /* Collect also EndReg and EndExcept. We do not want to change the walker. */
574 set_interprocedural_view(0);
576 set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph)-1);
577 irg_walk(get_irg_end_reg(current_ir_graph), clear_link, collect_node, current_ir_graph);
578 set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph)-1);
579 irg_walk(get_irg_end_except(current_ir_graph), clear_link, collect_node, current_ir_graph);
581 set_interprocedural_view(rem_view);
583 current_ir_graph = rem;
584 return ird_get_irg_link(irg);
587 typedef struct _list_tuple {
589 ir_extblk **extbb_list;
592 /** Construct lists to walk IR extended block-wise.
593 * Free the lists in the tuple with DEL_ARR_F().
594 * Sets the irg link field to NULL in all
595 * graphs not visited.
597 static list_tuple *construct_extblock_lists(ir_graph *irg) {
598 ir_node **blk_list = construct_block_lists(irg);
600 ir_graph *rem = current_ir_graph;
601 list_tuple *lists = xmalloc(sizeof(*lists));
603 current_ir_graph = irg;
605 lists->blk_list = NEW_ARR_F(ir_node *, 0);
606 lists->extbb_list = NEW_ARR_F(ir_extblk *, 0);
608 inc_irg_block_visited(irg);
609 for (i = ARR_LEN(blk_list) - 1; i >= 0; --i) {
612 if (is_Block(blk_list[i])) {
613 ext = get_Block_extbb(blk_list[i]);
615 if (extbb_not_visited(ext)) {
616 ARR_APP1(ir_extblk *, lists->extbb_list, ext);
617 mark_extbb_visited(ext);
621 ARR_APP1(ir_node *, lists->blk_list, blk_list[i]);
625 current_ir_graph = rem;
626 ird_set_irg_link(irg, lists);
630 /*-----------------------------------------------------------------*/
631 /* Routines to dump information about a single ir node. */
632 /*-----------------------------------------------------------------*/
635 * dump the name of a node n to the File F.
637 int dump_node_opcode(FILE *F, ir_node *n)
640 const ir_op_ops *ops = get_op_ops(get_irn_op(n));
642 /* call the dump_node operation if available */
644 return ops->dump_node(n, F, dump_node_opcode_txt);
646 /* implementation for default nodes */
647 switch (get_irn_opcode(n)) {
652 res = tarval_snprintf(buf, sizeof(buf), get_Const_tarval(n));
653 assert(res < sizeof(buf) && "buffer to small for tarval_snprintf");
658 if (get_SymConst_kind(n) == symconst_addr_name) {
659 /* don't use get_SymConst_ptr_info as it mangles the name. */
660 fprintf (F, "SymC %s", get_id_str(get_SymConst_name(n)));
661 } else if (get_SymConst_kind(n) == symconst_addr_ent) {
662 assert(get_SymConst_entity(n));
663 assert(is_entity(get_SymConst_entity(n)));
664 fprintf (F, "SymC &%s", get_entity_name(get_SymConst_entity(n)));
666 assert(get_kind(get_SymConst_type(n)) == k_type);
667 assert(get_type_ident(get_SymConst_type(n)));
668 fprintf (F, "SymC %s ", get_type_name_ex(get_SymConst_type(n), &bad));
669 if (get_SymConst_kind(n) == symconst_type_tag)
677 if (!get_interprocedural_view())
684 ir_node *pred = get_Proj_pred(n);
686 if (get_irn_opcode(pred) == iro_Cond
687 && get_Proj_proj(n) == get_Cond_defaultProj(pred)
688 && get_irn_mode(get_Cond_selector(pred)) != mode_b)
689 fprintf (F, "defProj");
697 if (get_interprocedural_view()) {
698 fprintf(F, "%s %s", get_irn_opname(n), get_ent_dump_name(get_irg_entity(get_irn_irg(n))));
703 case iro_CallBegin: {
704 ir_node *addr = get_CallBegin_ptr(n);
706 if (get_irn_op(addr) == op_Sel)
707 ent = get_Sel_entity(addr);
708 else if ((get_irn_op(addr) == op_SymConst) && (get_SymConst_kind(addr) == symconst_addr_ent))
709 ent = get_SymConst_entity(addr);
710 fprintf (F, "%s", get_irn_opname(n));
711 if (ent) fprintf (F, " %s", get_entity_name(ent));
715 fprintf (F, "%s[%s]", get_irn_opname(n), get_mode_name_ex(get_Load_mode(n), &bad));
718 fprintf (F, "%s%s", is_Block_dead(n) ? "Dead " : "", get_irn_opname(n));
723 fprintf (F, "%s", get_irn_opname(n));
730 * Dump the mode of a node n to a file F.
731 * Ignore modes that are "always known".
733 static int dump_node_mode(FILE *F, ir_node *n)
736 const ir_op_ops *ops = get_op_ops(get_irn_op(n));
739 /* call the dump_node operation if available */
741 return ops->dump_node(n, F, dump_node_mode_txt);
743 /* default implementation */
744 iro = get_irn_opcode(n);
756 ir_mode *mode = get_irn_mode(n);
758 if (mode && mode != mode_BB && mode != mode_ANY && mode != mode_BAD &&
759 (mode != mode_T || iro == iro_Proj))
760 fprintf(F, "%s", get_mode_name_ex(mode, &bad));
768 * Dump the type of a node n to a file F if it's known.
770 static int dump_node_typeinfo(FILE *F, ir_node *n) {
773 if (opt_dump_analysed_type_info) {
774 if (get_irg_typeinfo_state(current_ir_graph) == ir_typeinfo_consistent ||
775 get_irg_typeinfo_state(current_ir_graph) == ir_typeinfo_inconsistent) {
776 ir_type *tp = get_irn_typeinfo_type(n);
777 if (tp != firm_none_type)
778 fprintf(F, "[%s] ", get_type_name_ex(tp, &bad));
786 typedef struct _pns_lookup {
787 long nr; /**< the proj number */
788 const char *name; /**< the name of the Proj */
791 typedef struct _proj_lookup {
792 opcode code; /**< the opcode of the Proj predecessor */
793 unsigned num_data; /**< number of data entries */
794 const pns_lookup_t *data; /**< the data */
797 #define ARR_SIZE(a) (sizeof(a)/sizeof(a[0]))
799 /** the lookup table for Proj(Start) names */
800 static const pns_lookup_t start_lut[] = {
801 #define X(a) { pn_Start_##a, #a }
810 /** the lookup table for Proj(Cond) names */
811 static const pns_lookup_t cond_lut[] = {
812 #define X(a) { pn_Cond_##a, #a }
818 /** the lookup table for Proj(Call) names */
819 static const pns_lookup_t call_lut[] = {
820 #define X(a) { pn_Call_##a, #a }
829 /** the lookup table for Proj(Quot) names */
830 static const pns_lookup_t quot_lut[] = {
831 #define X(a) { pn_Quot_##a, #a }
838 /** the lookup table for Proj(DivMod) names */
839 static const pns_lookup_t divmod_lut[] = {
840 #define X(a) { pn_DivMod_##a, #a }
848 /** the lookup table for Proj(Div) names */
849 static const pns_lookup_t div_lut[] = {
850 #define X(a) { pn_Div_##a, #a }
857 /** the lookup table for Proj(Mod) names */
858 static const pns_lookup_t mod_lut[] = {
859 #define X(a) { pn_Mod_##a, #a }
866 /** the lookup table for Proj(Load) names */
867 static const pns_lookup_t load_lut[] = {
868 #define X(a) { pn_Load_##a, #a }
875 /** the lookup table for Proj(Store) names */
876 static const pns_lookup_t store_lut[] = {
877 #define X(a) { pn_Store_##a, #a }
883 /** the lookup table for Proj(Alloc) names */
884 static const pns_lookup_t alloc_lut[] = {
885 #define X(a) { pn_Alloc_##a, #a }
892 /** the lookup table for Proj(CopyB) names */
893 static const pns_lookup_t copyb_lut[] = {
894 #define X(a) { pn_CopyB_##a, #a }
901 /** the lookup table for Proj(InstOf) names */
902 static const pns_lookup_t instof_lut[] = {
903 #define X(a) { pn_InstOf_##a, #a }
911 /** the lookup table for Proj(Raise) names */
912 static const pns_lookup_t raise_lut[] = {
913 #define X(a) { pn_Raise_##a, #a }
919 /** the lookup table for Proj(Bound) names */
920 static const pns_lookup_t bound_lut[] = {
921 #define X(a) { pn_Bound_##a, #a }
929 /** the Proj lookup table */
930 static const proj_lookup_t proj_lut[] = {
931 #define E(a) ARR_SIZE(a), a
932 { iro_Start, E(start_lut) },
933 { iro_Cond, E(cond_lut) },
934 { iro_Call, E(call_lut) },
935 { iro_Quot, E(quot_lut) },
936 { iro_DivMod, E(divmod_lut) },
937 { iro_Div, E(div_lut) },
938 { iro_Mod, E(mod_lut) },
939 { iro_Load, E(load_lut) },
940 { iro_Store, E(store_lut) },
941 { iro_Alloc, E(alloc_lut) },
942 { iro_CopyB, E(copyb_lut) },
943 { iro_InstOf, E(instof_lut) },
944 { iro_Raise, E(raise_lut) },
945 { iro_Bound, E(bound_lut) }
950 * Dump additional node attributes of some nodes to a file F.
953 dump_node_nodeattr(FILE *F, ir_node *n)
959 const ir_op_ops *ops = get_op_ops(get_irn_op(n));
961 /* call the dump_node operation if available */
963 return ops->dump_node(n, F, dump_node_nodeattr_txt);
965 switch (get_irn_opcode(n)) {
967 if (0 && get_interprocedural_view()) {
968 fprintf (F, "%s ", get_ent_dump_name(get_irg_entity(current_ir_graph)));
973 pred = get_Proj_pred(n);
974 proj_nr = get_Proj_proj(n);
976 code = get_irn_opcode(pred);
979 fprintf (F, "%s ", get_pnc_string(get_Proj_proj(n)));
980 else if (code == iro_Proj && get_irn_opcode(get_Proj_pred(pred)) == iro_Start)
981 fprintf (F, "Arg %ld ", proj_nr);
982 else if (code == iro_Cond && get_irn_mode(get_Cond_selector(pred)) != mode_b)
983 fprintf (F, "%ld ", proj_nr);
985 unsigned i, j, f = 0;
987 for (i = 0; i < ARR_SIZE(proj_lut); ++i) {
988 if (code == proj_lut[i].code) {
989 for (j = 0; j < proj_lut[i].num_data; ++j) {
990 if (proj_nr == proj_lut[i].data[j].nr) {
991 fprintf (F, "%s ", proj_lut[i].data[j].name);
1000 fprintf (F, "%ld ", proj_nr);
1001 if (code == iro_Cond && get_Cond_jmp_pred(pred) != COND_JMP_PRED_NONE) {
1002 if (proj_nr == pn_Cond_false && get_Cond_jmp_pred(pred) == COND_JMP_PRED_FALSE)
1003 fprintf(F, "PRED ");
1004 if (proj_nr == pn_Cond_true && get_Cond_jmp_pred(pred) == COND_JMP_PRED_TRUE)
1005 fprintf(F, "PRED ");
1010 proj_nr = get_Filter_proj(n);
1011 if (! get_interprocedural_view()) {
1013 pred = get_Filter_pred(n);
1017 fprintf (F, "%ld ", proj_nr);
1020 fprintf (F, "%s ", get_ent_dump_name(get_Sel_entity(n)));
1023 fprintf (F, "(%s) ", get_type_name_ex(get_Cast_type(n), &bad));
1026 fprintf (F, "%s ", get_pnc_string(get_Confirm_cmp(n)));
1029 fprintf (F, "(%s) ", get_type_name_ex(get_CopyB_type(n), &bad));
1040 #include "execution_frequency.h"
1041 #include "callgraph.h"
1043 void dump_node_ana_vals(FILE *F, ir_node *n) {
1045 fprintf(F, " %lf*(%2.0lf + %2.0lf) = %2.0lf ",
1046 get_irn_exec_freq(n),
1047 get_irg_method_execution_frequency(get_irn_irg(n)),
1048 pow(5, get_irg_recursion_depth(get_irn_irg(n))),
1049 get_irn_exec_freq(n) * (get_irg_method_execution_frequency(get_irn_irg(n)) + pow(5, get_irg_recursion_depth(get_irn_irg(n))))
1054 /* Dumps a node label without the enclosing ". */
1055 int dump_node_label(FILE *F, ir_node *n) {
1058 bad |= dump_node_opcode(F, n);
1059 bad |= dump_node_mode(F, n);
1061 bad |= dump_node_typeinfo(F, n);
1062 bad |= dump_node_nodeattr(F, n);
1063 fprintf(F, "%ld", get_irn_node_nr(n));
1070 * Dumps the attributes of a node n into the file F.
1071 * Currently this is only the color of a node.
1073 static void dump_node_vcgattr(FILE *F, ir_node *node, ir_node *local, int bad)
1078 print_vcg_color(F, ird_color_red);
1082 if (dump_node_vcgattr_hook)
1083 if (dump_node_vcgattr_hook(F, node, local))
1086 n = local ? local : node;
1088 if (overrule_nodecolor != ird_color_default) {
1089 print_vcg_color(F, overrule_nodecolor);
1093 switch (get_irn_opcode(n)) {
1100 print_vcg_color(F, ird_color_blue);
1103 if (is_Block_dead(n))
1104 print_vcg_color(F, ird_color_lightred);
1106 print_vcg_color(F, ird_color_lightyellow);
1109 print_vcg_color(F, ird_color_green);
1113 print_vcg_color(F, ird_color_gold);
1119 print_vcg_color(F, ird_color_yellow);
1122 PRINT_DEFAULT_NODE_ATTR;
1128 * Dump the node information of a node n to a file F.
1130 static INLINE int dump_node_info(FILE *F, ir_node *n)
1133 const ir_op_ops *ops = get_op_ops(get_irn_op(n));
1135 fprintf (F, " info1: \"");
1136 bad = dump_irnode_to_file(F, n);
1137 /* call the dump_node operation if available */
1139 bad = ops->dump_node(n, F, dump_node_info_txt);
1146 * checks whether a node is "constant-like" ie can be treated "block-less"
1149 int is_constlike_node(ir_node *n) {
1150 ir_op *op = get_irn_op(n);
1151 return (op == op_Const || op == op_Bad || op == op_NoMem || op == op_SymConst || op == op_Unknown);
1155 /** outputs the predecessors of n, that are constants, local. I.e.,
1156 generates a copy of the constant predecessors for each node called with. */
1157 static void dump_const_node_local(FILE *F, ir_node *n) {
1159 if (!get_opt_dump_const_local()) return;
1161 /* Use visited flag to avoid outputting nodes twice.
1162 initialize it first. */
1163 for (i = 0; i < get_irn_arity(n); i++) {
1164 ir_node *con = get_irn_n(n, i);
1165 if (is_constlike_node(con)) {
1166 set_irn_visited(con, get_irg_visited(current_ir_graph) - 1);
1170 for (i = 0; i < get_irn_arity(n); i++) {
1171 ir_node *con = get_irn_n(n, i);
1172 if (is_constlike_node(con) && irn_not_visited(con)) {
1175 mark_irn_visited(con);
1176 /* Generate a new name for the node by appending the names of
1178 fprintf(F, "node: {title: "); PRINT_CONSTID(n, con);
1179 fprintf(F, " label: \"");
1180 bad |= dump_node_label(F, con);
1182 bad |= dump_node_info(F, con);
1183 dump_node_vcgattr(F, n, con, bad);
1189 /** If the block of an edge is a const_like node, dump it local with an edge */
1190 static void dump_const_block_local(FILE *F, ir_node *n) {
1193 if (!get_opt_dump_const_local()) return;
1195 blk = get_nodes_block(n);
1196 if (is_constlike_node(blk)) {
1199 /* Generate a new name for the node by appending the names of
1201 fprintf(F, "node: {title: \""); PRINT_CONSTBLKID(n, blk);
1202 fprintf(F, "\" label: \"");
1203 bad |= dump_node_label(F, blk);
1205 bad |= dump_node_info(F, blk);
1206 dump_node_vcgattr(F, n, blk, bad);
1209 fprintf (F, "edge: { sourcename: \"");
1211 fprintf (F, "\" targetname: \""); PRINT_CONSTBLKID(n,blk);
1213 if (dump_edge_vcgattr_hook) {
1215 if (dump_edge_vcgattr_hook(F, n, -1)) {
1220 fprintf (F, " " BLOCK_EDGE_ATTR "}\n");
1225 fprintf (F, "\" " BLOCK_EDGE_ATTR "}\n");
1230 * prints the error message of a node to a file F as info2.
1232 static void INLINE print_node_error(FILE *F, const char *err_msg)
1237 fprintf (F, " info2: \"%s\"", err_msg);
1241 * prints debug messages of a node to file F as info3.
1243 static void print_dbg_info(FILE *F, dbg_info *dbg)
1247 if (__dbg_info_snprint) {
1249 if (__dbg_info_snprint(buf, sizeof(buf), dbg) > 0)
1250 fprintf (F, " info3: \"%s\"\n", buf);
1257 static void dump_node(FILE *F, ir_node *n)
1262 if (get_opt_dump_const_local() && is_constlike_node(n))
1265 /* dump this node */
1266 fprintf(F, "node: {title: \""); PRINT_NODEID(n); fprintf(F, "\" label: \"");
1268 bad = ! irn_vrfy_irg_dump(n, current_ir_graph, &p);
1269 bad |= dump_node_label(F, n);
1270 dump_node_ana_vals(F, n);
1271 //dump_node_ana_info(F, n);
1273 bad |= dump_node_info(F, n);
1274 print_node_error(F, p);
1275 print_dbg_info(F, get_irn_dbg_info(n));
1276 dump_node_vcgattr(F, n, NULL, bad);
1278 dump_const_node_local(F, n);
1280 if(dump_node_edge_hook)
1281 dump_node_edge_hook(F, n);
1283 dump_irn_chi_term(F, n);
1284 dump_irn_state(F, n);
1288 /** dump the edge to the block this node belongs to */
1290 dump_ir_block_edge(FILE *F, ir_node *n) {
1291 if (get_opt_dump_const_local() && is_constlike_node(n)) return;
1292 if (is_no_Block(n)) {
1293 ir_node *block = get_nodes_block(n);
1295 if (get_opt_dump_const_local() && is_constlike_node(block)) {
1296 dump_const_block_local(F, n);
1299 fprintf (F, "edge: { sourcename: \"");
1301 fprintf (F, "\" targetname: ");
1302 fprintf(F, "\""); PRINT_NODEID(block); fprintf(F, "\"");
1304 if (dump_edge_vcgattr_hook) {
1306 if (dump_edge_vcgattr_hook(F, n, -1)) {
1311 fprintf (F, " " BLOCK_EDGE_ATTR "}\n");
1316 fprintf (F, " " BLOCK_EDGE_ATTR "}\n");
1322 print_data_edge_vcgattr(FILE *F, ir_node *from, int to) {
1324 * do not use get_nodes_block() here, will fail
1325 * if the irg is not pinned.
1327 if (get_irn_n(from, -1) == get_irn_n(get_irn_n(from, to), -1))
1328 fprintf (F, INTRA_DATA_EDGE_ATTR);
1330 fprintf (F, INTER_DATA_EDGE_ATTR);
1334 print_mem_edge_vcgattr(FILE *F, ir_node *from, int to) {
1336 * do not use get_nodes_block() here, will fail
1337 * if the irg is not pinned.
1339 if (get_irn_n(from, -1) == get_irn_n(get_irn_n(from, to), -1))
1340 fprintf (F, INTRA_MEM_EDGE_ATTR);
1342 fprintf (F, INTER_MEM_EDGE_ATTR);
1346 print_edge_vcgattr(FILE *F, ir_node *from, int to) {
1349 if (dump_edge_vcgattr_hook)
1350 if (dump_edge_vcgattr_hook(F, from, to))
1353 if (dump_backedge_information_flag && is_backedge(from, to))
1354 fprintf (F, BACK_EDGE_ATTR);
1356 switch (get_irn_opcode(from)) {
1358 fprintf (F, CF_EDGE_ATTR);
1360 case iro_Start: break;
1363 if (get_irn_mode(get_End_keepalive(from, to)) == mode_BB)
1364 fprintf (F, CF_EDGE_ATTR);
1365 if (get_irn_mode(get_End_keepalive(from, to)) == mode_X)
1366 fprintf (F, INTER_MEM_EDGE_ATTR);
1370 if (is_Proj(from)) {
1371 if (get_irn_mode(from) == mode_M)
1372 print_mem_edge_vcgattr(F, from, to);
1373 else if (get_irn_mode(from) == mode_X)
1374 fprintf(F, CF_EDGE_ATTR);
1376 print_data_edge_vcgattr(F, from, to);
1378 else if (get_irn_mode(get_irn_n(from, to)) == mode_M)
1379 print_mem_edge_vcgattr(F, from, to);
1380 else if (get_irn_mode(get_irn_n(from, to)) == mode_X)
1381 fprintf (F, CF_EDGE_ATTR);
1383 print_data_edge_vcgattr(F, from, to);
1387 /* dump edges to our inputs */
1389 dump_ir_data_edges(FILE *F, ir_node *n) {
1391 unsigned long visited = get_irn_visited(n);
1393 if ((get_irn_op(n) == op_End) && (!dump_keepalive))
1396 for (i = 0; i < get_irn_arity(n); i++) {
1397 ir_node * pred = get_irn_n(n, i);
1400 if ((get_interprocedural_view() && get_irn_visited(pred) < visited))
1401 continue; /* pred not dumped */
1403 if (dump_backedge_information_flag && is_backedge(n, i))
1404 fprintf (F, "backedge: {sourcename: \"");
1406 fprintf (F, "edge: {sourcename: \"");
1408 fprintf (F, "\" targetname: ");
1409 if ((get_opt_dump_const_local()) && is_constlike_node(pred)) {
1410 PRINT_CONSTID(n, pred);
1412 fprintf(F, "\""); PRINT_NODEID(pred); fprintf(F, "\"");
1414 fprintf (F, " label: \"%d\" ", i);
1415 print_edge_vcgattr(F, n, i);
1420 /** Dumps a node and its edges but not the block edge
1423 dump_node_wo_blockedge (ir_node *n, void *env) {
1426 dump_ir_data_edges(F, n);
1429 /** Dumps a node and its edges.
1432 dump_whole_node (ir_node *n, void *env) {
1434 dump_node_wo_blockedge(n, env);
1435 if (!node_floats(n)) dump_ir_block_edge(F, n);
1439 dump_const_node(ir_node *n, void *env) {
1440 if (is_Block(n)) return;
1441 dump_node_wo_blockedge(n, env);
1444 /***********************************************************************/
1445 /* the following routines dump the nodes/irgs bracketed to graphs. */
1446 /***********************************************************************/
1448 /** Dumps a constant expression as entity initializer, array bound ...
1450 static void dump_const_expression(FILE *F, ir_node *value) {
1451 ir_graph *rem = current_ir_graph;
1452 int rem_dump_const_local = dump_const_local;
1453 dump_const_local = 0;
1454 current_ir_graph = get_const_code_irg();
1455 irg_walk(value, dump_const_node, NULL, F);
1456 /* Decrease visited flag so that we walk with the same flag for the next
1457 expression. This guarantees that we don't dump the same node twice,
1458 as for const expressions cse is performed to save memory. */
1459 set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph) -1);
1460 current_ir_graph = rem;
1461 dump_const_local = rem_dump_const_local;
1464 /** Dump a block as graph containing its nodes.
1466 * Expects to find nodes belonging to the block as list in its
1468 * Dumps the edges of all nodes including itself. */
1470 dump_whole_block(FILE *F, ir_node *block) {
1472 dumper_colors color = ird_color_yellow;
1474 assert(is_Block(block));
1476 fprintf(F, "graph: { title: \"");
1477 PRINT_NODEID(block);
1478 fprintf(F, "\" label: \"");
1479 dump_node_label(F, block);
1481 if (get_opt_dump_abstvals())
1482 fprintf (F, " seqno: %d", (int)get_Block_seqno(block));
1485 /* colorize blocks */
1486 if (! get_Block_matured(block))
1487 color = ird_color_red;
1488 if (is_Block_dead(block))
1489 color = ird_color_orange;
1491 fprintf(F, "\" status:clustered ");
1492 print_vcg_color(F, color);
1495 /* yComp can show attributes for blocks, XVCG parses but ignores them */
1496 dump_node_info(F, block);
1497 print_dbg_info(F, get_irn_dbg_info(block));
1499 /* dump the blocks edges */
1500 dump_ir_data_edges(F, block);
1502 /* dump the nodes that go into the block */
1503 for (node = ird_get_irn_link(block); node; node = ird_get_irn_link(node)) {
1505 dump_ir_data_edges(F, node);
1508 /* Close the vcg information for the block */
1510 dump_const_node_local(F, block);
1512 dump_irn_chi_term(F, block);
1517 /** dumps a graph block-wise. Expects all blockless nodes in arr in irgs link.
1518 * The outermost nodes: blocks and nodes not op_pin_state_pinned, Bad, Unknown. */
1520 dump_block_graph(FILE *F, ir_graph *irg) {
1522 ir_graph *rem = current_ir_graph;
1523 ir_node **arr = ird_get_irg_link(irg);
1524 current_ir_graph = irg;
1526 for (i = ARR_LEN(arr) - 1; i >= 0; --i) {
1527 ir_node * node = arr[i];
1528 if (is_Block(node)) {
1529 /* Dumps the block and all the nodes in the block, which are to
1530 be found in Block->link. */
1531 dump_whole_block(F, node);
1533 /* Nodes that are not in a Block. */
1535 if (!node_floats(node) && is_Bad(get_nodes_block(node))) {
1536 dump_const_block_local(F, node);
1538 dump_ir_data_edges(F, node);
1542 if (dump_loop_information_flag && (get_irg_loopinfo_state(irg) & loopinfo_valid))
1543 dump_loop_nodes_into_graph(F, irg);
1545 current_ir_graph = rem;
1549 * Dump the info for an irg.
1550 * Parsed by XVCG but not shown. use yComp.
1552 static void dump_graph_info(FILE *F, ir_graph *irg) {
1553 fprintf(F, "info1: \"");
1554 dump_entity_to_file(F, get_irg_entity(irg), dump_verbosity_entattrs | dump_verbosity_entconsts);
1558 /** Dumps an irg as a graph clustered by block nodes.
1559 * If interprocedural view edges can point to nodes out of this graph.
1561 static void dump_graph_from_list(FILE *F, ir_graph *irg) {
1562 entity *ent = get_irg_entity(irg);
1564 fprintf(F, "graph: { title: \"");
1566 fprintf(F, "\" label: \"%s\" status:clustered color:white \n",
1567 get_ent_dump_name(ent));
1569 dump_graph_info(F, irg);
1570 print_dbg_info(F, get_entity_dbg_info(ent));
1572 dump_block_graph(F, irg);
1574 /* Close the vcg information for the irg */
1575 fprintf(F, "}\n\n");
1578 /** dumps a graph extended block-wise. Expects all blockless nodes in arr in irgs link.
1579 * The outermost nodes: blocks and nodes not op_pin_state_pinned, Bad, Unknown. */
1581 dump_extblock_graph(FILE *F, ir_graph *irg) {
1583 ir_graph *rem = current_ir_graph;
1584 ir_extblk **arr = ird_get_irg_link(irg);
1585 current_ir_graph = irg;
1587 for (i = ARR_LEN(arr) - 1; i >= 0; --i) {
1588 ir_extblk *extbb = arr[i];
1589 ir_node *leader = get_extbb_leader(extbb);
1592 fprintf(F, "graph: { title: \"");
1593 PRINT_EXTBBID(leader);
1594 fprintf(F, "\" label: \"ExtBB %ld\" status:clustered color:lightgreen\n",
1595 get_irn_node_nr(leader));
1597 for (j = ARR_LEN(extbb->blks) - 1; j >= 0; --j) {
1598 ir_node * node = extbb->blks[j];
1599 if (is_Block(node)) {
1600 /* Dumps the block and all the nodes in the block, which are to
1601 be found in Block->link. */
1602 dump_whole_block(F, node);
1604 /* Nodes that are not in a Block. */
1606 if (is_Bad(get_nodes_block(node)) && !node_floats(node)) {
1607 dump_const_block_local(F, node);
1609 dump_ir_data_edges(F, node);
1615 if (dump_loop_information_flag && (get_irg_loopinfo_state(irg) & loopinfo_valid))
1616 dump_loop_nodes_into_graph(F, irg);
1618 current_ir_graph = rem;
1623 /*******************************************************************/
1624 /* Basic type and entity nodes and edges. */
1625 /*******************************************************************/
1627 /** dumps the edges between nodes and their type or entity attributes. */
1628 static void dump_node2type_edges(ir_node *n, void *env)
1633 switch (get_irn_opcode(n)) {
1635 /* @@@ some consts have an entity */
1638 if ( (get_SymConst_kind(n) ==symconst_type_tag)
1639 || (get_SymConst_kind(n) ==symconst_size))
1641 print_node_type_edge(F,n,get_SymConst_type(n),NODE2TYPE_EDGE_ATTR);
1645 print_node_ent_edge(F,n,get_Sel_entity(n),NODE2TYPE_EDGE_ATTR);
1648 print_node_type_edge(F,n,get_Call_type(n),NODE2TYPE_EDGE_ATTR);
1651 print_node_type_edge(F,n,get_Alloc_type(n),NODE2TYPE_EDGE_ATTR);
1654 print_node_type_edge(F,n,get_Free_type(n),NODE2TYPE_EDGE_ATTR);
1657 print_node_type_edge(F,n,get_Cast_type(n),NODE2TYPE_EDGE_ATTR);
1665 static int print_type_info(FILE *F, ir_type *tp) {
1668 if (get_type_state(tp) == layout_undefined) {
1669 fprintf(F, "state: layout_undefined\n");
1671 fprintf(F, "state: layout_fixed,\n");
1673 if (get_type_mode(tp))
1674 fprintf(F, "mode: %s,\n", get_mode_name_ex(get_type_mode(tp), &bad));
1675 fprintf(F, "size: %db,\n", get_type_size_bits(tp));
1680 static void print_typespecific_info(FILE *F, ir_type *tp) {
1681 switch (get_type_tpop_code(tp)) {
1684 fprintf(F, "peculiarity: %s\n", get_peculiarity_string(get_class_peculiarity(tp)));
1691 fprintf(F, "variadicity: %s\n", get_variadicity_name(get_method_variadicity(tp)));
1692 fprintf(F, "params: %d\n", get_method_n_params(tp));
1693 fprintf(F, "results: %d\n", get_method_n_ress(tp));
1701 case tpo_enumeration:
1715 static void print_typespecific_vcgattr(FILE *F, ir_type *tp) {
1716 switch (get_type_tpop_code(tp)) {
1719 if (peculiarity_existent == get_class_peculiarity(tp))
1720 fprintf (F, " " TYPE_CLASS_NODE_ATTR);
1722 fprintf (F, " " TYPE_DESCRIPTION_NODE_ATTR);
1726 fprintf (F, " " TYPE_METH_NODE_ATTR);
1737 case tpo_enumeration:
1751 int dump_type_node(FILE *F, ir_type *tp)
1755 fprintf (F, "node: {title: ");
1757 fprintf (F, " label: \"%s %s\"", get_type_tpop_name(tp), get_type_name_ex(tp, &bad));
1758 fprintf (F, " info1: \"");
1760 bad |= print_type_info(F, tp);
1761 print_typespecific_info(F, tp);
1763 dump_type_to_file(F, tp, dump_verbosity_max);
1765 fprintf (F, "\"\n");
1766 print_dbg_info(F, get_type_dbg_info(tp));
1767 print_typespecific_vcgattr(F, tp);
1774 #define X(a) case a: fprintf(F, #a); break
1775 void dump_entity_node(FILE *F, entity *ent, int color)
1777 fprintf (F, "node: {title: \"");
1778 PRINT_ENTID(ent); fprintf(F, "\"");
1779 fprintf (F, DEFAULT_TYPE_ATTRIBUTE);
1780 fprintf (F, "label: ");
1781 fprintf (F, "\"ent %s\" ", get_ent_dump_name(ent));
1783 fprintf(F, "color:%d", color);
1785 fprintf (F, ENTITY_NODE_ATTR);
1786 fprintf (F, "\n info1: \"");
1788 dump_entity_to_file(F, ent, dump_verbosity_entattrs | dump_verbosity_entconsts);
1791 print_dbg_info(F, get_entity_dbg_info(ent));
1796 static void dump_enum_item(FILE *F, ir_type *tp, int pos)
1799 ident *id = get_enumeration_nameid(tp, pos);
1800 tarval *tv = get_enumeration_enum(tp, pos);
1802 tarval_snprintf(buf, sizeof(buf), tv);
1803 fprintf (F, "node: {title: \"");
1804 PRINT_ITEMID(tp, pos); fprintf(F, "\"");
1805 fprintf (F, DEFAULT_ENUM_ITEM_ATTRIBUTE);
1806 fprintf (F, "label: ");
1807 fprintf (F, "\"enum item %s\" " ENUM_ITEM_NODE_ATTR, get_id_str(id));
1808 fprintf (F, "\n info1: \"value: %s\"}\n", buf);
1811 /* dumps a type or entity and it's edges. */
1813 dump_type_info(type_or_ent *tore, void *env) {
1815 int i = 0; /* to shutup gcc */
1817 /* dump this type or entity */
1819 switch (get_kind(tore)) {
1822 entity *ent = (entity *)tore;
1825 dump_entity_node(F, ent, 0);
1827 /* skip this to reduce graph. Member edge of type is parallel to this edge. *
1828 fprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
1829 ENT_OWN_EDGE_ATTR "}\n", ent, get_entity_owner(ent));*/
1830 print_ent_type_edge(F,ent, get_entity_type(ent), ENT_TYPE_EDGE_ATTR);
1831 if (is_Class_type(get_entity_owner(ent))) {
1832 for(i = 0; i < get_entity_n_overwrites(ent); i++)
1833 print_ent_ent_edge(F,ent, get_entity_overwrites(ent, i), 0, ENT_OVERWRITES_EDGE_ATTR);
1835 /* attached subgraphs */
1836 if (const_entities && (get_entity_variability(ent) != variability_uninitialized)) {
1837 if (is_atomic_entity(ent)) {
1838 value = get_atomic_ent_value(ent);
1840 print_ent_node_edge(F, ent, value, ENT_VALUE_EDGE_ATTR, i);
1841 /* DDMN(value); $$$ */
1842 dump_const_expression(F, value);
1845 if (is_compound_entity(ent)) {
1846 for (i = 0; i < get_compound_ent_n_values(ent); i++) {
1847 value = get_compound_ent_value(ent, i);
1849 print_ent_node_edge(F, ent, value, ENT_VALUE_EDGE_ATTR, i);
1850 dump_const_expression(F, value);
1851 print_ent_ent_edge(F, ent, get_compound_ent_value_member(ent, i), 0, ENT_CORR_EDGE_ATTR, i);
1853 fprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
1854 ENT_CORR_EDGE_ATTR "}\n", GET_ENTID(ent),
1855 get_compound_ent_value_member(ent, i), i);
1864 ir_type *tp = (ir_type *)tore;
1865 dump_type_node(F, tp);
1866 /* and now the edges */
1867 switch (get_type_tpop_code(tp)) {
1870 for (i=0; i < get_class_n_supertypes(tp); i++)
1871 print_type_type_edge(F, tp,get_class_supertype(tp, i),TYPE_SUPER_EDGE_ATTR);
1872 for (i=0; i < get_class_n_members(tp); i++)
1873 print_type_ent_edge(F,tp,get_class_member(tp, i),TYPE_MEMBER_EDGE_ATTR);
1877 for (i=0; i < get_struct_n_members(tp); i++)
1878 print_type_ent_edge(F,tp,get_struct_member(tp, i),TYPE_MEMBER_EDGE_ATTR);
1882 for (i = 0; i < get_method_n_params(tp); i++)
1883 print_type_type_edge(F,tp,get_method_param_type(tp, i),METH_PAR_EDGE_ATTR,i);
1884 for (i = 0; i < get_method_n_ress(tp); i++)
1885 print_type_type_edge(F,tp,get_method_res_type(tp, i),METH_RES_EDGE_ATTR,i);
1889 for (i = 0; i < get_union_n_members(tp); i++)
1890 print_type_ent_edge(F,tp,get_union_member(tp, i),UNION_EDGE_ATTR);
1894 print_type_type_edge(F,tp,get_array_element_type(tp),ARR_ELT_TYPE_EDGE_ATTR);
1895 print_type_ent_edge(F,tp,get_array_element_entity(tp),ARR_ENT_EDGE_ATTR);
1896 for (i = 0; i < get_array_n_dimensions(tp); i++) {
1897 ir_node *upper = get_array_upper_bound(tp, i);
1898 ir_node *lower = get_array_lower_bound(tp, i);
1899 print_node_type_edge(F, upper, tp, "label: \"upper %d\"", get_array_order(tp, i));
1900 print_node_type_edge(F, lower, tp, "label: \"lower %d\"", get_array_order(tp, i));
1901 dump_const_expression(F, upper);
1902 dump_const_expression(F, lower);
1906 case tpo_enumeration:
1908 for (i = 0; i < get_enumeration_n_enums(tp); ++i) {
1909 dump_enum_item(F, tp, i);
1910 print_enum_item_edge(F, tp, i, "label: \"item %d\"", i);
1915 print_type_type_edge(F,tp,get_pointer_points_to_type(tp), PTR_PTS_TO_EDGE_ATTR);
1923 break; /* case k_type */
1926 printf(" *** irdump, dump_type_info(l.%i), faulty type.\n", __LINE__);
1928 } /* switch kind_or_entity */
1931 typedef struct _h_env {
1936 /** For dumping class hierarchies.
1937 * Dumps a class type node and a superclass edge.
1938 * If env->dump_ent dumps entities of classes and overwrites edges.
1941 dump_class_hierarchy_node (type_or_ent *tore, void *ctx) {
1944 int i = 0; /* to shutup gcc */
1946 /* dump this type or entity */
1947 switch (get_kind(tore)) {
1949 entity *ent = (entity *)tore;
1950 if (get_entity_owner(ent) == get_glob_type()) break;
1951 if (!is_Method_type(get_entity_type(ent))) break; /* GL */
1952 if (env->dump_ent && is_Class_type(get_entity_owner(ent))) {
1954 dump_entity_node(F, ent, 0);
1956 print_type_ent_edge(F,get_entity_owner(ent),ent,TYPE_MEMBER_EDGE_ATTR);
1957 for(i = 0; i < get_entity_n_overwrites(ent); i++)
1958 print_ent_ent_edge(F, get_entity_overwrites(ent, i), ent, 0, ENT_OVERWRITES_EDGE_ATTR);
1960 } break; /* case k_entity */
1963 ir_type *tp = (ir_type *)tore;
1964 if (tp == get_glob_type()) break;
1965 switch (get_type_tpop_code(tp)) {
1967 dump_type_node(F, tp);
1968 /* and now the edges */
1969 for (i=0; i < get_class_n_supertypes(tp); i++)
1971 print_type_type_edge(F,tp,get_class_supertype(tp, i),TYPE_SUPER_EDGE_ATTR);
1977 break; /* case k_type */
1980 printf(" *** irdump, dump_class_hierarchy_node(l.%i), faulty type.\n", __LINE__);
1982 } /* switch kind_or_entity */
1985 /*******************************************************************/
1986 /* dump analysis information that is expressed in graph terms. */
1987 /*******************************************************************/
1989 /* dump out edges */
1991 dump_out_edge(ir_node *n, void *env) {
1994 for (i = 0; i < get_irn_n_outs(n); i++) {
1995 assert(get_irn_out(n, i));
1996 fprintf (F, "edge: {sourcename: \"");
1998 fprintf (F, "\" targetname: \"");
1999 PRINT_NODEID(get_irn_out(n, i));
2000 fprintf (F, "\" color: red linestyle: dashed");
2006 dump_loop_label(FILE *F, ir_loop *loop) {
2007 fprintf (F, "loop %d, %d sons, %d nodes",
2008 get_loop_depth(loop), get_loop_n_sons(loop), get_loop_n_nodes(loop));
2011 static INLINE void dump_loop_info(FILE *F, ir_loop *loop) {
2012 fprintf (F, " info1: \"");
2013 fprintf (F, " loop nr: %d", get_loop_loop_nr(loop));
2014 #if DEBUG_libfirm /* GL @@@ debug analyses */
2015 fprintf (F, "\n The loop was analyzed %d times.", PTR_TO_INT(get_loop_link(loop)));
2021 dump_loop_node(FILE *F, ir_loop *loop) {
2022 fprintf (F, "node: {title: \"");
2024 fprintf (F, "\" label: \"");
2025 dump_loop_label(F, loop);
2027 dump_loop_info(F, loop);
2033 dump_loop_node_edge(FILE *F, ir_loop *loop, int i) {
2035 fprintf (F, "edge: {sourcename: \"");
2037 fprintf (F, "\" targetname: \"");
2038 PRINT_NODEID(get_loop_node(loop, i));
2039 fprintf (F, "\" color: green");
2044 dump_loop_son_edge(FILE *F, ir_loop *loop, int i) {
2046 fprintf (F, "edge: {sourcename: \"");
2048 fprintf (F, "\" targetname: \"");
2049 PRINT_LOOPID(get_loop_son(loop, i));
2050 fprintf (F, "\" color: darkgreen label: \"%d\"}\n",
2051 get_loop_element_pos(loop, get_loop_son(loop, i)));
2055 void dump_loops(FILE *F, ir_loop *loop) {
2057 /* dump this loop node */
2058 dump_loop_node(F, loop);
2060 /* dump edges to nodes in loop -- only if it is a real loop */
2061 if (get_loop_depth(loop) != 0) {
2062 for (i = 0; i < get_loop_n_nodes(loop); i++) {
2063 dump_loop_node_edge(F, loop, i);
2066 for (i = 0; i < get_loop_n_sons(loop); i++) {
2067 dump_loops(F, get_loop_son(loop, i));
2068 dump_loop_son_edge(F, loop, i);
2073 void dump_loop_nodes_into_graph(FILE *F, ir_graph *irg) {
2074 ir_graph *rem = current_ir_graph;
2075 current_ir_graph = irg;
2077 if (get_irg_loop(irg)) dump_loops(F, get_irg_loop(irg));
2079 current_ir_graph = rem;
2084 * dumps the VCG header
2086 void dump_vcg_header(FILE *F, const char *name, const char *orientation) {
2095 if (!orientation) orientation = "bottom_to_top";
2099 "graph: { title: \"ir graph of %s\"\n"
2100 "display_edge_labels: %s\n"
2101 "layoutalgorithm: mindepth\n"
2102 "manhattan_edges: yes\n"
2103 "port_sharing: no\n"
2105 "classname 1: \"intrablock Data\"\n"
2106 "classname 2: \"Block\"\n"
2107 "classname 3: \"Entity type\"\n"
2108 "classname 4: \"Entity owner\"\n"
2109 "classname 5: \"Method Param\"\n"
2110 "classname 6: \"Method Res\"\n"
2111 "classname 7: \"Super\"\n"
2112 "classname 8: \"Union\"\n"
2113 "classname 9: \"Points-to\"\n"
2114 "classname 10: \"Array Element Type\"\n"
2115 "classname 11: \"Overwrites\"\n"
2116 "classname 12: \"Member\"\n"
2117 "classname 13: \"Control Flow\"\n"
2118 "classname 14: \"intrablock Memory\"\n"
2119 "classname 15: \"Dominators\"\n"
2120 "classname 16: \"interblock Data\"\n"
2121 "classname 17: \"interblock Memory\"\n"
2122 "classname 18: \"Exception Control Flow for Interval Analysis\"\n"
2123 "classname 19: \"Postdominators\"\n"
2124 "infoname 1: \"Attribute\"\n"
2125 "infoname 2: \"Verification errors\"\n"
2126 "infoname 3: \"Debug info\"\n",
2127 name, label, orientation);
2129 /* don't use all, the range is too whith/black. */
2133 "colorentry 100: 0 0 0\n"
2134 "colorentry 101: 20 0 0\n"
2135 "colorentry 102: 40 0 0\n"
2136 "colorentry 103: 60 0 0\n"
2137 "colorentry 104: 80 0 0\n"
2138 "colorentry 105: 100 0 0\n"
2139 "colorentry 106: 120 0 0\n"
2140 "colorentry 107: 140 0 0\n"
2141 "colorentry 108: 150 0 0\n"
2142 "colorentry 109: 180 0 0\n"
2143 "colorentry 110: 200 0 0\n"
2144 "colorentry 111: 220 0 0\n"
2145 "colorentry 112: 240 0 0\n"
2146 "colorentry 113: 255 0 0\n"
2147 "colorentry 113: 255 20 20\n"
2148 "colorentry 114: 255 40 40\n"
2149 "colorentry 115: 255 60 60\n"
2150 "colorentry 116: 255 80 80\n"
2151 "colorentry 117: 255 100 100\n"
2152 "colorentry 118: 255 120 120\n"
2153 "colorentry 119: 255 140 140\n"
2154 "colorentry 120: 255 150 150\n"
2155 "colorentry 121: 255 180 180\n"
2156 "colorentry 122: 255 200 200\n"
2157 "colorentry 123: 255 220 220\n"
2158 "colorentry 124: 255 240 240\n"
2159 "colorentry 125: 255 250 250\n"
2162 fprintf (F, "\n"); /* a separator */
2168 * @param irg The graph to be dumped
2169 * @param suffix1 first filename suffix
2170 * @param suffix2 second filename suffix
2172 FILE *vcg_open (ir_graph *irg, const char * suffix1, const char *suffix2) {
2174 const char *nm = get_irg_dump_name(irg);
2175 int len = strlen(nm), i, j;
2176 char *fname; /* filename to put the vcg information in */
2178 if (!suffix1) suffix1 = "";
2179 if (!suffix2) suffix2 = "";
2181 /* open file for vcg graph */
2182 fname = malloc (len * 2 + strlen(suffix1) + strlen(suffix2) + 5);
2184 /* strncpy (fname, nm, len); */ /* copy the filename */
2186 for (i = 0; i < len; ++i) { /* replace '/' in the name: escape by @. */
2188 fname[j] = '@'; j++; fname[j] = '1'; j++;
2189 } else if (nm[i] == '@') {
2190 fname[j] = '@'; j++; fname[j] = '2'; j++;
2192 fname[j] = nm[i]; j++;
2196 strcat (fname, suffix1); /* append file suffix */
2197 strcat (fname, suffix2); /* append file suffix */
2198 strcat (fname, ".vcg"); /* append the .vcg suffix */
2200 /* vcg really expect only a <CR> at end of line, so
2201 * the "b"inary mode is what you mean (and even needed for Win32)
2203 F = fopen (fname, "wb"); /* open file for writing */
2205 panic("cannot open %s for writing (%m)", fname); /* not reached */
2215 * @param name prefix file name
2216 * @param suffix filename suffix
2218 FILE *vcg_open_name (const char *name, const char *suffix) {
2220 char *fname; /* filename to put the vcg information in */
2221 int i, j, len = strlen(name);
2223 if (!suffix) suffix = "";
2225 /** open file for vcg graph */
2226 fname = xmalloc(len * 2 + 5 + strlen(suffix));
2227 /* strcpy (fname, name);*/ /* copy the filename */
2229 for (i = 0; i < len; ++i) { /* replace '/' in the name: escape by @. */
2230 if (name[i] == '/') {
2231 fname[j] = '@'; j++; fname[j] = '1'; j++;
2232 } else if (name[i] == '@') {
2233 fname[j] = '@'; j++; fname[j] = '2'; j++;
2235 fname[j] = name[i]; j++;
2239 strcat (fname, suffix);
2240 strcat (fname, ".vcg"); /* append the .vcg suffix */
2242 /* vcg really expect only a <CR> at end of line, so
2243 * the "b"inary mode is what you mean (and even needed for Win32)
2245 F = fopen (fname, "wb"); /* open file for writing */
2247 panic ("cannot open %s for writing (%m)", fname); /* not reached */
2255 * Dumps the vcg file footer
2257 static INLINE void dump_vcg_footer (FILE *F) {
2262 * close the vcg file
2264 void vcg_close (FILE *F) {
2265 dump_vcg_footer(F); /* print footer */
2266 fclose (F); /* close vcg file */
2269 /************************************************************************/
2270 /************************************************************************/
2271 /* Routines that dump all or parts of the firm representation to a file */
2272 /************************************************************************/
2273 /************************************************************************/
2275 /************************************************************************/
2276 /* Dump ir graphs, different formats and additional information. */
2277 /************************************************************************/
2279 /** Routine to dump a graph, blocks as conventional nodes. */
2281 dump_ir_graph (ir_graph *irg, const char *suffix )
2286 rem = current_ir_graph;
2288 if (!is_filtered_dump_name(get_entity_ident(get_irg_entity(irg)))) return;
2290 current_ir_graph = irg;
2291 if (get_interprocedural_view()) suffix1 = "-pure-ip";
2292 else suffix1 = "-pure";
2293 f = vcg_open(irg, suffix, suffix1);
2294 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
2296 /* call the dump graph hook */
2297 if (dump_ir_graph_hook)
2298 if (dump_ir_graph_hook(f, irg))
2301 /* walk over the graph */
2302 /* dump_whole_node must be called in post visiting predecessors */
2303 ird_walk_graph(irg, NULL, dump_whole_node, f);
2305 /* dump the out edges in a separate walk */
2306 if ((dump_out_edge_flag) && (get_irg_outs_state(irg) != outs_none)) {
2307 irg_out_walk(get_irg_start(irg), dump_out_edge, NULL, f);
2312 current_ir_graph = rem;
2315 /* Dump a firm graph without explicit block nodes. */
2316 void dump_ir_block_graph (ir_graph *irg, const char *suffix)
2322 if (!is_filtered_dump_name(get_entity_ident(get_irg_entity(irg))))
2325 if (get_interprocedural_view()) suffix1 = "-ip";
2327 f = vcg_open(irg, suffix, suffix1);
2328 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
2330 construct_block_lists(irg);
2333 * If we are in the interprocedural view, we dump not
2334 * only the requested irg but also all irgs that can be reached
2337 for (i = get_irp_n_irgs() - 1; i >= 0; --i) {
2338 ir_node **arr = ird_get_irg_link(get_irp_irg(i));
2340 dump_graph_from_list(f, get_irp_irg(i));
2348 /* Dump a firm graph without explicit block nodes but grouped in extended blocks. */
2349 void dump_ir_extblock_graph (ir_graph *irg, const char *suffix)
2356 if (!is_filtered_dump_name(get_entity_ident(get_irg_entity(irg))))
2359 if (get_irg_extblk_state(irg) != extblk_valid)
2362 if (get_interprocedural_view()) suffix1 = "-ip";
2365 ent = get_irg_entity(irg);
2367 F = vcg_open(irg, suffix, suffix1);
2368 dump_vcg_header(F, get_irg_dump_name(irg), NULL);
2370 construct_extblock_lists(irg);
2372 fprintf(F, "graph: { title: \"");
2374 fprintf(F, "\" label: \"%s\" status:clustered color: white \n",
2375 get_ent_dump_name(ent));
2377 dump_graph_info(F, irg);
2378 print_dbg_info(F, get_entity_dbg_info(ent));
2380 for (i = get_irp_n_irgs() - 1; i >= 0; --i) {
2381 ir_graph *irg = get_irp_irg(i);
2382 list_tuple *lists = ird_get_irg_link(irg);
2385 /* dump the extended blocks first */
2386 if (ARR_LEN(lists->extbb_list)) {
2387 ird_set_irg_link(irg, lists->extbb_list);
2388 dump_extblock_graph(F, irg);
2391 /* we may have blocks without extended blocks, bad for instance */
2392 if (ARR_LEN(lists->blk_list)) {
2393 ird_set_irg_link(irg, lists->blk_list);
2394 dump_block_graph(F, irg);
2397 DEL_ARR_F(lists->extbb_list);
2398 DEL_ARR_F(lists->blk_list);
2403 /* Close the vcg information for the irg */
2404 fprintf(F, "}\n\n");
2410 /* dumps a graph with type information */
2412 dump_ir_graph_w_types (ir_graph *irg, const char *suffix)
2415 ir_graph *rem = current_ir_graph;
2417 int rem_dump_const_local;
2419 /* if a filter is set, dump only the irg's that match the filter */
2420 if (!is_filtered_dump_name(get_entity_ident(get_irg_entity(irg))))
2423 current_ir_graph = irg;
2424 rem_dump_const_local = dump_const_local;
2425 /* dumping types does not work with local nodes */
2426 dump_const_local = 0;
2428 if (get_interprocedural_view()) suffix1 = "-pure-wtypes-ip";
2429 else suffix1 = "-pure-wtypes";
2430 f = vcg_open(irg,suffix, suffix1);
2431 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
2433 /* dump common ir graph */
2434 irg_walk(get_irg_end(irg), NULL, dump_whole_node, f);
2435 /* dump type info */
2436 type_walk_irg(irg, dump_type_info, NULL, f);
2437 inc_irg_visited(get_const_code_irg());
2438 /* dump edges from graph to type info */
2439 irg_walk(get_irg_end(irg), dump_node2type_edges, NULL, f);
2442 dump_const_local = rem_dump_const_local;
2443 current_ir_graph = rem;
2447 dump_ir_block_graph_w_types (ir_graph *irg, const char *suffix)
2452 ir_graph *rem = current_ir_graph;
2453 int rem_dump_const_local;
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 rem_dump_const_local = dump_const_local;
2460 /* dumping types does not work with local nodes */
2461 dump_const_local = 0;
2463 if (get_interprocedural_view()) suffix1 = "-wtypes-ip";
2464 else suffix1 = "-wtypes";
2465 f = vcg_open(irg, suffix, suffix1);
2466 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
2468 /* dump common blocked ir graph */
2469 construct_block_lists(irg);
2471 for (i = get_irp_n_irgs() - 1; i >= 0; --i) {
2472 ir_node **arr = ird_get_irg_link(get_irp_irg(i));
2474 dump_graph_from_list(f, get_irp_irg(i));
2479 /* dump type info */
2480 current_ir_graph = irg;
2481 type_walk_irg(irg, dump_type_info, NULL, f);
2482 inc_irg_visited(get_const_code_irg());
2484 /* dump edges from graph to type info */
2485 irg_walk(get_irg_end(irg), dump_node2type_edges, NULL, f);
2488 dump_const_local = rem_dump_const_local;
2489 current_ir_graph = rem;
2492 /*---------------------------------------------------------------------*/
2493 /* The following routines dump a control flow graph. */
2494 /*---------------------------------------------------------------------*/
2497 dump_block_to_cfg(ir_node *block, void *env) {
2502 if (is_Block(block)) {
2503 /* This is a block. Dump a node for the block. */
2504 fprintf (F, "node: {title: \""); PRINT_NODEID(block);
2505 fprintf (F, "\" label: \"");
2506 if (block == get_irg_start_block(get_irn_irg(block)))
2507 fprintf(F, "Start ");
2508 if (block == get_irg_end_block(get_irn_irg(block)))
2511 fprintf (F, "%s ", get_op_name(get_irn_op(block)));
2512 PRINT_NODEID(block);
2514 fprintf(F, "info1:\"");
2516 /* the generic version. */
2517 dump_irnode_to_file(F, block);
2519 /* Check whether we have bad predecessors to color the block. */
2520 for (i = 0; i < get_Block_n_cfgpreds(block); ++i)
2521 if ((fl = is_Bad(get_Block_cfgpred(block, i))))
2524 fprintf (F, "\""); /* closing quote of info */
2526 if ((block == get_irg_start_block(get_irn_irg(block))) ||
2527 (block == get_irg_end_block(get_irn_irg(block))) )
2528 fprintf(F, " color:blue ");
2530 fprintf(F, " color:yellow ");
2533 /* Dump the edges */
2534 for ( i = 0; i < get_Block_n_cfgpreds(block); i++)
2535 if (get_irn_op(skip_Proj(get_Block_cfgpred(block, i))) != op_Bad) {
2536 pred = get_nodes_block(skip_Proj(get_Block_cfgpred(block, i)));
2537 fprintf (F, "edge: { sourcename: \"");
2538 PRINT_NODEID(block);
2539 fprintf (F, "\" targetname: \"");
2541 fprintf (F, "\"}\n");
2544 /* Dump dominator/postdominator edge */
2545 if (dump_dominator_information_flag) {
2546 if (get_irg_dom_state(current_ir_graph) == dom_consistent && get_Block_idom(block)) {
2547 pred = get_Block_idom(block);
2548 fprintf (F, "edge: { sourcename: \"");
2549 PRINT_NODEID(block);
2550 fprintf (F, "\" targetname: \"");
2552 fprintf (F, "\" " DOMINATOR_EDGE_ATTR "}\n");
2554 if (get_irg_postdom_state(current_ir_graph) == dom_consistent && get_Block_ipostdom(block)) {
2555 pred = get_Block_ipostdom(block);
2556 fprintf (F, "edge: { sourcename: \"");
2557 PRINT_NODEID(block);
2558 fprintf (F, "\" targetname: \"");
2560 fprintf (F, "\" " POSTDOMINATOR_EDGE_ATTR "}\n");
2567 dump_cfg (ir_graph *irg, const char *suffix)
2570 ir_graph *rem = current_ir_graph;
2571 int ipv = get_interprocedural_view();
2573 /* if a filter is set, dump only the irg's that match the filter */
2574 if (!is_filtered_dump_name(get_entity_ident(get_irg_entity(irg))))
2577 current_ir_graph = irg;
2579 f = vcg_open(irg, suffix, "-cfg");
2580 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
2583 printf("Warning: dumping cfg not in interprocedural view!\n");
2584 set_interprocedural_view(0);
2587 /* walk over the blocks in the graph */
2588 irg_block_walk(get_irg_end(irg), dump_block_to_cfg, NULL, f);
2589 dump_node(f, get_irg_bad(irg));
2591 set_interprocedural_view(ipv);
2593 current_ir_graph = rem;
2597 static void descend_and_dump(FILE *F, ir_node *n, int depth, pset *mark_set) {
2598 if (pset_find_ptr(mark_set, n)) return;
2600 pset_insert_ptr(mark_set, n);
2603 int i, start = is_Block(n) ? 0 : -1;
2604 dump_whole_node(n, F);
2605 for (i = start; i < get_irn_arity(n); ++i)
2606 descend_and_dump(F, get_irn_n(n, i), depth-1, mark_set);
2609 /* Don't dump edges to nodes further out. These might be edges to
2610 nodes we already dumped, if there is a shorter path to these. */
2614 static int subgraph_counter = 0;
2615 void dump_subgraph (ir_node *root, int depth, const char *suffix) {
2618 pset *mark_set = pset_new_ptr(1);
2619 sprintf(buf, "-subg_%03d", subgraph_counter++);
2620 F = vcg_open(get_irn_irg(root), suffix, buf);
2621 dump_vcg_header(F, get_irg_dump_name(get_irn_irg(root)), NULL);
2622 descend_and_dump(F, root, depth, mark_set);
2628 static int weight_overall(int rec, int loop) {
2629 return 2*rec + loop;
2632 static int compute_color (int my, int max) {
2639 /* if small, scale to the full color range. */
2641 my = my * (n_colors/max);
2643 step = 1 + (max / n_colors);
2647 return base_color + n_colors - color;
2650 static int get_entity_color(entity *ent) {
2651 ir_graph *irg = get_entity_irg(ent);
2655 int rec_depth = get_irg_recursion_depth(irg);
2656 int loop_depth = get_irg_loop_depth(irg);
2657 int overall_depth = weight_overall(rec_depth, loop_depth);
2659 int max_rec_depth = irp->max_callgraph_recursion_depth;
2660 int max_loop_depth = irp->max_callgraph_loop_depth;
2661 int max_overall_depth = weight_overall(max_rec_depth, max_loop_depth);
2663 /* int my_rec_color = compute_color(rec_depth, max_rec_depth); */
2664 /* int my_loop_color = compute_color(loop_depth, max_loop_depth); */
2665 int my_overall_color = compute_color(overall_depth, max_overall_depth);;
2667 return my_overall_color;
2671 void dump_callgraph(const char *suffix) {
2674 int rem = edge_label;
2676 //ident *prefix = new_id_from_str("java/");
2678 F = vcg_open_name("Callgraph", suffix);
2679 dump_vcg_header(F, "Callgraph", NULL);
2681 for (i = get_irp_n_irgs() - 1; i >= 0; --i) {
2682 ir_graph *irg = get_irp_irg(i);
2683 entity *ent = get_irg_entity(irg);
2684 int j, n_callees = get_irg_n_callees(irg);
2686 /* Do not dump runtime system. */
2687 //if (id_is_prefix(prefix, get_entity_ld_ident(ent))) continue;
2689 dump_entity_node(F, ent, get_entity_color(ent));
2690 for (j = 0; j < n_callees; ++j) {
2691 entity *c = get_irg_entity(get_irg_callee(irg, j));
2692 //if (id_is_prefix(prefix, get_entity_ld_ident(c))) continue;
2693 int be = is_irg_callee_backedge(irg, j);
2696 "label:\"recursion %d\" color:%d" :
2697 "label:\"calls %d\" color:%d";
2698 print_ent_ent_edge(F, ent, c, be, attr, get_irg_callee_loop_depth(irg, j), get_entity_color(ent));
2706 /* Dump all irgs in interprocedural view to a single file. */
2707 void dump_all_cg_block_graph(const char *suffix) {
2710 int rem_view = get_interprocedural_view();
2711 set_interprocedural_view(1);
2713 f = vcg_open_name("All_graphs", suffix);
2714 dump_vcg_header(f, "All_graphs", NULL);
2716 /* collect nodes in all irgs reachable in call graph*/
2717 for (i = get_irp_n_irgs() - 1; i >= 0; --i)
2718 ird_set_irg_link(get_irp_irg(i), NULL);
2720 cg_walk(clear_link, collect_node, NULL);
2722 /* dump all graphs */
2723 for (i = get_irp_n_irgs() - 1; i >= 0; --i) {
2724 current_ir_graph = get_irp_irg(i);
2725 assert(ird_get_irg_link(current_ir_graph));
2726 dump_graph_from_list(f, current_ir_graph);
2727 DEL_ARR_F(ird_get_irg_link(current_ir_graph));
2731 set_interprocedural_view(rem_view);
2734 /*---------------------------------------------------------------------*/
2735 /* the following routines dumps type information without any ir nodes. */
2736 /*---------------------------------------------------------------------*/
2739 dump_type_graph (ir_graph *irg, const char *suffix)
2743 rem = current_ir_graph;
2745 /* if a filter is set, dump only the irg's that match the filter */
2746 if (!is_filtered_dump_name(get_entity_ident(get_irg_entity(irg)))) return;
2748 current_ir_graph = irg;
2750 f = vcg_open(irg, suffix, "-type");
2751 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
2753 /* walk over the blocks in the graph */
2754 type_walk_irg(irg, dump_type_info, NULL, f);
2755 /* The walker for the const code can be called several times for the
2756 same (sub) expression. So that no nodes are dumped several times
2757 we decrease the visited flag of the corresponding graph after each
2758 walk. So now increase it finally. */
2759 inc_irg_visited(get_const_code_irg());
2762 current_ir_graph = rem;
2766 dump_all_types (const char *suffix)
2768 FILE *f = vcg_open_name("All_types", suffix);
2769 dump_vcg_header(f, "All_types", NULL);
2770 type_walk(dump_type_info, NULL, f);
2771 inc_irg_visited(get_const_code_irg());
2776 dump_class_hierarchy (int entities, const char *suffix)
2778 FILE *f = vcg_open_name("class_hierarchy", suffix);
2782 env.dump_ent = entities;
2783 dump_vcg_header(f, "class_hierarchy", NULL);
2784 type_walk(dump_class_hierarchy_node, NULL, &env);
2788 /*---------------------------------------------------------------------*/
2789 /* dumps all graphs with the graph-dumper passed. Possible dumpers: */
2791 /* dump_ir_block_graph */
2793 /* dump_type_graph */
2794 /* dump_ir_graph_w_types */
2795 /*---------------------------------------------------------------------*/
2797 void dump_all_ir_graphs(dump_graph_func *dmp_grph, const char *suffix) {
2799 for (i = get_irp_n_irgs() - 1; i >= 0; --i)
2800 dmp_grph(get_irp_irg(i), suffix);
2804 /*--------------------------------------------------------------------------------*
2805 * Dumps a stand alone loop graph with firm nodes which belong to one loop node *
2806 * packed together in one subgraph/box *
2807 *--------------------------------------------------------------------------------*/
2809 void dump_loops_standalone(FILE *F, ir_loop *loop) {
2810 int i = 0, loop_node_started = 0, son_number = 0, first = 0;
2812 ir_loop *son = NULL;
2814 /* Dump a new loop node. */
2815 dump_loop_node(F, loop);
2817 /* Dump the loop elements. */
2819 for(i = 0; i < get_loop_n_elements(loop); i++) {
2820 le = get_loop_element(loop, i);
2822 if (get_kind(son) == k_ir_loop) {
2824 /* We are a loop son -> Recurse */
2826 if(loop_node_started) { /* Close the "firm-nodes" node first if we started one. */
2827 fprintf(F, "\" }\n");
2828 fprintf (F, "edge: {sourcename: \"");
2830 fprintf (F, "\" targetname: \"");
2832 fprintf (F, "-%d-nodes\" label:\"%d...%d\"}\n", first, first, i-1);
2833 loop_node_started = 0;
2835 dump_loop_son_edge(F, loop, son_number++);
2836 dump_loops_standalone(F, son);
2837 } else if (get_kind(son) == k_ir_node) {
2838 /* We are a loop node -> Collect firm nodes */
2840 ir_node *n = le.node;
2843 if (!loop_node_started) {
2844 /* Start a new node which contains all firm nodes of the current loop */
2845 fprintf (F, "node: { title: \"");
2847 fprintf (F, "-%d-nodes\" color: lightyellow label: \"", i);
2848 loop_node_started = 1;
2854 bad |= dump_node_label(F, n);
2855 /* Causes indeterministic output: if (is_Block(n)) fprintf (F, "\t ->%d", (int)get_irn_link(n)); */
2856 if (has_backedges(n)) fprintf(F, "\t loop head!");
2857 } else { /* for callgraph loop tree */
2859 assert(get_kind(son) == k_ir_graph);
2861 /* We are a loop node -> Collect firm graphs */
2862 n = (ir_graph *)le.node;
2863 if (!loop_node_started) {
2864 /* Start a new node which contains all firm nodes of the current loop */
2865 fprintf (F, "node: { title: \"");
2867 fprintf (F, "-%d-nodes\" color: lightyellow label: \"", i);
2868 loop_node_started = 1;
2873 fprintf (F, " %s", get_irg_dump_name(n));
2874 /* fprintf (F, " %s (depth %d)", get_irg_dump_name(n), n->callgraph_weighted_loop_depth); */
2878 if (loop_node_started) {
2879 fprintf(F, "\" }\n");
2880 fprintf (F, "edge: {sourcename: \"");
2882 fprintf (F, "\" targetname: \"");
2884 fprintf (F, "-%d-nodes\" label:\"%d...%d\"}\n", first, first, i-1);
2885 loop_node_started = 0;
2889 void dump_loop_tree(ir_graph *irg, const char *suffix)
2892 ir_graph *rem = current_ir_graph;
2893 int el_rem = edge_label;
2896 /* if a filter is set, dump only the irg's that match the filter */
2897 if (!is_filtered_dump_name(get_entity_ident(get_irg_entity(irg)))) return;
2899 current_ir_graph = irg;
2901 f = vcg_open(irg, suffix, "-looptree");
2902 dump_vcg_header(f, get_irg_dump_name(irg), "top_to_bottom");
2904 if (get_irg_loop(irg)) dump_loops_standalone(f, get_irg_loop(irg));
2908 edge_label = el_rem;
2909 current_ir_graph = rem;
2912 void dump_callgraph_loop_tree(const char *suffix) {
2914 F = vcg_open_name("Callgraph_looptree", suffix);
2915 dump_vcg_header(F, "callgraph looptree", "top_to_bottom");
2916 dump_loops_standalone(F, irp->outermost_cg_loop);
2921 /*-----------------------------------------------------------------------------*/
2922 /* Dumps the firm nodes in the loop tree to a graph along with the loop nodes. */
2923 /*-----------------------------------------------------------------------------*/
2925 void collect_nodeloop(FILE *F, ir_loop *loop, eset *loopnodes) {
2926 int i, son_number = 0, node_number = 0;
2928 if (dump_loop_information_flag) dump_loop_node(F, loop);
2930 for (i = 0; i < get_loop_n_elements(loop); i++) {
2931 loop_element le = get_loop_element(loop, i);
2932 if (*(le.kind) == k_ir_loop) {
2933 if (dump_loop_information_flag) dump_loop_son_edge(F, loop, son_number++);
2935 collect_nodeloop(F, le.son, loopnodes);
2937 if (dump_loop_information_flag) dump_loop_node_edge(F, loop, node_number++);
2938 eset_insert(loopnodes, le.node);
2943 void collect_nodeloop_external_nodes(ir_loop *loop, eset *loopnodes, eset *extnodes) {
2946 for(i = 0; i < get_loop_n_elements(loop); i++) {
2947 loop_element le = get_loop_element(loop, i);
2948 if (*(le.kind) == k_ir_loop) {
2950 collect_nodeloop_external_nodes(le.son, loopnodes, extnodes);
2952 if (is_Block(le.node)) start = 0; else start = -1;
2953 for (j = start; j < get_irn_arity(le.node); j++) {
2954 ir_node *pred = get_irn_n(le.node, j);
2955 if (!eset_contains(loopnodes, pred)) {
2956 eset_insert(extnodes, pred);
2957 if (!is_Block(pred)) {
2958 pred = get_nodes_block(pred);
2959 if (!eset_contains(loopnodes, pred)) eset_insert(extnodes, pred);
2967 void dump_loop(ir_loop *l, const char *suffix) {
2970 eset *loopnodes = eset_create();
2971 eset *extnodes = eset_create();
2974 snprintf(name, sizeof(name), "loop_%d", get_loop_loop_nr(l));
2975 F = vcg_open_name (name, suffix);
2976 dump_vcg_header(F, name, NULL);
2978 /* collect all nodes to dump */
2979 collect_nodeloop(F, l, loopnodes);
2980 collect_nodeloop_external_nodes(l, loopnodes, extnodes);
2982 /* build block lists */
2983 for (n = eset_first(loopnodes); n != NULL; n = eset_next(loopnodes))
2984 set_irn_link(n, NULL);
2985 for (n = eset_first(extnodes); n != NULL; n = eset_next(extnodes))
2986 set_irn_link(n, NULL);
2987 for (n = eset_first(loopnodes); n != NULL; n = eset_next(loopnodes))
2989 b = get_nodes_block(n);
2990 set_irn_link(n, get_irn_link(b));
2993 for (n = eset_first(extnodes); n != NULL; n = eset_next(extnodes))
2995 b = get_nodes_block(n);
2996 set_irn_link(n, get_irn_link(b));
3000 for (b = eset_first(loopnodes); b != NULL; b = eset_next(loopnodes))
3002 fprintf(F, "graph: { title: \"");
3004 fprintf(F, "\" label: \"");
3005 dump_node_opcode(F, b);
3006 fprintf (F, " %ld", get_irn_node_nr(b));
3007 fprintf(F, "\" status:clustered color:yellow\n");
3009 /* dump the blocks edges */
3010 dump_ir_data_edges(F, b);
3012 /* dump the nodes that go into the block */
3013 for (n = get_irn_link(b); n; n = get_irn_link(n)) {
3014 if (eset_contains(extnodes, n))
3015 overrule_nodecolor = ird_color_lightblue;
3017 overrule_nodecolor = ird_color_default;
3018 if (!eset_contains(extnodes, n)) dump_ir_data_edges(F, n);
3021 /* Close the vcg information for the block */
3023 dump_const_node_local(F, b);
3026 for (b = eset_first(extnodes); b != NULL; b = eset_next(extnodes))
3028 fprintf(F, "graph: { title: \"");
3030 fprintf(F, "\" label: \"");
3031 dump_node_opcode(F, b);
3032 fprintf (F, " %ld", get_irn_node_nr(b));
3033 fprintf(F, "\" status:clustered color:lightblue\n");
3035 /* dump the nodes that go into the block */
3036 for (n = get_irn_link(b); n; n = get_irn_link(n)) {
3037 if (!eset_contains(loopnodes, n))
3038 overrule_nodecolor = ird_color_lightblue;
3040 overrule_nodecolor = ird_color_default;
3041 if (eset_contains(loopnodes, n)) dump_ir_data_edges(F, n);
3044 /* Close the vcg information for the block */
3046 dump_const_node_local(F, b);
3050 eset_destroy(loopnodes);
3051 eset_destroy(extnodes);