2 * Copyright (C) 1995-2008 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
35 #include "irgraph_t.h"
49 #include "callgraph.h"
50 #include "irextbb_t.h"
52 #include "dbginfo_t.h"
65 /** Dump only irgs with names that start with this prefix. */
66 static ident *dump_file_filter_id = NULL;
68 #define ERROR_TXT "<ERROR>"
70 /*******************************************************************/
71 /* flags to steer output */
72 /*******************************************************************/
74 /** An option to turn off edge labels */
75 static int edge_label = 1;
76 /** An option to turn off dumping values of constant entities */
77 static int const_entities = 1;
78 /** An option to dump the keep alive edges */
79 static int dump_keepalive = 1;
80 /** An option to dump the new out edges */
81 static int dump_new_edges_flag = 0;
82 /** An option to dump ld_names instead of names. */
83 static int dump_ld_name = 1;
84 /** Compiler options to dump analysis information in dump_ir_graph */
85 static int dump_out_edge_flag = 0;
86 static int dump_loop_information_flag = 0;
87 static int dump_backedge_information_flag = 1;
88 /** An option to dump const-like nodes locally. */
89 static int dump_const_local = 1;
90 /** An option to dump the node index number. */
91 static int dump_node_idx_labels = 1;
92 /** An option to dump the node number */
93 static int dump_node_nr = 1;
94 /** An option to dump all graph anchors */
95 static int dump_anchors = 0;
96 /** An option to dump the macro block edges. */
97 static int dump_macro_block_edges = 0;
98 /** An option to dump block marker in the block title */
99 static int dump_block_marker = 0;
101 int dump_dominator_information_flag = 0;
102 int opt_dump_analysed_type_info = 1;
103 int opt_dump_pointer_values_to_info = 0; /* default off: for test compares!! */
105 static ird_color_t overrule_nodecolor = ird_color_default_node;
107 /** The vcg node attribute hook. */
108 static DUMP_IR_GRAPH_FUNC dump_ir_graph_hook = NULL;
109 /** The vcg node attribute hook. */
110 static DUMP_NODE_VCGATTR_FUNC dump_node_vcgattr_hook = NULL;
111 /** The vcg edge attribute hook. */
112 static DUMP_EDGE_VCGATTR_FUNC dump_edge_vcgattr_hook = NULL;
113 /** The vcg dump block edge hook */
114 static DUMP_NODE_EDGE_FUNC dump_block_edge_hook = NULL;
115 /** The vcg dump node edge hook. */
116 static DUMP_NODE_EDGE_FUNC dump_node_edge_hook = NULL;
118 /* Set the hook to be called to dump additional edges to a node. */
119 void set_dump_node_edge_hook(DUMP_NODE_EDGE_FUNC func)
121 dump_node_edge_hook = func;
124 /* Get the additional edge dump hook. */
125 DUMP_NODE_EDGE_FUNC get_dump_node_edge_hook(void)
127 return dump_node_edge_hook;
130 /* Set the hook to be called to dump additional edges to a block. */
131 void set_dump_block_edge_hook(DUMP_NODE_EDGE_FUNC func)
133 dump_block_edge_hook = func;
136 /* Get the additional block edge dump hook. */
137 DUMP_NODE_EDGE_FUNC get_dump_block_edge_hook(void)
139 return dump_node_edge_hook;
142 /* set the ir graph hook */
143 void set_dump_ir_graph_hook(DUMP_IR_GRAPH_FUNC hook)
145 dump_ir_graph_hook = hook;
148 /* set the node attribute hook */
149 void set_dump_node_vcgattr_hook(DUMP_NODE_VCGATTR_FUNC hook)
151 dump_node_vcgattr_hook = hook;
154 /* set the edge attribute hook */
155 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 static int get_opt_dump_const_local(void)
165 if (dump_out_edge_flag || dump_loop_information_flag || (dump_new_edges_flag && edges_activated(current_ir_graph)))
167 return dump_const_local;
170 /* Set a prefix filter for output functions. */
171 void only_dump_method_with_name(ident *name)
173 dump_file_filter_id = name;
176 /* Returns the prefix filter set with only_dump_method_with_name(). */
177 ident *get_dump_file_filter_ident(void)
179 return dump_file_filter_id;
182 /* Returns non-zero if dump file filter is not set, or if it is a prefix of name. */
183 int is_filtered_dump_name(ident *name)
185 if (!dump_file_filter_id) return 1;
186 return id_is_prefix(dump_file_filter_id, name);
189 /* To turn off display of edge labels. Edge labels often cause xvcg to
190 abort with a segmentation fault. */
191 void turn_off_edge_labels(void)
196 void dump_consts_local(int flag)
198 dump_const_local = flag;
201 void dump_node_idx_label(int flag)
203 dump_node_idx_labels = flag;
206 void dump_constant_entity_values(int flag)
208 const_entities = flag;
211 void dump_keepalive_edges(int flag)
213 dump_keepalive = flag;
216 void dump_new_edges(int flag)
218 dump_new_edges_flag = flag;
221 int get_opt_dump_keepalive_edges(void)
223 return dump_keepalive;
226 void dump_out_edges(int flag)
228 dump_out_edge_flag = flag;
231 void dump_dominator_information(int flag)
233 dump_dominator_information_flag = flag;
236 void dump_loop_information(int flag)
238 dump_loop_information_flag = flag;
241 void dump_backedge_information(int flag)
243 dump_backedge_information_flag = flag;
246 /* Dump the information of type field specified in ana/irtypeinfo.h.
247 * If the flag is set, the type name is output in [] in the node label,
248 * else it is output as info.
250 void set_opt_dump_analysed_type_info(int flag)
252 opt_dump_analysed_type_info = flag;
255 void dump_pointer_values_to_info(int flag)
257 opt_dump_pointer_values_to_info = flag;
260 void dump_ld_names(int flag)
265 void dump_all_anchors(int flag)
270 void dump_macroblock_edges(int flag)
272 dump_macro_block_edges = flag;
275 void dump_block_marker_in_title(int flag)
277 dump_block_marker = flag;
280 /* -------------- some extended helper functions ----------------- */
283 * returns the name of a mode or ERROR_TXT if mode is NOT a mode object.
284 * in the later case, sets bad.
286 const char *get_mode_name_ex(const ir_mode *mode, int *bad)
289 return get_mode_name(mode);
294 #define CUSTOM_COLOR_BASE 100
295 static const char *color_names[ird_color_count];
296 static const char *color_rgb[ird_color_count];
297 static struct obstack color_obst;
299 /** define a custom color. */
300 static void custom_color(int num, const char *rgb_def)
302 assert(num < ird_color_count);
303 obstack_printf(&color_obst, "%d", CUSTOM_COLOR_BASE + num);
304 obstack_1grow(&color_obst, '\0');
306 color_rgb[num] = rgb_def;
307 color_names[num] = obstack_finish(&color_obst);
310 /** Define a named color. */
311 static void named_color(int num, const char *name)
313 assert(num < ird_color_count);
314 color_rgb[num] = NULL;
315 color_names[num] = name;
318 /** Initializes the used colors. */
319 static void init_colors(void)
321 static int initialized = 0;
325 obstack_init(&color_obst);
327 custom_color(ird_color_prog_background, "204 204 204");
328 custom_color(ird_color_block_background, "255 255 0");
329 custom_color(ird_color_dead_block_background, "190 150 150");
330 named_color(ird_color_block_inout, "lightblue");
331 named_color(ird_color_default_node, "white");
332 custom_color(ird_color_memory, "153 153 255");
333 custom_color(ird_color_controlflow, "255 153 153");
334 custom_color(ird_color_const, "204 255 255");
335 custom_color(ird_color_proj, "255 255 153");
336 custom_color(ird_color_uses_memory, "153 153 255");
337 custom_color(ird_color_phi, "105 255 105");
338 custom_color(ird_color_anchor, "100 100 255");
339 named_color(ird_color_error, "red");
340 custom_color(ird_color_entity, "204 204 255");
346 * Prints the VCG color to a file.
348 static void print_vcg_color(FILE *F, ird_color_t color)
350 assert(color < ird_color_count);
351 fprintf(F, "color:%s", color_names[color]);
355 * Prints the edge kind of a given IR node.
357 * Projs should be dumped near their predecessor, so they get "nearedge".
359 static void print_node_edge_kind(FILE *F, ir_node *node)
362 fprintf(F, "nearedge: ");
364 fprintf(F, "edge: ");
369 * Prints the edge from a type S to a type T with additional info fmt, ...
372 static void print_type_type_edge(FILE *F, const ir_type *S, const ir_type *T, const char *fmt, ...)
377 fprintf(F, "edge: { sourcename: "); PRINT_TYPEID(S);
378 fprintf(F, " targetname: "); PRINT_TYPEID(T);
379 vfprintf(F, fmt, ap);
385 * Prints the edge from a type tp to an entity ent with additional info fmt, ...
388 static void print_type_ent_edge(FILE *F, const ir_type *tp, const ir_entity *ent, const char *fmt, ...)
393 fprintf(F, "edge: { sourcename: "); PRINT_TYPEID(tp);
394 fprintf(F, " targetname: \""); PRINT_ENTID(ent); fprintf(F, "\"");
395 vfprintf(F, fmt, ap);
401 * Prints the edge from an entity ent1 to an entity ent2 with additional info fmt, ...
404 static void print_ent_ent_edge(FILE *F, const ir_entity *ent1, const ir_entity *ent2, int backedge, ird_color_t color, const char *fmt, ...)
410 fprintf(F, "backedge: { sourcename: \"");
412 fprintf(F, "edge: { sourcename: \"");
414 fprintf(F, "\" targetname: \""); PRINT_ENTID(ent2); fprintf(F, "\"");
415 vfprintf(F, fmt, ap);
417 if (color != (ird_color_t) -1)
418 print_vcg_color(F, color);
424 * Prints the edge from an entity ent to a type tp with additional info fmt, ...
427 static void print_ent_type_edge(FILE *F, const ir_entity *ent, const ir_type *tp, const char *fmt, ...)
432 fprintf(F, "edge: { sourcename: \""); PRINT_ENTID(ent);
433 fprintf(F, "\" targetname: "); PRINT_TYPEID(tp);
434 vfprintf(F, fmt, ap);
440 * Prints the edge from a node irn to a type tp with additional info fmt, ...
443 static void print_node_type_edge(FILE *F, const ir_node *irn, ir_type *tp, const char *fmt, ...)
448 fprintf(F, "edge: { sourcename: \""); PRINT_NODEID(irn);
449 fprintf(F, "\" targetname: "); PRINT_TYPEID(tp);
450 vfprintf(F, fmt, ap);
456 * Prints the edge from a node irn to an entity ent with additional info fmt, ...
459 static void print_node_ent_edge(FILE *F, const ir_node *irn, const ir_entity *ent, const char *fmt, ...)
464 fprintf(F, "edge: { sourcename: \""); PRINT_NODEID(irn);
465 fprintf(F, "\" targetname: \""); PRINT_ENTID(ent);
467 vfprintf(F, fmt, ap);
473 * Prints the edge from an entity ent to a node irn with additional info fmt, ...
476 static void print_ent_node_edge(FILE *F, const ir_entity *ent, const ir_node *irn, const char *fmt, ...)
481 fprintf(F, "edge: { sourcename: \""); PRINT_ENTID(ent);
482 fprintf(F, "\" targetname: \""); PRINT_NODEID(irn); fprintf(F, "\"");
483 vfprintf(F, fmt, ap);
489 * Prints the edge from a type tp to an enumeration item item with additional info fmt, ...
492 static void print_enum_item_edge(FILE *F, const ir_type *tp, int item, const char *fmt, ...)
497 fprintf(F, "edge: { sourcename: "); PRINT_TYPEID(tp);
498 fprintf(F, " targetname: \""); PRINT_ITEMID(tp, item); fprintf(F, "\" ");
499 vfprintf(F, fmt, ap);
504 /*-----------------------------------------------------------------*/
505 /* global and ahead declarations */
506 /*-----------------------------------------------------------------*/
508 static void dump_whole_node(ir_node *n, void *env);
509 static inline void dump_loop_nodes_into_graph(FILE *F, ir_graph *irg);
511 /*-----------------------------------------------------------------*/
512 /* Helper functions. */
513 /*-----------------------------------------------------------------*/
516 * This map is used as a private link attr to be able to call dumper
517 * anywhere without destroying link fields.
519 static pmap *irdump_link_map = NULL;
521 /** NOT A STANDARD LIBFIRM INIT METHOD
523 * We do not want to integrate dumping into libfirm, i.e., if the dumpers
524 * are off, we want to have as few interferences as possible. Therefore the
525 * initialization is performed lazily and not called from within init_firm.
527 * Creates the link attribute map. */
528 static void init_irdump(void)
530 /* We need a new, empty map. */
531 if (irdump_link_map) pmap_destroy(irdump_link_map);
532 irdump_link_map = pmap_create();
533 if (!dump_file_filter_id)
534 dump_file_filter_id = new_id_from_str("");
538 * Returns the private link field.
540 static void *ird_get_irn_link(const ir_node *n)
543 if (irdump_link_map == NULL)
546 if (pmap_contains(irdump_link_map, n))
547 res = pmap_get(irdump_link_map, n);
552 * Sets the private link field.
554 static void ird_set_irn_link(const ir_node *n, void *x)
556 if (irdump_link_map == NULL)
558 pmap_insert(irdump_link_map, n, x);
562 * Gets the private link field of an irg.
564 static void *ird_get_irg_link(const ir_graph *irg)
567 if (irdump_link_map == NULL)
570 if (pmap_contains(irdump_link_map, irg))
571 res = pmap_get(irdump_link_map, irg);
576 * Sets the private link field of an irg.
578 static void ird_set_irg_link(const ir_graph *irg, void *x)
580 if (irdump_link_map == NULL)
582 pmap_insert(irdump_link_map, irg, x);
586 * Walker, clears the private link field.
588 static void clear_link(ir_node *node, void *env)
591 ird_set_irn_link(node, NULL);
595 * If the entity has a ld_name, returns it if the dump_ld_name is set,
596 * else returns the name of the entity.
598 static const char *_get_ent_dump_name(const ir_entity *ent, int dump_ld_name)
601 return "<NULL entity>";
603 /* Don't use get_entity_ld_ident (ent) as it computes the mangled name! */
604 if (ent->ld_name != NULL)
605 return get_id_str(ent->ld_name);
607 return get_id_str(ent->name);
611 * If the entity has a ld_name, returns it if the option dump_ld_name is set,
612 * else returns the name of the entity.
614 const char *get_ent_dump_name(const ir_entity *ent)
616 return _get_ent_dump_name(ent, dump_ld_name);
619 /* Returns the name of an IRG. */
620 const char *get_irg_dump_name(const ir_graph *irg)
622 /* Don't use get_entity_ld_ident (ent) as it computes the mangled name! */
623 return _get_ent_dump_name(get_irg_entity(irg), 1);
627 * Returns non-zero if a node is in floating state.
629 static int node_floats(const ir_node *n)
631 return ((get_irn_pinned(n) == op_pin_state_floats) &&
632 (get_irg_pinned(current_ir_graph) == op_pin_state_floats));
636 * Walker that visits the anchors
638 static void ird_walk_graph(ir_graph *irg, irg_walk_func *pre, irg_walk_func *post, void *env)
640 if (dump_anchors || (dump_new_edges_flag && edges_activated(irg))) {
641 irg_walk_anchors(irg, pre, post, env);
643 irg_walk_graph(irg, pre, post, env);
648 * Walker, allocates an array for all blocks and puts it's nodes non-floating nodes into this array.
650 static void collect_node(ir_node *node, void *env)
655 || (get_op_flags(get_irn_op(node)) & irop_flag_dump_noblock)) {
656 ir_node ** arr = (ir_node **) ird_get_irg_link(get_irn_irg(node));
657 if (!arr) arr = NEW_ARR_F(ir_node *, 0);
658 ARR_APP1(ir_node *, arr, node);
659 ird_set_irg_link(get_irn_irg(node), arr); /* arr is an l-value, APP_ARR might change it! */
661 ir_node * block = get_nodes_block(node);
664 /* this node is in a Bad block, so we must place it into the graph's list */
665 ir_node ** arr = (ir_node **) ird_get_irg_link(get_irn_irg(node));
666 if (!arr) arr = NEW_ARR_F(ir_node *, 0);
667 ARR_APP1(ir_node *, arr, node);
668 ird_set_irg_link(get_irn_irg(node), arr); /* arr is an l-value, APP_ARR might change it! */
670 ird_set_irn_link(node, ird_get_irn_link(block));
671 ird_set_irn_link(block, node);
676 /** Construct lists to walk ir block-wise.
678 * Collects all blocks, nodes not op_pin_state_pinned,
679 * Bad, NoMem and Unknown into a flexible array in link field of
680 * irg they belong to. Sets the irg link field to NULL in all
681 * graphs not visited.
682 * Free the list with DEL_ARR_F().
684 static ir_node **construct_block_lists(ir_graph *irg)
687 #ifdef INTERPROCEDURAL_VIEW
688 int rem_view = get_interprocedural_view();
690 int walk_flag = ir_resources_reserved(irg) & IR_RESOURCE_IRN_VISITED;
691 ir_graph *rem = current_ir_graph;
693 current_ir_graph = irg;
696 ir_free_resources(irg, IR_RESOURCE_IRN_VISITED);
699 for (i = get_irp_n_irgs() - 1; i >= 0; --i)
700 ird_set_irg_link(get_irp_irg(i), NULL);
702 ird_walk_graph(current_ir_graph, clear_link, collect_node, current_ir_graph);
704 #ifdef INTERPROCEDURAL_VIEW
705 /* Collect also EndReg and EndExcept. We do not want to change the walker. */
706 set_interprocedural_view(0);
709 set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph)-1);
710 irg_walk(get_irg_end_reg(current_ir_graph), clear_link, collect_node, current_ir_graph);
711 set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph)-1);
712 irg_walk(get_irg_end_except(current_ir_graph), clear_link, collect_node, current_ir_graph);
714 #ifdef INTERPROCEDURAL_VIEW
715 set_interprocedural_view(rem_view);
719 ir_reserve_resources(irg, IR_RESOURCE_IRN_VISITED);
722 current_ir_graph = rem;
723 return ird_get_irg_link(irg);
726 typedef struct _list_tuple {
728 ir_extblk **extbb_list;
731 /** Construct lists to walk IR extended block-wise.
732 * Free the lists in the tuple with DEL_ARR_F().
733 * Sets the irg link field to NULL in all
734 * graphs not visited.
736 static list_tuple *construct_extblock_lists(ir_graph *irg)
738 ir_node **blk_list = construct_block_lists(irg);
740 ir_graph *rem = current_ir_graph;
741 list_tuple *lists = XMALLOC(list_tuple);
743 current_ir_graph = irg;
745 lists->blk_list = NEW_ARR_F(ir_node *, 0);
746 lists->extbb_list = NEW_ARR_F(ir_extblk *, 0);
748 inc_irg_block_visited(irg);
749 for (i = ARR_LEN(blk_list) - 1; i >= 0; --i) {
752 if (is_Block(blk_list[i])) {
753 ext = get_Block_extbb(blk_list[i]);
755 if (extbb_not_visited(ext)) {
756 ARR_APP1(ir_extblk *, lists->extbb_list, ext);
757 mark_extbb_visited(ext);
760 ARR_APP1(ir_node *, lists->blk_list, blk_list[i]);
764 current_ir_graph = rem;
765 ird_set_irg_link(irg, lists);
769 /*-----------------------------------------------------------------*/
770 /* Routines to dump information about a single ir node. */
771 /*-----------------------------------------------------------------*/
774 * dump the name of a node n to the File F.
776 int dump_node_opcode(FILE *F, ir_node *n)
779 const ir_op_ops *ops = get_op_ops(get_irn_op(n));
781 /* call the dump_node operation if available */
783 return ops->dump_node(n, F, dump_node_opcode_txt);
785 /* implementation for default nodes */
786 switch (get_irn_opcode(n)) {
788 switch (get_SymConst_kind(n)) {
789 case symconst_addr_ent:
790 fprintf(F, "SymC &%s", get_entity_name(get_SymConst_entity(n)));
792 case symconst_ofs_ent:
793 fprintf(F, "SymC %s offset", get_entity_name(get_SymConst_entity(n)));
795 case symconst_type_tag:
796 ir_fprintf(F, "SymC %+F tag", get_SymConst_type(n));
798 case symconst_type_size:
799 ir_fprintf(F, "SymC %+F size", get_SymConst_type(n));
801 case symconst_type_align:
802 ir_fprintf(F, "SymC %+F align", get_SymConst_type(n));
804 case symconst_enum_const:
805 fprintf(F, "SymC %s enum", get_enumeration_const_name(get_SymConst_enum(n)));
810 #ifdef INTERPROCEDURAL_VIEW
812 if (!get_interprocedural_view())
820 ir_node *pred = get_Proj_pred(n);
822 if (get_irn_opcode(pred) == iro_Cond
823 && get_Proj_proj(n) == get_Cond_default_proj(pred)
824 && get_irn_mode(get_Cond_selector(pred)) != mode_b)
825 fprintf(F, "defProj");
830 #ifdef INTERPROCEDURAL_VIEW
835 if (get_interprocedural_view()) {
836 fprintf(F, "%s %s", get_irn_opname(n), get_ent_dump_name(get_irg_entity(get_irn_irg(n))));
842 case iro_CallBegin: {
843 ir_node *addr = get_CallBegin_ptr(n);
844 ir_entity *ent = NULL;
846 ent = get_Sel_entity(addr);
847 else if (is_Global(addr))
848 ent = get_Global_entity(addr);
849 fprintf(F, "%s", get_irn_opname(n));
850 if (ent) fprintf(F, " %s", get_entity_name(ent));
854 if (get_Load_align(n) == align_non_aligned)
856 fprintf(F, "%s[%s]", get_irn_opname(n), get_mode_name_ex(get_Load_mode(n), &bad));
859 if (get_Store_align(n) == align_non_aligned)
861 fprintf(F, "%s", get_irn_opname(n));
864 if (is_Block_dead(n))
866 if (n == get_irg_start_block(get_irn_irg(n)))
868 if (n == get_irg_end_block(get_irn_irg(n)))
870 fprintf(F, "%s%s", get_irn_opname(n),
871 dump_block_marker ? (get_Block_mark(n) ? "*" : "") : "");
874 if (get_Conv_strict(n))
875 fprintf(F, "strict");
876 fprintf(F, "%s", get_irn_opname(n));
879 fprintf(F, "%s", get_irn_opname(n));
880 if (get_Div_no_remainder(n))
882 fprintf(F, "[%s]", get_mode_name_ex(get_Div_resmode(n), &bad));
885 fprintf(F, "%s[%s]", get_irn_opname(n), get_mode_name_ex(get_Mod_resmode(n), &bad));
888 fprintf(F, "%s[%s]", get_irn_opname(n), get_mode_name_ex(get_DivMod_resmode(n), &bad));
891 fprintf(F, "%s[%s]", get_irn_opname(n), get_builtin_kind_name(get_Builtin_kind(n)));
896 fprintf(F, "%s", get_irn_opname(n));
903 * Dump the mode of a node n to a file F.
904 * Ignore modes that are "always known".
906 static int dump_node_mode(FILE *F, ir_node *n)
909 const ir_op_ops *ops = get_op_ops(get_irn_op(n));
913 /* call the dump_node operation if available */
915 return ops->dump_node(n, F, dump_node_mode_txt);
917 /* default implementation */
918 iro = get_irn_opcode(n);
930 mode = get_irn_mode(n);
932 if (mode != NULL && mode != mode_BB && mode != mode_ANY && mode != mode_BAD &&
933 (mode != mode_T || iro == iro_Proj))
934 fprintf(F, "%s", get_mode_name_ex(mode, &bad));
940 * Dump the type of a node n to a file F if it's known.
942 static int dump_node_typeinfo(FILE *F, ir_node *n)
946 if (opt_dump_analysed_type_info) {
947 if (get_irg_typeinfo_state(current_ir_graph) == ir_typeinfo_consistent ||
948 get_irg_typeinfo_state(current_ir_graph) == ir_typeinfo_inconsistent) {
949 ir_type *tp = get_irn_typeinfo_type(n);
950 if (tp != firm_none_type) {
951 ir_fprintf(F, "[%+F]", tp);
960 typedef struct _pns_lookup {
961 long nr; /**< the proj number */
962 const char *name; /**< the name of the Proj */
965 typedef struct _proj_lookup {
966 ir_opcode code; /**< the opcode of the Proj predecessor */
967 unsigned num_data; /**< number of data entries */
968 const pns_lookup_t *data; /**< the data */
971 /** the lookup table for Proj(Start) names */
972 static const pns_lookup_t start_lut[] = {
973 #define X(a) { pn_Start_##a, #a }
981 /** the lookup table for Proj(Cond) names */
982 static const pns_lookup_t cond_lut[] = {
983 #define X(a) { pn_Cond_##a, #a }
989 /** the lookup table for Proj(Call) names */
990 static const pns_lookup_t call_lut[] = {
991 #define X(a) { pn_Call_##a, #a }
1000 /** the lookup table for Proj(Quot) names */
1001 static const pns_lookup_t quot_lut[] = {
1002 #define X(a) { pn_Quot_##a, #a }
1010 /** the lookup table for Proj(DivMod) names */
1011 static const pns_lookup_t divmod_lut[] = {
1012 #define X(a) { pn_DivMod_##a, #a }
1021 /** the lookup table for Proj(Div) names */
1022 static const pns_lookup_t div_lut[] = {
1023 #define X(a) { pn_Div_##a, #a }
1031 /** the lookup table for Proj(Mod) names */
1032 static const pns_lookup_t mod_lut[] = {
1033 #define X(a) { pn_Mod_##a, #a }
1041 /** the lookup table for Proj(Load) names */
1042 static const pns_lookup_t load_lut[] = {
1043 #define X(a) { pn_Load_##a, #a }
1051 /** the lookup table for Proj(Store) names */
1052 static const pns_lookup_t store_lut[] = {
1053 #define X(a) { pn_Store_##a, #a }
1060 /** the lookup table for Proj(Alloc) names */
1061 static const pns_lookup_t alloc_lut[] = {
1062 #define X(a) { pn_Alloc_##a, #a }
1070 /** the lookup table for Proj(CopyB) names */
1071 static const pns_lookup_t copyb_lut[] = {
1072 #define X(a) { pn_CopyB_##a, #a }
1079 /** the lookup table for Proj(InstOf) names */
1080 static const pns_lookup_t instof_lut[] = {
1081 #define X(a) { pn_InstOf_##a, #a }
1089 /** the lookup table for Proj(Raise) names */
1090 static const pns_lookup_t raise_lut[] = {
1091 #define X(a) { pn_Raise_##a, #a }
1097 /** the lookup table for Proj(Bound) names */
1098 static const pns_lookup_t bound_lut[] = {
1099 #define X(a) { pn_Bound_##a, #a }
1107 /** the Proj lookup table */
1108 static const proj_lookup_t proj_lut[] = {
1109 #define E(a) ARRAY_SIZE(a), a
1110 { iro_Start, E(start_lut) },
1111 { iro_Cond, E(cond_lut) },
1112 { iro_Call, E(call_lut) },
1113 { iro_Quot, E(quot_lut) },
1114 { iro_DivMod, E(divmod_lut) },
1115 { iro_Div, E(div_lut) },
1116 { iro_Mod, E(mod_lut) },
1117 { iro_Load, E(load_lut) },
1118 { iro_Store, E(store_lut) },
1119 { iro_Alloc, E(alloc_lut) },
1120 { iro_CopyB, E(copyb_lut) },
1121 { iro_InstOf, E(instof_lut) },
1122 { iro_Raise, E(raise_lut) },
1123 { iro_Bound, E(bound_lut) }
1128 * Dump additional node attributes of some nodes to a file F.
1130 static int dump_node_nodeattr(FILE *F, ir_node *n)
1136 const ir_op_ops *ops = get_op_ops(get_irn_op(n));
1138 /* call the dump_node operation if available */
1140 return ops->dump_node(n, F, dump_node_nodeattr_txt);
1142 switch (get_irn_opcode(n)) {
1144 ir_fprintf(F, "%T ", get_Const_tarval(n));
1148 pred = get_Proj_pred(n);
1149 proj_nr = get_Proj_proj(n);
1150 #ifdef INTERPROCEDURAL_VIEW
1153 code = get_irn_opcode(pred);
1155 if (code == iro_Cmp)
1156 fprintf(F, "%s ", get_pnc_string(get_Proj_proj(n)));
1157 else if (code == iro_Proj && get_irn_opcode(get_Proj_pred(pred)) == iro_Start)
1158 fprintf(F, "Arg %ld ", proj_nr);
1159 else if (code == iro_Cond && get_irn_mode(get_Cond_selector(pred)) != mode_b)
1160 fprintf(F, "%ld ", proj_nr);
1162 unsigned i, j, f = 0;
1164 for (i = 0; i < ARRAY_SIZE(proj_lut); ++i) {
1165 if (code == proj_lut[i].code) {
1166 for (j = 0; j < proj_lut[i].num_data; ++j) {
1167 if (proj_nr == proj_lut[i].data[j].nr) {
1168 fprintf(F, "%s ", proj_lut[i].data[j].name);
1177 fprintf(F, "%ld ", proj_nr);
1178 if (code == iro_Cond && get_Cond_jmp_pred(pred) != COND_JMP_PRED_NONE) {
1179 if (proj_nr == pn_Cond_false && get_Cond_jmp_pred(pred) == COND_JMP_PRED_FALSE)
1180 fprintf(F, "PRED ");
1181 if (proj_nr == pn_Cond_true && get_Cond_jmp_pred(pred) == COND_JMP_PRED_TRUE)
1182 fprintf(F, "PRED ");
1187 proj_nr = get_Filter_proj(n);
1188 #ifdef INTERPROCEDURAL_VIEW
1189 if (! get_interprocedural_view()) {
1191 pred = get_Filter_pred(n);
1195 fprintf(F, "%ld ", proj_nr);
1198 fprintf(F, "%s ", get_ent_dump_name(get_Sel_entity(n)));
1201 ir_fprintf(F, "(%+F)", get_Cast_type(n));
1204 fprintf(F, "%s ", get_pnc_string(get_Confirm_cmp(n)));
1207 ir_fprintf(F, "(%+F)", get_CopyB_type(n));
1218 #include "execution_frequency.h"
1220 static void dump_node_ana_vals(FILE *F, ir_node *n)
1225 #ifdef INTERPROCEDURAL_VIEW
1226 fprintf(F, " %lf*(%2.0lf + %2.0lf) = %2.0lf ",
1227 get_irn_exec_freq(n),
1228 get_irg_method_execution_frequency(get_irn_irg(n)),
1229 pow(5, get_irg_recursion_depth(get_irn_irg(n))),
1230 get_irn_exec_freq(n) * (get_irg_method_execution_frequency(get_irn_irg(n)) + pow(5, get_irg_recursion_depth(get_irn_irg(n))))
1236 /* Dumps a node label without the enclosing ". */
1237 int dump_node_label(FILE *F, ir_node *n)
1241 bad |= dump_node_opcode(F, n);
1243 bad |= dump_node_mode(F, n);
1245 bad |= dump_node_typeinfo(F, n);
1246 bad |= dump_node_nodeattr(F, n);
1248 fprintf(F, "%ld", get_irn_node_nr(n));
1250 if (dump_node_idx_labels) {
1251 fprintf(F, ":%u", get_irn_idx(n));
1257 /* Dumps the vrp information of a node to a file */
1258 int dump_vrp_info(FILE *F, ir_node *n)
1260 vrp_attr *vrp = vrp_get_info(n);
1265 fprintf(F, "range_type: %d\n", (int) vrp->range_type);
1266 if (vrp->range_type == VRP_RANGE || vrp->range_type ==
1268 ir_fprintf(F, "range_bottom: %F\n",vrp->range_bottom);
1269 ir_fprintf(F, "range_top: %F\n", vrp->range_top);
1271 ir_fprintf(F, "bits_set: %T\n", vrp->bits_set);
1272 ir_fprintf(F, "bits_not_set: %T\n", vrp->bits_not_set);
1278 * Dumps the attributes of a node n into the file F.
1279 * Currently this is only the color of a node.
1281 static void dump_node_vcgattr(FILE *F, ir_node *node, ir_node *local, int bad)
1287 print_vcg_color(F, ird_color_error);
1291 if (dump_node_vcgattr_hook)
1292 if (dump_node_vcgattr_hook(F, node, local))
1295 n = local ? local : node;
1297 if (overrule_nodecolor != ird_color_default_node) {
1298 print_vcg_color(F, overrule_nodecolor);
1302 mode = get_irn_mode(n);
1303 if (mode == mode_M) {
1304 print_vcg_color(F, ird_color_memory);
1307 if (mode == mode_X) {
1308 print_vcg_color(F, ird_color_controlflow);
1312 switch (get_irn_opcode(n)) {
1317 print_vcg_color(F, ird_color_anchor);
1320 print_vcg_color(F, ird_color_error);
1323 if (is_Block_dead(n))
1324 print_vcg_color(F, ird_color_dead_block_background);
1326 print_vcg_color(F, ird_color_block_background);
1329 print_vcg_color(F, ird_color_phi);
1332 print_vcg_color(F, ird_color_memory);
1336 print_vcg_color(F, ird_color_const);
1339 print_vcg_color(F, ird_color_proj);
1342 ir_op *op = get_irn_op(node);
1344 if (is_op_constlike(op)) {
1345 print_vcg_color(F, ird_color_const);
1346 } else if (is_op_uses_memory(op)) {
1347 print_vcg_color(F, ird_color_uses_memory);
1348 } else if (is_op_cfopcode(op) || is_op_forking(op)) {
1349 print_vcg_color(F, ird_color_controlflow);
1355 /* Adds a new node info dumper callback. */
1356 void *dump_add_node_info_callback(dump_node_info_cb_t *cb, void *data)
1358 hook_entry_t *info = XMALLOC(hook_entry_t);
1360 info->hook._hook_node_info = cb;
1361 info->context = data;
1362 register_hook(hook_node_info, info);
1367 /* Remove a previously added info dumper callback. */
1368 void dump_remv_node_info_callback(void *handle)
1370 hook_entry_t *info = handle;
1371 unregister_hook(hook_node_info, info);
1376 * Dump the node information of a node n to a file F.
1378 static inline int dump_node_info(FILE *F, ir_node *n)
1381 const ir_op_ops *ops = get_op_ops(get_irn_op(n));
1383 fprintf(F, " info1: \"");
1384 bad = dump_irnode_to_file(F, n);
1385 /* call the dump_node operation if available */
1387 bad = ops->dump_node(n, F, dump_node_info_txt);
1389 /* allow additional info to be added */
1390 hook_node_info(F, n);
1396 static inline int is_constlike_node(const ir_node *node)
1398 const ir_op *op = get_irn_op(node);
1399 return is_op_constlike(op);
1403 /** outputs the predecessors of n, that are constants, local. I.e.,
1404 generates a copy of the constant predecessors for each node called with. */
1405 static void dump_const_node_local(FILE *F, ir_node *n)
1408 if (!get_opt_dump_const_local()) return;
1410 /* Use visited flag to avoid outputting nodes twice.
1411 initialize it first. */
1412 for (i = 0; i < get_irn_arity(n); i++) {
1413 ir_node *con = get_irn_n(n, i);
1414 if (is_constlike_node(con)) {
1415 set_irn_visited(con, get_irg_visited(current_ir_graph) - 1);
1419 for (i = 0; i < get_irn_arity(n); i++) {
1420 ir_node *con = get_irn_n(n, i);
1421 if (is_constlike_node(con) && !irn_visited(con)) {
1424 mark_irn_visited(con);
1425 /* Generate a new name for the node by appending the names of
1427 fprintf(F, "node: {title: "); PRINT_CONSTID(n, con);
1428 fprintf(F, " label: \"");
1429 bad |= dump_node_label(F, con);
1431 bad |= dump_node_info(F, con);
1432 dump_node_vcgattr(F, n, con, bad);
1438 /** If the block of an edge is a const_like node, dump it local with an edge */
1439 static void dump_const_block_local(FILE *F, ir_node *n)
1443 if (!get_opt_dump_const_local()) return;
1445 blk = get_nodes_block(n);
1446 if (is_constlike_node(blk)) {
1449 /* Generate a new name for the node by appending the names of
1451 fprintf(F, "node: {title: \""); PRINT_CONSTBLKID(n, blk);
1452 fprintf(F, "\" label: \"");
1453 bad |= dump_node_label(F, blk);
1455 bad |= dump_node_info(F, blk);
1456 dump_node_vcgattr(F, n, blk, bad);
1459 fprintf(F, "edge: { sourcename: \"");
1461 fprintf(F, "\" targetname: \""); PRINT_CONSTBLKID(n,blk);
1463 if (dump_edge_vcgattr_hook) {
1465 if (dump_edge_vcgattr_hook(F, n, -1)) {
1469 fprintf(F, " " BLOCK_EDGE_ATTR "}\n");
1474 fprintf(F, "\" " BLOCK_EDGE_ATTR "}\n");
1479 * prints the error message of a node to a file F as info2.
1481 static void print_node_error(FILE *F, const char *err_msg)
1486 fprintf(F, " info2: \"%s\"", err_msg);
1490 * prints debug messages of a node to file F as info3.
1492 static void print_dbg_info(FILE *F, dbg_info *dbg)
1496 ir_dbg_info_snprint(buf, sizeof(buf), dbg);
1498 fprintf(F, " info3: \"%s\"\n", buf);
1502 static void print_type_dbg_info(FILE *F, type_dbg_info *dbg)
1512 static void dump_node(FILE *F, ir_node *n)
1517 if (get_opt_dump_const_local() && is_constlike_node(n))
1520 /* dump this node */
1521 fputs("node: {title: \"", F);
1525 fputs(" label: \"", F);
1526 bad = ! irn_vrfy_irg_dump(n, current_ir_graph, &p);
1527 bad |= dump_node_label(F, n);
1528 dump_node_ana_vals(F, n);
1529 //dump_node_ana_info(F, n);
1532 if (get_op_flags(get_irn_op(n)) & irop_flag_dump_noinput) {
1533 //fputs(" node_class:23", F);
1536 bad |= dump_node_info(F, n);
1537 print_node_error(F, p);
1538 print_dbg_info(F, get_irn_dbg_info(n));
1539 dump_node_vcgattr(F, n, NULL, bad);
1541 dump_const_node_local(F, n);
1543 if (dump_node_edge_hook)
1544 dump_node_edge_hook(F, n);
1547 /** dump the edge to the block this node belongs to */
1548 static void dump_ir_block_edge(FILE *F, ir_node *n)
1550 if (get_opt_dump_const_local() && is_constlike_node(n)) return;
1551 if (is_no_Block(n)) {
1552 ir_node *block = get_nodes_block(n);
1554 if (get_opt_dump_const_local() && is_constlike_node(block)) {
1555 dump_const_block_local(F, n);
1557 fprintf(F, "edge: { sourcename: \"");
1559 fprintf(F, "\" targetname: ");
1560 fprintf(F, "\""); PRINT_NODEID(block); fprintf(F, "\"");
1562 if (dump_edge_vcgattr_hook) {
1564 if (dump_edge_vcgattr_hook(F, n, -1)) {
1568 fprintf(F, " " BLOCK_EDGE_ATTR "}\n");
1573 fprintf(F, " " BLOCK_EDGE_ATTR "}\n");
1578 static void print_data_edge_vcgattr(FILE *F, ir_node *from, int to)
1581 * do not use get_nodes_block() here, will fail
1582 * if the irg is not pinned.
1584 if (get_irn_n(from, -1) == get_irn_n(get_irn_n(from, to), -1))
1585 fprintf(F, INTRA_DATA_EDGE_ATTR);
1587 fprintf(F, INTER_DATA_EDGE_ATTR);
1590 static void print_mem_edge_vcgattr(FILE *F, ir_node *from, int to)
1593 * do not use get_nodes_block() here, will fail
1594 * if the irg is not pinned.
1596 if (get_irn_n(from, -1) == get_irn_n(get_irn_n(from, to), -1))
1597 fprintf(F, INTRA_MEM_EDGE_ATTR);
1599 fprintf(F, INTER_MEM_EDGE_ATTR);
1602 /** Print the vcg attributes for the edge from node from to it's to's input */
1603 static void print_edge_vcgattr(FILE *F, ir_node *from, int to)
1607 if (dump_edge_vcgattr_hook)
1608 if (dump_edge_vcgattr_hook(F, from, to))
1611 if (dump_backedge_information_flag && is_backedge(from, to))
1612 fprintf(F, BACK_EDGE_ATTR);
1614 switch (get_irn_opcode(from)) {
1616 fprintf(F, CF_EDGE_ATTR);
1618 case iro_Start: break;
1621 if (get_irn_mode(get_End_keepalive(from, to)) == mode_BB)
1622 fprintf(F, KEEP_ALIVE_CF_EDGE_ATTR);
1624 fprintf(F, KEEP_ALIVE_DF_EDGE_ATTR);
1628 if (is_Proj(from)) {
1629 if (get_irn_mode(from) == mode_M)
1630 print_mem_edge_vcgattr(F, from, to);
1631 else if (get_irn_mode(from) == mode_X)
1632 fprintf(F, CF_EDGE_ATTR);
1634 print_data_edge_vcgattr(F, from, to);
1636 else if (get_irn_mode(get_irn_n(from, to)) == mode_M)
1637 print_mem_edge_vcgattr(F, from, to);
1638 else if (get_irn_mode(get_irn_n(from, to)) == mode_X)
1639 fprintf(F, CF_EDGE_ATTR);
1641 print_data_edge_vcgattr(F, from, to);
1645 /** dump edges to our inputs */
1646 static void dump_ir_data_edges(FILE *F, ir_node *n)
1650 if (!dump_keepalive && is_End(n)) {
1651 /* the End node has only keep-alive edges */
1655 /* dump the dependency edges. */
1656 num = get_irn_deps(n);
1657 for (i = 0; i < num; ++i) {
1658 ir_node *dep = get_irn_dep(n, i);
1661 print_node_edge_kind(F, n);
1662 fprintf(F, "{sourcename: \"");
1664 fprintf(F, "\" targetname: ");
1665 if ((get_opt_dump_const_local()) && is_constlike_node(dep)) {
1666 PRINT_CONSTID(n, dep);
1672 fprintf(F, " label: \"%d\" ", i);
1673 fprintf(F, " color: darkgreen}\n");
1677 num = get_irn_arity(n);
1678 for (i = 0; i < num; i++) {
1679 ir_node *pred = get_irn_n(n, i);
1682 #ifdef INTERPROCEDURAL_VIEW
1683 if ((get_interprocedural_view() && get_irn_visited(pred) < get_irn_visited(n)))
1684 continue; /* pred not dumped */
1687 if (dump_backedge_information_flag && is_backedge(n, i))
1688 fprintf(F, "backedge: {sourcename: \"");
1690 print_node_edge_kind(F, n);
1691 fprintf(F, "{sourcename: \"");
1694 fprintf(F, "\" targetname: ");
1695 if ((get_opt_dump_const_local()) && is_constlike_node(pred)) {
1696 PRINT_CONSTID(n, pred);
1698 fprintf(F, "\""); PRINT_NODEID(pred); fprintf(F, "\"");
1700 fprintf(F, " label: \"%d\" ", i);
1701 print_edge_vcgattr(F, n, i);
1705 if (dump_macro_block_edges && is_Block(n)) {
1706 ir_node *mb = get_Block_MacroBlock(n);
1707 fprintf(F, "edge: {sourcename: \"");
1709 fprintf(F, "\" targetname: \"");
1711 fprintf(F, "\" label: \"mb\" " MACROBLOCK_EDGE_ATTR);
1719 static void dump_ir_edges(FILE *F, ir_node *n)
1721 const ir_edge_t *edge;
1724 foreach_out_edge(n, edge) {
1725 ir_node *succ = get_edge_src_irn(edge);
1727 print_node_edge_kind(F, succ);
1728 fprintf(F, "{sourcename: \"");
1730 fprintf(F, "\" targetname: \"");
1734 fprintf(F, " label: \"%d\" ", i);
1735 fprintf(F, OUT_EDGE_ATTR);
1742 /** Dumps a node and its edges but not the block edge */
1743 static void dump_node_wo_blockedge(ir_node *n, void *env)
1747 dump_ir_data_edges(F, n);
1750 /** Dumps a node and its edges. */
1751 static void dump_whole_node(ir_node *n, void *env)
1754 dump_node_wo_blockedge(n, env);
1755 if (!node_floats(n))
1756 dump_ir_block_edge(F, n);
1757 if (dump_new_edges_flag && edges_activated(current_ir_graph))
1758 dump_ir_edges(F, n);
1761 /** Dumps a const-like node. */
1762 static void dump_const_node(ir_node *n, void *env)
1764 if (is_Block(n)) return;
1765 dump_node_wo_blockedge(n, env);
1768 /***********************************************************************/
1769 /* the following routines dump the nodes/irgs bracketed to graphs. */
1770 /***********************************************************************/
1772 /** Dumps a constant expression as entity initializer, array bound ...
1774 static void dump_const_expression(FILE *F, ir_node *value)
1776 ir_graph *rem = current_ir_graph;
1777 int rem_dump_const_local = dump_const_local;
1778 dump_const_local = 0;
1779 current_ir_graph = get_const_code_irg();
1780 irg_walk(value, dump_const_node, NULL, F);
1781 /* Decrease visited flag so that we walk with the same flag for the next
1782 expression. This guarantees that we don't dump the same node twice,
1783 as for const expressions cse is performed to save memory. */
1784 set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph) -1);
1785 current_ir_graph = rem;
1786 dump_const_local = rem_dump_const_local;
1789 /** Dump a block as graph containing its nodes.
1791 * Expects to find nodes belonging to the block as list in its
1793 * Dumps the edges of all nodes including itself. */
1794 static void dump_whole_block(FILE *F, ir_node *block)
1797 ird_color_t color = ird_color_block_background;
1799 assert(is_Block(block));
1801 fprintf(F, "graph: { title: \"");
1802 PRINT_NODEID(block);
1803 fprintf(F, "\" label: \"");
1804 dump_node_label(F, block);
1806 /* colorize blocks */
1807 if (! get_Block_matured(block))
1808 color = ird_color_block_background;
1809 if (is_Block_dead(block))
1810 color = ird_color_dead_block_background;
1812 fprintf(F, "\" status:clustered ");
1813 print_vcg_color(F, color);
1816 /* yComp can show attributes for blocks, XVCG parses but ignores them */
1817 dump_node_info(F, block);
1818 print_dbg_info(F, get_irn_dbg_info(block));
1820 /* dump the blocks edges */
1821 dump_ir_data_edges(F, block);
1823 if (dump_block_edge_hook)
1824 dump_block_edge_hook(F, block);
1826 /* dump the nodes that go into the block */
1827 for (node = ird_get_irn_link(block); node; node = ird_get_irn_link(node)) {
1829 dump_ir_data_edges(F, node);
1832 /* Close the vcg information for the block */
1834 dump_const_node_local(F, block);
1838 /** dumps a graph block-wise. Expects all blockless nodes in arr in irgs link.
1839 * The outermost nodes: blocks and nodes not op_pin_state_pinned, Bad, Unknown. */
1840 static void dump_block_graph(FILE *F, ir_graph *irg)
1843 ir_graph *rem = current_ir_graph;
1844 ir_node **arr = ird_get_irg_link(irg);
1845 current_ir_graph = irg;
1847 for (i = ARR_LEN(arr) - 1; i >= 0; --i) {
1848 ir_node * node = arr[i];
1849 if (is_Block(node)) {
1850 /* Dumps the block and all the nodes in the block, which are to
1851 be found in Block->link. */
1852 dump_whole_block(F, node);
1854 /* Nodes that are not in a Block. */
1856 if (!node_floats(node) && is_Bad(get_nodes_block(node))) {
1857 dump_const_block_local(F, node);
1859 dump_ir_data_edges(F, node);
1861 if (dump_new_edges_flag && edges_activated(irg))
1862 dump_ir_edges(F, node);
1865 if (dump_loop_information_flag && (get_irg_loopinfo_state(irg) & loopinfo_valid))
1866 dump_loop_nodes_into_graph(F, irg);
1868 current_ir_graph = rem;
1872 * Dump the info for an irg.
1873 * Parsed by XVCG but not shown. use yComp.
1875 static void dump_graph_info(FILE *F, ir_graph *irg)
1877 fprintf(F, "info1: \"");
1878 dump_entity_to_file(F, get_irg_entity(irg), dump_verbosity_entattrs | dump_verbosity_entconsts);
1882 /** Dumps an irg as a graph clustered by block nodes.
1883 * If interprocedural view edges can point to nodes out of this graph.
1885 static void dump_graph_from_list(FILE *F, ir_graph *irg)
1887 ir_entity *ent = get_irg_entity(irg);
1889 fprintf(F, "graph: { title: \"");
1891 fprintf(F, "\" label: \"%s\" status:clustered color:%s \n",
1892 get_ent_dump_name(ent), color_names[ird_color_prog_background]);
1894 dump_graph_info(F, irg);
1895 print_dbg_info(F, get_entity_dbg_info(ent));
1897 dump_block_graph(F, irg);
1899 /* Close the vcg information for the irg */
1900 fprintf(F, "}\n\n");
1903 /** dumps a graph extended block-wise. Expects all blockless nodes in arr in irgs link.
1904 * The outermost nodes: blocks and nodes not op_pin_state_pinned, Bad, Unknown. */
1905 static void dump_extblock_graph(FILE *F, ir_graph *irg)
1908 ir_graph *rem = current_ir_graph;
1909 ir_extblk **arr = ird_get_irg_link(irg);
1910 current_ir_graph = irg;
1912 for (i = ARR_LEN(arr) - 1; i >= 0; --i) {
1913 ir_extblk *extbb = arr[i];
1914 ir_node *leader = get_extbb_leader(extbb);
1917 fprintf(F, "graph: { title: \"");
1918 PRINT_EXTBBID(leader);
1919 fprintf(F, "\" label: \"ExtBB %ld\" status:clustered color:lightgreen\n",
1920 get_irn_node_nr(leader));
1922 for (j = ARR_LEN(extbb->blks) - 1; j >= 0; --j) {
1923 ir_node * node = extbb->blks[j];
1924 if (is_Block(node)) {
1925 /* Dumps the block and all the nodes in the block, which are to
1926 be found in Block->link. */
1927 dump_whole_block(F, node);
1929 /* Nodes that are not in a Block. */
1931 if (is_Bad(get_nodes_block(node)) && !node_floats(node)) {
1932 dump_const_block_local(F, node);
1934 dump_ir_data_edges(F, node);
1940 if (dump_loop_information_flag && (get_irg_loopinfo_state(irg) & loopinfo_valid))
1941 dump_loop_nodes_into_graph(F, irg);
1943 current_ir_graph = rem;
1948 /*******************************************************************/
1949 /* Basic type and entity nodes and edges. */
1950 /*******************************************************************/
1952 /** dumps the edges between nodes and their type or entity attributes. */
1953 static void dump_node2type_edges(ir_node *n, void *env)
1958 switch (get_irn_opcode(n)) {
1960 /* @@@ some consts have an entity */
1963 if (SYMCONST_HAS_TYPE(get_SymConst_kind(n)))
1964 print_node_type_edge(F,n,get_SymConst_type(n),NODE2TYPE_EDGE_ATTR);
1967 print_node_ent_edge(F,n,get_Sel_entity(n),NODE2TYPE_EDGE_ATTR);
1970 print_node_type_edge(F,n,get_Call_type(n),NODE2TYPE_EDGE_ATTR);
1973 print_node_type_edge(F,n,get_Alloc_type(n),NODE2TYPE_EDGE_ATTR);
1976 print_node_type_edge(F,n,get_Free_type(n),NODE2TYPE_EDGE_ATTR);
1979 print_node_type_edge(F,n,get_Cast_type(n),NODE2TYPE_EDGE_ATTR);
1987 static int print_type_info(FILE *F, ir_type *tp)
1991 if (get_type_state(tp) == layout_undefined) {
1992 fprintf(F, "state: layout_undefined\n");
1994 fprintf(F, "state: layout_fixed,\n");
1996 if (get_type_mode(tp))
1997 fprintf(F, "mode: %s,\n", get_mode_name_ex(get_type_mode(tp), &bad));
1998 fprintf(F, "size: %db,\n", get_type_size_bits(tp));
2003 static void print_typespecific_info(FILE *F, ir_type *tp)
2005 switch (get_type_tpop_code(tp)) {
2007 fprintf(F, "peculiarity: %s\n", get_peculiarity_string(get_class_peculiarity(tp)));
2012 fprintf(F, "variadicity: %s\n", get_variadicity_name(get_method_variadicity(tp)));
2013 fprintf(F, "params: %d\n", get_method_n_params(tp));
2014 fprintf(F, "results: %d\n", get_method_n_ress(tp));
2020 case tpo_enumeration:
2032 static void print_typespecific_vcgattr(FILE *F, ir_type *tp)
2034 switch (get_type_tpop_code(tp)) {
2036 fprintf(F, " " TYPE_CLASS_NODE_ATTR);
2039 fprintf(F, " " TYPE_METH_NODE_ATTR);
2047 case tpo_enumeration:
2058 int dump_type_node(FILE *F, ir_type *tp)
2062 fprintf(F, "node: {title: ");
2064 fprintf(F, " label: \"%s ", get_type_tpop_name(tp));
2065 if (tp->dbi != NULL) {
2067 ir_print_type(buf, sizeof(buf), tp);
2068 fprintf(F, "'%s'", buf);
2070 ir_fprintf(F, "%+F", tp);
2072 fputs("\" info1: \"", F);
2073 dump_type_to_file(F, tp, dump_verbosity_max);
2075 print_type_dbg_info(F, get_type_dbg_info(tp));
2076 print_typespecific_vcgattr(F, tp);
2083 static void dump_entity_node(FILE *F, ir_entity *ent)
2085 fprintf(F, "node: {title: \"");
2086 PRINT_ENTID(ent); fprintf(F, "\"");
2087 fprintf(F, " label: ");
2088 fprintf(F, "\"%s\" ", get_ent_dump_name(ent));
2090 print_vcg_color(F, ird_color_entity);
2091 fprintf(F, "\n info1: \"");
2093 dump_entity_to_file(F, ent, dump_verbosity_entattrs | dump_verbosity_entconsts);
2096 print_dbg_info(F, get_entity_dbg_info(ent));
2100 static void dump_enum_item(FILE *F, ir_type *tp, int pos)
2103 ir_enum_const *ec = get_enumeration_const(tp, pos);
2104 ident *id = get_enumeration_const_nameid(ec);
2105 tarval *tv = get_enumeration_value(ec);
2108 tarval_snprintf(buf, sizeof(buf), tv);
2110 strncpy(buf, "<not set>", sizeof(buf));
2111 fprintf(F, "node: {title: \"");
2112 PRINT_ITEMID(tp, pos); fprintf(F, "\"");
2113 fprintf(F, " label: ");
2114 fprintf(F, "\"enum item %s\" " ENUM_ITEM_NODE_ATTR, get_id_str(id));
2115 fprintf(F, "\n info1: \"value: %s\"}\n", buf);
2119 * Dumps a new style initializer.
2121 static void dump_entity_initializer(FILE *F, const ir_entity *ent)
2128 /** Dumps a type or entity and it's edges. */
2129 static void dump_type_info(type_or_ent tore, void *env)
2132 int i = 0; /* to shutup gcc */
2134 /* dump this type or entity */
2136 switch (get_kind(tore.ent)) {
2138 ir_entity *ent = tore.ent;
2141 dump_entity_node(F, ent);
2143 /* skip this to reduce graph. Member edge of type is parallel to this edge. *
2144 fprintf(F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
2145 ENT_OWN_EDGE_ATTR "}\n", ent, get_entity_owner(ent));*/
2146 print_ent_type_edge(F,ent, get_entity_type(ent), ENT_TYPE_EDGE_ATTR);
2147 if (is_Class_type(get_entity_owner(ent))) {
2148 for (i = get_entity_n_overwrites(ent) - 1; i >= 0; --i)
2149 print_ent_ent_edge(F,ent, get_entity_overwrites(ent, i), 0, -1, ENT_OVERWRITES_EDGE_ATTR);
2151 /* attached subgraphs */
2152 if (const_entities) {
2153 if (ent->initializer != NULL) {
2154 /* new style initializers */
2155 dump_entity_initializer(F, ent);
2156 } else if (entity_has_compound_ent_values(ent)) {
2157 /* old style compound entity values */
2158 for (i = get_compound_ent_n_values(ent) - 1; i >= 0; --i) {
2159 value = get_compound_ent_value(ent, i);
2161 print_ent_node_edge(F, ent, value, ENT_VALUE_EDGE_ATTR, i);
2162 dump_const_expression(F, value);
2163 print_ent_ent_edge(F, ent, get_compound_ent_value_member(ent, i), 0, -1, ENT_CORR_EDGE_ATTR, i);
2165 fprintf(F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
2166 ENT_CORR_EDGE_ATTR "}\n", GET_ENTID(ent),
2167 get_compound_ent_value_member(ent, i), i);
2176 ir_type *tp = tore.typ;
2177 dump_type_node(F, tp);
2178 /* and now the edges */
2179 switch (get_type_tpop_code(tp)) {
2181 for (i = get_class_n_supertypes(tp) - 1; i >= 0; --i)
2182 print_type_type_edge(F, tp, get_class_supertype(tp, i), TYPE_SUPER_EDGE_ATTR);
2183 for (i = get_class_n_members(tp) - 1; i >= 0; --i)
2184 print_type_ent_edge(F, tp, get_class_member(tp, i), TYPE_MEMBER_EDGE_ATTR);
2187 for (i = get_struct_n_members(tp) - 1; i >= 0; --i)
2188 print_type_ent_edge(F, tp, get_struct_member(tp, i), TYPE_MEMBER_EDGE_ATTR);
2191 for (i = get_method_n_params(tp) - 1; i >= 0; --i)
2192 print_type_type_edge(F, tp, get_method_param_type(tp, i), METH_PAR_EDGE_ATTR,i);
2193 for (i = get_method_n_ress(tp) - 1; i >= 0; --i)
2194 print_type_type_edge(F, tp, get_method_res_type(tp, i), METH_RES_EDGE_ATTR,i);
2197 for (i = get_union_n_members(tp) - 1; i >= 0; --i)
2198 print_type_ent_edge(F, tp, get_union_member(tp, i), UNION_EDGE_ATTR);
2201 print_type_type_edge(F, tp, get_array_element_type(tp), ARR_ELT_TYPE_EDGE_ATTR);
2202 print_type_ent_edge(F, tp, get_array_element_entity(tp), ARR_ENT_EDGE_ATTR);
2203 for (i = get_array_n_dimensions(tp) - 1; i >= 0; --i) {
2204 ir_node *upper = get_array_upper_bound(tp, i);
2205 ir_node *lower = get_array_lower_bound(tp, i);
2206 print_node_type_edge(F, upper, tp, "label: \"upper %d\"", get_array_order(tp, i));
2207 print_node_type_edge(F, lower, tp, "label: \"lower %d\"", get_array_order(tp, i));
2208 dump_const_expression(F, upper);
2209 dump_const_expression(F, lower);
2212 case tpo_enumeration:
2213 for (i = get_enumeration_n_enums(tp) - 1; i >= 0; --i) {
2214 dump_enum_item(F, tp, i);
2215 print_enum_item_edge(F, tp, i, "label: \"item %d\"", i);
2219 print_type_type_edge(F, tp, get_pointer_points_to_type(tp), PTR_PTS_TO_EDGE_ATTR);
2226 break; /* case k_type */
2229 printf(" *** irdump, dump_type_info(l.%i), faulty type.\n", __LINE__);
2230 } /* switch kind_or_entity */
2233 typedef struct _h_env {
2238 /** For dumping class hierarchies.
2239 * Dumps a class type node and a superclass edge.
2240 * If env->dump_ent dumps entities of classes and overwrites edges.
2242 static void dump_class_hierarchy_node(type_or_ent tore, void *ctx)
2246 int i = 0; /* to shutup gcc */
2248 /* dump this type or entity */
2249 switch (get_kind(tore.ent)) {
2251 ir_entity *ent = tore.ent;
2252 if (get_entity_owner(ent) == get_glob_type()) break;
2253 if (!is_Method_type(get_entity_type(ent)))
2255 if (env->dump_ent && is_Class_type(get_entity_owner(ent))) {
2257 dump_entity_node(F, ent);
2259 print_type_ent_edge(F, get_entity_owner(ent), ent, TYPE_MEMBER_EDGE_ATTR);
2260 for (i = get_entity_n_overwrites(ent) - 1; i >= 0; --i)
2261 print_ent_ent_edge(F, get_entity_overwrites(ent, i), ent, 0, -1, ENT_OVERWRITES_EDGE_ATTR);
2266 ir_type *tp = tore.typ;
2267 if (tp == get_glob_type())
2269 switch (get_type_tpop_code(tp)) {
2271 dump_type_node(F, tp);
2272 /* and now the edges */
2273 for (i = get_class_n_supertypes(tp) - 1; i >= 0; --i) {
2274 print_type_type_edge(F,tp,get_class_supertype(tp, i),TYPE_SUPER_EDGE_ATTR);
2279 break; /* case k_type */
2282 printf(" *** irdump, dump_class_hierarchy_node(l.%i), faulty type.\n", __LINE__);
2283 } /* switch kind_or_entity */
2286 /*******************************************************************/
2287 /* dump analysis information that is expressed in graph terms. */
2288 /*******************************************************************/
2290 /* dump out edges */
2291 static void dump_out_edge(ir_node *n, void *env)
2295 for (i = get_irn_n_outs(n) - 1; i >= 0; --i) {
2296 ir_node *succ = get_irn_out(n, i);
2298 print_node_edge_kind(F, succ);
2299 fprintf(F, "{sourcename: \"");
2301 fprintf(F, "\" targetname: \"");
2303 fprintf(F, "\" color: red linestyle: dashed");
2308 static inline void dump_loop_label(FILE *F, ir_loop *loop)
2310 fprintf(F, "loop %d, %d sons, %d nodes",
2311 get_loop_depth(loop), get_loop_n_sons(loop), get_loop_n_nodes(loop));
2314 static inline void dump_loop_info(FILE *F, ir_loop *loop)
2316 fprintf(F, " info1: \"");
2317 fprintf(F, " loop nr: %d", get_loop_loop_nr(loop));
2318 #ifdef DEBUG_libfirm /* GL @@@ debug analyses */
2319 fprintf(F, "\n The loop was analyzed %d times.", PTR_TO_INT(get_loop_link(loop)));
2324 static inline void dump_loop_node(FILE *F, ir_loop *loop)
2326 fprintf(F, "node: {title: \"");
2328 fprintf(F, "\" label: \"");
2329 dump_loop_label(F, loop);
2331 dump_loop_info(F, loop);
2335 static inline void dump_loop_node_edge(FILE *F, ir_loop *loop, int i)
2338 fprintf(F, "edge: {sourcename: \"");
2340 fprintf(F, "\" targetname: \"");
2341 PRINT_NODEID(get_loop_node(loop, i));
2342 fprintf(F, "\" color: green");
2346 static inline void dump_loop_son_edge(FILE *F, ir_loop *loop, int i)
2349 fprintf(F, "edge: {sourcename: \"");
2351 fprintf(F, "\" targetname: \"");
2352 PRINT_LOOPID(get_loop_son(loop, i));
2353 fprintf(F, "\" color: darkgreen label: \"%d\"}\n",
2354 get_loop_element_pos(loop, get_loop_son(loop, i)));
2357 static void dump_loops(FILE *F, ir_loop *loop)
2360 /* dump this loop node */
2361 dump_loop_node(F, loop);
2363 /* dump edges to nodes in loop -- only if it is a real loop */
2364 if (get_loop_depth(loop) != 0) {
2365 for (i = get_loop_n_nodes(loop) - 1; i >= 0; --i) {
2366 dump_loop_node_edge(F, loop, i);
2369 for (i = get_loop_n_sons(loop) - 1; i >= 0; --i) {
2370 dump_loops(F, get_loop_son(loop, i));
2371 dump_loop_son_edge(F, loop, i);
2375 static inline void dump_loop_nodes_into_graph(FILE *F, ir_graph *irg)
2377 ir_loop *loop = get_irg_loop(irg);
2380 ir_graph *rem = current_ir_graph;
2381 current_ir_graph = irg;
2383 dump_loops(F, loop);
2385 current_ir_graph = rem;
2391 * dumps the VCG header
2393 void dump_vcg_header(FILE *F, const char *name, const char *layout, const char *orientation)
2400 label = edge_label ? "yes" : "no";
2401 if (! layout) layout = "Compilergraph";
2402 if (!orientation) orientation = "bottom_to_top";
2406 "graph: { title: \"ir graph of %s\"\n"
2407 "display_edge_labels: %s\n"
2408 "layoutalgorithm: mindepth //$ \"%s\"\n"
2409 "manhattan_edges: yes\n"
2410 "port_sharing: no\n"
2412 "classname 1: \"intrablock Data\"\n"
2413 "classname 2: \"Block\"\n"
2414 "classname 3: \"Entity type\"\n"
2415 "classname 4: \"Entity owner\"\n"
2416 "classname 5: \"Method Param\"\n"
2417 "classname 6: \"Method Res\"\n"
2418 "classname 7: \"Super\"\n"
2419 "classname 8: \"Union\"\n"
2420 "classname 9: \"Points-to\"\n"
2421 "classname 10: \"Array Element Type\"\n"
2422 "classname 11: \"Overwrites\"\n"
2423 "classname 12: \"Member\"\n"
2424 "classname 13: \"Control Flow\"\n"
2425 "classname 14: \"intrablock Memory\"\n"
2426 "classname 15: \"Dominators\"\n"
2427 "classname 16: \"interblock Data\"\n"
2428 "classname 17: \"interblock Memory\"\n"
2429 "classname 18: \"Exception Control Flow for Interval Analysis\"\n"
2430 "classname 19: \"Postdominators\"\n"
2431 "classname 20: \"Keep Alive\"\n"
2432 "classname 21: \"Out Edges\"\n"
2433 "classname 22: \"Macro Block Edges\"\n"
2434 //"classname 23: \"NoInput Nodes\"\n"
2435 "infoname 1: \"Attribute\"\n"
2436 "infoname 2: \"Verification errors\"\n"
2437 "infoname 3: \"Debug info\"\n",
2438 name, label, layout, orientation);
2440 for (i = 0; i < ird_color_count; ++i) {
2441 if (color_rgb[i] != NULL) {
2442 fprintf(F, "colorentry %s: %s\n", color_names[i], color_rgb[i]);
2445 fprintf(F, "\n"); /* a separator */
2451 * @param irg The graph to be dumped
2452 * @param suffix1 first filename suffix
2453 * @param suffix2 second filename suffix
2455 FILE *vcg_open(const ir_graph *irg, const char *suffix1, const char *suffix2)
2458 const char *nm = get_irg_dump_name(irg);
2459 int len = strlen(nm), i, j;
2460 char *fname; /* filename to put the vcg information in */
2462 if (!suffix1) suffix1 = "";
2463 if (!suffix2) suffix2 = "";
2465 /* open file for vcg graph */
2466 fname = XMALLOCN(char, len * 2 + strlen(suffix1) + strlen(suffix2) + 5);
2468 /* strncpy (fname, nm, len); */ /* copy the filename */
2470 for (i = 0; i < len; ++i) { /* replace '/' in the name: escape by @. */
2472 fname[j] = '@'; j++; fname[j] = '1'; j++;
2473 } else if (nm[i] == '@') {
2474 fname[j] = '@'; j++; fname[j] = '2'; j++;
2476 fname[j] = nm[i]; j++;
2480 strcat(fname, suffix1); /* append file suffix */
2481 strcat(fname, suffix2); /* append file suffix */
2482 strcat(fname, ".vcg"); /* append the .vcg suffix */
2484 /* vcg really expect only a <CR> at end of line, so
2485 * the "b"inary mode is what you mean (and even needed for Win32)
2487 F = fopen(fname, "wb"); /* open file for writing */
2499 * @param name prefix file name
2500 * @param suffix filename suffix
2502 FILE *vcg_open_name(const char *name, const char *suffix)
2505 char *fname; /* filename to put the vcg information in */
2506 int i, j, len = strlen(name);
2508 if (!suffix) suffix = "";
2510 /** open file for vcg graph */
2511 fname = XMALLOCN(char, len * 2 + 5 + strlen(suffix));
2512 /* strcpy (fname, name);*/ /* copy the filename */
2514 for (i = 0; i < len; ++i) { /* replace '/' in the name: escape by @. */
2515 if (name[i] == '/') {
2516 fname[j] = '@'; j++; fname[j] = '1'; j++;
2517 } else if (name[i] == '@') {
2518 fname[j] = '@'; j++; fname[j] = '2'; j++;
2520 fname[j] = name[i]; j++;
2524 strcat(fname, suffix);
2525 strcat(fname, ".vcg"); /* append the .vcg suffix */
2527 /* vcg really expect only a <CR> at end of line, so
2528 * the "b"inary mode is what you mean (and even needed for Win32)
2530 F = fopen(fname, "wb"); /* open file for writing */
2540 * Dumps the vcg file footer
2542 void dump_vcg_footer(FILE *F)
2547 /************************************************************************/
2548 /************************************************************************/
2549 /* Routines that dump all or parts of the firm representation to a file */
2550 /************************************************************************/
2551 /************************************************************************/
2553 /************************************************************************/
2554 /* Dump ir graphs, different formats and additional information. */
2555 /************************************************************************/
2557 typedef void (*do_dump_graph_func) (ir_graph *irg, FILE *out);
2559 static void do_dump(ir_graph *irg, const char *suffix, const char *suffix_ip,
2560 const char *suffix_nonip, do_dump_graph_func dump_func)
2564 const char *suffix1;
2566 if (!is_filtered_dump_name(get_entity_ident(get_irg_entity(irg))))
2569 rem = current_ir_graph;
2570 current_ir_graph = irg;
2572 #ifdef INTERPROCEDURAL_VIEW
2573 if (get_interprocedural_view())
2574 suffix1 = suffix_ip;
2577 suffix1 = suffix_nonip;
2578 current_ir_graph = rem;
2580 out = vcg_open(irg, suffix, suffix1);
2582 dump_func(irg, out);
2587 void dump_ir_graph_file(ir_graph *irg, FILE *out)
2589 if (dump_backedge_information_flag
2590 && get_irg_loopinfo_state(irg) != loopinfo_consistent) {
2591 construct_backedges(irg);
2594 dump_vcg_header(out, get_irg_dump_name(irg), NULL, NULL);
2596 /* call the dump graph hook */
2597 if (dump_ir_graph_hook) {
2598 if (dump_ir_graph_hook(out, irg)) {
2603 /* walk over the graph */
2604 /* dump_whole_node must be called in post visiting predecessors */
2605 ird_walk_graph(irg, NULL, dump_whole_node, out);
2607 /* dump the out edges in a separate walk */
2608 if ((dump_out_edge_flag) && (get_irg_outs_state(irg) != outs_none)) {
2609 irg_out_walk(get_irg_start(irg), dump_out_edge, NULL, out);
2612 dump_vcg_footer(out);
2615 /** Routine to dump a graph, blocks as conventional nodes. */
2616 void dump_ir_graph(ir_graph *irg, const char *suffix )
2618 do_dump(irg, suffix, "-pure-ip", "-pure", dump_ir_graph_file);
2621 void dump_ir_block_graph_file(ir_graph *irg, FILE *out)
2625 dump_vcg_header(out, get_irg_dump_name(irg), NULL, NULL);
2627 construct_block_lists(irg);
2630 * If we are in the interprocedural view, we dump not
2631 * only the requested irg but also all irgs that can be reached
2634 for (i = get_irp_n_irgs() - 1; i >= 0; --i) {
2635 ir_graph *g = get_irp_irg(i);
2636 ir_node **arr = ird_get_irg_link(g);
2638 dump_graph_from_list(out, g);
2643 dump_vcg_footer(out);
2646 /* Dump a firm graph without explicit block nodes. */
2647 void dump_ir_block_graph(ir_graph *irg, const char *suffix)
2649 do_dump(irg, suffix, "-ip", "", dump_ir_block_graph_file);
2652 void dump_ir_extblock_graph_file(ir_graph *irg, FILE *F)
2655 ir_entity *ent = get_irg_entity(irg);
2657 if (get_irg_extblk_state(irg) != extblk_valid)
2660 dump_vcg_header(F, get_irg_dump_name(irg), NULL, NULL);
2662 construct_extblock_lists(irg);
2664 fprintf(F, "graph: { title: \"");
2666 fprintf(F, "\" label: \"%s\" status:clustered color: white \n",
2667 get_ent_dump_name(ent));
2669 dump_graph_info(F, irg);
2670 print_dbg_info(F, get_entity_dbg_info(ent));
2672 for (i = get_irp_n_irgs() - 1; i >= 0; --i) {
2673 ir_graph *irg = get_irp_irg(i);
2674 list_tuple *lists = ird_get_irg_link(irg);
2677 /* dump the extended blocks first */
2678 if (ARR_LEN(lists->extbb_list)) {
2679 ird_set_irg_link(irg, lists->extbb_list);
2680 dump_extblock_graph(F, irg);
2683 /* we may have blocks without extended blocks, bad for instance */
2684 if (ARR_LEN(lists->blk_list)) {
2685 ird_set_irg_link(irg, lists->blk_list);
2686 dump_block_graph(F, irg);
2689 DEL_ARR_F(lists->extbb_list);
2690 DEL_ARR_F(lists->blk_list);
2695 /* Close the vcg information for the irg */
2696 fprintf(F, "}\n\n");
2702 /* Dump a firm graph without explicit block nodes but grouped in extended blocks. */
2703 void dump_ir_extblock_graph(ir_graph *irg, const char *suffix)
2705 do_dump(irg, suffix, "-ip", "", dump_ir_extblock_graph_file);
2708 void dump_ir_graph_w_types_file(ir_graph *irg, FILE *out)
2710 ir_graph *rem = current_ir_graph;
2711 int rem_dump_const_local;
2713 rem = current_ir_graph;
2714 current_ir_graph = irg;
2715 rem_dump_const_local = dump_const_local;
2716 /* dumping types does not work with local nodes */
2717 dump_const_local = 0;
2719 dump_vcg_header(out, get_irg_dump_name(irg), NULL, NULL);
2721 /* dump common ir graph */
2722 irg_walk(get_irg_end(irg), NULL, dump_whole_node, out);
2723 /* dump type info */
2724 type_walk_irg(irg, dump_type_info, NULL, out);
2725 inc_irg_visited(get_const_code_irg());
2726 /* dump edges from graph to type info */
2727 irg_walk(get_irg_end(irg), dump_node2type_edges, NULL, out);
2729 dump_vcg_footer(out);
2730 dump_const_local = rem_dump_const_local;
2731 current_ir_graph = rem;
2734 /* dumps a graph with type information */
2735 void dump_ir_graph_w_types(ir_graph *irg, const char *suffix)
2737 do_dump(irg, suffix, "-pure-wtypes-ip", "-pure-wtypes",
2738 dump_ir_graph_w_types_file);
2741 void dump_ir_block_graph_w_types_file(ir_graph *irg, FILE *out)
2744 int rem_dump_const_local;
2745 ir_graph *rem = current_ir_graph;
2747 rem_dump_const_local = dump_const_local;
2748 /* dumping types does not work with local nodes */
2749 dump_const_local = 0;
2751 dump_vcg_header(out, get_irg_dump_name(irg), NULL, NULL);
2753 /* dump common blocked ir graph */
2754 construct_block_lists(irg);
2756 for (i = get_irp_n_irgs() - 1; i >= 0; --i) {
2757 ir_node **arr = ird_get_irg_link(get_irp_irg(i));
2759 dump_graph_from_list(out, get_irp_irg(i));
2764 /* dump type info */
2765 current_ir_graph = irg;
2766 type_walk_irg(irg, dump_type_info, NULL, out);
2767 inc_irg_visited(get_const_code_irg());
2769 /* dump edges from graph to type info */
2770 irg_walk(get_irg_end(irg), dump_node2type_edges, NULL, out);
2772 dump_vcg_footer(out);
2773 dump_const_local = rem_dump_const_local;
2774 current_ir_graph = rem;
2777 void dump_ir_block_graph_w_types(ir_graph *irg, const char *suffix)
2779 do_dump(irg, suffix, "-wtypes-ip", "-wtypes",
2780 dump_ir_block_graph_w_types_file);
2783 /*---------------------------------------------------------------------*/
2784 /* The following routines dump a control flow graph. */
2785 /*---------------------------------------------------------------------*/
2787 static void dump_block_to_cfg(ir_node *block, void *env)
2793 if (is_Block(block)) {
2794 /* This is a block. Dump a node for the block. */
2795 fprintf(F, "node: {title: \""); PRINT_NODEID(block);
2796 fprintf(F, "\" label: \"");
2797 if (block == get_irg_start_block(get_irn_irg(block)))
2798 fprintf(F, "Start ");
2799 if (block == get_irg_end_block(get_irn_irg(block)))
2802 fprintf(F, "%s ", get_op_name(get_irn_op(block)));
2803 PRINT_NODEID(block);
2805 fprintf(F, "info1:\"");
2807 /* the generic version. */
2808 dump_irnode_to_file(F, block);
2810 /* Check whether we have bad predecessors to color the block. */
2811 for (i = get_Block_n_cfgpreds(block) - 1; i >= 0; --i)
2812 if ((fl = is_Bad(get_Block_cfgpred(block, i))))
2815 fprintf(F, "\""); /* closing quote of info */
2817 if ((block == get_irg_start_block(get_irn_irg(block))) ||
2818 (block == get_irg_end_block(get_irn_irg(block))) )
2819 fprintf(F, " color:blue ");
2821 fprintf(F, " color:yellow ");
2824 /* Dump the edges */
2825 for (i = get_Block_n_cfgpreds(block) - 1; i >= 0; --i)
2826 if (!is_Bad(skip_Proj(get_Block_cfgpred(block, i)))) {
2827 pred = get_nodes_block(skip_Proj(get_Block_cfgpred(block, i)));
2828 fprintf(F, "edge: { sourcename: \"");
2829 PRINT_NODEID(block);
2830 fprintf(F, "\" targetname: \"");
2832 fprintf(F, "\"}\n");
2835 /* Dump dominator/postdominator edge */
2836 if (dump_dominator_information_flag) {
2837 if (get_irg_dom_state(current_ir_graph) == dom_consistent && get_Block_idom(block)) {
2838 pred = get_Block_idom(block);
2839 fprintf(F, "edge: { sourcename: \"");
2840 PRINT_NODEID(block);
2841 fprintf(F, "\" targetname: \"");
2843 fprintf(F, "\" " DOMINATOR_EDGE_ATTR "}\n");
2845 if (get_irg_postdom_state(current_ir_graph) == dom_consistent && get_Block_ipostdom(block)) {
2846 pred = get_Block_ipostdom(block);
2847 fprintf(F, "edge: { sourcename: \"");
2848 PRINT_NODEID(block);
2849 fprintf(F, "\" targetname: \"");
2851 fprintf(F, "\" " POSTDOMINATOR_EDGE_ATTR "}\n");
2857 void dump_cfg(ir_graph *irg, const char *suffix)
2860 /* if a filter is set, dump only the irg's that match the filter */
2861 if (!is_filtered_dump_name(get_entity_ident(get_irg_entity(irg))))
2864 f = vcg_open(irg, suffix, "-cfg");
2866 ir_graph *rem = current_ir_graph;
2867 #ifdef INTERPROCEDURAL_VIEW
2868 int ipv = get_interprocedural_view();
2871 current_ir_graph = irg;
2872 dump_vcg_header(f, get_irg_dump_name(irg), NULL, NULL);
2874 #ifdef INTERPROCEDURAL_VIEW
2876 printf("Warning: dumping cfg not in interprocedural view!\n");
2877 set_interprocedural_view(0);
2881 /* walk over the blocks in the graph */
2882 irg_block_walk(get_irg_end(irg), dump_block_to_cfg, NULL, f);
2883 dump_node(f, get_irg_bad(irg));
2885 #ifdef INTERPROCEDURAL_VIEW
2886 set_interprocedural_view(ipv);
2890 current_ir_graph = rem;
2895 static void descend_and_dump(FILE *F, ir_node *n, int depth, pset *mark_set)
2897 if (pset_find_ptr(mark_set, n))
2900 pset_insert_ptr(mark_set, n);
2903 int i, start = is_Block(n) ? 0 : -1;
2904 dump_whole_node(n, F);
2905 for (i = start; i < get_irn_arity(n); ++i)
2906 descend_and_dump(F, get_irn_n(n, i), depth-1, mark_set);
2909 /* Don't dump edges to nodes further out. These might be edges to
2910 nodes we already dumped, if there is a shorter path to these. */
2914 static int subgraph_counter = 0;
2915 void dump_subgraph(ir_node *root, int depth, const char *suffix)
2920 sprintf(buf, "-subg_%03d", subgraph_counter++);
2921 F = vcg_open(get_irn_irg(root), suffix, buf);
2923 pset *mark_set = pset_new_ptr(1);
2924 dump_vcg_header(F, get_irg_dump_name(get_irn_irg(root)), NULL, NULL);
2925 descend_and_dump(F, root, depth, mark_set);
2932 void dump_callgraph(const char *suffix)
2934 FILE *F = vcg_open_name("Callgraph", suffix);
2937 int i, rem = edge_label;
2940 dump_vcg_header(F, "Callgraph", "Hierarchiv", NULL);
2942 for (i = get_irp_n_irgs() - 1; i >= 0; --i) {
2943 ir_graph *irg = get_irp_irg(i);
2944 ir_entity *ent = get_irg_entity(irg);
2946 int n_callees = get_irg_n_callees(irg);
2948 dump_entity_node(F, ent);
2949 for (j = 0; j < n_callees; ++j) {
2950 ir_entity *c = get_irg_entity(get_irg_callee(irg, j));
2951 //if (id_is_prefix(prefix, get_entity_ld_ident(c))) continue;
2952 int be = is_irg_callee_backedge(irg, j);
2955 "label:\"recursion %d\"" :
2956 "label:\"calls %d\"";
2957 print_ent_ent_edge(F, ent, c, be, ird_color_entity, attr, get_irg_callee_loop_depth(irg, j));
2968 /* Dump all irgs in interprocedural view to a single file. */
2969 void dump_all_cg_block_graph(const char *suffix)
2971 FILE *f = vcg_open_name("All_graphs", suffix);
2975 int rem_view = get_interprocedural_view();
2977 set_interprocedural_view(1);
2978 dump_vcg_header(f, "All_graphs", NULL);
2980 /* collect nodes in all irgs reachable in call graph*/
2981 for (i = get_irp_n_irgs() - 1; i >= 0; --i)
2982 ird_set_irg_link(get_irp_irg(i), NULL);
2984 cg_walk(clear_link, collect_node, NULL);
2986 /* dump all graphs */
2987 for (i = get_irp_n_irgs() - 1; i >= 0; --i) {
2988 current_ir_graph = get_irp_irg(i);
2989 assert(ird_get_irg_link(current_ir_graph));
2990 dump_graph_from_list(f, current_ir_graph);
2991 DEL_ARR_F(ird_get_irg_link(current_ir_graph));
2996 set_interprocedural_view(rem_view);
3001 /*---------------------------------------------------------------------*/
3002 /* the following routines dumps type information without any ir nodes. */
3003 /*---------------------------------------------------------------------*/
3005 void dump_type_graph(ir_graph *irg, const char *suffix)
3009 /* if a filter is set, dump only the irg's that match the filter */
3010 if (!is_filtered_dump_name(get_entity_ident(get_irg_entity(irg)))) return;
3012 f = vcg_open(irg, suffix, "-type");
3014 ir_graph *rem = current_ir_graph;
3015 current_ir_graph = irg;
3017 dump_vcg_header(f, get_irg_dump_name(irg), "Hierarchic", NULL);
3019 /* walk over the blocks in the graph */
3020 type_walk_irg(irg, dump_type_info, NULL, f);
3021 /* The walker for the const code can be called several times for the
3022 same (sub) expression. So that no nodes are dumped several times
3023 we decrease the visited flag of the corresponding graph after each
3024 walk. So now increase it finally. */
3025 inc_irg_visited(get_const_code_irg());
3029 current_ir_graph = rem;
3033 void dump_all_types(const char *suffix)
3035 FILE *f = vcg_open_name("All_types", suffix);
3037 dump_vcg_header(f, "All_types", "Hierarchic", NULL);
3038 type_walk(dump_type_info, NULL, f);
3039 inc_irg_visited(get_const_code_irg());
3046 void dump_class_hierarchy(int entities, const char *suffix)
3048 FILE *f = vcg_open_name("class_hierarchy", suffix);
3053 env.dump_ent = entities;
3054 dump_vcg_header(f, "class_hierarchy", "Hierarchic", NULL);
3055 type_walk(dump_class_hierarchy_node, NULL, &env);
3062 /*---------------------------------------------------------------------*/
3063 /* dumps all graphs with the graph-dumper passed. Possible dumpers: */
3065 /* dump_ir_block_graph */
3067 /* dump_type_graph */
3068 /* dump_ir_graph_w_types */
3069 /*---------------------------------------------------------------------*/
3071 void dump_all_ir_graphs(dump_graph_func *dmp_grph, const char *suffix)
3074 for (i = get_irp_n_irgs() - 1; i >= 0; --i)
3075 dmp_grph(get_irp_irg(i), suffix);
3079 ir_prog_pass_t pass;
3080 dump_graph_func *dump_graph;
3085 * Wrapper around dump_all_ir_graphs().
3087 static int dump_all_ir_graphs_wrapper(ir_prog *irp, void *context)
3089 struct pass_t *pass = context;
3092 dump_all_ir_graphs(pass->dump_graph, pass->suffix);
3096 ir_prog_pass_t *dump_all_ir_graph_pass(const char *name,
3097 dump_graph_func *dump_graph,
3100 size_t len = strlen(suffix);
3101 struct pass_t *pass = xmalloc(sizeof(*pass) + len);
3102 ir_prog_pass_t *res = def_prog_pass_constructor(
3103 &pass->pass, name ? name : "dump_all_graphs", dump_all_ir_graphs_wrapper);
3105 /* this pass does not change anything, so neither dump nor verify is needed. */
3106 res->dump_irprog = ir_prog_no_dump;
3107 res->verify_irprog = ir_prog_no_verify;
3109 pass->dump_graph = dump_graph;
3110 strcpy(pass->suffix, suffix);
3115 /*--------------------------------------------------------------------------------*
3116 * Dumps a stand alone loop graph with firm nodes which belong to one loop node *
3117 * packed together in one subgraph/box *
3118 *--------------------------------------------------------------------------------*/
3120 static void dump_loops_standalone(FILE *F, ir_loop *loop)
3122 int i = 0, loop_node_started = 0, son_number = 0, first = 0;
3124 ir_loop *son = NULL;
3126 /* Dump a new loop node. */
3127 dump_loop_node(F, loop);
3129 /* Dump the loop elements. */
3130 for (i = 0; i < get_loop_n_elements(loop); i++) {
3131 le = get_loop_element(loop, i);
3133 if (get_kind(son) == k_ir_loop) {
3135 /* We are a loop son -> Recurse */
3137 if (loop_node_started) { /* Close the "firm-nodes" node first if we started one. */
3138 fprintf(F, "\" }\n");
3139 fprintf(F, "edge: {sourcename: \"");
3141 fprintf(F, "\" targetname: \"");
3143 fprintf(F, "-%d-nodes\" label:\"%d...%d\"}\n", first, first, i-1);
3144 loop_node_started = 0;
3146 dump_loop_son_edge(F, loop, son_number++);
3147 dump_loops_standalone(F, son);
3148 } else if (get_kind(son) == k_ir_node) {
3149 /* We are a loop node -> Collect firm nodes */
3151 ir_node *n = le.node;
3154 if (!loop_node_started) {
3155 /* Start a new node which contains all firm nodes of the current loop */
3156 fprintf(F, "node: { title: \"");
3158 fprintf(F, "-%d-nodes\" color: lightyellow label: \"", i);
3159 loop_node_started = 1;
3164 bad |= dump_node_label(F, n);
3165 /* Causes indeterministic output: if (is_Block(n)) fprintf(F, "\t ->%d", (int)get_irn_link(n)); */
3166 if (has_backedges(n)) fprintf(F, "\t loop head!");
3167 } else { /* for callgraph loop tree */
3169 assert(get_kind(son) == k_ir_graph);
3171 /* We are a loop node -> Collect firm graphs */
3173 if (!loop_node_started) {
3174 /* Start a new node which contains all firm nodes of the current loop */
3175 fprintf(F, "node: { title: \"");
3177 fprintf(F, "-%d-nodes\" color: lightyellow label: \"", i);
3178 loop_node_started = 1;
3182 fprintf(F, " %s", get_irg_dump_name(n));
3183 /* fprintf(F, " %s (depth %d)", get_irg_dump_name(n), n->callgraph_weighted_loop_depth); */
3187 if (loop_node_started) {
3188 fprintf(F, "\" }\n");
3189 fprintf(F, "edge: {sourcename: \"");
3191 fprintf(F, "\" targetname: \"");
3193 fprintf(F, "-%d-nodes\" label:\"%d...%d\"}\n", first, first, i-1);
3194 loop_node_started = 0;
3198 void dump_loop_tree(ir_graph *irg, const char *suffix)
3202 /* if a filter is set, dump only the irg's that match the filter */
3203 if (!is_filtered_dump_name(get_entity_ident(get_irg_entity(irg))))
3206 f = vcg_open(irg, suffix, "-looptree");
3208 ir_graph *rem = current_ir_graph;
3209 int el_rem = edge_label;
3211 current_ir_graph = irg;
3214 dump_vcg_header(f, get_irg_dump_name(irg), "Tree", "top_to_bottom");
3216 if (get_irg_loop(irg))
3217 dump_loops_standalone(f, get_irg_loop(irg));
3222 edge_label = el_rem;
3223 current_ir_graph = rem;
3227 void dump_callgraph_loop_tree(const char *suffix)
3230 F = vcg_open_name("Callgraph_looptree", suffix);
3231 dump_vcg_header(F, "callgraph looptree", "Tree", "top_to_bottom");
3232 dump_loops_standalone(F, irp->outermost_cg_loop);
3238 /*----------------------------------------------------------------------------*/
3239 /* Dumps the firm nodes in the loop tree to a graph along with the loop nodes.*/
3240 /*----------------------------------------------------------------------------*/
3242 static void collect_nodeloop(FILE *F, ir_loop *loop, eset *loopnodes)
3244 int i, son_number = 0, node_number = 0;
3246 if (dump_loop_information_flag) dump_loop_node(F, loop);
3248 for (i = 0; i < get_loop_n_elements(loop); i++) {
3249 loop_element le = get_loop_element(loop, i);
3250 if (*(le.kind) == k_ir_loop) {
3251 if (dump_loop_information_flag) dump_loop_son_edge(F, loop, son_number++);
3253 collect_nodeloop(F, le.son, loopnodes);
3255 if (dump_loop_information_flag) dump_loop_node_edge(F, loop, node_number++);
3256 eset_insert(loopnodes, le.node);
3261 static void collect_nodeloop_external_nodes(ir_loop *loop, eset *loopnodes,
3266 for (i = 0; i < get_loop_n_elements(loop); i++) {
3267 loop_element le = get_loop_element(loop, i);
3268 if (*(le.kind) == k_ir_loop) {
3270 collect_nodeloop_external_nodes(le.son, loopnodes, extnodes);
3272 if (is_Block(le.node)) start = 0; else start = -1;
3273 for (j = start; j < get_irn_arity(le.node); j++) {
3274 ir_node *pred = get_irn_n(le.node, j);
3275 if (!eset_contains(loopnodes, pred)) {
3276 eset_insert(extnodes, pred);
3277 if (!is_Block(pred)) {
3278 pred = get_nodes_block(pred);
3279 if (!eset_contains(loopnodes, pred)) eset_insert(extnodes, pred);
3287 void dump_loop(ir_loop *l, const char *suffix)
3292 snprintf(name, sizeof(name), "loop_%d", get_loop_loop_nr(l));
3293 F = vcg_open_name(name, suffix);
3295 eset *loopnodes = eset_create();
3296 eset *extnodes = eset_create();
3299 dump_vcg_header(F, name, NULL, NULL);
3301 /* collect all nodes to dump */
3302 collect_nodeloop(F, l, loopnodes);
3303 collect_nodeloop_external_nodes(l, loopnodes, extnodes);
3305 /* build block lists */
3306 for (n = eset_first(loopnodes); n != NULL; n = eset_next(loopnodes))
3307 set_irn_link(n, NULL);
3308 for (n = eset_first(extnodes); n != NULL; n = eset_next(extnodes))
3309 set_irn_link(n, NULL);
3310 for (n = eset_first(loopnodes); n != NULL; n = eset_next(loopnodes)) {
3312 b = get_nodes_block(n);
3313 set_irn_link(n, get_irn_link(b));
3317 for (n = eset_first(extnodes); n != NULL; n = eset_next(extnodes)) {
3319 b = get_nodes_block(n);
3320 set_irn_link(n, get_irn_link(b));
3325 for (b = eset_first(loopnodes); b != NULL; b = eset_next(loopnodes)) {
3327 fprintf(F, "graph: { title: \"");
3329 fprintf(F, "\" label: \"");
3330 dump_node_opcode(F, b);
3331 fprintf(F, " %ld:%d", get_irn_node_nr(b), get_irn_idx(b));
3332 fprintf(F, "\" status:clustered color:yellow\n");
3334 /* dump the blocks edges */
3335 dump_ir_data_edges(F, b);
3337 /* dump the nodes that go into the block */
3338 for (n = get_irn_link(b); n; n = get_irn_link(n)) {
3339 if (eset_contains(extnodes, n))
3340 overrule_nodecolor = ird_color_block_inout;
3342 overrule_nodecolor = ird_color_default_node;
3343 if (!eset_contains(extnodes, n)) dump_ir_data_edges(F, n);
3346 /* Close the vcg information for the block */
3348 dump_const_node_local(F, b);
3352 for (b = eset_first(extnodes); b != NULL; b = eset_next(extnodes)) {
3354 fprintf(F, "graph: { title: \"");
3356 fprintf(F, "\" label: \"");
3357 dump_node_opcode(F, b);
3358 fprintf(F, " %ld:%d", get_irn_node_nr(b), get_irn_idx(b));
3359 fprintf(F, "\" status:clustered color:lightblue\n");
3361 /* dump the nodes that go into the block */
3362 for (n = get_irn_link(b); n; n = get_irn_link(n)) {
3363 if (!eset_contains(loopnodes, n))
3364 overrule_nodecolor = ird_color_block_inout;
3366 overrule_nodecolor = ird_color_default_node;
3367 if (eset_contains(loopnodes, n)) dump_ir_data_edges(F, n);
3370 /* Close the vcg information for the block */
3372 dump_const_node_local(F, b);
3376 eset_destroy(loopnodes);
3377 eset_destroy(extnodes);