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-2006 Universit�t Karlsruhe
10 * Licence: This file protected by GPL - GNU GENERAL PUBLIC LICENSE.
24 #include "firm_common_t.h"
39 #include "type_or_entity.h"
43 #include "callgraph.h"
44 #include "irextbb_t.h"
46 #include "dbginfo_t.h"
58 extern void dump_irn_chi_term(FILE *FL, ir_node *n);
59 extern void dump_irn_state(FILE *FL, ir_node *n);
60 extern int get_opt_dump_abstvals(void);
61 typedef unsigned long SeqNo;
62 extern SeqNo get_Block_seqno(ir_node *n);
65 /* basis for a color range for vcg */
66 static int n_colors = 0;
67 static int base_color = 0;
69 /** Dump only irgs with names that start with this string */
70 static ident *dump_file_filter_id = NULL;
72 #define ERROR_TXT "<ERROR>"
74 /*******************************************************************/
75 /* flags to steer output */
76 /*******************************************************************/
78 /** An option to turn off edge labels */
79 static int edge_label = 1;
80 /** An option to turn off dumping values of constant entities */
81 static int const_entities = 1;
82 /** An option to dump the keep alive edges */
83 static int dump_keepalive = 0;
84 /** An option to dump ld_names instead of names. */
85 static int dump_ld_name = 1;
86 /** Compiler options to dump analysis information in dump_ir_graph */
87 static int dump_out_edge_flag = 0;
88 static int dump_loop_information_flag = 0;
89 static int dump_backedge_information_flag = 1;
90 static int dump_const_local = 0;
91 /** An option to dump all graph anchors */
92 static int dump_anchors = 0;
94 int dump_dominator_information_flag = 0;
95 int opt_dump_analysed_type_info = 1;
96 int opt_dump_pointer_values_to_info = 0; /* default off: for test compares!! */
98 static dumper_colors overrule_nodecolor = ird_color_default;
100 /** An additional edge hook. */
101 static DUMP_NODE_EDGE_FUNC dump_node_edge_hook = NULL;
103 void set_dump_node_edge_hook(DUMP_NODE_EDGE_FUNC func)
105 dump_node_edge_hook = func;
108 DUMP_NODE_EDGE_FUNC get_dump_node_edge_hook(void)
110 return dump_node_edge_hook;
114 static DUMP_NODE_EDGE_FUNC dump_block_edge_hook = NULL;
116 void set_dump_block_edge_hook(DUMP_NODE_EDGE_FUNC func)
118 dump_block_edge_hook = func;
121 DUMP_NODE_EDGE_FUNC get_dump_block_edge_hook(void)
123 return dump_node_edge_hook;
127 /** The vcg node attribute hook. */
128 static DUMP_IR_GRAPH_FUNC dump_ir_graph_hook = NULL;
129 /** The vcg node attribute hook. */
130 static DUMP_NODE_VCGATTR_FUNC dump_node_vcgattr_hook = NULL;
131 /** The vcg edge attribute hook. */
132 static DUMP_EDGE_VCGATTR_FUNC dump_edge_vcgattr_hook = NULL;
134 /* set the ir graph hook */
135 void set_dump_ir_graph_hook(DUMP_IR_GRAPH_FUNC hook) {
136 dump_ir_graph_hook = hook;
138 /* set the node attribute hook */
139 void set_dump_node_vcgattr_hook(DUMP_NODE_VCGATTR_FUNC hook) {
140 dump_node_vcgattr_hook = hook;
142 /* set the edge attribute hook */
143 void set_dump_edge_vcgattr_hook(DUMP_EDGE_VCGATTR_FUNC hook) {
144 dump_edge_vcgattr_hook = hook;
147 int get_opt_dump_const_local(void) {
148 if (!dump_out_edge_flag && !dump_loop_information_flag)
149 return dump_const_local;
154 void only_dump_method_with_name(ident *name) {
155 dump_file_filter_id = name;
158 ident *get_dump_file_filter_ident(void) {
159 return dump_file_filter_id;
162 /** Returns non-zero if dump file filter is not set, or if it is a
164 int is_filtered_dump_name(ident *name) {
165 if (!dump_file_filter_id) return 1;
166 return id_is_prefix(dump_file_filter_id, name);
169 /* To turn off display of edge labels. Edge labels often cause xvcg to
170 abort with a segmentation fault. */
171 void turn_off_edge_labels(void) {
175 void dump_consts_local(int flag) {
176 dump_const_local = flag;
179 void dump_constant_entity_values(int flag) {
180 const_entities = flag;
183 void dump_keepalive_edges(int flag) {
184 dump_keepalive = flag;
187 int get_opt_dump_keepalive_edges(void) {
188 return dump_keepalive;
191 void dump_out_edges(int flag) {
192 dump_out_edge_flag = flag;
195 void dump_dominator_information(int flag) {
196 dump_dominator_information_flag = flag;
199 void dump_loop_information(int flag) {
200 dump_loop_information_flag = flag;
203 void dump_backedge_information(int flag) {
204 dump_backedge_information_flag = flag;
207 /* Dump the information of type field specified in ana/irtypeinfo.h.
208 * If the flag is set, the type name is output in [] in the node label,
209 * else it is output as info.
211 void set_opt_dump_analysed_type_info(int flag) {
212 opt_dump_analysed_type_info = flag;
215 void dump_pointer_values_to_info(int flag) {
216 opt_dump_pointer_values_to_info = flag;
219 void dump_ld_names(int flag) {
223 void dump_all_anchors(int flag) {
227 /* -------------- some extended helper functions ----------------- */
230 * returns the name of a mode or <ERROR> if mode is NOT a mode object.
231 * in the later case, sets bad
233 const char *get_mode_name_ex(ir_mode *mode, int *bad)
236 return get_mode_name(mode);
242 * returns the name of a type or <ERROR> if mode is NOT a mode object.
243 * in the later case, sets bad
245 const char *get_type_name_ex(ir_type *tp, int *bad)
248 return get_type_name(tp);
254 * printf the VCG color
256 static void print_vcg_color(FILE *F, dumper_colors color) {
257 static const char *color_names[32] = {
258 "white", "blue", "red", "green",
259 "yellow", "magenta", "cyan", "darkgray",
260 "darkblue", "darkred", "darkgreen", "darkyellow",
261 "darkmagenta", "darkcyan", "gold", "lightgray",
262 "lightblue", "lightred", "lightgreen", "lightyellow",
263 "lightmagenta", "lightcyan", "lilac", "turquoise",
264 "aquamarine", "khaki", "purple", "yellowgreen",
265 "pink", "orange", "orchid", "black"
268 if (color != ird_color_default)
269 fprintf(F, "color:%s", color_names[color]);
273 * prints the edge from a type S to a type T with additional info fmt, ...
276 static void print_type_type_edge(FILE *F, ir_type *S, ir_type *T, const char *fmt, ...)
281 fprintf(F, "edge: { sourcename: "); PRINT_TYPEID(S);
282 fprintf(F, " targetname: "); PRINT_TYPEID(T);
283 vfprintf(F, fmt, ap);
289 * prints the edge from a type T to an entity E with additional info fmt, ...
292 static void print_type_ent_edge(FILE *F, ir_type *T, entity *E, const char *fmt, ...)
297 fprintf(F, "edge: { sourcename: "); PRINT_TYPEID(T);
298 fprintf(F, " targetname: \""); PRINT_ENTID(E); fprintf(F, "\"");
299 vfprintf(F, fmt, ap);
305 * prints the edge from an entity E to an entity T with additional info fmt, ...
308 static void print_ent_ent_edge(FILE *F, entity *E, entity *T, int backedge, const char *fmt, ...)
314 fprintf(F, "backedge: { sourcename: \"");
316 fprintf(F, "edge: { sourcename: \"");
318 fprintf(F, "\" targetname: \""); PRINT_ENTID(T); fprintf(F, "\"");
319 vfprintf(F, fmt, ap);
325 * prints the edge from an entity E to a type T with additional info fmt, ...
328 static void print_ent_type_edge(FILE *F, entity *E, ir_type *T, const char *fmt, ...)
333 fprintf(F, "edge: { sourcename: \""); PRINT_ENTID(E);
334 fprintf(F, "\" targetname: "); PRINT_TYPEID(T);
335 vfprintf(F, fmt, ap);
341 * prints the edge from a node N to a type T with additional info fmt, ...
344 static void print_node_type_edge(FILE *F, const ir_node *N, ir_type *T, const char *fmt, ...)
349 fprintf(F, "edge: { sourcename: \""); PRINT_NODEID(N);
350 fprintf(F, "\" targetname: "); PRINT_TYPEID(T);
351 vfprintf(F, fmt, ap);
357 * prints the edge from a node N to an entity E with additional info fmt, ...
360 static void print_node_ent_edge(FILE *F, const ir_node *N, entity *E, const char *fmt, ...)
365 fprintf(F, "edge: { sourcename: \""); PRINT_NODEID(N);
366 fprintf(F, "\" targetname: \""); PRINT_ENTID(E);
368 vfprintf(F, fmt, ap);
374 * prints the edge from an entity E to a node N with additional info fmt, ...
377 static void print_ent_node_edge(FILE *F, entity *E, const ir_node *N, const char *fmt, ...)
382 fprintf(F, "edge: { sourcename: \""); PRINT_ENTID(E);
383 fprintf(F, "\" targetname: \""); PRINT_NODEID(N); fprintf(F, "\"");
384 vfprintf(F, fmt, ap);
390 * prints the edge from a type E to an enumeration item item with additional info fmt, ...
393 static void print_enum_item_edge(FILE *F, ir_type *E, int item, const char *fmt, ...)
398 fprintf(F, "edge: { sourcename: "); PRINT_TYPEID(E);
399 fprintf(F, " targetname: \""); PRINT_ITEMID(E, item); fprintf(F, "\" ");
400 vfprintf(F, fmt, ap);
405 /*-----------------------------------------------------------------*/
406 /* global and ahead declarations */
407 /*-----------------------------------------------------------------*/
409 static void dump_whole_node(ir_node *n, void *env);
410 static INLINE void dump_loop_nodes_into_graph(FILE *F, ir_graph *irg);
412 /*-----------------------------------------------------------------*/
413 /* Helper functions. */
414 /*-----------------------------------------------------------------*/
417 * This map is used as a private link attr to be able to call dumper
418 * anywhere without destroying link fields.
420 static pmap *irdump_link_map = NULL;
422 /** NOT A STANDARD LIBFIRM INIT METHOD
424 * We do not want to integrate dumping into libfirm, i.e., if the dumpers
425 * are off, we want to have as few interferences as possible. Therefore the
426 * initialization is performed lazily and not called from within init_firm.
428 * Creates the link attribute map. */
429 static void init_irdump(void) {
430 /* We need a new, empty map. */
431 if (irdump_link_map) pmap_destroy(irdump_link_map);
432 irdump_link_map = pmap_create();
433 if (!dump_file_filter_id)
434 dump_file_filter_id = new_id_from_str("");
437 * Returns the private link field.
439 static void *ird_get_irn_link(ir_node *n) {
441 if (!irdump_link_map) return NULL;
443 if (pmap_contains(irdump_link_map, (void *)n))
444 res = pmap_get(irdump_link_map, (void *)n);
449 * Sets the private link field.
451 static void ird_set_irn_link(ir_node *n, void *x) {
452 if (!irdump_link_map)
454 pmap_insert(irdump_link_map, (void *)n, x);
458 * Gets the private link field of an irg.
460 static void *ird_get_irg_link(ir_graph *irg) {
462 if (!irdump_link_map) return NULL;
464 if (pmap_contains(irdump_link_map, (void *)irg))
465 res = pmap_get(irdump_link_map, (void *)irg);
470 * Sets the private link field of an irg.
472 static void ird_set_irg_link(ir_graph *irg, void *x) {
473 if (!irdump_link_map) init_irdump();
474 pmap_insert(irdump_link_map, (void *)irg, x);
478 * Walker, clears the private link field.
480 static void clear_link(ir_node * node, void * env) {
481 ird_set_irn_link(node, NULL);
485 * If the entity has a ld_name, returns it if the dump_ld_name is set,
486 * else returns the name of the entity.
488 static const char *_get_ent_dump_name(entity *ent, int dump_ld_name) {
490 return "<NULL entity>";
492 /* Don't use get_entity_ld_ident (ent) as it computes the mangled name! */
493 if (ent->ld_name) return get_id_str(ent->ld_name);
495 return get_id_str(ent->name);
499 * If the entity has a ld_name, returns it if the option dump_ld_name is set,
500 * else returns the name of the entity.
502 const char *get_ent_dump_name(entity *ent) {
503 return _get_ent_dump_name(ent, dump_ld_name);
506 /* Returns the name of an IRG. */
507 const char *get_irg_dump_name(ir_graph *irg) {
508 /* Don't use get_entity_ld_ident (ent) as it computes the mangled name! */
509 return _get_ent_dump_name(get_irg_entity(irg), 1);
513 * Returns non-zero if a node is in floating state.
515 static int node_floats(ir_node *n) {
516 return ((get_irn_pinned(n) == op_pin_state_floats) &&
517 (get_irg_pinned(current_ir_graph) == op_pin_state_floats));
521 * Walker that visits the anchors
523 static void ird_walk_graph(ir_graph *irg, irg_walk_func *pre, irg_walk_func *post, void *env) {
524 irg_walk_graph(irg, pre, post, env);
529 for (i = anchor_max - 1; i >= 0; --i) {
530 ir_node *n = irg->anchors[i];
533 /* reset the visit flag: will be increase in the walker */
534 set_irg_visited(irg, get_irg_visited(irg) - 1);
535 irg_walk(n, pre, post, env);
542 * Walker, allocates an array for all blocks and puts it's nodes non-floating nodes into this array.
544 static void collect_node(ir_node * node, void *env) {
547 || get_irn_op(node) == op_Bad
548 || get_irn_op(node) == op_Unknown
549 || get_irn_op(node) == op_NoMem) {
550 ir_node ** arr = (ir_node **) ird_get_irg_link(get_irn_irg(node));
551 if (!arr) arr = NEW_ARR_F(ir_node *, 0);
552 ARR_APP1(ir_node *, arr, node);
553 ird_set_irg_link(get_irn_irg(node), arr); /* arr is an l-value, APP_ARR might change it! */
555 ir_node * block = get_nodes_block(node);
558 /* this node is in a Bad block, so we must place it into the graph's list */
559 ir_node ** arr = (ir_node **) ird_get_irg_link(get_irn_irg(node));
560 if (!arr) arr = NEW_ARR_F(ir_node *, 0);
561 ARR_APP1(ir_node *, arr, node);
562 ird_set_irg_link(get_irn_irg(node), arr); /* arr is an l-value, APP_ARR might change it! */
565 ird_set_irn_link(node, ird_get_irn_link(block));
566 ird_set_irn_link(block, node);
571 /** Construct lists to walk ir block-wise.
573 * Collects all blocks, nodes not op_pin_state_pinned,
574 * Bad, NoMem and Unknown into a flexible array in link field of
575 * irg they belong to. Sets the irg link field to NULL in all
576 * graphs not visited.
577 * Free the list with DEL_ARR_F().
579 static ir_node **construct_block_lists(ir_graph *irg) {
580 int i, rem_view = get_interprocedural_view();
581 ir_graph *rem = current_ir_graph;
582 current_ir_graph = irg;
584 for (i = get_irp_n_irgs() - 1; i >= 0; --i)
585 ird_set_irg_link(get_irp_irg(i), NULL);
587 ird_walk_graph(current_ir_graph, clear_link, collect_node, current_ir_graph);
589 /* Collect also EndReg and EndExcept. We do not want to change the walker. */
590 set_interprocedural_view(0);
592 set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph)-1);
593 irg_walk(get_irg_end_reg(current_ir_graph), clear_link, collect_node, current_ir_graph);
594 set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph)-1);
595 irg_walk(get_irg_end_except(current_ir_graph), clear_link, collect_node, current_ir_graph);
597 set_interprocedural_view(rem_view);
599 current_ir_graph = rem;
600 return ird_get_irg_link(irg);
603 typedef struct _list_tuple {
605 ir_extblk **extbb_list;
608 /** Construct lists to walk IR extended block-wise.
609 * Free the lists in the tuple with DEL_ARR_F().
610 * Sets the irg link field to NULL in all
611 * graphs not visited.
613 static list_tuple *construct_extblock_lists(ir_graph *irg) {
614 ir_node **blk_list = construct_block_lists(irg);
616 ir_graph *rem = current_ir_graph;
617 list_tuple *lists = xmalloc(sizeof(*lists));
619 current_ir_graph = irg;
621 lists->blk_list = NEW_ARR_F(ir_node *, 0);
622 lists->extbb_list = NEW_ARR_F(ir_extblk *, 0);
624 inc_irg_block_visited(irg);
625 for (i = ARR_LEN(blk_list) - 1; i >= 0; --i) {
628 if (is_Block(blk_list[i])) {
629 ext = get_Block_extbb(blk_list[i]);
631 if (extbb_not_visited(ext)) {
632 ARR_APP1(ir_extblk *, lists->extbb_list, ext);
633 mark_extbb_visited(ext);
637 ARR_APP1(ir_node *, lists->blk_list, blk_list[i]);
641 current_ir_graph = rem;
642 ird_set_irg_link(irg, lists);
646 /*-----------------------------------------------------------------*/
647 /* Routines to dump information about a single ir node. */
648 /*-----------------------------------------------------------------*/
651 * dump the name of a node n to the File F.
653 int dump_node_opcode(FILE *F, ir_node *n)
656 const ir_op_ops *ops = get_op_ops(get_irn_op(n));
658 /* call the dump_node operation if available */
660 return ops->dump_node(n, F, dump_node_opcode_txt);
662 /* implementation for default nodes */
663 switch (get_irn_opcode(n)) {
668 res = tarval_snprintf(buf, sizeof(buf), get_Const_tarval(n));
669 assert(res < sizeof(buf) && "buffer to small for tarval_snprintf");
674 switch (get_SymConst_kind(n)) {
675 case symconst_addr_name:
676 /* don't use get_SymConst_ptr_info as it mangles the name. */
677 fprintf(F, "SymC %s", get_id_str(get_SymConst_name(n)));
679 case symconst_addr_ent:
680 fprintf(F, "SymC &%s", get_entity_name(get_SymConst_entity(n)));
682 case symconst_type_tag:
683 fprintf(F, "SymC %s tag", get_type_name_ex(get_SymConst_type(n), &bad));
685 case symconst_type_size:
686 fprintf(F, "SymC %s size", get_type_name_ex(get_SymConst_type(n), &bad));
688 case symconst_type_align:
689 fprintf(F, "SymC %s align", get_type_name_ex(get_SymConst_type(n), &bad));
691 case symconst_enum_const:
692 fprintf(F, "SymC %s enum", get_enumeration_name(get_SymConst_enum(n)));
698 if (!get_interprocedural_view())
705 ir_node *pred = get_Proj_pred(n);
707 if (get_irn_opcode(pred) == iro_Cond
708 && get_Proj_proj(n) == get_Cond_defaultProj(pred)
709 && get_irn_mode(get_Cond_selector(pred)) != mode_b)
710 fprintf (F, "defProj");
718 if (get_interprocedural_view()) {
719 fprintf(F, "%s %s", get_irn_opname(n), get_ent_dump_name(get_irg_entity(get_irn_irg(n))));
724 case iro_CallBegin: {
725 ir_node *addr = get_CallBegin_ptr(n);
727 if (get_irn_op(addr) == op_Sel)
728 ent = get_Sel_entity(addr);
729 else if ((get_irn_op(addr) == op_SymConst) && (get_SymConst_kind(addr) == symconst_addr_ent))
730 ent = get_SymConst_entity(addr);
731 fprintf (F, "%s", get_irn_opname(n));
732 if (ent) fprintf (F, " %s", get_entity_name(ent));
736 fprintf (F, "%s[%s]", get_irn_opname(n), get_mode_name_ex(get_Load_mode(n), &bad));
739 fprintf (F, "%s%s", is_Block_dead(n) ? "Dead " : "", get_irn_opname(n));
742 if (get_Conv_strict(n))
743 fprintf (F, "strict");
744 fprintf (F, "%s", get_irn_opname(n));
749 fprintf (F, "%s", get_irn_opname(n));
756 * Dump the mode of a node n to a file F.
757 * Ignore modes that are "always known".
759 static int dump_node_mode(FILE *F, ir_node *n)
762 const ir_op_ops *ops = get_op_ops(get_irn_op(n));
765 /* call the dump_node operation if available */
767 return ops->dump_node(n, F, dump_node_mode_txt);
769 /* default implementation */
770 iro = get_irn_opcode(n);
782 ir_mode *mode = get_irn_mode(n);
784 if (mode && mode != mode_BB && mode != mode_ANY && mode != mode_BAD &&
785 (mode != mode_T || iro == iro_Proj))
786 fprintf(F, "%s", get_mode_name_ex(mode, &bad));
794 * Dump the type of a node n to a file F if it's known.
796 static int dump_node_typeinfo(FILE *F, ir_node *n) {
799 if (opt_dump_analysed_type_info) {
800 if (get_irg_typeinfo_state(current_ir_graph) == ir_typeinfo_consistent ||
801 get_irg_typeinfo_state(current_ir_graph) == ir_typeinfo_inconsistent) {
802 ir_type *tp = get_irn_typeinfo_type(n);
803 if (tp != firm_none_type)
804 fprintf(F, "[%s] ", get_type_name_ex(tp, &bad));
812 typedef struct _pns_lookup {
813 long nr; /**< the proj number */
814 const char *name; /**< the name of the Proj */
817 typedef struct _proj_lookup {
818 opcode code; /**< the opcode of the Proj predecessor */
819 unsigned num_data; /**< number of data entries */
820 const pns_lookup_t *data; /**< the data */
823 #define ARR_SIZE(a) (sizeof(a)/sizeof(a[0]))
825 /** the lookup table for Proj(Start) names */
826 static const pns_lookup_t start_lut[] = {
827 #define X(a) { pn_Start_##a, #a }
837 /** the lookup table for Proj(Cond) names */
838 static const pns_lookup_t cond_lut[] = {
839 #define X(a) { pn_Cond_##a, #a }
845 /** the lookup table for Proj(Call) names */
846 static const pns_lookup_t call_lut[] = {
847 #define X(a) { pn_Call_##a, #a }
856 /** the lookup table for Proj(Quot) names */
857 static const pns_lookup_t quot_lut[] = {
858 #define X(a) { pn_Quot_##a, #a }
865 /** the lookup table for Proj(DivMod) names */
866 static const pns_lookup_t divmod_lut[] = {
867 #define X(a) { pn_DivMod_##a, #a }
875 /** the lookup table for Proj(Div) names */
876 static const pns_lookup_t div_lut[] = {
877 #define X(a) { pn_Div_##a, #a }
884 /** the lookup table for Proj(Mod) names */
885 static const pns_lookup_t mod_lut[] = {
886 #define X(a) { pn_Mod_##a, #a }
893 /** the lookup table for Proj(Load) names */
894 static const pns_lookup_t load_lut[] = {
895 #define X(a) { pn_Load_##a, #a }
902 /** the lookup table for Proj(Store) names */
903 static const pns_lookup_t store_lut[] = {
904 #define X(a) { pn_Store_##a, #a }
910 /** the lookup table for Proj(Alloc) names */
911 static const pns_lookup_t alloc_lut[] = {
912 #define X(a) { pn_Alloc_##a, #a }
919 /** the lookup table for Proj(CopyB) names */
920 static const pns_lookup_t copyb_lut[] = {
921 #define X(a) { pn_CopyB_##a, #a }
928 /** the lookup table for Proj(InstOf) names */
929 static const pns_lookup_t instof_lut[] = {
930 #define X(a) { pn_InstOf_##a, #a }
938 /** the lookup table for Proj(Raise) names */
939 static const pns_lookup_t raise_lut[] = {
940 #define X(a) { pn_Raise_##a, #a }
946 /** the lookup table for Proj(Bound) names */
947 static const pns_lookup_t bound_lut[] = {
948 #define X(a) { pn_Bound_##a, #a }
955 /** the Proj lookup table */
956 static const proj_lookup_t proj_lut[] = {
957 #define E(a) ARR_SIZE(a), a
958 { iro_Start, E(start_lut) },
959 { iro_Cond, E(cond_lut) },
960 { iro_Call, E(call_lut) },
961 { iro_Quot, E(quot_lut) },
962 { iro_DivMod, E(divmod_lut) },
963 { iro_Div, E(div_lut) },
964 { iro_Mod, E(mod_lut) },
965 { iro_Load, E(load_lut) },
966 { iro_Store, E(store_lut) },
967 { iro_Alloc, E(alloc_lut) },
968 { iro_CopyB, E(copyb_lut) },
969 { iro_InstOf, E(instof_lut) },
970 { iro_Raise, E(raise_lut) },
971 { iro_Bound, E(bound_lut) }
976 * Dump additional node attributes of some nodes to a file F.
979 dump_node_nodeattr(FILE *F, ir_node *n)
985 const ir_op_ops *ops = get_op_ops(get_irn_op(n));
987 /* call the dump_node operation if available */
989 return ops->dump_node(n, F, dump_node_nodeattr_txt);
991 switch (get_irn_opcode(n)) {
993 if (0 && get_interprocedural_view()) {
994 fprintf (F, "%s ", get_ent_dump_name(get_irg_entity(current_ir_graph)));
999 pred = get_Proj_pred(n);
1000 proj_nr = get_Proj_proj(n);
1002 code = get_irn_opcode(pred);
1004 if (code == iro_Cmp)
1005 fprintf (F, "%s ", get_pnc_string(get_Proj_proj(n)));
1006 else if (code == iro_Proj && get_irn_opcode(get_Proj_pred(pred)) == iro_Start)
1007 fprintf (F, "Arg %ld ", proj_nr);
1008 else if (code == iro_Cond && get_irn_mode(get_Cond_selector(pred)) != mode_b)
1009 fprintf (F, "%ld ", proj_nr);
1011 unsigned i, j, f = 0;
1013 for (i = 0; i < ARR_SIZE(proj_lut); ++i) {
1014 if (code == proj_lut[i].code) {
1015 for (j = 0; j < proj_lut[i].num_data; ++j) {
1016 if (proj_nr == proj_lut[i].data[j].nr) {
1017 fprintf (F, "%s ", proj_lut[i].data[j].name);
1026 fprintf (F, "%ld ", proj_nr);
1027 if (code == iro_Cond && get_Cond_jmp_pred(pred) != COND_JMP_PRED_NONE) {
1028 if (proj_nr == pn_Cond_false && get_Cond_jmp_pred(pred) == COND_JMP_PRED_FALSE)
1029 fprintf(F, "PRED ");
1030 if (proj_nr == pn_Cond_true && get_Cond_jmp_pred(pred) == COND_JMP_PRED_TRUE)
1031 fprintf(F, "PRED ");
1036 proj_nr = get_Filter_proj(n);
1037 if (! get_interprocedural_view()) {
1039 pred = get_Filter_pred(n);
1043 fprintf (F, "%ld ", proj_nr);
1046 fprintf (F, "%s ", get_ent_dump_name(get_Sel_entity(n)));
1049 fprintf (F, "(%s) ", get_type_name_ex(get_Cast_type(n), &bad));
1052 fprintf (F, "%s ", get_pnc_string(get_Confirm_cmp(n)));
1055 fprintf (F, "(%s) ", get_type_name_ex(get_CopyB_type(n), &bad));
1066 #include "execution_frequency.h"
1067 #include "callgraph.h"
1069 void dump_node_ana_vals(FILE *F, ir_node *n) {
1071 fprintf(F, " %lf*(%2.0lf + %2.0lf) = %2.0lf ",
1072 get_irn_exec_freq(n),
1073 get_irg_method_execution_frequency(get_irn_irg(n)),
1074 pow(5, get_irg_recursion_depth(get_irn_irg(n))),
1075 get_irn_exec_freq(n) * (get_irg_method_execution_frequency(get_irn_irg(n)) + pow(5, get_irg_recursion_depth(get_irn_irg(n))))
1080 /* Dumps a node label without the enclosing ". */
1081 int dump_node_label(FILE *F, ir_node *n) {
1084 bad |= dump_node_opcode(F, n);
1085 bad |= dump_node_mode(F, n);
1087 bad |= dump_node_typeinfo(F, n);
1088 bad |= dump_node_nodeattr(F, n);
1089 fprintf(F, "%ld", get_irn_node_nr(n));
1096 * Dumps the attributes of a node n into the file F.
1097 * Currently this is only the color of a node.
1099 static void dump_node_vcgattr(FILE *F, ir_node *node, ir_node *local, int bad)
1104 print_vcg_color(F, ird_color_red);
1108 if (dump_node_vcgattr_hook)
1109 if (dump_node_vcgattr_hook(F, node, local))
1112 n = local ? local : node;
1114 if (overrule_nodecolor != ird_color_default) {
1115 print_vcg_color(F, overrule_nodecolor);
1119 switch (get_irn_opcode(n)) {
1126 print_vcg_color(F, ird_color_blue);
1129 if (is_Block_dead(n))
1130 print_vcg_color(F, ird_color_lightred);
1132 print_vcg_color(F, ird_color_lightyellow);
1135 print_vcg_color(F, ird_color_green);
1139 print_vcg_color(F, ird_color_gold);
1142 print_vcg_color(F, ird_color_orchid);
1148 print_vcg_color(F, ird_color_yellow);
1151 PRINT_DEFAULT_NODE_ATTR;
1155 /* Adds a new node info dumper callback. */
1156 void *dump_add_node_info_callback(dump_node_info_cb_t *cb, void *data)
1158 hook_entry_t *info = xmalloc(sizeof(*info));
1160 info->hook._hook_node_info = cb;
1161 info->context = data;
1162 register_hook(hook_node_info, info);
1167 /* Remove a previously added info dumper callback. */
1168 void dump_remv_node_info_callback(void *handle)
1170 hook_entry_t *info = handle;
1171 unregister_hook(hook_node_info, info);
1176 * Dump the node information of a node n to a file F.
1178 static INLINE int dump_node_info(FILE *F, ir_node *n)
1181 const ir_op_ops *ops = get_op_ops(get_irn_op(n));
1183 fprintf (F, " info1: \"");
1184 bad = dump_irnode_to_file(F, n);
1185 /* call the dump_node operation if available */
1187 bad = ops->dump_node(n, F, dump_node_info_txt);
1189 /* allow additional info to be added */
1190 hook_node_info(F, n);
1197 * checks whether a node is "constant-like" ie can be treated "block-less"
1200 int is_constlike_node(ir_node *n) {
1201 ir_op *op = get_irn_op(n);
1202 return (op == op_Const || op == op_Bad || op == op_NoMem || op == op_SymConst || op == op_Unknown);
1206 /** outputs the predecessors of n, that are constants, local. I.e.,
1207 generates a copy of the constant predecessors for each node called with. */
1208 static void dump_const_node_local(FILE *F, ir_node *n) {
1210 if (!get_opt_dump_const_local()) return;
1212 /* Use visited flag to avoid outputting nodes twice.
1213 initialize it first. */
1214 for (i = 0; i < get_irn_arity(n); i++) {
1215 ir_node *con = get_irn_n(n, i);
1216 if (is_constlike_node(con)) {
1217 set_irn_visited(con, get_irg_visited(current_ir_graph) - 1);
1221 for (i = 0; i < get_irn_arity(n); i++) {
1222 ir_node *con = get_irn_n(n, i);
1223 if (is_constlike_node(con) && irn_not_visited(con)) {
1226 mark_irn_visited(con);
1227 /* Generate a new name for the node by appending the names of
1229 fprintf(F, "node: {title: "); PRINT_CONSTID(n, con);
1230 fprintf(F, " label: \"");
1231 bad |= dump_node_label(F, con);
1233 bad |= dump_node_info(F, con);
1234 dump_node_vcgattr(F, n, con, bad);
1240 /** If the block of an edge is a const_like node, dump it local with an edge */
1241 static void dump_const_block_local(FILE *F, ir_node *n) {
1244 if (!get_opt_dump_const_local()) return;
1246 blk = get_nodes_block(n);
1247 if (is_constlike_node(blk)) {
1250 /* Generate a new name for the node by appending the names of
1252 fprintf(F, "node: {title: \""); PRINT_CONSTBLKID(n, blk);
1253 fprintf(F, "\" label: \"");
1254 bad |= dump_node_label(F, blk);
1256 bad |= dump_node_info(F, blk);
1257 dump_node_vcgattr(F, n, blk, bad);
1260 fprintf (F, "edge: { sourcename: \"");
1262 fprintf (F, "\" targetname: \""); PRINT_CONSTBLKID(n,blk);
1264 if (dump_edge_vcgattr_hook) {
1266 if (dump_edge_vcgattr_hook(F, n, -1)) {
1271 fprintf (F, " " BLOCK_EDGE_ATTR "}\n");
1276 fprintf (F, "\" " BLOCK_EDGE_ATTR "}\n");
1281 * prints the error message of a node to a file F as info2.
1283 static void INLINE print_node_error(FILE *F, const char *err_msg)
1288 fprintf (F, " info2: \"%s\"", err_msg);
1292 * prints debug messages of a node to file F as info3.
1294 static void print_dbg_info(FILE *F, dbg_info *dbg)
1298 if (__dbg_info_snprint) {
1300 if (__dbg_info_snprint(buf, sizeof(buf), dbg) > 0)
1301 fprintf (F, " info3: \"%s\"\n", buf);
1308 static void dump_node(FILE *F, ir_node *n)
1313 if (get_opt_dump_const_local() && is_constlike_node(n))
1316 /* dump this node */
1317 fprintf(F, "node: {title: \""); PRINT_NODEID(n); fprintf(F, "\" label: \"");
1319 bad = ! irn_vrfy_irg_dump(n, current_ir_graph, &p);
1320 bad |= dump_node_label(F, n);
1321 dump_node_ana_vals(F, n);
1322 //dump_node_ana_info(F, n);
1324 bad |= dump_node_info(F, n);
1325 print_node_error(F, p);
1326 print_dbg_info(F, get_irn_dbg_info(n));
1327 dump_node_vcgattr(F, n, NULL, bad);
1329 dump_const_node_local(F, n);
1331 if(dump_node_edge_hook)
1332 dump_node_edge_hook(F, n);
1334 dump_irn_chi_term(F, n);
1335 dump_irn_state(F, n);
1339 /** dump the edge to the block this node belongs to */
1341 dump_ir_block_edge(FILE *F, ir_node *n) {
1342 if (get_opt_dump_const_local() && is_constlike_node(n)) return;
1343 if (is_no_Block(n)) {
1344 ir_node *block = get_nodes_block(n);
1346 if (get_opt_dump_const_local() && is_constlike_node(block)) {
1347 dump_const_block_local(F, n);
1350 fprintf (F, "edge: { sourcename: \"");
1352 fprintf (F, "\" targetname: ");
1353 fprintf(F, "\""); PRINT_NODEID(block); fprintf(F, "\"");
1355 if (dump_edge_vcgattr_hook) {
1357 if (dump_edge_vcgattr_hook(F, n, -1)) {
1362 fprintf (F, " " BLOCK_EDGE_ATTR "}\n");
1367 fprintf (F, " " BLOCK_EDGE_ATTR "}\n");
1373 print_data_edge_vcgattr(FILE *F, ir_node *from, int to) {
1375 * do not use get_nodes_block() here, will fail
1376 * if the irg is not pinned.
1378 if (get_irn_n(from, -1) == get_irn_n(get_irn_n(from, to), -1))
1379 fprintf (F, INTRA_DATA_EDGE_ATTR);
1381 fprintf (F, INTER_DATA_EDGE_ATTR);
1385 print_mem_edge_vcgattr(FILE *F, ir_node *from, int to) {
1387 * do not use get_nodes_block() here, will fail
1388 * if the irg is not pinned.
1390 if (get_irn_n(from, -1) == get_irn_n(get_irn_n(from, to), -1))
1391 fprintf (F, INTRA_MEM_EDGE_ATTR);
1393 fprintf (F, INTER_MEM_EDGE_ATTR);
1397 print_edge_vcgattr(FILE *F, ir_node *from, int to) {
1400 if (dump_edge_vcgattr_hook)
1401 if (dump_edge_vcgattr_hook(F, from, to))
1404 if (dump_backedge_information_flag && is_backedge(from, to))
1405 fprintf (F, BACK_EDGE_ATTR);
1407 switch (get_irn_opcode(from)) {
1409 fprintf (F, CF_EDGE_ATTR);
1411 case iro_Start: break;
1414 if (get_irn_mode(get_End_keepalive(from, to)) == mode_BB)
1415 fprintf (F, CF_EDGE_ATTR);
1416 if (get_irn_mode(get_End_keepalive(from, to)) == mode_X)
1417 fprintf (F, INTER_MEM_EDGE_ATTR);
1421 if (is_Proj(from)) {
1422 if (get_irn_mode(from) == mode_M)
1423 print_mem_edge_vcgattr(F, from, to);
1424 else if (get_irn_mode(from) == mode_X)
1425 fprintf(F, CF_EDGE_ATTR);
1427 print_data_edge_vcgattr(F, from, to);
1429 else if (get_irn_mode(get_irn_n(from, to)) == mode_M)
1430 print_mem_edge_vcgattr(F, from, to);
1431 else if (get_irn_mode(get_irn_n(from, to)) == mode_X)
1432 fprintf (F, CF_EDGE_ATTR);
1434 print_data_edge_vcgattr(F, from, to);
1438 /* dump edges to our inputs */
1440 dump_ir_data_edges(FILE *F, ir_node *n) {
1442 unsigned long visited = get_irn_visited(n);
1444 if ((get_irn_op(n) == op_End) && (!dump_keepalive))
1447 /* dump the dependency edges. */
1448 for (i = 0; i < get_irn_deps(n); ++i) {
1449 ir_node *dep = get_irn_dep(n, i);
1452 fprintf(F, "edge: {sourcename: \"");
1454 fprintf(F, "\" targetname: ");
1455 if ((get_opt_dump_const_local()) && is_constlike_node(dep)) {
1456 PRINT_CONSTID(n, dep);
1462 fprintf(F, " label: \"%d\" ", i);
1463 fprintf(F, " color: darkgreen}\n");
1467 for (i = 0; i < get_irn_arity(n); i++) {
1468 ir_node * pred = get_irn_n(n, i);
1471 if ((get_interprocedural_view() && get_irn_visited(pred) < visited))
1472 continue; /* pred not dumped */
1474 if (dump_backedge_information_flag && is_backedge(n, i))
1475 fprintf (F, "backedge: {sourcename: \"");
1477 fprintf (F, "edge: {sourcename: \"");
1479 fprintf (F, "\" targetname: ");
1480 if ((get_opt_dump_const_local()) && is_constlike_node(pred)) {
1481 PRINT_CONSTID(n, pred);
1483 fprintf(F, "\""); PRINT_NODEID(pred); fprintf(F, "\"");
1485 fprintf (F, " label: \"%d\" ", i);
1486 print_edge_vcgattr(F, n, i);
1491 /** Dumps a node and its edges but not the block edge
1494 dump_node_wo_blockedge (ir_node *n, void *env) {
1497 dump_ir_data_edges(F, n);
1500 /** Dumps a node and its edges.
1503 dump_whole_node (ir_node *n, void *env) {
1505 dump_node_wo_blockedge(n, env);
1506 if (!node_floats(n)) dump_ir_block_edge(F, n);
1510 dump_const_node(ir_node *n, void *env) {
1511 if (is_Block(n)) return;
1512 dump_node_wo_blockedge(n, env);
1515 /***********************************************************************/
1516 /* the following routines dump the nodes/irgs bracketed to graphs. */
1517 /***********************************************************************/
1519 /** Dumps a constant expression as entity initializer, array bound ...
1521 static void dump_const_expression(FILE *F, ir_node *value) {
1522 ir_graph *rem = current_ir_graph;
1523 int rem_dump_const_local = dump_const_local;
1524 dump_const_local = 0;
1525 current_ir_graph = get_const_code_irg();
1526 irg_walk(value, dump_const_node, NULL, F);
1527 /* Decrease visited flag so that we walk with the same flag for the next
1528 expression. This guarantees that we don't dump the same node twice,
1529 as for const expressions cse is performed to save memory. */
1530 set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph) -1);
1531 current_ir_graph = rem;
1532 dump_const_local = rem_dump_const_local;
1535 /** Dump a block as graph containing its nodes.
1537 * Expects to find nodes belonging to the block as list in its
1539 * Dumps the edges of all nodes including itself. */
1541 dump_whole_block(FILE *F, ir_node *block) {
1543 dumper_colors color = ird_color_yellow;
1545 assert(is_Block(block));
1547 fprintf(F, "graph: { title: \"");
1548 PRINT_NODEID(block);
1549 fprintf(F, "\" label: \"");
1550 dump_node_label(F, block);
1552 if (get_opt_dump_abstvals())
1553 fprintf (F, " seqno: %d", (int)get_Block_seqno(block));
1556 /* colorize blocks */
1557 if (! get_Block_matured(block))
1558 color = ird_color_red;
1559 if (is_Block_dead(block))
1560 color = ird_color_orange;
1562 fprintf(F, "\" status:clustered ");
1563 print_vcg_color(F, color);
1566 /* yComp can show attributes for blocks, XVCG parses but ignores them */
1567 dump_node_info(F, block);
1568 print_dbg_info(F, get_irn_dbg_info(block));
1570 /* dump the blocks edges */
1571 dump_ir_data_edges(F, block);
1573 if (dump_block_edge_hook)
1574 dump_block_edge_hook(F, block);
1576 /* dump the nodes that go into the block */
1577 for (node = ird_get_irn_link(block); node; node = ird_get_irn_link(node)) {
1579 dump_ir_data_edges(F, node);
1582 /* Close the vcg information for the block */
1584 dump_const_node_local(F, block);
1586 dump_irn_chi_term(F, block);
1591 /** dumps a graph block-wise. Expects all blockless nodes in arr in irgs link.
1592 * The outermost nodes: blocks and nodes not op_pin_state_pinned, Bad, Unknown. */
1594 dump_block_graph(FILE *F, ir_graph *irg) {
1596 ir_graph *rem = current_ir_graph;
1597 ir_node **arr = ird_get_irg_link(irg);
1598 current_ir_graph = irg;
1600 for (i = ARR_LEN(arr) - 1; i >= 0; --i) {
1601 ir_node * node = arr[i];
1602 if (is_Block(node)) {
1603 /* Dumps the block and all the nodes in the block, which are to
1604 be found in Block->link. */
1605 dump_whole_block(F, node);
1607 /* Nodes that are not in a Block. */
1609 if (!node_floats(node) && is_Bad(get_nodes_block(node))) {
1610 dump_const_block_local(F, node);
1612 dump_ir_data_edges(F, node);
1616 if (dump_loop_information_flag && (get_irg_loopinfo_state(irg) & loopinfo_valid))
1617 dump_loop_nodes_into_graph(F, irg);
1619 current_ir_graph = rem;
1623 * Dump the info for an irg.
1624 * Parsed by XVCG but not shown. use yComp.
1626 static void dump_graph_info(FILE *F, ir_graph *irg) {
1627 fprintf(F, "info1: \"");
1628 dump_entity_to_file(F, get_irg_entity(irg), dump_verbosity_entattrs | dump_verbosity_entconsts);
1632 /** Dumps an irg as a graph clustered by block nodes.
1633 * If interprocedural view edges can point to nodes out of this graph.
1635 static void dump_graph_from_list(FILE *F, ir_graph *irg) {
1636 entity *ent = get_irg_entity(irg);
1638 fprintf(F, "graph: { title: \"");
1640 fprintf(F, "\" label: \"%s\" status:clustered color:white \n",
1641 get_ent_dump_name(ent));
1643 dump_graph_info(F, irg);
1644 print_dbg_info(F, get_entity_dbg_info(ent));
1646 dump_block_graph(F, irg);
1648 /* Close the vcg information for the irg */
1649 fprintf(F, "}\n\n");
1652 /** dumps a graph extended block-wise. Expects all blockless nodes in arr in irgs link.
1653 * The outermost nodes: blocks and nodes not op_pin_state_pinned, Bad, Unknown. */
1655 dump_extblock_graph(FILE *F, ir_graph *irg) {
1657 ir_graph *rem = current_ir_graph;
1658 ir_extblk **arr = ird_get_irg_link(irg);
1659 current_ir_graph = irg;
1661 for (i = ARR_LEN(arr) - 1; i >= 0; --i) {
1662 ir_extblk *extbb = arr[i];
1663 ir_node *leader = get_extbb_leader(extbb);
1666 fprintf(F, "graph: { title: \"");
1667 PRINT_EXTBBID(leader);
1668 fprintf(F, "\" label: \"ExtBB %ld\" status:clustered color:lightgreen\n",
1669 get_irn_node_nr(leader));
1671 for (j = ARR_LEN(extbb->blks) - 1; j >= 0; --j) {
1672 ir_node * node = extbb->blks[j];
1673 if (is_Block(node)) {
1674 /* Dumps the block and all the nodes in the block, which are to
1675 be found in Block->link. */
1676 dump_whole_block(F, node);
1678 /* Nodes that are not in a Block. */
1680 if (is_Bad(get_nodes_block(node)) && !node_floats(node)) {
1681 dump_const_block_local(F, node);
1683 dump_ir_data_edges(F, node);
1689 if (dump_loop_information_flag && (get_irg_loopinfo_state(irg) & loopinfo_valid))
1690 dump_loop_nodes_into_graph(F, irg);
1692 current_ir_graph = rem;
1697 /*******************************************************************/
1698 /* Basic type and entity nodes and edges. */
1699 /*******************************************************************/
1701 /** dumps the edges between nodes and their type or entity attributes. */
1702 static void dump_node2type_edges(ir_node *n, void *env)
1707 switch (get_irn_opcode(n)) {
1709 /* @@@ some consts have an entity */
1712 if (SYMCONST_HAS_TYPE(get_SymConst_kind(n)))
1713 print_node_type_edge(F,n,get_SymConst_type(n),NODE2TYPE_EDGE_ATTR);
1716 print_node_ent_edge(F,n,get_Sel_entity(n),NODE2TYPE_EDGE_ATTR);
1719 print_node_type_edge(F,n,get_Call_type(n),NODE2TYPE_EDGE_ATTR);
1722 print_node_type_edge(F,n,get_Alloc_type(n),NODE2TYPE_EDGE_ATTR);
1725 print_node_type_edge(F,n,get_Free_type(n),NODE2TYPE_EDGE_ATTR);
1728 print_node_type_edge(F,n,get_Cast_type(n),NODE2TYPE_EDGE_ATTR);
1736 static int print_type_info(FILE *F, ir_type *tp) {
1739 if (get_type_state(tp) == layout_undefined) {
1740 fprintf(F, "state: layout_undefined\n");
1742 fprintf(F, "state: layout_fixed,\n");
1744 if (get_type_mode(tp))
1745 fprintf(F, "mode: %s,\n", get_mode_name_ex(get_type_mode(tp), &bad));
1746 fprintf(F, "size: %db,\n", get_type_size_bits(tp));
1751 static void print_typespecific_info(FILE *F, ir_type *tp) {
1752 switch (get_type_tpop_code(tp)) {
1755 fprintf(F, "peculiarity: %s\n", get_peculiarity_string(get_class_peculiarity(tp)));
1762 fprintf(F, "variadicity: %s\n", get_variadicity_name(get_method_variadicity(tp)));
1763 fprintf(F, "params: %d\n", get_method_n_params(tp));
1764 fprintf(F, "results: %d\n", get_method_n_ress(tp));
1772 case tpo_enumeration:
1786 static void print_typespecific_vcgattr(FILE *F, ir_type *tp) {
1787 switch (get_type_tpop_code(tp)) {
1790 if (peculiarity_existent == get_class_peculiarity(tp))
1791 fprintf (F, " " TYPE_CLASS_NODE_ATTR);
1793 fprintf (F, " " TYPE_DESCRIPTION_NODE_ATTR);
1797 fprintf (F, " " TYPE_METH_NODE_ATTR);
1808 case tpo_enumeration:
1822 int dump_type_node(FILE *F, ir_type *tp)
1826 fprintf (F, "node: {title: ");
1828 fprintf (F, " label: \"%s %s\"", get_type_tpop_name(tp), get_type_name_ex(tp, &bad));
1829 fprintf (F, " info1: \"");
1831 bad |= print_type_info(F, tp);
1832 print_typespecific_info(F, tp);
1834 dump_type_to_file(F, tp, dump_verbosity_max);
1836 fprintf (F, "\"\n");
1837 print_dbg_info(F, get_type_dbg_info(tp));
1838 print_typespecific_vcgattr(F, tp);
1845 #define X(a) case a: fprintf(F, #a); break
1846 void dump_entity_node(FILE *F, entity *ent, int color)
1848 fprintf (F, "node: {title: \"");
1849 PRINT_ENTID(ent); fprintf(F, "\"");
1850 fprintf (F, DEFAULT_TYPE_ATTRIBUTE);
1851 fprintf (F, "label: ");
1852 fprintf (F, "\"ent %s\" ", get_ent_dump_name(ent));
1854 fprintf(F, "color:%d", color);
1856 fprintf (F, ENTITY_NODE_ATTR);
1857 fprintf (F, "\n info1: \"");
1859 dump_entity_to_file(F, ent, dump_verbosity_entattrs | dump_verbosity_entconsts);
1862 print_dbg_info(F, get_entity_dbg_info(ent));
1867 static void dump_enum_item(FILE *F, ir_type *tp, int pos)
1870 ir_enum_const *ec = get_enumeration_const(tp, pos);
1871 ident *id = get_enumeration_nameid(ec);
1872 tarval *tv = get_enumeration_value(ec);
1875 tarval_snprintf(buf, sizeof(buf), tv);
1877 strncpy(buf, "<not set>", sizeof(buf));
1878 fprintf(F, "node: {title: \"");
1879 PRINT_ITEMID(tp, pos); fprintf(F, "\"");
1880 fprintf(F, DEFAULT_ENUM_ITEM_ATTRIBUTE);
1881 fprintf(F, "label: ");
1882 fprintf(F, "\"enum item %s\" " ENUM_ITEM_NODE_ATTR, get_id_str(id));
1883 fprintf(F, "\n info1: \"value: %s\"}\n", buf);
1886 /* dumps a type or entity and it's edges. */
1888 dump_type_info(type_or_ent *tore, void *env) {
1890 int i = 0; /* to shutup gcc */
1892 /* dump this type or entity */
1894 switch (get_kind(tore)) {
1897 entity *ent = (entity *)tore;
1900 dump_entity_node(F, ent, 0);
1902 /* skip this to reduce graph. Member edge of type is parallel to this edge. *
1903 fprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
1904 ENT_OWN_EDGE_ATTR "}\n", ent, get_entity_owner(ent));*/
1905 print_ent_type_edge(F,ent, get_entity_type(ent), ENT_TYPE_EDGE_ATTR);
1906 if (is_Class_type(get_entity_owner(ent))) {
1907 for(i = 0; i < get_entity_n_overwrites(ent); i++)
1908 print_ent_ent_edge(F,ent, get_entity_overwrites(ent, i), 0, ENT_OVERWRITES_EDGE_ATTR);
1910 /* attached subgraphs */
1911 if (const_entities && (get_entity_variability(ent) != variability_uninitialized)) {
1912 if (is_atomic_entity(ent)) {
1913 value = get_atomic_ent_value(ent);
1915 print_ent_node_edge(F, ent, value, ENT_VALUE_EDGE_ATTR, i);
1916 /* DDMN(value); $$$ */
1917 dump_const_expression(F, value);
1920 if (is_compound_entity(ent)) {
1921 for (i = 0; i < get_compound_ent_n_values(ent); i++) {
1922 value = get_compound_ent_value(ent, i);
1924 print_ent_node_edge(F, ent, value, ENT_VALUE_EDGE_ATTR, i);
1925 dump_const_expression(F, value);
1926 print_ent_ent_edge(F, ent, get_compound_ent_value_member(ent, i), 0, ENT_CORR_EDGE_ATTR, i);
1928 fprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
1929 ENT_CORR_EDGE_ATTR "}\n", GET_ENTID(ent),
1930 get_compound_ent_value_member(ent, i), i);
1939 ir_type *tp = (ir_type *)tore;
1940 dump_type_node(F, tp);
1941 /* and now the edges */
1942 switch (get_type_tpop_code(tp)) {
1945 for (i=0; i < get_class_n_supertypes(tp); i++)
1946 print_type_type_edge(F, tp,get_class_supertype(tp, i),TYPE_SUPER_EDGE_ATTR);
1947 for (i=0; i < get_class_n_members(tp); i++)
1948 print_type_ent_edge(F,tp,get_class_member(tp, i),TYPE_MEMBER_EDGE_ATTR);
1952 for (i=0; i < get_struct_n_members(tp); i++)
1953 print_type_ent_edge(F,tp,get_struct_member(tp, i),TYPE_MEMBER_EDGE_ATTR);
1957 for (i = 0; i < get_method_n_params(tp); i++)
1958 print_type_type_edge(F,tp,get_method_param_type(tp, i),METH_PAR_EDGE_ATTR,i);
1959 for (i = 0; i < get_method_n_ress(tp); i++)
1960 print_type_type_edge(F,tp,get_method_res_type(tp, i),METH_RES_EDGE_ATTR,i);
1964 for (i = 0; i < get_union_n_members(tp); i++)
1965 print_type_ent_edge(F,tp,get_union_member(tp, i),UNION_EDGE_ATTR);
1969 print_type_type_edge(F,tp,get_array_element_type(tp),ARR_ELT_TYPE_EDGE_ATTR);
1970 print_type_ent_edge(F,tp,get_array_element_entity(tp),ARR_ENT_EDGE_ATTR);
1971 for (i = 0; i < get_array_n_dimensions(tp); i++) {
1972 ir_node *upper = get_array_upper_bound(tp, i);
1973 ir_node *lower = get_array_lower_bound(tp, i);
1974 print_node_type_edge(F, upper, tp, "label: \"upper %d\"", get_array_order(tp, i));
1975 print_node_type_edge(F, lower, tp, "label: \"lower %d\"", get_array_order(tp, i));
1976 dump_const_expression(F, upper);
1977 dump_const_expression(F, lower);
1981 case tpo_enumeration:
1983 for (i = 0; i < get_enumeration_n_enums(tp); ++i) {
1984 dump_enum_item(F, tp, i);
1985 print_enum_item_edge(F, tp, i, "label: \"item %d\"", i);
1990 print_type_type_edge(F,tp,get_pointer_points_to_type(tp), PTR_PTS_TO_EDGE_ATTR);
1998 break; /* case k_type */
2001 printf(" *** irdump, dump_type_info(l.%i), faulty type.\n", __LINE__);
2003 } /* switch kind_or_entity */
2006 typedef struct _h_env {
2011 /** For dumping class hierarchies.
2012 * Dumps a class type node and a superclass edge.
2013 * If env->dump_ent dumps entities of classes and overwrites edges.
2016 dump_class_hierarchy_node (type_or_ent *tore, void *ctx) {
2019 int i = 0; /* to shutup gcc */
2021 /* dump this type or entity */
2022 switch (get_kind(tore)) {
2024 entity *ent = (entity *)tore;
2025 if (get_entity_owner(ent) == get_glob_type()) break;
2026 if (!is_Method_type(get_entity_type(ent))) break; /* GL */
2027 if (env->dump_ent && is_Class_type(get_entity_owner(ent))) {
2029 dump_entity_node(F, ent, 0);
2031 print_type_ent_edge(F,get_entity_owner(ent),ent,TYPE_MEMBER_EDGE_ATTR);
2032 for(i = 0; i < get_entity_n_overwrites(ent); i++)
2033 print_ent_ent_edge(F, get_entity_overwrites(ent, i), ent, 0, ENT_OVERWRITES_EDGE_ATTR);
2035 } break; /* case k_entity */
2038 ir_type *tp = (ir_type *)tore;
2039 if (tp == get_glob_type()) break;
2040 switch (get_type_tpop_code(tp)) {
2042 dump_type_node(F, tp);
2043 /* and now the edges */
2044 for (i=0; i < get_class_n_supertypes(tp); i++)
2046 print_type_type_edge(F,tp,get_class_supertype(tp, i),TYPE_SUPER_EDGE_ATTR);
2052 break; /* case k_type */
2055 printf(" *** irdump, dump_class_hierarchy_node(l.%i), faulty type.\n", __LINE__);
2057 } /* switch kind_or_entity */
2060 /*******************************************************************/
2061 /* dump analysis information that is expressed in graph terms. */
2062 /*******************************************************************/
2064 /* dump out edges */
2066 dump_out_edge(ir_node *n, void *env) {
2069 for (i = 0; i < get_irn_n_outs(n); i++) {
2070 assert(get_irn_out(n, i));
2071 fprintf (F, "edge: {sourcename: \"");
2073 fprintf (F, "\" targetname: \"");
2074 PRINT_NODEID(get_irn_out(n, i));
2075 fprintf (F, "\" color: red linestyle: dashed");
2081 dump_loop_label(FILE *F, ir_loop *loop) {
2082 fprintf (F, "loop %d, %d sons, %d nodes",
2083 get_loop_depth(loop), get_loop_n_sons(loop), get_loop_n_nodes(loop));
2086 static INLINE void dump_loop_info(FILE *F, ir_loop *loop) {
2087 fprintf (F, " info1: \"");
2088 fprintf (F, " loop nr: %d", get_loop_loop_nr(loop));
2089 #if DEBUG_libfirm /* GL @@@ debug analyses */
2090 fprintf (F, "\n The loop was analyzed %d times.", PTR_TO_INT(get_loop_link(loop)));
2096 dump_loop_node(FILE *F, ir_loop *loop) {
2097 fprintf (F, "node: {title: \"");
2099 fprintf (F, "\" label: \"");
2100 dump_loop_label(F, loop);
2102 dump_loop_info(F, loop);
2108 dump_loop_node_edge(FILE *F, ir_loop *loop, int i) {
2110 fprintf (F, "edge: {sourcename: \"");
2112 fprintf (F, "\" targetname: \"");
2113 PRINT_NODEID(get_loop_node(loop, i));
2114 fprintf (F, "\" color: green");
2119 dump_loop_son_edge(FILE *F, ir_loop *loop, int i) {
2121 fprintf (F, "edge: {sourcename: \"");
2123 fprintf (F, "\" targetname: \"");
2124 PRINT_LOOPID(get_loop_son(loop, i));
2125 fprintf (F, "\" color: darkgreen label: \"%d\"}\n",
2126 get_loop_element_pos(loop, get_loop_son(loop, i)));
2130 void dump_loops(FILE *F, ir_loop *loop) {
2132 /* dump this loop node */
2133 dump_loop_node(F, loop);
2135 /* dump edges to nodes in loop -- only if it is a real loop */
2136 if (get_loop_depth(loop) != 0) {
2137 for (i = 0; i < get_loop_n_nodes(loop); i++) {
2138 dump_loop_node_edge(F, loop, i);
2141 for (i = 0; i < get_loop_n_sons(loop); i++) {
2142 dump_loops(F, get_loop_son(loop, i));
2143 dump_loop_son_edge(F, loop, i);
2148 void dump_loop_nodes_into_graph(FILE *F, ir_graph *irg) {
2149 ir_graph *rem = current_ir_graph;
2150 current_ir_graph = irg;
2152 if (get_irg_loop(irg)) dump_loops(F, get_irg_loop(irg));
2154 current_ir_graph = rem;
2159 * dumps the VCG header
2161 void dump_vcg_header(FILE *F, const char *name, const char *orientation) {
2170 if (!orientation) orientation = "bottom_to_top";
2174 "graph: { title: \"ir graph of %s\"\n"
2175 "display_edge_labels: %s\n"
2176 "layoutalgorithm: mindepth\n"
2177 "manhattan_edges: yes\n"
2178 "port_sharing: no\n"
2180 "classname 1: \"intrablock Data\"\n"
2181 "classname 2: \"Block\"\n"
2182 "classname 3: \"Entity type\"\n"
2183 "classname 4: \"Entity owner\"\n"
2184 "classname 5: \"Method Param\"\n"
2185 "classname 6: \"Method Res\"\n"
2186 "classname 7: \"Super\"\n"
2187 "classname 8: \"Union\"\n"
2188 "classname 9: \"Points-to\"\n"
2189 "classname 10: \"Array Element Type\"\n"
2190 "classname 11: \"Overwrites\"\n"
2191 "classname 12: \"Member\"\n"
2192 "classname 13: \"Control Flow\"\n"
2193 "classname 14: \"intrablock Memory\"\n"
2194 "classname 15: \"Dominators\"\n"
2195 "classname 16: \"interblock Data\"\n"
2196 "classname 17: \"interblock Memory\"\n"
2197 "classname 18: \"Exception Control Flow for Interval Analysis\"\n"
2198 "classname 19: \"Postdominators\"\n"
2199 "infoname 1: \"Attribute\"\n"
2200 "infoname 2: \"Verification errors\"\n"
2201 "infoname 3: \"Debug info\"\n",
2202 name, label, orientation);
2204 /* don't use all, the range is too whith/black. */
2208 "colorentry 100: 0 0 0\n"
2209 "colorentry 101: 20 0 0\n"
2210 "colorentry 102: 40 0 0\n"
2211 "colorentry 103: 60 0 0\n"
2212 "colorentry 104: 80 0 0\n"
2213 "colorentry 105: 100 0 0\n"
2214 "colorentry 106: 120 0 0\n"
2215 "colorentry 107: 140 0 0\n"
2216 "colorentry 108: 150 0 0\n"
2217 "colorentry 109: 180 0 0\n"
2218 "colorentry 110: 200 0 0\n"
2219 "colorentry 111: 220 0 0\n"
2220 "colorentry 112: 240 0 0\n"
2221 "colorentry 113: 255 0 0\n"
2222 "colorentry 113: 255 20 20\n"
2223 "colorentry 114: 255 40 40\n"
2224 "colorentry 115: 255 60 60\n"
2225 "colorentry 116: 255 80 80\n"
2226 "colorentry 117: 255 100 100\n"
2227 "colorentry 118: 255 120 120\n"
2228 "colorentry 119: 255 140 140\n"
2229 "colorentry 120: 255 150 150\n"
2230 "colorentry 121: 255 180 180\n"
2231 "colorentry 122: 255 200 200\n"
2232 "colorentry 123: 255 220 220\n"
2233 "colorentry 124: 255 240 240\n"
2234 "colorentry 125: 255 250 250\n"
2237 fprintf (F, "\n"); /* a separator */
2243 * @param irg The graph to be dumped
2244 * @param suffix1 first filename suffix
2245 * @param suffix2 second filename suffix
2247 FILE *vcg_open (ir_graph *irg, const char * suffix1, const char *suffix2) {
2249 const char *nm = get_irg_dump_name(irg);
2250 int len = strlen(nm), i, j;
2251 char *fname; /* filename to put the vcg information in */
2253 if (!suffix1) suffix1 = "";
2254 if (!suffix2) suffix2 = "";
2256 /* open file for vcg graph */
2257 fname = xmalloc (len * 2 + strlen(suffix1) + strlen(suffix2) + 5);
2259 /* strncpy (fname, nm, len); */ /* copy the filename */
2261 for (i = 0; i < len; ++i) { /* replace '/' in the name: escape by @. */
2263 fname[j] = '@'; j++; fname[j] = '1'; j++;
2264 } else if (nm[i] == '@') {
2265 fname[j] = '@'; j++; fname[j] = '2'; j++;
2267 fname[j] = nm[i]; j++;
2271 strcat (fname, suffix1); /* append file suffix */
2272 strcat (fname, suffix2); /* append file suffix */
2273 strcat (fname, ".vcg"); /* append the .vcg suffix */
2275 /* vcg really expect only a <CR> at end of line, so
2276 * the "b"inary mode is what you mean (and even needed for Win32)
2278 F = fopen (fname, "wb"); /* open file for writing */
2280 panic("cannot open %s for writing (%m)", fname); /* not reached */
2290 * @param name prefix file name
2291 * @param suffix filename suffix
2293 FILE *vcg_open_name (const char *name, const char *suffix) {
2295 char *fname; /* filename to put the vcg information in */
2296 int i, j, len = strlen(name);
2298 if (!suffix) suffix = "";
2300 /** open file for vcg graph */
2301 fname = xmalloc(len * 2 + 5 + strlen(suffix));
2302 /* strcpy (fname, name);*/ /* copy the filename */
2304 for (i = 0; i < len; ++i) { /* replace '/' in the name: escape by @. */
2305 if (name[i] == '/') {
2306 fname[j] = '@'; j++; fname[j] = '1'; j++;
2307 } else if (name[i] == '@') {
2308 fname[j] = '@'; j++; fname[j] = '2'; j++;
2310 fname[j] = name[i]; j++;
2314 strcat (fname, suffix);
2315 strcat (fname, ".vcg"); /* append the .vcg suffix */
2317 /* vcg really expect only a <CR> at end of line, so
2318 * the "b"inary mode is what you mean (and even needed for Win32)
2320 F = fopen (fname, "wb"); /* open file for writing */
2322 panic ("cannot open %s for writing (%m)", fname); /* not reached */
2330 * Dumps the vcg file footer
2332 static INLINE void dump_vcg_footer (FILE *F) {
2337 * close the vcg file
2339 void vcg_close (FILE *F) {
2340 dump_vcg_footer(F); /* print footer */
2341 fclose (F); /* close vcg file */
2344 /************************************************************************/
2345 /************************************************************************/
2346 /* Routines that dump all or parts of the firm representation to a file */
2347 /************************************************************************/
2348 /************************************************************************/
2350 /************************************************************************/
2351 /* Dump ir graphs, different formats and additional information. */
2352 /************************************************************************/
2354 /** Routine to dump a graph, blocks as conventional nodes. */
2356 dump_ir_graph (ir_graph *irg, const char *suffix )
2361 rem = current_ir_graph;
2363 if (!is_filtered_dump_name(get_entity_ident(get_irg_entity(irg)))) return;
2365 current_ir_graph = irg;
2366 if (get_interprocedural_view()) suffix1 = "-pure-ip";
2367 else suffix1 = "-pure";
2368 f = vcg_open(irg, suffix, suffix1);
2369 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
2371 /* call the dump graph hook */
2372 if (dump_ir_graph_hook)
2373 if (dump_ir_graph_hook(f, irg))
2376 /* walk over the graph */
2377 /* dump_whole_node must be called in post visiting predecessors */
2378 ird_walk_graph(irg, NULL, dump_whole_node, f);
2380 /* dump the out edges in a separate walk */
2381 if ((dump_out_edge_flag) && (get_irg_outs_state(irg) != outs_none)) {
2382 irg_out_walk(get_irg_start(irg), dump_out_edge, NULL, f);
2387 current_ir_graph = rem;
2390 /* Dump a firm graph without explicit block nodes. */
2391 void dump_ir_block_graph (ir_graph *irg, const char *suffix)
2397 if (!is_filtered_dump_name(get_entity_ident(get_irg_entity(irg))))
2400 if (get_interprocedural_view()) suffix1 = "-ip";
2402 f = vcg_open(irg, suffix, suffix1);
2403 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
2405 construct_block_lists(irg);
2408 * If we are in the interprocedural view, we dump not
2409 * only the requested irg but also all irgs that can be reached
2412 for (i = get_irp_n_irgs() - 1; i >= 0; --i) {
2413 ir_node **arr = ird_get_irg_link(get_irp_irg(i));
2415 dump_graph_from_list(f, get_irp_irg(i));
2423 /* Dump a firm graph without explicit block nodes but grouped in extended blocks. */
2424 void dump_ir_extblock_graph (ir_graph *irg, const char *suffix)
2431 if (!is_filtered_dump_name(get_entity_ident(get_irg_entity(irg))))
2434 if (get_irg_extblk_state(irg) != extblk_valid)
2437 if (get_interprocedural_view()) suffix1 = "-ip";
2440 ent = get_irg_entity(irg);
2442 F = vcg_open(irg, suffix, suffix1);
2443 dump_vcg_header(F, get_irg_dump_name(irg), NULL);
2445 construct_extblock_lists(irg);
2447 fprintf(F, "graph: { title: \"");
2449 fprintf(F, "\" label: \"%s\" status:clustered color: white \n",
2450 get_ent_dump_name(ent));
2452 dump_graph_info(F, irg);
2453 print_dbg_info(F, get_entity_dbg_info(ent));
2455 for (i = get_irp_n_irgs() - 1; i >= 0; --i) {
2456 ir_graph *irg = get_irp_irg(i);
2457 list_tuple *lists = ird_get_irg_link(irg);
2460 /* dump the extended blocks first */
2461 if (ARR_LEN(lists->extbb_list)) {
2462 ird_set_irg_link(irg, lists->extbb_list);
2463 dump_extblock_graph(F, irg);
2466 /* we may have blocks without extended blocks, bad for instance */
2467 if (ARR_LEN(lists->blk_list)) {
2468 ird_set_irg_link(irg, lists->blk_list);
2469 dump_block_graph(F, irg);
2472 DEL_ARR_F(lists->extbb_list);
2473 DEL_ARR_F(lists->blk_list);
2478 /* Close the vcg information for the irg */
2479 fprintf(F, "}\n\n");
2485 /* dumps a graph with type information */
2487 dump_ir_graph_w_types (ir_graph *irg, const char *suffix)
2490 ir_graph *rem = current_ir_graph;
2492 int rem_dump_const_local;
2494 /* if a filter is set, dump only the irg's that match the filter */
2495 if (!is_filtered_dump_name(get_entity_ident(get_irg_entity(irg))))
2498 current_ir_graph = irg;
2499 rem_dump_const_local = dump_const_local;
2500 /* dumping types does not work with local nodes */
2501 dump_const_local = 0;
2503 if (get_interprocedural_view()) suffix1 = "-pure-wtypes-ip";
2504 else suffix1 = "-pure-wtypes";
2505 f = vcg_open(irg,suffix, suffix1);
2506 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
2508 /* dump common ir graph */
2509 irg_walk(get_irg_end(irg), NULL, dump_whole_node, f);
2510 /* dump type info */
2511 type_walk_irg(irg, dump_type_info, NULL, f);
2512 inc_irg_visited(get_const_code_irg());
2513 /* dump edges from graph to type info */
2514 irg_walk(get_irg_end(irg), dump_node2type_edges, NULL, f);
2517 dump_const_local = rem_dump_const_local;
2518 current_ir_graph = rem;
2522 dump_ir_block_graph_w_types (ir_graph *irg, const char *suffix)
2527 ir_graph *rem = current_ir_graph;
2528 int rem_dump_const_local;
2530 /* if a filter is set, dump only the irg's that match the filter */
2531 if (!is_filtered_dump_name(get_entity_ident(get_irg_entity(irg))))
2534 rem_dump_const_local = dump_const_local;
2535 /* dumping types does not work with local nodes */
2536 dump_const_local = 0;
2538 if (get_interprocedural_view()) suffix1 = "-wtypes-ip";
2539 else suffix1 = "-wtypes";
2540 f = vcg_open(irg, suffix, suffix1);
2541 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
2543 /* dump common blocked ir graph */
2544 construct_block_lists(irg);
2546 for (i = get_irp_n_irgs() - 1; i >= 0; --i) {
2547 ir_node **arr = ird_get_irg_link(get_irp_irg(i));
2549 dump_graph_from_list(f, get_irp_irg(i));
2554 /* dump type info */
2555 current_ir_graph = irg;
2556 type_walk_irg(irg, dump_type_info, NULL, f);
2557 inc_irg_visited(get_const_code_irg());
2559 /* dump edges from graph to type info */
2560 irg_walk(get_irg_end(irg), dump_node2type_edges, NULL, f);
2563 dump_const_local = rem_dump_const_local;
2564 current_ir_graph = rem;
2567 /*---------------------------------------------------------------------*/
2568 /* The following routines dump a control flow graph. */
2569 /*---------------------------------------------------------------------*/
2572 dump_block_to_cfg(ir_node *block, void *env) {
2577 if (is_Block(block)) {
2578 /* This is a block. Dump a node for the block. */
2579 fprintf (F, "node: {title: \""); PRINT_NODEID(block);
2580 fprintf (F, "\" label: \"");
2581 if (block == get_irg_start_block(get_irn_irg(block)))
2582 fprintf(F, "Start ");
2583 if (block == get_irg_end_block(get_irn_irg(block)))
2586 fprintf (F, "%s ", get_op_name(get_irn_op(block)));
2587 PRINT_NODEID(block);
2589 fprintf(F, "info1:\"");
2591 /* the generic version. */
2592 dump_irnode_to_file(F, block);
2594 /* Check whether we have bad predecessors to color the block. */
2595 for (i = 0; i < get_Block_n_cfgpreds(block); ++i)
2596 if ((fl = is_Bad(get_Block_cfgpred(block, i))))
2599 fprintf (F, "\""); /* closing quote of info */
2601 if ((block == get_irg_start_block(get_irn_irg(block))) ||
2602 (block == get_irg_end_block(get_irn_irg(block))) )
2603 fprintf(F, " color:blue ");
2605 fprintf(F, " color:yellow ");
2608 /* Dump the edges */
2609 for ( i = 0; i < get_Block_n_cfgpreds(block); i++)
2610 if (get_irn_op(skip_Proj(get_Block_cfgpred(block, i))) != op_Bad) {
2611 pred = get_nodes_block(skip_Proj(get_Block_cfgpred(block, i)));
2612 fprintf (F, "edge: { sourcename: \"");
2613 PRINT_NODEID(block);
2614 fprintf (F, "\" targetname: \"");
2616 fprintf (F, "\"}\n");
2619 /* Dump dominator/postdominator edge */
2620 if (dump_dominator_information_flag) {
2621 if (get_irg_dom_state(current_ir_graph) == dom_consistent && get_Block_idom(block)) {
2622 pred = get_Block_idom(block);
2623 fprintf (F, "edge: { sourcename: \"");
2624 PRINT_NODEID(block);
2625 fprintf (F, "\" targetname: \"");
2627 fprintf (F, "\" " DOMINATOR_EDGE_ATTR "}\n");
2629 if (get_irg_postdom_state(current_ir_graph) == dom_consistent && get_Block_ipostdom(block)) {
2630 pred = get_Block_ipostdom(block);
2631 fprintf (F, "edge: { sourcename: \"");
2632 PRINT_NODEID(block);
2633 fprintf (F, "\" targetname: \"");
2635 fprintf (F, "\" " POSTDOMINATOR_EDGE_ATTR "}\n");
2642 dump_cfg (ir_graph *irg, const char *suffix)
2645 ir_graph *rem = current_ir_graph;
2646 int ipv = get_interprocedural_view();
2648 /* if a filter is set, dump only the irg's that match the filter */
2649 if (!is_filtered_dump_name(get_entity_ident(get_irg_entity(irg))))
2652 current_ir_graph = irg;
2654 f = vcg_open(irg, suffix, "-cfg");
2655 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
2658 printf("Warning: dumping cfg not in interprocedural view!\n");
2659 set_interprocedural_view(0);
2662 /* walk over the blocks in the graph */
2663 irg_block_walk(get_irg_end(irg), dump_block_to_cfg, NULL, f);
2664 dump_node(f, get_irg_bad(irg));
2666 set_interprocedural_view(ipv);
2668 current_ir_graph = rem;
2672 static void descend_and_dump(FILE *F, ir_node *n, int depth, pset *mark_set) {
2673 if (pset_find_ptr(mark_set, n)) return;
2675 pset_insert_ptr(mark_set, n);
2678 int i, start = is_Block(n) ? 0 : -1;
2679 dump_whole_node(n, F);
2680 for (i = start; i < get_irn_arity(n); ++i)
2681 descend_and_dump(F, get_irn_n(n, i), depth-1, mark_set);
2684 /* Don't dump edges to nodes further out. These might be edges to
2685 nodes we already dumped, if there is a shorter path to these. */
2689 static int subgraph_counter = 0;
2690 void dump_subgraph (ir_node *root, int depth, const char *suffix) {
2693 pset *mark_set = pset_new_ptr(1);
2694 sprintf(buf, "-subg_%03d", subgraph_counter++);
2695 F = vcg_open(get_irn_irg(root), suffix, buf);
2696 dump_vcg_header(F, get_irg_dump_name(get_irn_irg(root)), NULL);
2697 descend_and_dump(F, root, depth, mark_set);
2703 static int weight_overall(int rec, int loop) {
2704 return 2*rec + loop;
2707 static int compute_color (int my, int max) {
2714 /* if small, scale to the full color range. */
2716 my = my * (n_colors/max);
2718 step = 1 + (max / n_colors);
2722 return base_color + n_colors - color;
2725 static int get_entity_color(entity *ent) {
2726 ir_graph *irg = get_entity_irg(ent);
2730 int rec_depth = get_irg_recursion_depth(irg);
2731 int loop_depth = get_irg_loop_depth(irg);
2732 int overall_depth = weight_overall(rec_depth, loop_depth);
2734 int max_rec_depth = irp->max_callgraph_recursion_depth;
2735 int max_loop_depth = irp->max_callgraph_loop_depth;
2736 int max_overall_depth = weight_overall(max_rec_depth, max_loop_depth);
2738 /* int my_rec_color = compute_color(rec_depth, max_rec_depth); */
2739 /* int my_loop_color = compute_color(loop_depth, max_loop_depth); */
2740 int my_overall_color = compute_color(overall_depth, max_overall_depth);;
2742 return my_overall_color;
2746 void dump_callgraph(const char *suffix) {
2749 int rem = edge_label;
2751 //ident *prefix = new_id_from_str("java/");
2753 F = vcg_open_name("Callgraph", suffix);
2754 dump_vcg_header(F, "Callgraph", NULL);
2756 for (i = get_irp_n_irgs() - 1; i >= 0; --i) {
2757 ir_graph *irg = get_irp_irg(i);
2758 entity *ent = get_irg_entity(irg);
2759 int j, n_callees = get_irg_n_callees(irg);
2761 /* Do not dump runtime system. */
2762 //if (id_is_prefix(prefix, get_entity_ld_ident(ent))) continue;
2764 dump_entity_node(F, ent, get_entity_color(ent));
2765 for (j = 0; j < n_callees; ++j) {
2766 entity *c = get_irg_entity(get_irg_callee(irg, j));
2767 //if (id_is_prefix(prefix, get_entity_ld_ident(c))) continue;
2768 int be = is_irg_callee_backedge(irg, j);
2771 "label:\"recursion %d\" color:%d" :
2772 "label:\"calls %d\" color:%d";
2773 print_ent_ent_edge(F, ent, c, be, attr, get_irg_callee_loop_depth(irg, j), get_entity_color(ent));
2781 /* Dump all irgs in interprocedural view to a single file. */
2782 void dump_all_cg_block_graph(const char *suffix) {
2785 int rem_view = get_interprocedural_view();
2786 set_interprocedural_view(1);
2788 f = vcg_open_name("All_graphs", suffix);
2789 dump_vcg_header(f, "All_graphs", NULL);
2791 /* collect nodes in all irgs reachable in call graph*/
2792 for (i = get_irp_n_irgs() - 1; i >= 0; --i)
2793 ird_set_irg_link(get_irp_irg(i), NULL);
2795 cg_walk(clear_link, collect_node, NULL);
2797 /* dump all graphs */
2798 for (i = get_irp_n_irgs() - 1; i >= 0; --i) {
2799 current_ir_graph = get_irp_irg(i);
2800 assert(ird_get_irg_link(current_ir_graph));
2801 dump_graph_from_list(f, current_ir_graph);
2802 DEL_ARR_F(ird_get_irg_link(current_ir_graph));
2806 set_interprocedural_view(rem_view);
2809 /*---------------------------------------------------------------------*/
2810 /* the following routines dumps type information without any ir nodes. */
2811 /*---------------------------------------------------------------------*/
2814 dump_type_graph (ir_graph *irg, const char *suffix)
2818 rem = current_ir_graph;
2820 /* if a filter is set, dump only the irg's that match the filter */
2821 if (!is_filtered_dump_name(get_entity_ident(get_irg_entity(irg)))) return;
2823 current_ir_graph = irg;
2825 f = vcg_open(irg, suffix, "-type");
2826 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
2828 /* walk over the blocks in the graph */
2829 type_walk_irg(irg, dump_type_info, NULL, f);
2830 /* The walker for the const code can be called several times for the
2831 same (sub) expression. So that no nodes are dumped several times
2832 we decrease the visited flag of the corresponding graph after each
2833 walk. So now increase it finally. */
2834 inc_irg_visited(get_const_code_irg());
2837 current_ir_graph = rem;
2841 dump_all_types (const char *suffix)
2843 FILE *f = vcg_open_name("All_types", suffix);
2844 dump_vcg_header(f, "All_types", NULL);
2845 type_walk(dump_type_info, NULL, f);
2846 inc_irg_visited(get_const_code_irg());
2851 dump_class_hierarchy (int entities, const char *suffix)
2853 FILE *f = vcg_open_name("class_hierarchy", suffix);
2857 env.dump_ent = entities;
2858 dump_vcg_header(f, "class_hierarchy", NULL);
2859 type_walk(dump_class_hierarchy_node, NULL, &env);
2863 /*---------------------------------------------------------------------*/
2864 /* dumps all graphs with the graph-dumper passed. Possible dumpers: */
2866 /* dump_ir_block_graph */
2868 /* dump_type_graph */
2869 /* dump_ir_graph_w_types */
2870 /*---------------------------------------------------------------------*/
2872 void dump_all_ir_graphs(dump_graph_func *dmp_grph, const char *suffix) {
2874 for (i = get_irp_n_irgs() - 1; i >= 0; --i)
2875 dmp_grph(get_irp_irg(i), suffix);
2879 /*--------------------------------------------------------------------------------*
2880 * Dumps a stand alone loop graph with firm nodes which belong to one loop node *
2881 * packed together in one subgraph/box *
2882 *--------------------------------------------------------------------------------*/
2884 void dump_loops_standalone(FILE *F, ir_loop *loop) {
2885 int i = 0, loop_node_started = 0, son_number = 0, first = 0;
2887 ir_loop *son = NULL;
2889 /* Dump a new loop node. */
2890 dump_loop_node(F, loop);
2892 /* Dump the loop elements. */
2894 for(i = 0; i < get_loop_n_elements(loop); i++) {
2895 le = get_loop_element(loop, i);
2897 if (get_kind(son) == k_ir_loop) {
2899 /* We are a loop son -> Recurse */
2901 if(loop_node_started) { /* Close the "firm-nodes" node first if we started one. */
2902 fprintf(F, "\" }\n");
2903 fprintf (F, "edge: {sourcename: \"");
2905 fprintf (F, "\" targetname: \"");
2907 fprintf (F, "-%d-nodes\" label:\"%d...%d\"}\n", first, first, i-1);
2908 loop_node_started = 0;
2910 dump_loop_son_edge(F, loop, son_number++);
2911 dump_loops_standalone(F, son);
2912 } else if (get_kind(son) == k_ir_node) {
2913 /* We are a loop node -> Collect firm nodes */
2915 ir_node *n = le.node;
2918 if (!loop_node_started) {
2919 /* Start a new node which contains all firm nodes of the current loop */
2920 fprintf (F, "node: { title: \"");
2922 fprintf (F, "-%d-nodes\" color: lightyellow label: \"", i);
2923 loop_node_started = 1;
2929 bad |= dump_node_label(F, n);
2930 /* Causes indeterministic output: if (is_Block(n)) fprintf (F, "\t ->%d", (int)get_irn_link(n)); */
2931 if (has_backedges(n)) fprintf(F, "\t loop head!");
2932 } else { /* for callgraph loop tree */
2934 assert(get_kind(son) == k_ir_graph);
2936 /* We are a loop node -> Collect firm graphs */
2937 n = (ir_graph *)le.node;
2938 if (!loop_node_started) {
2939 /* Start a new node which contains all firm nodes of the current loop */
2940 fprintf (F, "node: { title: \"");
2942 fprintf (F, "-%d-nodes\" color: lightyellow label: \"", i);
2943 loop_node_started = 1;
2948 fprintf (F, " %s", get_irg_dump_name(n));
2949 /* fprintf (F, " %s (depth %d)", get_irg_dump_name(n), n->callgraph_weighted_loop_depth); */
2953 if (loop_node_started) {
2954 fprintf(F, "\" }\n");
2955 fprintf (F, "edge: {sourcename: \"");
2957 fprintf (F, "\" targetname: \"");
2959 fprintf (F, "-%d-nodes\" label:\"%d...%d\"}\n", first, first, i-1);
2960 loop_node_started = 0;
2964 void dump_loop_tree(ir_graph *irg, const char *suffix)
2967 ir_graph *rem = current_ir_graph;
2968 int el_rem = edge_label;
2971 /* if a filter is set, dump only the irg's that match the filter */
2972 if (!is_filtered_dump_name(get_entity_ident(get_irg_entity(irg)))) return;
2974 current_ir_graph = irg;
2976 f = vcg_open(irg, suffix, "-looptree");
2977 dump_vcg_header(f, get_irg_dump_name(irg), "top_to_bottom");
2979 if (get_irg_loop(irg)) dump_loops_standalone(f, get_irg_loop(irg));
2983 edge_label = el_rem;
2984 current_ir_graph = rem;
2987 void dump_callgraph_loop_tree(const char *suffix) {
2989 F = vcg_open_name("Callgraph_looptree", suffix);
2990 dump_vcg_header(F, "callgraph looptree", "top_to_bottom");
2991 dump_loops_standalone(F, irp->outermost_cg_loop);
2996 /*-----------------------------------------------------------------------------*/
2997 /* Dumps the firm nodes in the loop tree to a graph along with the loop nodes. */
2998 /*-----------------------------------------------------------------------------*/
3000 void collect_nodeloop(FILE *F, ir_loop *loop, eset *loopnodes) {
3001 int i, son_number = 0, node_number = 0;
3003 if (dump_loop_information_flag) dump_loop_node(F, loop);
3005 for (i = 0; i < get_loop_n_elements(loop); i++) {
3006 loop_element le = get_loop_element(loop, i);
3007 if (*(le.kind) == k_ir_loop) {
3008 if (dump_loop_information_flag) dump_loop_son_edge(F, loop, son_number++);
3010 collect_nodeloop(F, le.son, loopnodes);
3012 if (dump_loop_information_flag) dump_loop_node_edge(F, loop, node_number++);
3013 eset_insert(loopnodes, le.node);
3018 void collect_nodeloop_external_nodes(ir_loop *loop, eset *loopnodes, eset *extnodes) {
3021 for(i = 0; i < get_loop_n_elements(loop); i++) {
3022 loop_element le = get_loop_element(loop, i);
3023 if (*(le.kind) == k_ir_loop) {
3025 collect_nodeloop_external_nodes(le.son, loopnodes, extnodes);
3027 if (is_Block(le.node)) start = 0; else start = -1;
3028 for (j = start; j < get_irn_arity(le.node); j++) {
3029 ir_node *pred = get_irn_n(le.node, j);
3030 if (!eset_contains(loopnodes, pred)) {
3031 eset_insert(extnodes, pred);
3032 if (!is_Block(pred)) {
3033 pred = get_nodes_block(pred);
3034 if (!eset_contains(loopnodes, pred)) eset_insert(extnodes, pred);
3042 void dump_loop(ir_loop *l, const char *suffix) {
3045 eset *loopnodes = eset_create();
3046 eset *extnodes = eset_create();
3049 snprintf(name, sizeof(name), "loop_%d", get_loop_loop_nr(l));
3050 F = vcg_open_name (name, suffix);
3051 dump_vcg_header(F, name, NULL);
3053 /* collect all nodes to dump */
3054 collect_nodeloop(F, l, loopnodes);
3055 collect_nodeloop_external_nodes(l, loopnodes, extnodes);
3057 /* build block lists */
3058 for (n = eset_first(loopnodes); n != NULL; n = eset_next(loopnodes))
3059 set_irn_link(n, NULL);
3060 for (n = eset_first(extnodes); n != NULL; n = eset_next(extnodes))
3061 set_irn_link(n, NULL);
3062 for (n = eset_first(loopnodes); n != NULL; n = eset_next(loopnodes))
3064 b = get_nodes_block(n);
3065 set_irn_link(n, get_irn_link(b));
3068 for (n = eset_first(extnodes); n != NULL; n = eset_next(extnodes))
3070 b = get_nodes_block(n);
3071 set_irn_link(n, get_irn_link(b));
3075 for (b = eset_first(loopnodes); b != NULL; b = eset_next(loopnodes))
3077 fprintf(F, "graph: { title: \"");
3079 fprintf(F, "\" label: \"");
3080 dump_node_opcode(F, b);
3081 fprintf (F, " %ld", get_irn_node_nr(b));
3082 fprintf(F, "\" status:clustered color:yellow\n");
3084 /* dump the blocks edges */
3085 dump_ir_data_edges(F, b);
3087 /* dump the nodes that go into the block */
3088 for (n = get_irn_link(b); n; n = get_irn_link(n)) {
3089 if (eset_contains(extnodes, n))
3090 overrule_nodecolor = ird_color_lightblue;
3092 overrule_nodecolor = ird_color_default;
3093 if (!eset_contains(extnodes, n)) dump_ir_data_edges(F, n);
3096 /* Close the vcg information for the block */
3098 dump_const_node_local(F, b);
3101 for (b = eset_first(extnodes); b != NULL; b = eset_next(extnodes))
3103 fprintf(F, "graph: { title: \"");
3105 fprintf(F, "\" label: \"");
3106 dump_node_opcode(F, b);
3107 fprintf (F, " %ld", get_irn_node_nr(b));
3108 fprintf(F, "\" status:clustered color:lightblue\n");
3110 /* dump the nodes that go into the block */
3111 for (n = get_irn_link(b); n; n = get_irn_link(n)) {
3112 if (!eset_contains(loopnodes, n))
3113 overrule_nodecolor = ird_color_lightblue;
3115 overrule_nodecolor = ird_color_default;
3116 if (eset_contains(loopnodes, n)) dump_ir_data_edges(F, n);
3119 /* Close the vcg information for the block */
3121 dump_const_node_local(F, b);
3125 eset_destroy(loopnodes);
3126 eset_destroy(extnodes);