2 * Copyright (C) 1995-2007 University of Karlsruhe. All right reserved.
4 * This file is part of libFirm.
6 * This file may be distributed and/or modified under the terms of the
7 * GNU General Public License version 2 as published by the Free Software
8 * Foundation and appearing in the file LICENSE.GPL included in the
9 * packaging of this file.
11 * Licensees holding valid libFirm Professional Edition licenses may use
12 * this file in accordance with the libFirm Commercial License.
13 * Agreement provided with the Software.
15 * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
16 * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * @brief Write vcg representation of firm to file.
23 * @author Martin Trapp, Christian Schaefer, Goetz Lindenmaier, Hubert Schmidt
38 #include "firm_common_t.h"
53 #include "type_or_entity.h"
57 #include "callgraph.h"
58 #include "irextbb_t.h"
60 #include "dbginfo_t.h"
72 extern void dump_irn_chi_term(FILE *FL, ir_node *n);
73 extern void dump_irn_state(FILE *FL, ir_node *n);
74 extern int get_opt_dump_abstvals(void);
75 typedef unsigned long SeqNo;
76 extern SeqNo get_Block_seqno(ir_node *n);
79 /* basis for a color range for vcg */
80 static int n_colors = 0;
81 static int base_color = 0;
83 /** Dump only irgs with names that start with this string */
84 static ident *dump_file_filter_id = NULL;
86 #define ERROR_TXT "<ERROR>"
88 /*******************************************************************/
89 /* flags to steer output */
90 /*******************************************************************/
92 /** An option to turn off edge labels */
93 static int edge_label = 1;
94 /** An option to turn off dumping values of constant entities */
95 static int const_entities = 1;
96 /** An option to dump the keep alive edges */
97 static int dump_keepalive = 0;
98 /** An option to dump ld_names instead of names. */
99 static int dump_ld_name = 1;
100 /** Compiler options to dump analysis information in dump_ir_graph */
101 static int dump_out_edge_flag = 0;
102 static int dump_loop_information_flag = 0;
103 static int dump_backedge_information_flag = 1;
104 static int dump_const_local = 0;
105 /** An option to dump all graph anchors */
106 static int dump_anchors = 0;
108 int dump_dominator_information_flag = 0;
109 int opt_dump_analysed_type_info = 1;
110 int opt_dump_pointer_values_to_info = 0; /* default off: for test compares!! */
112 static dumper_colors overrule_nodecolor = ird_color_default;
114 /** The vcg node attribute hook. */
115 static DUMP_IR_GRAPH_FUNC dump_ir_graph_hook = NULL;
116 /** The vcg node attribute hook. */
117 static DUMP_NODE_VCGATTR_FUNC dump_node_vcgattr_hook = NULL;
118 /** The vcg edge attribute hook. */
119 static DUMP_EDGE_VCGATTR_FUNC dump_edge_vcgattr_hook = NULL;
120 /** The vcg dump block edge hook */
121 static DUMP_NODE_EDGE_FUNC dump_block_edge_hook = NULL;
122 /** The vcg dump node edge hook. */
123 static DUMP_NODE_EDGE_FUNC dump_node_edge_hook = NULL;
125 /* Set the hook to be called to dump additional edges to a node. */
126 void set_dump_node_edge_hook(DUMP_NODE_EDGE_FUNC func) {
127 dump_node_edge_hook = func;
130 /* Get the additional edge dump hook. */
131 DUMP_NODE_EDGE_FUNC get_dump_node_edge_hook(void) {
132 return dump_node_edge_hook;
135 /* Set the hook to be called to dump additional edges to a block. */
136 void set_dump_block_edge_hook(DUMP_NODE_EDGE_FUNC func) {
137 dump_block_edge_hook = func;
140 /* Get the additional block edge dump hook. */
141 DUMP_NODE_EDGE_FUNC get_dump_block_edge_hook(void) {
142 return dump_node_edge_hook;
145 /* set the ir graph hook */
146 void set_dump_ir_graph_hook(DUMP_IR_GRAPH_FUNC hook) {
147 dump_ir_graph_hook = hook;
150 /* set the node attribute hook */
151 void set_dump_node_vcgattr_hook(DUMP_NODE_VCGATTR_FUNC hook) {
152 dump_node_vcgattr_hook = hook;
155 /* set the edge attribute hook */
156 void set_dump_edge_vcgattr_hook(DUMP_EDGE_VCGATTR_FUNC hook) {
157 dump_edge_vcgattr_hook = hook;
160 /* Returns 0 if dump_out_edge_flag or dump_loop_information_flag
161 * are set, else returns dump_const_local_flag.
163 int get_opt_dump_const_local(void) {
164 if (!dump_out_edge_flag && !dump_loop_information_flag)
165 return dump_const_local;
170 /* Set a prefix filter for output functions. */
171 void only_dump_method_with_name(ident *name) {
172 dump_file_filter_id = name;
175 /* Returns the prefix filter set with only_dump_method_with_name(). */
176 ident *get_dump_file_filter_ident(void) {
177 return dump_file_filter_id;
180 /* Returns non-zero if dump file filter is not set, or if it is a prefix of name. */
181 int is_filtered_dump_name(ident *name) {
182 if (!dump_file_filter_id) return 1;
183 return id_is_prefix(dump_file_filter_id, name);
186 /* To turn off display of edge labels. Edge labels often cause xvcg to
187 abort with a segmentation fault. */
188 void turn_off_edge_labels(void) {
192 void dump_consts_local(int flag) {
193 dump_const_local = flag;
196 void dump_constant_entity_values(int flag) {
197 const_entities = flag;
200 void dump_keepalive_edges(int flag) {
201 dump_keepalive = flag;
204 int get_opt_dump_keepalive_edges(void) {
205 return dump_keepalive;
208 void dump_out_edges(int flag) {
209 dump_out_edge_flag = flag;
212 void dump_dominator_information(int flag) {
213 dump_dominator_information_flag = flag;
216 void dump_loop_information(int flag) {
217 dump_loop_information_flag = flag;
220 void dump_backedge_information(int flag) {
221 dump_backedge_information_flag = flag;
224 /* Dump the information of type field specified in ana/irtypeinfo.h.
225 * If the flag is set, the type name is output in [] in the node label,
226 * else it is output as info.
228 void set_opt_dump_analysed_type_info(int flag) {
229 opt_dump_analysed_type_info = flag;
232 void dump_pointer_values_to_info(int flag) {
233 opt_dump_pointer_values_to_info = flag;
236 void dump_ld_names(int flag) {
240 void dump_all_anchors(int flag) {
244 /* -------------- some extended helper functions ----------------- */
247 * returns the name of a mode or <ERROR> if mode is NOT a mode object.
248 * in the later case, sets bad
250 const char *get_mode_name_ex(ir_mode *mode, int *bad) {
252 return get_mode_name(mode);
258 * returns the name of a type or <ERROR> if mode is NOT a mode object.
259 * in the later case, sets bad
261 const char *get_type_name_ex(ir_type *tp, int *bad) {
263 return get_type_name(tp);
269 * printf the VCG color to a file
271 static void print_vcg_color(FILE *F, dumper_colors color) {
272 static const char *color_names[32] = {
273 "white", "blue", "red", "green",
274 "yellow", "magenta", "cyan", "darkgray",
275 "darkblue", "darkred", "darkgreen", "darkyellow",
276 "darkmagenta", "darkcyan", "gold", "lightgray",
277 "lightblue", "lightred", "lightgreen", "lightyellow",
278 "lightmagenta", "lightcyan", "lilac", "turquoise",
279 "aquamarine", "khaki", "purple", "yellowgreen",
280 "pink", "orange", "orchid", "black"
283 if (color != ird_color_default)
284 fprintf(F, "color:%s", color_names[color]);
288 * prints the edge from a type S to a type T with additional info fmt, ...
291 static void print_type_type_edge(FILE *F, ir_type *S, ir_type *T, const char *fmt, ...)
296 fprintf(F, "edge: { sourcename: "); PRINT_TYPEID(S);
297 fprintf(F, " targetname: "); PRINT_TYPEID(T);
298 vfprintf(F, fmt, ap);
304 * prints the edge from a type T to an entity E with additional info fmt, ...
307 static void print_type_ent_edge(FILE *F, ir_type *T, ir_entity *E, const char *fmt, ...)
312 fprintf(F, "edge: { sourcename: "); PRINT_TYPEID(T);
313 fprintf(F, " targetname: \""); PRINT_ENTID(E); fprintf(F, "\"");
314 vfprintf(F, fmt, ap);
320 * prints the edge from an entity E to an entity T with additional info fmt, ...
323 static void print_ent_ent_edge(FILE *F, ir_entity *E, ir_entity *T, int backedge, const char *fmt, ...)
329 fprintf(F, "backedge: { sourcename: \"");
331 fprintf(F, "edge: { sourcename: \"");
333 fprintf(F, "\" targetname: \""); PRINT_ENTID(T); fprintf(F, "\"");
334 vfprintf(F, fmt, ap);
340 * prints the edge from an entity E to a type T with additional info fmt, ...
343 static void print_ent_type_edge(FILE *F, ir_entity *E, ir_type *T, const char *fmt, ...)
348 fprintf(F, "edge: { sourcename: \""); PRINT_ENTID(E);
349 fprintf(F, "\" targetname: "); PRINT_TYPEID(T);
350 vfprintf(F, fmt, ap);
356 * prints the edge from a node N to a type T with additional info fmt, ...
359 static void print_node_type_edge(FILE *F, const ir_node *N, ir_type *T, const char *fmt, ...)
364 fprintf(F, "edge: { sourcename: \""); PRINT_NODEID(N);
365 fprintf(F, "\" targetname: "); PRINT_TYPEID(T);
366 vfprintf(F, fmt, ap);
372 * prints the edge from a node N to an entity E with additional info fmt, ...
375 static void print_node_ent_edge(FILE *F, const ir_node *N, ir_entity *E, const char *fmt, ...)
380 fprintf(F, "edge: { sourcename: \""); PRINT_NODEID(N);
381 fprintf(F, "\" targetname: \""); PRINT_ENTID(E);
383 vfprintf(F, fmt, ap);
389 * prints the edge from an entity E to a node N with additional info fmt, ...
392 static void print_ent_node_edge(FILE *F, ir_entity *E, const ir_node *N, const char *fmt, ...)
397 fprintf(F, "edge: { sourcename: \""); PRINT_ENTID(E);
398 fprintf(F, "\" targetname: \""); PRINT_NODEID(N); fprintf(F, "\"");
399 vfprintf(F, fmt, ap);
405 * prints the edge from a type E to an enumeration item item with additional info fmt, ...
408 static void print_enum_item_edge(FILE *F, ir_type *E, int item, const char *fmt, ...)
413 fprintf(F, "edge: { sourcename: "); PRINT_TYPEID(E);
414 fprintf(F, " targetname: \""); PRINT_ITEMID(E, item); fprintf(F, "\" ");
415 vfprintf(F, fmt, ap);
420 /*-----------------------------------------------------------------*/
421 /* global and ahead declarations */
422 /*-----------------------------------------------------------------*/
424 static void dump_whole_node(ir_node *n, void *env);
425 static INLINE void dump_loop_nodes_into_graph(FILE *F, ir_graph *irg);
427 /*-----------------------------------------------------------------*/
428 /* Helper functions. */
429 /*-----------------------------------------------------------------*/
432 * This map is used as a private link attr to be able to call dumper
433 * anywhere without destroying link fields.
435 static pmap *irdump_link_map = NULL;
437 /** NOT A STANDARD LIBFIRM INIT METHOD
439 * We do not want to integrate dumping into libfirm, i.e., if the dumpers
440 * are off, we want to have as few interferences as possible. Therefore the
441 * initialization is performed lazily and not called from within init_firm.
443 * Creates the link attribute map. */
444 static void init_irdump(void) {
445 /* We need a new, empty map. */
446 if (irdump_link_map) pmap_destroy(irdump_link_map);
447 irdump_link_map = pmap_create();
448 if (!dump_file_filter_id)
449 dump_file_filter_id = new_id_from_str("");
453 * Returns the private link field.
455 static void *ird_get_irn_link(ir_node *n) {
457 if (!irdump_link_map) return NULL;
459 if (pmap_contains(irdump_link_map, (void *)n))
460 res = pmap_get(irdump_link_map, (void *)n);
465 * Sets the private link field.
467 static void ird_set_irn_link(ir_node *n, void *x) {
468 if (!irdump_link_map)
470 pmap_insert(irdump_link_map, (void *)n, x);
474 * Gets the private link field of an irg.
476 static void *ird_get_irg_link(ir_graph *irg) {
478 if (!irdump_link_map) return NULL;
480 if (pmap_contains(irdump_link_map, (void *)irg))
481 res = pmap_get(irdump_link_map, (void *)irg);
486 * Sets the private link field of an irg.
488 static void ird_set_irg_link(ir_graph *irg, void *x) {
489 if (!irdump_link_map) init_irdump();
490 pmap_insert(irdump_link_map, (void *)irg, x);
494 * Walker, clears the private link field.
496 static void clear_link(ir_node * node, void * env) {
497 ird_set_irn_link(node, NULL);
501 * If the entity has a ld_name, returns it if the dump_ld_name is set,
502 * else returns the name of the entity.
504 static const char *_get_ent_dump_name(ir_entity *ent, int dump_ld_name) {
506 return "<NULL entity>";
508 /* Don't use get_entity_ld_ident (ent) as it computes the mangled name! */
509 if (ent->ld_name) return get_id_str(ent->ld_name);
511 return get_id_str(ent->name);
515 * If the entity has a ld_name, returns it if the option dump_ld_name is set,
516 * else returns the name of the entity.
518 const char *get_ent_dump_name(ir_entity *ent) {
519 return _get_ent_dump_name(ent, dump_ld_name);
522 /* Returns the name of an IRG. */
523 const char *get_irg_dump_name(ir_graph *irg) {
524 /* Don't use get_entity_ld_ident (ent) as it computes the mangled name! */
525 return _get_ent_dump_name(get_irg_entity(irg), 1);
529 * Returns non-zero if a node is in floating state.
531 static int node_floats(ir_node *n) {
532 return ((get_irn_pinned(n) == op_pin_state_floats) &&
533 (get_irg_pinned(current_ir_graph) == op_pin_state_floats));
537 * Walker that visits the anchors
539 static void ird_walk_graph(ir_graph *irg, irg_walk_func *pre, irg_walk_func *post, void *env) {
540 irg_walk_graph(irg, pre, post, env);
545 for (i = anchor_max - 1; i >= 0; --i) {
546 ir_node *n = irg->anchors[i];
549 /* reset the visit flag: will be increase in the walker */
550 set_irg_visited(irg, get_irg_visited(irg) - 1);
551 irg_walk(n, pre, post, env);
558 * Walker, allocates an array for all blocks and puts it's nodes non-floating nodes into this array.
560 static void collect_node(ir_node * node, void *env) {
563 || get_irn_op(node) == op_Bad
564 || get_irn_op(node) == op_Unknown
565 || get_irn_op(node) == op_NoMem) {
566 ir_node ** arr = (ir_node **) ird_get_irg_link(get_irn_irg(node));
567 if (!arr) arr = NEW_ARR_F(ir_node *, 0);
568 ARR_APP1(ir_node *, arr, node);
569 ird_set_irg_link(get_irn_irg(node), arr); /* arr is an l-value, APP_ARR might change it! */
571 ir_node * block = get_nodes_block(node);
574 /* this node is in a Bad block, so we must place it into the graph's list */
575 ir_node ** arr = (ir_node **) ird_get_irg_link(get_irn_irg(node));
576 if (!arr) arr = NEW_ARR_F(ir_node *, 0);
577 ARR_APP1(ir_node *, arr, node);
578 ird_set_irg_link(get_irn_irg(node), arr); /* arr is an l-value, APP_ARR might change it! */
580 ird_set_irn_link(node, ird_get_irn_link(block));
581 ird_set_irn_link(block, node);
586 /** Construct lists to walk ir block-wise.
588 * Collects all blocks, nodes not op_pin_state_pinned,
589 * Bad, NoMem and Unknown into a flexible array in link field of
590 * irg they belong to. Sets the irg link field to NULL in all
591 * graphs not visited.
592 * Free the list with DEL_ARR_F().
594 static ir_node **construct_block_lists(ir_graph *irg) {
596 int rem_view = get_interprocedural_view();
597 int walk_flag = using_visited(irg);
598 ir_graph *rem = current_ir_graph;
600 current_ir_graph = irg;
603 clear_using_visited(current_ir_graph);
605 for (i = get_irp_n_irgs() - 1; i >= 0; --i)
606 ird_set_irg_link(get_irp_irg(i), NULL);
608 ird_walk_graph(current_ir_graph, clear_link, collect_node, current_ir_graph);
610 /* Collect also EndReg and EndExcept. We do not want to change the walker. */
611 set_interprocedural_view(0);
613 set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph)-1);
614 irg_walk(get_irg_end_reg(current_ir_graph), clear_link, collect_node, current_ir_graph);
615 set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph)-1);
616 irg_walk(get_irg_end_except(current_ir_graph), clear_link, collect_node, current_ir_graph);
618 set_interprocedural_view(rem_view);
621 set_using_visited(current_ir_graph);
623 current_ir_graph = rem;
624 return ird_get_irg_link(irg);
627 typedef struct _list_tuple {
629 ir_extblk **extbb_list;
632 /** Construct lists to walk IR extended block-wise.
633 * Free the lists in the tuple with DEL_ARR_F().
634 * Sets the irg link field to NULL in all
635 * graphs not visited.
637 static list_tuple *construct_extblock_lists(ir_graph *irg) {
638 ir_node **blk_list = construct_block_lists(irg);
640 ir_graph *rem = current_ir_graph;
641 list_tuple *lists = xmalloc(sizeof(*lists));
643 current_ir_graph = irg;
645 lists->blk_list = NEW_ARR_F(ir_node *, 0);
646 lists->extbb_list = NEW_ARR_F(ir_extblk *, 0);
648 inc_irg_block_visited(irg);
649 for (i = ARR_LEN(blk_list) - 1; i >= 0; --i) {
652 if (is_Block(blk_list[i])) {
653 ext = get_Block_extbb(blk_list[i]);
655 if (extbb_not_visited(ext)) {
656 ARR_APP1(ir_extblk *, lists->extbb_list, ext);
657 mark_extbb_visited(ext);
660 ARR_APP1(ir_node *, lists->blk_list, blk_list[i]);
664 current_ir_graph = rem;
665 ird_set_irg_link(irg, lists);
669 /*-----------------------------------------------------------------*/
670 /* Routines to dump information about a single ir node. */
671 /*-----------------------------------------------------------------*/
674 * dump the name of a node n to the File F.
676 int dump_node_opcode(FILE *F, ir_node *n)
679 const ir_op_ops *ops = get_op_ops(get_irn_op(n));
681 /* call the dump_node operation if available */
683 return ops->dump_node(n, F, dump_node_opcode_txt);
685 /* implementation for default nodes */
686 switch (get_irn_opcode(n)) {
691 res = tarval_snprintf(buf, sizeof(buf), get_Const_tarval(n));
692 assert(res < sizeof(buf) && "buffer to small for tarval_snprintf");
697 switch (get_SymConst_kind(n)) {
698 case symconst_addr_name:
699 /* don't use get_SymConst_ptr_info as it mangles the name. */
700 fprintf(F, "SymC %s", get_id_str(get_SymConst_name(n)));
702 case symconst_addr_ent:
703 fprintf(F, "SymC &%s", get_entity_name(get_SymConst_entity(n)));
705 case symconst_ofs_ent:
706 fprintf(F, "SymC %s offset", get_entity_name(get_SymConst_entity(n)));
708 case symconst_type_tag:
709 fprintf(F, "SymC %s tag", get_type_name_ex(get_SymConst_type(n), &bad));
711 case symconst_type_size:
712 fprintf(F, "SymC %s size", get_type_name_ex(get_SymConst_type(n), &bad));
714 case symconst_type_align:
715 fprintf(F, "SymC %s align", get_type_name_ex(get_SymConst_type(n), &bad));
717 case symconst_enum_const:
718 fprintf(F, "SymC %s enum", get_enumeration_name(get_SymConst_enum(n)));
724 if (!get_interprocedural_view())
731 ir_node *pred = get_Proj_pred(n);
733 if (get_irn_opcode(pred) == iro_Cond
734 && get_Proj_proj(n) == get_Cond_defaultProj(pred)
735 && get_irn_mode(get_Cond_selector(pred)) != mode_b)
736 fprintf(F, "defProj");
744 if (get_interprocedural_view()) {
745 fprintf(F, "%s %s", get_irn_opname(n), get_ent_dump_name(get_irg_entity(get_irn_irg(n))));
750 case iro_CallBegin: {
751 ir_node *addr = get_CallBegin_ptr(n);
752 ir_entity *ent = NULL;
753 if (get_irn_op(addr) == op_Sel)
754 ent = get_Sel_entity(addr);
755 else if ((get_irn_op(addr) == op_SymConst) && (get_SymConst_kind(addr) == symconst_addr_ent))
756 ent = get_SymConst_entity(addr);
757 fprintf(F, "%s", get_irn_opname(n));
758 if (ent) fprintf(F, " %s", get_entity_name(ent));
762 fprintf(F, "%s[%s]", get_irn_opname(n), get_mode_name_ex(get_Load_mode(n), &bad));
765 fprintf(F, "%s%s", is_Block_dead(n) ? "Dead " : "", get_irn_opname(n));
768 if (get_Conv_strict(n))
769 fprintf(F, "strict");
770 fprintf(F, "%s", get_irn_opname(n));
775 fprintf(F, "%s", get_irn_opname(n));
782 * Dump the mode of a node n to a file F.
783 * Ignore modes that are "always known".
785 static int dump_node_mode(FILE *F, ir_node *n)
788 const ir_op_ops *ops = get_op_ops(get_irn_op(n));
791 /* call the dump_node operation if available */
793 return ops->dump_node(n, F, dump_node_mode_txt);
795 /* default implementation */
796 iro = get_irn_opcode(n);
808 ir_mode *mode = get_irn_mode(n);
810 if (mode && mode != mode_BB && mode != mode_ANY && mode != mode_BAD &&
811 (mode != mode_T || iro == iro_Proj))
812 fprintf(F, "%s", get_mode_name_ex(mode, &bad));
820 * Dump the type of a node n to a file F if it's known.
822 static int dump_node_typeinfo(FILE *F, ir_node *n) {
825 if (opt_dump_analysed_type_info) {
826 if (get_irg_typeinfo_state(current_ir_graph) == ir_typeinfo_consistent ||
827 get_irg_typeinfo_state(current_ir_graph) == ir_typeinfo_inconsistent) {
828 ir_type *tp = get_irn_typeinfo_type(n);
829 if (tp != firm_none_type)
830 fprintf(F, "[%s] ", get_type_name_ex(tp, &bad));
838 typedef struct _pns_lookup {
839 long nr; /**< the proj number */
840 const char *name; /**< the name of the Proj */
843 typedef struct _proj_lookup {
844 ir_opcode code; /**< the opcode of the Proj predecessor */
845 unsigned num_data; /**< number of data entries */
846 const pns_lookup_t *data; /**< the data */
849 #define ARR_SIZE(a) (sizeof(a)/sizeof(a[0]))
851 /** the lookup table for Proj(Start) names */
852 static const pns_lookup_t start_lut[] = {
853 #define X(a) { pn_Start_##a, #a }
863 /** the lookup table for Proj(Cond) names */
864 static const pns_lookup_t cond_lut[] = {
865 #define X(a) { pn_Cond_##a, #a }
871 /** the lookup table for Proj(Call) names */
872 static const pns_lookup_t call_lut[] = {
873 #define X(a) { pn_Call_##a, #a }
882 /** the lookup table for Proj(Quot) names */
883 static const pns_lookup_t quot_lut[] = {
884 #define X(a) { pn_Quot_##a, #a }
891 /** the lookup table for Proj(DivMod) names */
892 static const pns_lookup_t divmod_lut[] = {
893 #define X(a) { pn_DivMod_##a, #a }
901 /** the lookup table for Proj(Div) names */
902 static const pns_lookup_t div_lut[] = {
903 #define X(a) { pn_Div_##a, #a }
910 /** the lookup table for Proj(Mod) names */
911 static const pns_lookup_t mod_lut[] = {
912 #define X(a) { pn_Mod_##a, #a }
919 /** the lookup table for Proj(Load) names */
920 static const pns_lookup_t load_lut[] = {
921 #define X(a) { pn_Load_##a, #a }
928 /** the lookup table for Proj(Store) names */
929 static const pns_lookup_t store_lut[] = {
930 #define X(a) { pn_Store_##a, #a }
936 /** the lookup table for Proj(Alloc) names */
937 static const pns_lookup_t alloc_lut[] = {
938 #define X(a) { pn_Alloc_##a, #a }
945 /** the lookup table for Proj(CopyB) names */
946 static const pns_lookup_t copyb_lut[] = {
947 #define X(a) { pn_CopyB_##a, #a }
954 /** the lookup table for Proj(InstOf) names */
955 static const pns_lookup_t instof_lut[] = {
956 #define X(a) { pn_InstOf_##a, #a }
964 /** the lookup table for Proj(Raise) names */
965 static const pns_lookup_t raise_lut[] = {
966 #define X(a) { pn_Raise_##a, #a }
972 /** the lookup table for Proj(Bound) names */
973 static const pns_lookup_t bound_lut[] = {
974 #define X(a) { pn_Bound_##a, #a }
981 /** the Proj lookup table */
982 static const proj_lookup_t proj_lut[] = {
983 #define E(a) ARR_SIZE(a), a
984 { iro_Start, E(start_lut) },
985 { iro_Cond, E(cond_lut) },
986 { iro_Call, E(call_lut) },
987 { iro_Quot, E(quot_lut) },
988 { iro_DivMod, E(divmod_lut) },
989 { iro_Div, E(div_lut) },
990 { iro_Mod, E(mod_lut) },
991 { iro_Load, E(load_lut) },
992 { iro_Store, E(store_lut) },
993 { iro_Alloc, E(alloc_lut) },
994 { iro_CopyB, E(copyb_lut) },
995 { iro_InstOf, E(instof_lut) },
996 { iro_Raise, E(raise_lut) },
997 { iro_Bound, E(bound_lut) }
1002 * Dump additional node attributes of some nodes to a file F.
1005 dump_node_nodeattr(FILE *F, ir_node *n)
1011 const ir_op_ops *ops = get_op_ops(get_irn_op(n));
1013 /* call the dump_node operation if available */
1015 return ops->dump_node(n, F, dump_node_nodeattr_txt);
1017 switch (get_irn_opcode(n)) {
1019 if (0 && get_interprocedural_view()) {
1020 fprintf(F, "%s ", get_ent_dump_name(get_irg_entity(current_ir_graph)));
1025 pred = get_Proj_pred(n);
1026 proj_nr = get_Proj_proj(n);
1028 code = get_irn_opcode(pred);
1030 if (code == iro_Cmp)
1031 fprintf(F, "%s ", get_pnc_string(get_Proj_proj(n)));
1032 else if (code == iro_Proj && get_irn_opcode(get_Proj_pred(pred)) == iro_Start)
1033 fprintf(F, "Arg %ld ", proj_nr);
1034 else if (code == iro_Cond && get_irn_mode(get_Cond_selector(pred)) != mode_b)
1035 fprintf(F, "%ld ", proj_nr);
1037 unsigned i, j, f = 0;
1039 for (i = 0; i < ARR_SIZE(proj_lut); ++i) {
1040 if (code == proj_lut[i].code) {
1041 for (j = 0; j < proj_lut[i].num_data; ++j) {
1042 if (proj_nr == proj_lut[i].data[j].nr) {
1043 fprintf(F, "%s ", proj_lut[i].data[j].name);
1052 fprintf(F, "%ld ", proj_nr);
1053 if (code == iro_Cond && get_Cond_jmp_pred(pred) != COND_JMP_PRED_NONE) {
1054 if (proj_nr == pn_Cond_false && get_Cond_jmp_pred(pred) == COND_JMP_PRED_FALSE)
1055 fprintf(F, "PRED ");
1056 if (proj_nr == pn_Cond_true && get_Cond_jmp_pred(pred) == COND_JMP_PRED_TRUE)
1057 fprintf(F, "PRED ");
1062 proj_nr = get_Filter_proj(n);
1063 if (! get_interprocedural_view()) {
1065 pred = get_Filter_pred(n);
1068 fprintf(F, "%ld ", proj_nr);
1071 fprintf(F, "%s ", get_ent_dump_name(get_Sel_entity(n)));
1074 fprintf(F, "(%s) ", get_type_name_ex(get_Cast_type(n), &bad));
1077 fprintf(F, "%s ", get_pnc_string(get_Confirm_cmp(n)));
1080 fprintf(F, "(%s) ", get_type_name_ex(get_CopyB_type(n), &bad));
1091 #include "execution_frequency.h"
1093 static void dump_node_ana_vals(FILE *F, ir_node *n) {
1095 fprintf(F, " %lf*(%2.0lf + %2.0lf) = %2.0lf ",
1096 get_irn_exec_freq(n),
1097 get_irg_method_execution_frequency(get_irn_irg(n)),
1098 pow(5, get_irg_recursion_depth(get_irn_irg(n))),
1099 get_irn_exec_freq(n) * (get_irg_method_execution_frequency(get_irn_irg(n)) + pow(5, get_irg_recursion_depth(get_irn_irg(n))))
1104 /* Dumps a node label without the enclosing ". */
1105 int dump_node_label(FILE *F, ir_node *n) {
1108 bad |= dump_node_opcode(F, n);
1109 bad |= dump_node_mode(F, n);
1111 bad |= dump_node_typeinfo(F, n);
1112 bad |= dump_node_nodeattr(F, n);
1113 fprintf(F, "%ld:%d", get_irn_node_nr(n), get_irn_idx(n));
1120 * Dumps the attributes of a node n into the file F.
1121 * Currently this is only the color of a node.
1123 static void dump_node_vcgattr(FILE *F, ir_node *node, ir_node *local, int bad)
1128 print_vcg_color(F, ird_color_red);
1132 if (dump_node_vcgattr_hook)
1133 if (dump_node_vcgattr_hook(F, node, local))
1136 n = local ? local : node;
1138 if (overrule_nodecolor != ird_color_default) {
1139 print_vcg_color(F, overrule_nodecolor);
1143 switch (get_irn_opcode(n)) {
1150 print_vcg_color(F, ird_color_blue);
1153 if (is_Block_dead(n))
1154 print_vcg_color(F, ird_color_lightred);
1156 print_vcg_color(F, ird_color_lightyellow);
1159 print_vcg_color(F, ird_color_green);
1163 print_vcg_color(F, ird_color_gold);
1166 print_vcg_color(F, ird_color_orchid);
1172 print_vcg_color(F, ird_color_yellow);
1175 PRINT_DEFAULT_NODE_ATTR;
1179 /* Adds a new node info dumper callback. */
1180 void *dump_add_node_info_callback(dump_node_info_cb_t *cb, void *data)
1182 hook_entry_t *info = xmalloc(sizeof(*info));
1184 info->hook._hook_node_info = cb;
1185 info->context = data;
1186 register_hook(hook_node_info, info);
1191 /* Remove a previously added info dumper callback. */
1192 void dump_remv_node_info_callback(void *handle)
1194 hook_entry_t *info = handle;
1195 unregister_hook(hook_node_info, info);
1200 * Dump the node information of a node n to a file F.
1202 static INLINE int dump_node_info(FILE *F, ir_node *n)
1205 const ir_op_ops *ops = get_op_ops(get_irn_op(n));
1207 fprintf(F, " info1: \"");
1208 bad = dump_irnode_to_file(F, n);
1209 /* call the dump_node operation if available */
1211 bad = ops->dump_node(n, F, dump_node_info_txt);
1213 /* allow additional info to be added */
1214 hook_node_info(F, n);
1221 * checks whether a node is "constant-like" ie can be treated "block-less"
1224 int is_constlike_node(ir_node *n) {
1225 ir_opcode code = get_irn_opcode(n);
1226 return (code == iro_Const || code == iro_Bad || code == iro_NoMem || code == iro_SymConst || code == iro_Unknown);
1230 /** outputs the predecessors of n, that are constants, local. I.e.,
1231 generates a copy of the constant predecessors for each node called with. */
1232 static void dump_const_node_local(FILE *F, ir_node *n) {
1234 if (!get_opt_dump_const_local()) return;
1236 /* Use visited flag to avoid outputting nodes twice.
1237 initialize it first. */
1238 for (i = 0; i < get_irn_arity(n); i++) {
1239 ir_node *con = get_irn_n(n, i);
1240 if (is_constlike_node(con)) {
1241 set_irn_visited(con, get_irg_visited(current_ir_graph) - 1);
1245 for (i = 0; i < get_irn_arity(n); i++) {
1246 ir_node *con = get_irn_n(n, i);
1247 if (is_constlike_node(con) && irn_not_visited(con)) {
1250 mark_irn_visited(con);
1251 /* Generate a new name for the node by appending the names of
1253 fprintf(F, "node: {title: "); PRINT_CONSTID(n, con);
1254 fprintf(F, " label: \"");
1255 bad |= dump_node_label(F, con);
1257 bad |= dump_node_info(F, con);
1258 dump_node_vcgattr(F, n, con, bad);
1264 /** If the block of an edge is a const_like node, dump it local with an edge */
1265 static void dump_const_block_local(FILE *F, ir_node *n) {
1268 if (!get_opt_dump_const_local()) return;
1270 blk = get_nodes_block(n);
1271 if (is_constlike_node(blk)) {
1274 /* Generate a new name for the node by appending the names of
1276 fprintf(F, "node: {title: \""); PRINT_CONSTBLKID(n, blk);
1277 fprintf(F, "\" label: \"");
1278 bad |= dump_node_label(F, blk);
1280 bad |= dump_node_info(F, blk);
1281 dump_node_vcgattr(F, n, blk, bad);
1284 fprintf(F, "edge: { sourcename: \"");
1286 fprintf(F, "\" targetname: \""); PRINT_CONSTBLKID(n,blk);
1288 if (dump_edge_vcgattr_hook) {
1290 if (dump_edge_vcgattr_hook(F, n, -1)) {
1294 fprintf(F, " " BLOCK_EDGE_ATTR "}\n");
1299 fprintf(F, "\" " BLOCK_EDGE_ATTR "}\n");
1304 * prints the error message of a node to a file F as info2.
1306 static void print_node_error(FILE *F, const char *err_msg)
1311 fprintf(F, " info2: \"%s\"", err_msg);
1315 * prints debug messages of a node to file F as info3.
1317 static void print_dbg_info(FILE *F, dbg_info *dbg)
1321 if (__dbg_info_snprint) {
1323 if (__dbg_info_snprint(buf, sizeof(buf), dbg) > 0)
1324 fprintf(F, " info3: \"%s\"\n", buf);
1331 static void dump_node(FILE *F, ir_node *n)
1336 if (get_opt_dump_const_local() && is_constlike_node(n))
1339 /* dump this node */
1340 fprintf(F, "node: {title: \""); PRINT_NODEID(n); fprintf(F, "\" label: \"");
1342 bad = ! irn_vrfy_irg_dump(n, current_ir_graph, &p);
1343 bad |= dump_node_label(F, n);
1344 dump_node_ana_vals(F, n);
1345 //dump_node_ana_info(F, n);
1347 bad |= dump_node_info(F, n);
1348 print_node_error(F, p);
1349 print_dbg_info(F, get_irn_dbg_info(n));
1350 dump_node_vcgattr(F, n, NULL, bad);
1352 dump_const_node_local(F, n);
1354 if(dump_node_edge_hook)
1355 dump_node_edge_hook(F, n);
1357 dump_irn_chi_term(F, n);
1358 dump_irn_state(F, n);
1362 /** dump the edge to the block this node belongs to */
1364 dump_ir_block_edge(FILE *F, ir_node *n) {
1365 if (get_opt_dump_const_local() && is_constlike_node(n)) return;
1366 if (is_no_Block(n)) {
1367 ir_node *block = get_nodes_block(n);
1369 if (get_opt_dump_const_local() && is_constlike_node(block)) {
1370 dump_const_block_local(F, n);
1372 fprintf(F, "edge: { sourcename: \"");
1374 fprintf(F, "\" targetname: ");
1375 fprintf(F, "\""); PRINT_NODEID(block); fprintf(F, "\"");
1377 if (dump_edge_vcgattr_hook) {
1379 if (dump_edge_vcgattr_hook(F, n, -1)) {
1383 fprintf(F, " " BLOCK_EDGE_ATTR "}\n");
1388 fprintf(F, " " BLOCK_EDGE_ATTR "}\n");
1394 print_data_edge_vcgattr(FILE *F, ir_node *from, int to) {
1396 * do not use get_nodes_block() here, will fail
1397 * if the irg is not pinned.
1399 if (get_irn_n(from, -1) == get_irn_n(get_irn_n(from, to), -1))
1400 fprintf(F, INTRA_DATA_EDGE_ATTR);
1402 fprintf(F, INTER_DATA_EDGE_ATTR);
1406 print_mem_edge_vcgattr(FILE *F, ir_node *from, int to) {
1408 * do not use get_nodes_block() here, will fail
1409 * if the irg is not pinned.
1411 if (get_irn_n(from, -1) == get_irn_n(get_irn_n(from, to), -1))
1412 fprintf(F, INTRA_MEM_EDGE_ATTR);
1414 fprintf(F, INTER_MEM_EDGE_ATTR);
1418 print_edge_vcgattr(FILE *F, ir_node *from, int to) {
1421 if (dump_edge_vcgattr_hook)
1422 if (dump_edge_vcgattr_hook(F, from, to))
1425 if (dump_backedge_information_flag && is_backedge(from, to))
1426 fprintf(F, BACK_EDGE_ATTR);
1428 switch (get_irn_opcode(from)) {
1430 fprintf(F, CF_EDGE_ATTR);
1432 case iro_Start: break;
1435 if (get_irn_mode(get_End_keepalive(from, to)) == mode_BB)
1436 fprintf(F, CF_EDGE_ATTR);
1437 if (get_irn_mode(get_End_keepalive(from, to)) == mode_X)
1438 fprintf(F, INTER_MEM_EDGE_ATTR);
1442 if (is_Proj(from)) {
1443 if (get_irn_mode(from) == mode_M)
1444 print_mem_edge_vcgattr(F, from, to);
1445 else if (get_irn_mode(from) == mode_X)
1446 fprintf(F, CF_EDGE_ATTR);
1448 print_data_edge_vcgattr(F, from, to);
1450 else if (get_irn_mode(get_irn_n(from, to)) == mode_M)
1451 print_mem_edge_vcgattr(F, from, to);
1452 else if (get_irn_mode(get_irn_n(from, to)) == mode_X)
1453 fprintf(F, CF_EDGE_ATTR);
1455 print_data_edge_vcgattr(F, from, to);
1459 /* dump edges to our inputs */
1461 dump_ir_data_edges(FILE *F, ir_node *n) {
1463 unsigned long visited = get_irn_visited(n);
1465 if ((get_irn_op(n) == op_End) && (!dump_keepalive))
1468 /* dump the dependency edges. */
1469 for (i = 0; i < get_irn_deps(n); ++i) {
1470 ir_node *dep = get_irn_dep(n, i);
1473 fprintf(F, "edge: {sourcename: \"");
1475 fprintf(F, "\" targetname: ");
1476 if ((get_opt_dump_const_local()) && is_constlike_node(dep)) {
1477 PRINT_CONSTID(n, dep);
1483 fprintf(F, " label: \"%d\" ", i);
1484 fprintf(F, " color: darkgreen}\n");
1488 for (i = 0; i < get_irn_arity(n); i++) {
1489 ir_node * pred = get_irn_n(n, i);
1492 if ((get_interprocedural_view() && get_irn_visited(pred) < visited))
1493 continue; /* pred not dumped */
1495 if (dump_backedge_information_flag && is_backedge(n, i))
1496 fprintf(F, "backedge: {sourcename: \"");
1498 fprintf(F, "edge: {sourcename: \"");
1500 fprintf(F, "\" targetname: ");
1501 if ((get_opt_dump_const_local()) && is_constlike_node(pred)) {
1502 PRINT_CONSTID(n, pred);
1504 fprintf(F, "\""); PRINT_NODEID(pred); fprintf(F, "\"");
1506 fprintf(F, " label: \"%d\" ", i);
1507 print_edge_vcgattr(F, n, i);
1512 /** Dumps a node and its edges but not the block edge
1515 dump_node_wo_blockedge(ir_node *n, void *env) {
1518 dump_ir_data_edges(F, n);
1521 /** Dumps a node and its edges.
1524 dump_whole_node(ir_node *n, void *env) {
1526 dump_node_wo_blockedge(n, env);
1527 if (!node_floats(n)) dump_ir_block_edge(F, n);
1531 dump_const_node(ir_node *n, void *env) {
1532 if (is_Block(n)) return;
1533 dump_node_wo_blockedge(n, env);
1536 /***********************************************************************/
1537 /* the following routines dump the nodes/irgs bracketed to graphs. */
1538 /***********************************************************************/
1540 /** Dumps a constant expression as entity initializer, array bound ...
1542 static void dump_const_expression(FILE *F, ir_node *value) {
1543 ir_graph *rem = current_ir_graph;
1544 int rem_dump_const_local = dump_const_local;
1545 dump_const_local = 0;
1546 current_ir_graph = get_const_code_irg();
1547 irg_walk(value, dump_const_node, NULL, F);
1548 /* Decrease visited flag so that we walk with the same flag for the next
1549 expression. This guarantees that we don't dump the same node twice,
1550 as for const expressions cse is performed to save memory. */
1551 set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph) -1);
1552 current_ir_graph = rem;
1553 dump_const_local = rem_dump_const_local;
1556 /** Dump a block as graph containing its nodes.
1558 * Expects to find nodes belonging to the block as list in its
1560 * Dumps the edges of all nodes including itself. */
1562 dump_whole_block(FILE *F, ir_node *block) {
1564 dumper_colors color = ird_color_yellow;
1566 assert(is_Block(block));
1568 fprintf(F, "graph: { title: \"");
1569 PRINT_NODEID(block);
1570 fprintf(F, "\" label: \"");
1571 dump_node_label(F, block);
1573 if (get_opt_dump_abstvals())
1574 fprintf(F, " seqno: %d", (int)get_Block_seqno(block));
1577 /* colorize blocks */
1578 if (! get_Block_matured(block))
1579 color = ird_color_red;
1580 if (is_Block_dead(block))
1581 color = ird_color_orange;
1583 fprintf(F, "\" status:clustered ");
1584 print_vcg_color(F, color);
1587 /* yComp can show attributes for blocks, XVCG parses but ignores them */
1588 dump_node_info(F, block);
1589 print_dbg_info(F, get_irn_dbg_info(block));
1591 /* dump the blocks edges */
1592 dump_ir_data_edges(F, block);
1594 if (dump_block_edge_hook)
1595 dump_block_edge_hook(F, block);
1597 /* dump the nodes that go into the block */
1598 for (node = ird_get_irn_link(block); node; node = ird_get_irn_link(node)) {
1600 dump_ir_data_edges(F, node);
1603 /* Close the vcg information for the block */
1605 dump_const_node_local(F, block);
1607 dump_irn_chi_term(F, block);
1612 /** dumps a graph block-wise. Expects all blockless nodes in arr in irgs link.
1613 * The outermost nodes: blocks and nodes not op_pin_state_pinned, Bad, Unknown. */
1615 dump_block_graph(FILE *F, ir_graph *irg) {
1617 ir_graph *rem = current_ir_graph;
1618 ir_node **arr = ird_get_irg_link(irg);
1619 current_ir_graph = irg;
1621 for (i = ARR_LEN(arr) - 1; i >= 0; --i) {
1622 ir_node * node = arr[i];
1623 if (is_Block(node)) {
1624 /* Dumps the block and all the nodes in the block, which are to
1625 be found in Block->link. */
1626 dump_whole_block(F, node);
1628 /* Nodes that are not in a Block. */
1630 if (!node_floats(node) && is_Bad(get_nodes_block(node))) {
1631 dump_const_block_local(F, node);
1633 dump_ir_data_edges(F, node);
1637 if (dump_loop_information_flag && (get_irg_loopinfo_state(irg) & loopinfo_valid))
1638 dump_loop_nodes_into_graph(F, irg);
1640 current_ir_graph = rem;
1644 * Dump the info for an irg.
1645 * Parsed by XVCG but not shown. use yComp.
1647 static void dump_graph_info(FILE *F, ir_graph *irg) {
1648 fprintf(F, "info1: \"");
1649 dump_entity_to_file(F, get_irg_entity(irg), dump_verbosity_entattrs | dump_verbosity_entconsts);
1653 /** Dumps an irg as a graph clustered by block nodes.
1654 * If interprocedural view edges can point to nodes out of this graph.
1656 static void dump_graph_from_list(FILE *F, ir_graph *irg) {
1657 ir_entity *ent = get_irg_entity(irg);
1659 fprintf(F, "graph: { title: \"");
1661 fprintf(F, "\" label: \"%s\" status:clustered color:white \n",
1662 get_ent_dump_name(ent));
1664 dump_graph_info(F, irg);
1665 print_dbg_info(F, get_entity_dbg_info(ent));
1667 dump_block_graph(F, irg);
1669 /* Close the vcg information for the irg */
1670 fprintf(F, "}\n\n");
1673 /** dumps a graph extended block-wise. Expects all blockless nodes in arr in irgs link.
1674 * The outermost nodes: blocks and nodes not op_pin_state_pinned, Bad, Unknown. */
1676 dump_extblock_graph(FILE *F, ir_graph *irg) {
1678 ir_graph *rem = current_ir_graph;
1679 ir_extblk **arr = ird_get_irg_link(irg);
1680 current_ir_graph = irg;
1682 for (i = ARR_LEN(arr) - 1; i >= 0; --i) {
1683 ir_extblk *extbb = arr[i];
1684 ir_node *leader = get_extbb_leader(extbb);
1687 fprintf(F, "graph: { title: \"");
1688 PRINT_EXTBBID(leader);
1689 fprintf(F, "\" label: \"ExtBB %ld\" status:clustered color:lightgreen\n",
1690 get_irn_node_nr(leader));
1692 for (j = ARR_LEN(extbb->blks) - 1; j >= 0; --j) {
1693 ir_node * node = extbb->blks[j];
1694 if (is_Block(node)) {
1695 /* Dumps the block and all the nodes in the block, which are to
1696 be found in Block->link. */
1697 dump_whole_block(F, node);
1699 /* Nodes that are not in a Block. */
1701 if (is_Bad(get_nodes_block(node)) && !node_floats(node)) {
1702 dump_const_block_local(F, node);
1704 dump_ir_data_edges(F, node);
1710 if (dump_loop_information_flag && (get_irg_loopinfo_state(irg) & loopinfo_valid))
1711 dump_loop_nodes_into_graph(F, irg);
1713 current_ir_graph = rem;
1718 /*******************************************************************/
1719 /* Basic type and entity nodes and edges. */
1720 /*******************************************************************/
1722 /** dumps the edges between nodes and their type or entity attributes. */
1723 static void dump_node2type_edges(ir_node *n, void *env)
1728 switch (get_irn_opcode(n)) {
1730 /* @@@ some consts have an entity */
1733 if (SYMCONST_HAS_TYPE(get_SymConst_kind(n)))
1734 print_node_type_edge(F,n,get_SymConst_type(n),NODE2TYPE_EDGE_ATTR);
1737 print_node_ent_edge(F,n,get_Sel_entity(n),NODE2TYPE_EDGE_ATTR);
1740 print_node_type_edge(F,n,get_Call_type(n),NODE2TYPE_EDGE_ATTR);
1743 print_node_type_edge(F,n,get_Alloc_type(n),NODE2TYPE_EDGE_ATTR);
1746 print_node_type_edge(F,n,get_Free_type(n),NODE2TYPE_EDGE_ATTR);
1749 print_node_type_edge(F,n,get_Cast_type(n),NODE2TYPE_EDGE_ATTR);
1757 static int print_type_info(FILE *F, ir_type *tp) {
1760 if (get_type_state(tp) == layout_undefined) {
1761 fprintf(F, "state: layout_undefined\n");
1763 fprintf(F, "state: layout_fixed,\n");
1765 if (get_type_mode(tp))
1766 fprintf(F, "mode: %s,\n", get_mode_name_ex(get_type_mode(tp), &bad));
1767 fprintf(F, "size: %db,\n", get_type_size_bits(tp));
1772 static void print_typespecific_info(FILE *F, ir_type *tp) {
1773 switch (get_type_tpop_code(tp)) {
1775 fprintf(F, "peculiarity: %s\n", get_peculiarity_string(get_class_peculiarity(tp)));
1780 fprintf(F, "variadicity: %s\n", get_variadicity_name(get_method_variadicity(tp)));
1781 fprintf(F, "params: %d\n", get_method_n_params(tp));
1782 fprintf(F, "results: %d\n", get_method_n_ress(tp));
1788 case tpo_enumeration:
1800 static void print_typespecific_vcgattr(FILE *F, ir_type *tp) {
1801 switch (get_type_tpop_code(tp)) {
1803 if (peculiarity_existent == get_class_peculiarity(tp))
1804 fprintf(F, " " TYPE_CLASS_NODE_ATTR);
1806 fprintf(F, " " TYPE_DESCRIPTION_NODE_ATTR);
1809 fprintf(F, " " TYPE_METH_NODE_ATTR);
1817 case tpo_enumeration:
1829 int dump_type_node(FILE *F, ir_type *tp)
1833 fprintf(F, "node: {title: ");
1835 fprintf(F, " label: \"%s %s\"", get_type_tpop_name(tp), get_type_name_ex(tp, &bad));
1836 fprintf(F, " info1: \"");
1838 bad |= print_type_info(F, tp);
1839 print_typespecific_info(F, tp);
1841 dump_type_to_file(F, tp, dump_verbosity_max);
1844 print_dbg_info(F, get_type_dbg_info(tp));
1845 print_typespecific_vcgattr(F, tp);
1852 void dump_entity_node(FILE *F, ir_entity *ent, int color)
1854 fprintf(F, "node: {title: \"");
1855 PRINT_ENTID(ent); fprintf(F, "\"");
1856 fprintf(F, DEFAULT_TYPE_ATTRIBUTE);
1857 fprintf(F, "label: ");
1858 fprintf(F, "\"ent %s\" ", get_ent_dump_name(ent));
1860 fprintf(F, "color:%d", color);
1862 fprintf(F, ENTITY_NODE_ATTR);
1863 fprintf(F, "\n info1: \"");
1865 dump_entity_to_file(F, ent, dump_verbosity_entattrs | dump_verbosity_entconsts);
1868 print_dbg_info(F, get_entity_dbg_info(ent));
1872 static void dump_enum_item(FILE *F, ir_type *tp, int pos)
1875 ir_enum_const *ec = get_enumeration_const(tp, pos);
1876 ident *id = get_enumeration_nameid(ec);
1877 tarval *tv = get_enumeration_value(ec);
1880 tarval_snprintf(buf, sizeof(buf), tv);
1882 strncpy(buf, "<not set>", sizeof(buf));
1883 fprintf(F, "node: {title: \"");
1884 PRINT_ITEMID(tp, pos); fprintf(F, "\"");
1885 fprintf(F, DEFAULT_ENUM_ITEM_ATTRIBUTE);
1886 fprintf(F, "label: ");
1887 fprintf(F, "\"enum item %s\" " ENUM_ITEM_NODE_ATTR, get_id_str(id));
1888 fprintf(F, "\n info1: \"value: %s\"}\n", buf);
1891 /* dumps a type or entity and it's edges. */
1893 dump_type_info(type_or_ent *tore, void *env) {
1895 int i = 0; /* to shutup gcc */
1897 /* dump this type or entity */
1899 switch (get_kind(tore)) {
1901 ir_entity *ent = (ir_entity *)tore;
1904 dump_entity_node(F, ent, 0);
1906 /* skip this to reduce graph. Member edge of type is parallel to this edge. *
1907 fprintf(F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
1908 ENT_OWN_EDGE_ATTR "}\n", ent, get_entity_owner(ent));*/
1909 print_ent_type_edge(F,ent, get_entity_type(ent), ENT_TYPE_EDGE_ATTR);
1910 if (is_Class_type(get_entity_owner(ent))) {
1911 for(i = 0; i < get_entity_n_overwrites(ent); i++)
1912 print_ent_ent_edge(F,ent, get_entity_overwrites(ent, i), 0, ENT_OVERWRITES_EDGE_ATTR);
1914 /* attached subgraphs */
1915 if (const_entities && (get_entity_variability(ent) != variability_uninitialized)) {
1916 if (is_atomic_entity(ent)) {
1917 value = get_atomic_ent_value(ent);
1919 print_ent_node_edge(F, ent, value, ENT_VALUE_EDGE_ATTR, i);
1920 /* DDMN(value); $$$ */
1921 dump_const_expression(F, value);
1924 if (is_compound_entity(ent)) {
1925 for (i = 0; i < get_compound_ent_n_values(ent); i++) {
1926 value = get_compound_ent_value(ent, i);
1928 print_ent_node_edge(F, ent, value, ENT_VALUE_EDGE_ATTR, i);
1929 dump_const_expression(F, value);
1930 print_ent_ent_edge(F, ent, get_compound_ent_value_member(ent, i), 0, ENT_CORR_EDGE_ATTR, i);
1932 fprintf(F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
1933 ENT_CORR_EDGE_ATTR "}\n", GET_ENTID(ent),
1934 get_compound_ent_value_member(ent, i), i);
1943 ir_type *tp = (ir_type *)tore;
1944 dump_type_node(F, tp);
1945 /* and now the edges */
1946 switch (get_type_tpop_code(tp)) {
1948 for (i=0; i < get_class_n_supertypes(tp); i++)
1949 print_type_type_edge(F, tp,get_class_supertype(tp, i),TYPE_SUPER_EDGE_ATTR);
1950 for (i=0; i < get_class_n_members(tp); i++)
1951 print_type_ent_edge(F,tp,get_class_member(tp, i),TYPE_MEMBER_EDGE_ATTR);
1954 for (i=0; i < get_struct_n_members(tp); i++)
1955 print_type_ent_edge(F,tp,get_struct_member(tp, i),TYPE_MEMBER_EDGE_ATTR);
1958 for (i = 0; i < get_method_n_params(tp); i++)
1959 print_type_type_edge(F,tp,get_method_param_type(tp, i),METH_PAR_EDGE_ATTR,i);
1960 for (i = 0; i < get_method_n_ress(tp); i++)
1961 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);
1968 print_type_type_edge(F,tp,get_array_element_type(tp),ARR_ELT_TYPE_EDGE_ATTR);
1969 print_type_ent_edge(F,tp,get_array_element_entity(tp),ARR_ENT_EDGE_ATTR);
1970 for (i = 0; i < get_array_n_dimensions(tp); i++) {
1971 ir_node *upper = get_array_upper_bound(tp, i);
1972 ir_node *lower = get_array_lower_bound(tp, i);
1973 print_node_type_edge(F, upper, tp, "label: \"upper %d\"", get_array_order(tp, i));
1974 print_node_type_edge(F, lower, tp, "label: \"lower %d\"", get_array_order(tp, i));
1975 dump_const_expression(F, upper);
1976 dump_const_expression(F, lower);
1979 case tpo_enumeration:
1980 for (i = 0; i < get_enumeration_n_enums(tp); ++i) {
1981 dump_enum_item(F, tp, i);
1982 print_enum_item_edge(F, tp, i, "label: \"item %d\"", i);
1986 print_type_type_edge(F,tp,get_pointer_points_to_type(tp), PTR_PTS_TO_EDGE_ATTR);
1993 break; /* case k_type */
1996 printf(" *** irdump, dump_type_info(l.%i), faulty type.\n", __LINE__);
1997 } /* switch kind_or_entity */
2000 typedef struct _h_env {
2005 /** For dumping class hierarchies.
2006 * Dumps a class type node and a superclass edge.
2007 * If env->dump_ent dumps entities of classes and overwrites edges.
2010 dump_class_hierarchy_node(type_or_ent *tore, void *ctx) {
2013 int i = 0; /* to shutup gcc */
2015 /* dump this type or entity */
2016 switch (get_kind(tore)) {
2018 ir_entity *ent = (ir_entity *)tore;
2019 if (get_entity_owner(ent) == get_glob_type()) break;
2020 if (!is_Method_type(get_entity_type(ent))) break; /* GL */
2021 if (env->dump_ent && is_Class_type(get_entity_owner(ent))) {
2023 dump_entity_node(F, ent, 0);
2025 print_type_ent_edge(F,get_entity_owner(ent),ent,TYPE_MEMBER_EDGE_ATTR);
2026 for(i = 0; i < get_entity_n_overwrites(ent); i++)
2027 print_ent_ent_edge(F, get_entity_overwrites(ent, i), ent, 0, ENT_OVERWRITES_EDGE_ATTR);
2032 ir_type *tp = (ir_type *)tore;
2033 if (tp == get_glob_type()) break;
2034 switch (get_type_tpop_code(tp)) {
2036 dump_type_node(F, tp);
2037 /* and now the edges */
2038 for (i=0; i < get_class_n_supertypes(tp); i++) {
2039 print_type_type_edge(F,tp,get_class_supertype(tp, i),TYPE_SUPER_EDGE_ATTR);
2044 break; /* case k_type */
2047 printf(" *** irdump, dump_class_hierarchy_node(l.%i), faulty type.\n", __LINE__);
2048 } /* switch kind_or_entity */
2051 /*******************************************************************/
2052 /* dump analysis information that is expressed in graph terms. */
2053 /*******************************************************************/
2055 /* dump out edges */
2057 dump_out_edge(ir_node *n, void *env) {
2060 for (i = 0; i < get_irn_n_outs(n); i++) {
2061 assert(get_irn_out(n, i));
2062 fprintf(F, "edge: {sourcename: \"");
2064 fprintf(F, "\" targetname: \"");
2065 PRINT_NODEID(get_irn_out(n, i));
2066 fprintf(F, "\" color: red linestyle: dashed");
2072 dump_loop_label(FILE *F, ir_loop *loop) {
2073 fprintf(F, "loop %d, %d sons, %d nodes",
2074 get_loop_depth(loop), get_loop_n_sons(loop), get_loop_n_nodes(loop));
2077 static INLINE void dump_loop_info(FILE *F, ir_loop *loop) {
2078 fprintf(F, " info1: \"");
2079 fprintf(F, " loop nr: %d", get_loop_loop_nr(loop));
2080 #ifdef DEBUG_libfirm /* GL @@@ debug analyses */
2081 fprintf(F, "\n The loop was analyzed %d times.", PTR_TO_INT(get_loop_link(loop)));
2087 dump_loop_node(FILE *F, ir_loop *loop) {
2088 fprintf(F, "node: {title: \"");
2090 fprintf(F, "\" label: \"");
2091 dump_loop_label(F, loop);
2093 dump_loop_info(F, loop);
2098 dump_loop_node_edge(FILE *F, ir_loop *loop, int i) {
2100 fprintf(F, "edge: {sourcename: \"");
2102 fprintf(F, "\" targetname: \"");
2103 PRINT_NODEID(get_loop_node(loop, i));
2104 fprintf(F, "\" color: green");
2109 dump_loop_son_edge(FILE *F, ir_loop *loop, int i) {
2111 fprintf(F, "edge: {sourcename: \"");
2113 fprintf(F, "\" targetname: \"");
2114 PRINT_LOOPID(get_loop_son(loop, i));
2115 fprintf(F, "\" color: darkgreen label: \"%d\"}\n",
2116 get_loop_element_pos(loop, get_loop_son(loop, i)));
2120 void dump_loops(FILE *F, ir_loop *loop) {
2122 /* dump this loop node */
2123 dump_loop_node(F, loop);
2125 /* dump edges to nodes in loop -- only if it is a real loop */
2126 if (get_loop_depth(loop) != 0) {
2127 for (i = 0; i < get_loop_n_nodes(loop); i++) {
2128 dump_loop_node_edge(F, loop, i);
2131 for (i = 0; i < get_loop_n_sons(loop); i++) {
2132 dump_loops(F, get_loop_son(loop, i));
2133 dump_loop_son_edge(F, loop, i);
2138 void dump_loop_nodes_into_graph(FILE *F, ir_graph *irg) {
2139 ir_graph *rem = current_ir_graph;
2140 current_ir_graph = irg;
2142 if (get_irg_loop(irg)) dump_loops(F, get_irg_loop(irg));
2144 current_ir_graph = rem;
2149 * dumps the VCG header
2151 void dump_vcg_header(FILE *F, const char *name, const char *orientation) {
2160 if (!orientation) orientation = "bottom_to_top";
2164 "graph: { title: \"ir graph of %s\"\n"
2165 "display_edge_labels: %s\n"
2166 "layoutalgorithm: mindepth\n"
2167 "manhattan_edges: yes\n"
2168 "port_sharing: no\n"
2170 "classname 1: \"intrablock Data\"\n"
2171 "classname 2: \"Block\"\n"
2172 "classname 3: \"Entity type\"\n"
2173 "classname 4: \"Entity owner\"\n"
2174 "classname 5: \"Method Param\"\n"
2175 "classname 6: \"Method Res\"\n"
2176 "classname 7: \"Super\"\n"
2177 "classname 8: \"Union\"\n"
2178 "classname 9: \"Points-to\"\n"
2179 "classname 10: \"Array Element Type\"\n"
2180 "classname 11: \"Overwrites\"\n"
2181 "classname 12: \"Member\"\n"
2182 "classname 13: \"Control Flow\"\n"
2183 "classname 14: \"intrablock Memory\"\n"
2184 "classname 15: \"Dominators\"\n"
2185 "classname 16: \"interblock Data\"\n"
2186 "classname 17: \"interblock Memory\"\n"
2187 "classname 18: \"Exception Control Flow for Interval Analysis\"\n"
2188 "classname 19: \"Postdominators\"\n"
2189 "infoname 1: \"Attribute\"\n"
2190 "infoname 2: \"Verification errors\"\n"
2191 "infoname 3: \"Debug info\"\n",
2192 name, label, orientation);
2194 /* don't use all, the range is too whith/black. */
2198 "colorentry 100: 0 0 0\n"
2199 "colorentry 101: 20 0 0\n"
2200 "colorentry 102: 40 0 0\n"
2201 "colorentry 103: 60 0 0\n"
2202 "colorentry 104: 80 0 0\n"
2203 "colorentry 105: 100 0 0\n"
2204 "colorentry 106: 120 0 0\n"
2205 "colorentry 107: 140 0 0\n"
2206 "colorentry 108: 150 0 0\n"
2207 "colorentry 109: 180 0 0\n"
2208 "colorentry 110: 200 0 0\n"
2209 "colorentry 111: 220 0 0\n"
2210 "colorentry 112: 240 0 0\n"
2211 "colorentry 113: 255 0 0\n"
2212 "colorentry 113: 255 20 20\n"
2213 "colorentry 114: 255 40 40\n"
2214 "colorentry 115: 255 60 60\n"
2215 "colorentry 116: 255 80 80\n"
2216 "colorentry 117: 255 100 100\n"
2217 "colorentry 118: 255 120 120\n"
2218 "colorentry 119: 255 140 140\n"
2219 "colorentry 120: 255 150 150\n"
2220 "colorentry 121: 255 180 180\n"
2221 "colorentry 122: 255 200 200\n"
2222 "colorentry 123: 255 220 220\n"
2223 "colorentry 124: 255 240 240\n"
2224 "colorentry 125: 255 250 250\n"
2227 fprintf(F, "\n"); /* a separator */
2233 * @param irg The graph to be dumped
2234 * @param suffix1 first filename suffix
2235 * @param suffix2 second filename suffix
2237 FILE *vcg_open(ir_graph *irg, const char * suffix1, const char *suffix2) {
2239 const char *nm = get_irg_dump_name(irg);
2240 int len = strlen(nm), i, j;
2241 char *fname; /* filename to put the vcg information in */
2243 if (!suffix1) suffix1 = "";
2244 if (!suffix2) suffix2 = "";
2246 /* open file for vcg graph */
2247 fname = xmalloc (len * 2 + strlen(suffix1) + strlen(suffix2) + 5);
2249 /* strncpy (fname, nm, len); */ /* copy the filename */
2251 for (i = 0; i < len; ++i) { /* replace '/' in the name: escape by @. */
2253 fname[j] = '@'; j++; fname[j] = '1'; j++;
2254 } else if (nm[i] == '@') {
2255 fname[j] = '@'; j++; fname[j] = '2'; j++;
2257 fname[j] = nm[i]; j++;
2261 strcat(fname, suffix1); /* append file suffix */
2262 strcat(fname, suffix2); /* append file suffix */
2263 strcat(fname, ".vcg"); /* append the .vcg suffix */
2265 /* vcg really expect only a <CR> at end of line, so
2266 * the "b"inary mode is what you mean (and even needed for Win32)
2268 F = fopen(fname, "wb"); /* open file for writing */
2280 * @param name prefix file name
2281 * @param suffix filename suffix
2283 FILE *vcg_open_name(const char *name, const char *suffix) {
2285 char *fname; /* filename to put the vcg information in */
2286 int i, j, len = strlen(name);
2288 if (!suffix) suffix = "";
2290 /** open file for vcg graph */
2291 fname = xmalloc(len * 2 + 5 + strlen(suffix));
2292 /* strcpy (fname, name);*/ /* copy the filename */
2294 for (i = 0; i < len; ++i) { /* replace '/' in the name: escape by @. */
2295 if (name[i] == '/') {
2296 fname[j] = '@'; j++; fname[j] = '1'; j++;
2297 } else if (name[i] == '@') {
2298 fname[j] = '@'; j++; fname[j] = '2'; j++;
2300 fname[j] = name[i]; j++;
2304 strcat(fname, suffix);
2305 strcat(fname, ".vcg"); /* append the .vcg suffix */
2307 /* vcg really expect only a <CR> at end of line, so
2308 * the "b"inary mode is what you mean (and even needed for Win32)
2310 F = fopen(fname, "wb"); /* open file for writing */
2320 * Dumps the vcg file footer
2322 static void dump_vcg_footer(FILE *F) {
2327 * close the vcg file
2329 void vcg_close(FILE *F) {
2330 dump_vcg_footer(F); /* print footer */
2331 fclose (F); /* close vcg file */
2334 /************************************************************************/
2335 /************************************************************************/
2336 /* Routines that dump all or parts of the firm representation to a file */
2337 /************************************************************************/
2338 /************************************************************************/
2340 /************************************************************************/
2341 /* Dump ir graphs, different formats and additional information. */
2342 /************************************************************************/
2344 /** Routine to dump a graph, blocks as conventional nodes. */
2346 dump_ir_graph(ir_graph *irg, const char *suffix )
2352 if (!is_filtered_dump_name(get_entity_ident(get_irg_entity(irg))))
2355 if (dump_backedge_information_flag && get_irg_loopinfo_state(irg) != loopinfo_consistent) {
2356 construct_backedges(irg);
2359 rem = current_ir_graph;
2360 current_ir_graph = irg;
2361 if (get_interprocedural_view()) suffix1 = "-pure-ip";
2362 else suffix1 = "-pure";
2363 f = vcg_open(irg, suffix, suffix1);
2365 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
2367 /* call the dump graph hook */
2368 if (dump_ir_graph_hook)
2369 if (dump_ir_graph_hook(f, irg)) {
2370 current_ir_graph = rem;
2374 /* walk over the graph */
2375 /* dump_whole_node must be called in post visiting predecessors */
2376 ird_walk_graph(irg, NULL, dump_whole_node, f);
2378 /* dump the out edges in a separate walk */
2379 if ((dump_out_edge_flag) && (get_irg_outs_state(irg) != outs_none)) {
2380 irg_out_walk(get_irg_start(irg), dump_out_edge, NULL, f);
2385 current_ir_graph = rem;
2388 /* Dump a firm graph without explicit block nodes. */
2389 void dump_ir_block_graph(ir_graph *irg, const char *suffix)
2395 if (!is_filtered_dump_name(get_entity_ident(get_irg_entity(irg))))
2398 if (get_interprocedural_view()) suffix1 = "-ip";
2400 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));
2424 /* Dump a firm graph without explicit block nodes but grouped in extended blocks. */
2425 void dump_ir_extblock_graph(ir_graph *irg, const char *suffix)
2432 if (!is_filtered_dump_name(get_entity_ident(get_irg_entity(irg))))
2435 if (get_irg_extblk_state(irg) != extblk_valid)
2438 if (get_interprocedural_view()) suffix1 = "-ip";
2441 ent = get_irg_entity(irg);
2443 F = vcg_open(irg, suffix, suffix1);
2445 dump_vcg_header(F, get_irg_dump_name(irg), NULL);
2447 construct_extblock_lists(irg);
2449 fprintf(F, "graph: { title: \"");
2451 fprintf(F, "\" label: \"%s\" status:clustered color: white \n",
2452 get_ent_dump_name(ent));
2454 dump_graph_info(F, irg);
2455 print_dbg_info(F, get_entity_dbg_info(ent));
2457 for (i = get_irp_n_irgs() - 1; i >= 0; --i) {
2458 ir_graph *irg = get_irp_irg(i);
2459 list_tuple *lists = ird_get_irg_link(irg);
2462 /* dump the extended blocks first */
2463 if (ARR_LEN(lists->extbb_list)) {
2464 ird_set_irg_link(irg, lists->extbb_list);
2465 dump_extblock_graph(F, irg);
2468 /* we may have blocks without extended blocks, bad for instance */
2469 if (ARR_LEN(lists->blk_list)) {
2470 ird_set_irg_link(irg, lists->blk_list);
2471 dump_block_graph(F, irg);
2474 DEL_ARR_F(lists->extbb_list);
2475 DEL_ARR_F(lists->blk_list);
2480 /* Close the vcg information for the irg */
2481 fprintf(F, "}\n\n");
2488 /* dumps a graph with type information */
2490 dump_ir_graph_w_types(ir_graph *irg, const char *suffix)
2495 /* if a filter is set, dump only the irg's that match the filter */
2496 if (!is_filtered_dump_name(get_entity_ident(get_irg_entity(irg))))
2499 if (get_interprocedural_view()) suffix1 = "-pure-wtypes-ip";
2500 else suffix1 = "-pure-wtypes";
2501 f = vcg_open(irg,suffix, suffix1);
2503 ir_graph *rem = current_ir_graph;
2504 int rem_dump_const_local;
2506 current_ir_graph = irg;
2507 rem_dump_const_local = dump_const_local;
2508 /* dumping types does not work with local nodes */
2509 dump_const_local = 0;
2511 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
2513 /* dump common ir graph */
2514 irg_walk(get_irg_end(irg), NULL, dump_whole_node, f);
2515 /* dump type info */
2516 type_walk_irg(irg, dump_type_info, NULL, f);
2517 inc_irg_visited(get_const_code_irg());
2518 /* dump edges from graph to type info */
2519 irg_walk(get_irg_end(irg), dump_node2type_edges, NULL, f);
2522 dump_const_local = rem_dump_const_local;
2523 current_ir_graph = rem;
2528 dump_ir_block_graph_w_types(ir_graph *irg, const char *suffix)
2534 /* if a filter is set, dump only the irg's that match the filter */
2535 if (!is_filtered_dump_name(get_entity_ident(get_irg_entity(irg))))
2538 if (get_interprocedural_view()) suffix1 = "-wtypes-ip";
2539 else suffix1 = "-wtypes";
2540 f = vcg_open(irg, suffix, suffix1);
2542 ir_graph *rem = current_ir_graph;
2543 int rem_dump_const_local;
2545 rem_dump_const_local = dump_const_local;
2546 /* dumping types does not work with local nodes */
2547 dump_const_local = 0;
2549 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
2551 /* dump common blocked ir graph */
2552 construct_block_lists(irg);
2554 for (i = get_irp_n_irgs() - 1; i >= 0; --i) {
2555 ir_node **arr = ird_get_irg_link(get_irp_irg(i));
2557 dump_graph_from_list(f, get_irp_irg(i));
2562 /* dump type info */
2563 current_ir_graph = irg;
2564 type_walk_irg(irg, dump_type_info, NULL, f);
2565 inc_irg_visited(get_const_code_irg());
2567 /* dump edges from graph to type info */
2568 irg_walk(get_irg_end(irg), dump_node2type_edges, NULL, f);
2571 dump_const_local = rem_dump_const_local;
2572 current_ir_graph = rem;
2576 /*---------------------------------------------------------------------*/
2577 /* The following routines dump a control flow graph. */
2578 /*---------------------------------------------------------------------*/
2581 dump_block_to_cfg(ir_node *block, void *env) {
2586 if (is_Block(block)) {
2587 /* This is a block. Dump a node for the block. */
2588 fprintf(F, "node: {title: \""); PRINT_NODEID(block);
2589 fprintf(F, "\" label: \"");
2590 if (block == get_irg_start_block(get_irn_irg(block)))
2591 fprintf(F, "Start ");
2592 if (block == get_irg_end_block(get_irn_irg(block)))
2595 fprintf(F, "%s ", get_op_name(get_irn_op(block)));
2596 PRINT_NODEID(block);
2598 fprintf(F, "info1:\"");
2600 /* the generic version. */
2601 dump_irnode_to_file(F, block);
2603 /* Check whether we have bad predecessors to color the block. */
2604 for (i = 0; i < get_Block_n_cfgpreds(block); ++i)
2605 if ((fl = is_Bad(get_Block_cfgpred(block, i))))
2608 fprintf(F, "\""); /* closing quote of info */
2610 if ((block == get_irg_start_block(get_irn_irg(block))) ||
2611 (block == get_irg_end_block(get_irn_irg(block))) )
2612 fprintf(F, " color:blue ");
2614 fprintf(F, " color:yellow ");
2617 /* Dump the edges */
2618 for ( i = 0; i < get_Block_n_cfgpreds(block); i++)
2619 if (get_irn_op(skip_Proj(get_Block_cfgpred(block, i))) != op_Bad) {
2620 pred = get_nodes_block(skip_Proj(get_Block_cfgpred(block, i)));
2621 fprintf(F, "edge: { sourcename: \"");
2622 PRINT_NODEID(block);
2623 fprintf(F, "\" targetname: \"");
2625 fprintf(F, "\"}\n");
2628 /* Dump dominator/postdominator edge */
2629 if (dump_dominator_information_flag) {
2630 if (get_irg_dom_state(current_ir_graph) == dom_consistent && get_Block_idom(block)) {
2631 pred = get_Block_idom(block);
2632 fprintf(F, "edge: { sourcename: \"");
2633 PRINT_NODEID(block);
2634 fprintf(F, "\" targetname: \"");
2636 fprintf(F, "\" " DOMINATOR_EDGE_ATTR "}\n");
2638 if (get_irg_postdom_state(current_ir_graph) == dom_consistent && get_Block_ipostdom(block)) {
2639 pred = get_Block_ipostdom(block);
2640 fprintf(F, "edge: { sourcename: \"");
2641 PRINT_NODEID(block);
2642 fprintf(F, "\" targetname: \"");
2644 fprintf(F, "\" " POSTDOMINATOR_EDGE_ATTR "}\n");
2651 dump_cfg(ir_graph *irg, const char *suffix)
2654 /* if a filter is set, dump only the irg's that match the filter */
2655 if (!is_filtered_dump_name(get_entity_ident(get_irg_entity(irg))))
2658 f = vcg_open(irg, suffix, "-cfg");
2660 ir_graph *rem = current_ir_graph;
2661 int ipv = get_interprocedural_view();
2663 current_ir_graph = irg;
2664 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
2667 printf("Warning: dumping cfg not in interprocedural view!\n");
2668 set_interprocedural_view(0);
2671 /* walk over the blocks in the graph */
2672 irg_block_walk(get_irg_end(irg), dump_block_to_cfg, NULL, f);
2673 dump_node(f, get_irg_bad(irg));
2675 set_interprocedural_view(ipv);
2677 current_ir_graph = rem;
2682 static void descend_and_dump(FILE *F, ir_node *n, int depth, pset *mark_set) {
2683 if (pset_find_ptr(mark_set, n)) return;
2685 pset_insert_ptr(mark_set, n);
2688 int i, start = is_Block(n) ? 0 : -1;
2689 dump_whole_node(n, F);
2690 for (i = start; i < get_irn_arity(n); ++i)
2691 descend_and_dump(F, get_irn_n(n, i), depth-1, mark_set);
2694 /* Don't dump edges to nodes further out. These might be edges to
2695 nodes we already dumped, if there is a shorter path to these. */
2699 static int subgraph_counter = 0;
2700 void dump_subgraph(ir_node *root, int depth, const char *suffix) {
2704 sprintf(buf, "-subg_%03d", subgraph_counter++);
2705 F = vcg_open(get_irn_irg(root), suffix, buf);
2707 pset *mark_set = pset_new_ptr(1);
2708 dump_vcg_header(F, get_irg_dump_name(get_irn_irg(root)), NULL);
2709 descend_and_dump(F, root, depth, mark_set);
2716 static int weight_overall(int rec, int loop) {
2717 return 2*rec + loop;
2720 static int compute_color(int my, int max) {
2727 /* if small, scale to the full color range. */
2729 my = my * (n_colors/max);
2731 step = 1 + (max / n_colors);
2735 return base_color + n_colors - color;
2739 * Calculate a entity color depending on it's execution propability.
2741 static int get_entity_color(ir_entity *ent) {
2742 ir_graph *irg = get_entity_irg(ent);
2746 int rec_depth = get_irg_recursion_depth(irg);
2747 int loop_depth = get_irg_loop_depth(irg);
2748 int overall_depth = weight_overall(rec_depth, loop_depth);
2750 int max_rec_depth = irp->max_callgraph_recursion_depth;
2751 int max_loop_depth = irp->max_callgraph_loop_depth;
2752 int max_overall_depth = weight_overall(max_rec_depth, max_loop_depth);
2754 /* int my_rec_color = compute_color(rec_depth, max_rec_depth); */
2755 /* int my_loop_color = compute_color(loop_depth, max_loop_depth); */
2756 int my_overall_color = compute_color(overall_depth, max_overall_depth);
2758 return my_overall_color;
2762 void dump_callgraph(const char *suffix) {
2763 FILE *F = vcg_open_name("Callgraph", suffix);
2766 int i, rem = edge_label, colorize;
2768 dump_vcg_header(F, "Callgraph", NULL);
2770 colorize = get_irp_callgraph_state() == irp_callgraph_and_calltree_consistent;
2772 for (i = get_irp_n_irgs() - 1; i >= 0; --i) {
2773 ir_graph *irg = get_irp_irg(i);
2774 ir_entity *ent = get_irg_entity(irg);
2775 int j, n_callees = get_irg_n_callees(irg);
2778 color = colorize ? get_entity_color(ent) : ird_color_green;
2779 dump_entity_node(F, ent, color);
2780 for (j = 0; j < n_callees; ++j) {
2781 ir_entity *c = get_irg_entity(get_irg_callee(irg, j));
2782 //if (id_is_prefix(prefix, get_entity_ld_ident(c))) continue;
2783 int be = is_irg_callee_backedge(irg, j);
2786 "label:\"recursion %d\" color:%d" :
2787 "label:\"calls %d\" color:%d";
2788 print_ent_ent_edge(F, ent, c, be, attr, get_irg_callee_loop_depth(irg, j), color);
2797 /* Dump all irgs in interprocedural view to a single file. */
2798 void dump_all_cg_block_graph(const char *suffix) {
2799 FILE *f = vcg_open_name("All_graphs", suffix);
2803 int rem_view = get_interprocedural_view();
2805 set_interprocedural_view(1);
2806 dump_vcg_header(f, "All_graphs", NULL);
2808 /* collect nodes in all irgs reachable in call graph*/
2809 for (i = get_irp_n_irgs() - 1; i >= 0; --i)
2810 ird_set_irg_link(get_irp_irg(i), NULL);
2812 cg_walk(clear_link, collect_node, NULL);
2814 /* dump all graphs */
2815 for (i = get_irp_n_irgs() - 1; i >= 0; --i) {
2816 current_ir_graph = get_irp_irg(i);
2817 assert(ird_get_irg_link(current_ir_graph));
2818 dump_graph_from_list(f, current_ir_graph);
2819 DEL_ARR_F(ird_get_irg_link(current_ir_graph));
2823 set_interprocedural_view(rem_view);
2827 /*---------------------------------------------------------------------*/
2828 /* the following routines dumps type information without any ir nodes. */
2829 /*---------------------------------------------------------------------*/
2832 dump_type_graph(ir_graph *irg, const char *suffix)
2836 /* if a filter is set, dump only the irg's that match the filter */
2837 if (!is_filtered_dump_name(get_entity_ident(get_irg_entity(irg)))) return;
2839 f = vcg_open(irg, suffix, "-type");
2841 ir_graph *rem = current_ir_graph;
2842 current_ir_graph = irg;
2844 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
2846 /* walk over the blocks in the graph */
2847 type_walk_irg(irg, dump_type_info, NULL, f);
2848 /* The walker for the const code can be called several times for the
2849 same (sub) expression. So that no nodes are dumped several times
2850 we decrease the visited flag of the corresponding graph after each
2851 walk. So now increase it finally. */
2852 inc_irg_visited(get_const_code_irg());
2855 current_ir_graph = rem;
2860 dump_all_types(const char *suffix)
2862 FILE *f = vcg_open_name("All_types", suffix);
2864 dump_vcg_header(f, "All_types", NULL);
2865 type_walk(dump_type_info, NULL, f);
2866 inc_irg_visited(get_const_code_irg());
2872 dump_class_hierarchy(int entities, const char *suffix)
2874 FILE *f = vcg_open_name("class_hierarchy", suffix);
2879 env.dump_ent = entities;
2880 dump_vcg_header(f, "class_hierarchy", NULL);
2881 type_walk(dump_class_hierarchy_node, NULL, &env);
2886 /*---------------------------------------------------------------------*/
2887 /* dumps all graphs with the graph-dumper passed. Possible dumpers: */
2889 /* dump_ir_block_graph */
2891 /* dump_type_graph */
2892 /* dump_ir_graph_w_types */
2893 /*---------------------------------------------------------------------*/
2895 void dump_all_ir_graphs(dump_graph_func *dmp_grph, const char *suffix) {
2897 for (i = get_irp_n_irgs() - 1; i >= 0; --i)
2898 dmp_grph(get_irp_irg(i), suffix);
2902 /*--------------------------------------------------------------------------------*
2903 * Dumps a stand alone loop graph with firm nodes which belong to one loop node *
2904 * packed together in one subgraph/box *
2905 *--------------------------------------------------------------------------------*/
2907 void dump_loops_standalone(FILE *F, ir_loop *loop) {
2908 int i = 0, loop_node_started = 0, son_number = 0, first = 0;
2910 ir_loop *son = NULL;
2912 /* Dump a new loop node. */
2913 dump_loop_node(F, loop);
2915 /* Dump the loop elements. */
2917 for(i = 0; i < get_loop_n_elements(loop); i++) {
2918 le = get_loop_element(loop, i);
2920 if (get_kind(son) == k_ir_loop) {
2922 /* We are a loop son -> Recurse */
2924 if(loop_node_started) { /* Close the "firm-nodes" node first if we started one. */
2925 fprintf(F, "\" }\n");
2926 fprintf(F, "edge: {sourcename: \"");
2928 fprintf(F, "\" targetname: \"");
2930 fprintf(F, "-%d-nodes\" label:\"%d...%d\"}\n", first, first, i-1);
2931 loop_node_started = 0;
2933 dump_loop_son_edge(F, loop, son_number++);
2934 dump_loops_standalone(F, son);
2935 } else if (get_kind(son) == k_ir_node) {
2936 /* We are a loop node -> Collect firm nodes */
2938 ir_node *n = le.node;
2941 if (!loop_node_started) {
2942 /* Start a new node which contains all firm nodes of the current loop */
2943 fprintf(F, "node: { title: \"");
2945 fprintf(F, "-%d-nodes\" color: lightyellow label: \"", i);
2946 loop_node_started = 1;
2951 bad |= dump_node_label(F, n);
2952 /* Causes indeterministic output: if (is_Block(n)) fprintf(F, "\t ->%d", (int)get_irn_link(n)); */
2953 if (has_backedges(n)) fprintf(F, "\t loop head!");
2954 } else { /* for callgraph loop tree */
2956 assert(get_kind(son) == k_ir_graph);
2958 /* We are a loop node -> Collect firm graphs */
2959 n = (ir_graph *)le.node;
2960 if (!loop_node_started) {
2961 /* Start a new node which contains all firm nodes of the current loop */
2962 fprintf(F, "node: { title: \"");
2964 fprintf(F, "-%d-nodes\" color: lightyellow label: \"", i);
2965 loop_node_started = 1;
2969 fprintf(F, " %s", get_irg_dump_name(n));
2970 /* fprintf(F, " %s (depth %d)", get_irg_dump_name(n), n->callgraph_weighted_loop_depth); */
2974 if (loop_node_started) {
2975 fprintf(F, "\" }\n");
2976 fprintf(F, "edge: {sourcename: \"");
2978 fprintf(F, "\" targetname: \"");
2980 fprintf(F, "-%d-nodes\" label:\"%d...%d\"}\n", first, first, i-1);
2981 loop_node_started = 0;
2985 void dump_loop_tree(ir_graph *irg, const char *suffix)
2989 /* if a filter is set, dump only the irg's that match the filter */
2990 if (!is_filtered_dump_name(get_entity_ident(get_irg_entity(irg)))) return;
2992 f = vcg_open(irg, suffix, "-looptree");
2994 ir_graph *rem = current_ir_graph;
2995 int el_rem = edge_label;
2997 current_ir_graph = irg;
3000 dump_vcg_header(f, get_irg_dump_name(irg), "top_to_bottom");
3002 if (get_irg_loop(irg)) dump_loops_standalone(f, get_irg_loop(irg));
3006 edge_label = el_rem;
3007 current_ir_graph = rem;
3011 void dump_callgraph_loop_tree(const char *suffix) {
3013 F = vcg_open_name("Callgraph_looptree", suffix);
3014 dump_vcg_header(F, "callgraph looptree", "top_to_bottom");
3015 dump_loops_standalone(F, irp->outermost_cg_loop);
3020 /*----------------------------------------------------------------------------*/
3021 /* Dumps the firm nodes in the loop tree to a graph along with the loop nodes.*/
3022 /*----------------------------------------------------------------------------*/
3024 void collect_nodeloop(FILE *F, ir_loop *loop, eset *loopnodes) {
3025 int i, son_number = 0, node_number = 0;
3027 if (dump_loop_information_flag) dump_loop_node(F, loop);
3029 for (i = 0; i < get_loop_n_elements(loop); i++) {
3030 loop_element le = get_loop_element(loop, i);
3031 if (*(le.kind) == k_ir_loop) {
3032 if (dump_loop_information_flag) dump_loop_son_edge(F, loop, son_number++);
3034 collect_nodeloop(F, le.son, loopnodes);
3036 if (dump_loop_information_flag) dump_loop_node_edge(F, loop, node_number++);
3037 eset_insert(loopnodes, le.node);
3042 void collect_nodeloop_external_nodes(ir_loop *loop, eset *loopnodes, eset *extnodes) {
3045 for(i = 0; i < get_loop_n_elements(loop); i++) {
3046 loop_element le = get_loop_element(loop, i);
3047 if (*(le.kind) == k_ir_loop) {
3049 collect_nodeloop_external_nodes(le.son, loopnodes, extnodes);
3051 if (is_Block(le.node)) start = 0; else start = -1;
3052 for (j = start; j < get_irn_arity(le.node); j++) {
3053 ir_node *pred = get_irn_n(le.node, j);
3054 if (!eset_contains(loopnodes, pred)) {
3055 eset_insert(extnodes, pred);
3056 if (!is_Block(pred)) {
3057 pred = get_nodes_block(pred);
3058 if (!eset_contains(loopnodes, pred)) eset_insert(extnodes, pred);
3066 void dump_loop(ir_loop *l, const char *suffix) {
3070 snprintf(name, sizeof(name), "loop_%d", get_loop_loop_nr(l));
3071 F = vcg_open_name(name, suffix);
3073 eset *loopnodes = eset_create();
3074 eset *extnodes = eset_create();
3077 dump_vcg_header(F, name, NULL);
3079 /* collect all nodes to dump */
3080 collect_nodeloop(F, l, loopnodes);
3081 collect_nodeloop_external_nodes(l, loopnodes, extnodes);
3083 /* build block lists */
3084 for (n = eset_first(loopnodes); n != NULL; n = eset_next(loopnodes))
3085 set_irn_link(n, NULL);
3086 for (n = eset_first(extnodes); n != NULL; n = eset_next(extnodes))
3087 set_irn_link(n, NULL);
3088 for (n = eset_first(loopnodes); n != NULL; n = eset_next(loopnodes)) {
3090 b = get_nodes_block(n);
3091 set_irn_link(n, get_irn_link(b));
3095 for (n = eset_first(extnodes); n != NULL; n = eset_next(extnodes)) {
3097 b = get_nodes_block(n);
3098 set_irn_link(n, get_irn_link(b));
3103 for (b = eset_first(loopnodes); b != NULL; b = eset_next(loopnodes)) {
3105 fprintf(F, "graph: { title: \"");
3107 fprintf(F, "\" label: \"");
3108 dump_node_opcode(F, b);
3109 fprintf(F, " %ld:%d", get_irn_node_nr(b), get_irn_idx(b));
3110 fprintf(F, "\" status:clustered color:yellow\n");
3112 /* dump the blocks edges */
3113 dump_ir_data_edges(F, b);
3115 /* dump the nodes that go into the block */
3116 for (n = get_irn_link(b); n; n = get_irn_link(n)) {
3117 if (eset_contains(extnodes, n))
3118 overrule_nodecolor = ird_color_lightblue;
3120 overrule_nodecolor = ird_color_default;
3121 if (!eset_contains(extnodes, n)) dump_ir_data_edges(F, n);
3124 /* Close the vcg information for the block */
3126 dump_const_node_local(F, b);
3130 for (b = eset_first(extnodes); b != NULL; b = eset_next(extnodes)) {
3132 fprintf(F, "graph: { title: \"");
3134 fprintf(F, "\" label: \"");
3135 dump_node_opcode(F, b);
3136 fprintf(F, " %ld:%d", get_irn_node_nr(b), get_irn_idx(b));
3137 fprintf(F, "\" status:clustered color:lightblue\n");
3139 /* dump the nodes that go into the block */
3140 for (n = get_irn_link(b); n; n = get_irn_link(n)) {
3141 if (!eset_contains(loopnodes, n))
3142 overrule_nodecolor = ird_color_lightblue;
3144 overrule_nodecolor = ird_color_default;
3145 if (eset_contains(loopnodes, n)) dump_ir_data_edges(F, n);
3148 /* Close the vcg information for the block */
3150 dump_const_node_local(F, b);
3154 eset_destroy(loopnodes);
3155 eset_destroy(extnodes);