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"
64 /** Dump only irgs with names that start with this prefix. */
65 static ident *dump_file_filter_id = NULL;
67 #define ERROR_TXT "<ERROR>"
69 /*******************************************************************/
70 /* flags to steer output */
71 /*******************************************************************/
73 /** An option to turn off edge labels */
74 static int edge_label = 1;
75 /** An option to turn off dumping values of constant entities */
76 static int const_entities = 1;
77 /** An option to dump the keep alive edges */
78 static int dump_keepalive = 1;
79 /** An option to dump the new out edges */
80 static int dump_new_edges_flag = 0;
81 /** An option to dump ld_names instead of names. */
82 static int dump_ld_name = 1;
83 /** Compiler options to dump analysis information in dump_ir_graph */
84 static int dump_out_edge_flag = 0;
85 static int dump_loop_information_flag = 0;
86 static int dump_backedge_information_flag = 1;
87 /** An option to dump const-like nodes locally. */
88 static int dump_const_local = 1;
89 /** An option to dump the node index number. */
90 static int dump_node_idx_labels = 0;
91 /** An option to dump all graph anchors */
92 static int dump_anchors = 0;
93 /** An option to dump the macro block edges. */
94 static int dump_macro_block_edges = 0;
95 /** An option to dump block marker in the block title */
96 static int dump_block_marker = 0;
98 int dump_dominator_information_flag = 0;
99 int opt_dump_analysed_type_info = 1;
100 int opt_dump_pointer_values_to_info = 0; /* default off: for test compares!! */
102 static ird_color_t overrule_nodecolor = ird_color_default_node;
104 /** The vcg node attribute hook. */
105 static DUMP_IR_GRAPH_FUNC dump_ir_graph_hook = NULL;
106 /** The vcg node attribute hook. */
107 static DUMP_NODE_VCGATTR_FUNC dump_node_vcgattr_hook = NULL;
108 /** The vcg edge attribute hook. */
109 static DUMP_EDGE_VCGATTR_FUNC dump_edge_vcgattr_hook = NULL;
110 /** The vcg dump block edge hook */
111 static DUMP_NODE_EDGE_FUNC dump_block_edge_hook = NULL;
112 /** The vcg dump node edge hook. */
113 static DUMP_NODE_EDGE_FUNC dump_node_edge_hook = NULL;
115 /* Set the hook to be called to dump additional edges to a node. */
116 void set_dump_node_edge_hook(DUMP_NODE_EDGE_FUNC func)
118 dump_node_edge_hook = func;
121 /* Get the additional edge dump hook. */
122 DUMP_NODE_EDGE_FUNC get_dump_node_edge_hook(void)
124 return dump_node_edge_hook;
127 /* Set the hook to be called to dump additional edges to a block. */
128 void set_dump_block_edge_hook(DUMP_NODE_EDGE_FUNC func)
130 dump_block_edge_hook = func;
133 /* Get the additional block edge dump hook. */
134 DUMP_NODE_EDGE_FUNC get_dump_block_edge_hook(void)
136 return dump_node_edge_hook;
139 /* set the ir graph hook */
140 void set_dump_ir_graph_hook(DUMP_IR_GRAPH_FUNC hook)
142 dump_ir_graph_hook = hook;
145 /* set the node attribute hook */
146 void set_dump_node_vcgattr_hook(DUMP_NODE_VCGATTR_FUNC hook)
148 dump_node_vcgattr_hook = hook;
151 /* set the edge attribute hook */
152 void set_dump_edge_vcgattr_hook(DUMP_EDGE_VCGATTR_FUNC hook)
154 dump_edge_vcgattr_hook = hook;
157 /** Returns 0 if dump_out_edge_flag or dump_loop_information_flag
158 * are set, else returns dump_const_local_flag.
160 static int get_opt_dump_const_local(void)
162 if (dump_out_edge_flag || dump_loop_information_flag || (dump_new_edges_flag && edges_activated(current_ir_graph)))
164 return dump_const_local;
167 /* Set a prefix filter for output functions. */
168 void only_dump_method_with_name(ident *name)
170 dump_file_filter_id = name;
173 /* Returns the prefix filter set with only_dump_method_with_name(). */
174 ident *get_dump_file_filter_ident(void)
176 return dump_file_filter_id;
179 /* Returns non-zero if dump file filter is not set, or if it is a prefix of name. */
180 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)
193 void dump_consts_local(int flag)
195 dump_const_local = flag;
198 void dump_node_idx_label(int flag)
200 dump_node_idx_labels = flag;
203 void dump_constant_entity_values(int flag)
205 const_entities = flag;
208 void dump_keepalive_edges(int flag)
210 dump_keepalive = flag;
213 void dump_new_edges(int flag)
215 dump_new_edges_flag = flag;
218 int get_opt_dump_keepalive_edges(void)
220 return dump_keepalive;
223 void dump_out_edges(int flag)
225 dump_out_edge_flag = flag;
228 void dump_dominator_information(int flag)
230 dump_dominator_information_flag = flag;
233 void dump_loop_information(int flag)
235 dump_loop_information_flag = flag;
238 void dump_backedge_information(int flag)
240 dump_backedge_information_flag = flag;
243 /* Dump the information of type field specified in ana/irtypeinfo.h.
244 * If the flag is set, the type name is output in [] in the node label,
245 * else it is output as info.
247 void set_opt_dump_analysed_type_info(int flag)
249 opt_dump_analysed_type_info = flag;
252 void dump_pointer_values_to_info(int flag)
254 opt_dump_pointer_values_to_info = flag;
257 void dump_ld_names(int flag)
262 void dump_all_anchors(int flag)
267 void dump_macroblock_edges(int flag)
269 dump_macro_block_edges = flag;
272 void dump_block_marker_in_title(int flag)
274 dump_block_marker = flag;
277 /* -------------- some extended helper functions ----------------- */
280 * returns the name of a mode or ERROR_TXT if mode is NOT a mode object.
281 * in the later case, sets bad.
283 const char *get_mode_name_ex(const ir_mode *mode, int *bad)
286 return get_mode_name(mode);
291 #define CUSTOM_COLOR_BASE 100
292 static const char *color_names[ird_color_count];
293 static const char *color_rgb[ird_color_count];
294 static struct obstack color_obst;
296 /** define a custom color. */
297 static void custom_color(int num, const char *rgb_def)
299 assert(num < ird_color_count);
300 obstack_printf(&color_obst, "%d", CUSTOM_COLOR_BASE + num);
301 obstack_1grow(&color_obst, '\0');
303 color_rgb[num] = rgb_def;
304 color_names[num] = obstack_finish(&color_obst);
307 /** Define a named color. */
308 static void named_color(int num, const char *name)
310 assert(num < ird_color_count);
311 color_rgb[num] = NULL;
312 color_names[num] = name;
315 /** Initializes the used colors. */
316 static void init_colors(void)
318 static int initialized = 0;
322 obstack_init(&color_obst);
324 custom_color(ird_color_prog_background, "204 204 204");
325 custom_color(ird_color_block_background, "255 255 0");
326 custom_color(ird_color_dead_block_background, "190 150 150");
327 named_color(ird_color_block_inout, "lightblue");
328 named_color(ird_color_default_node, "white");
329 custom_color(ird_color_memory, "153 153 255");
330 custom_color(ird_color_controlflow, "255 153 153");
331 custom_color(ird_color_const, "204 255 255");
332 custom_color(ird_color_proj, "255 255 153");
333 custom_color(ird_color_uses_memory, "153 153 255");
334 custom_color(ird_color_phi, "105 255 105");
335 custom_color(ird_color_anchor, "100 100 255");
336 named_color(ird_color_error, "red");
337 custom_color(ird_color_entity, "204 204 255");
343 * Prints the VCG color to a file.
345 static void print_vcg_color(FILE *F, ird_color_t color)
347 assert(color < ird_color_count);
348 fprintf(F, "color:%s", color_names[color]);
352 * Prints the edge kind of a given IR node.
354 * Projs should be dumped near their predecessor, so they get "nearedge".
356 static void print_node_edge_kind(FILE *F, ir_node *node)
359 fprintf(F, "nearedge: ");
361 fprintf(F, "edge: ");
366 * Prints the edge from a type S to a type T with additional info fmt, ...
369 static void print_type_type_edge(FILE *F, const ir_type *S, const ir_type *T, const char *fmt, ...)
374 fprintf(F, "edge: { sourcename: "); PRINT_TYPEID(S);
375 fprintf(F, " targetname: "); PRINT_TYPEID(T);
376 vfprintf(F, fmt, ap);
382 * Prints the edge from a type tp to an entity ent with additional info fmt, ...
385 static void print_type_ent_edge(FILE *F, const ir_type *tp, const ir_entity *ent, const char *fmt, ...)
390 fprintf(F, "edge: { sourcename: "); PRINT_TYPEID(tp);
391 fprintf(F, " targetname: \""); PRINT_ENTID(ent); fprintf(F, "\"");
392 vfprintf(F, fmt, ap);
398 * Prints the edge from an entity ent1 to an entity ent2 with additional info fmt, ...
401 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, ...)
407 fprintf(F, "backedge: { sourcename: \"");
409 fprintf(F, "edge: { sourcename: \"");
411 fprintf(F, "\" targetname: \""); PRINT_ENTID(ent2); fprintf(F, "\"");
412 vfprintf(F, fmt, ap);
414 if (color != (ird_color_t) -1)
415 print_vcg_color(F, color);
421 * Prints the edge from an entity ent to a type tp with additional info fmt, ...
424 static void print_ent_type_edge(FILE *F, const ir_entity *ent, const ir_type *tp, const char *fmt, ...)
429 fprintf(F, "edge: { sourcename: \""); PRINT_ENTID(ent);
430 fprintf(F, "\" targetname: "); PRINT_TYPEID(tp);
431 vfprintf(F, fmt, ap);
437 * Prints the edge from a node irn to a type tp with additional info fmt, ...
440 static void print_node_type_edge(FILE *F, const ir_node *irn, ir_type *tp, const char *fmt, ...)
445 fprintf(F, "edge: { sourcename: \""); PRINT_NODEID(irn);
446 fprintf(F, "\" targetname: "); PRINT_TYPEID(tp);
447 vfprintf(F, fmt, ap);
453 * Prints the edge from a node irn to an entity ent with additional info fmt, ...
456 static void print_node_ent_edge(FILE *F, const ir_node *irn, const ir_entity *ent, const char *fmt, ...)
461 fprintf(F, "edge: { sourcename: \""); PRINT_NODEID(irn);
462 fprintf(F, "\" targetname: \""); PRINT_ENTID(ent);
464 vfprintf(F, fmt, ap);
470 * Prints the edge from an entity ent to a node irn with additional info fmt, ...
473 static void print_ent_node_edge(FILE *F, const ir_entity *ent, const ir_node *irn, const char *fmt, ...)
478 fprintf(F, "edge: { sourcename: \""); PRINT_ENTID(ent);
479 fprintf(F, "\" targetname: \""); PRINT_NODEID(irn); fprintf(F, "\"");
480 vfprintf(F, fmt, ap);
486 * Prints the edge from a type tp to an enumeration item item with additional info fmt, ...
489 static void print_enum_item_edge(FILE *F, const ir_type *tp, int item, const char *fmt, ...)
494 fprintf(F, "edge: { sourcename: "); PRINT_TYPEID(tp);
495 fprintf(F, " targetname: \""); PRINT_ITEMID(tp, item); fprintf(F, "\" ");
496 vfprintf(F, fmt, ap);
501 /*-----------------------------------------------------------------*/
502 /* global and ahead declarations */
503 /*-----------------------------------------------------------------*/
505 static void dump_whole_node(ir_node *n, void *env);
506 static inline void dump_loop_nodes_into_graph(FILE *F, ir_graph *irg);
508 /*-----------------------------------------------------------------*/
509 /* Helper functions. */
510 /*-----------------------------------------------------------------*/
513 * This map is used as a private link attr to be able to call dumper
514 * anywhere without destroying link fields.
516 static pmap *irdump_link_map = NULL;
518 /** NOT A STANDARD LIBFIRM INIT METHOD
520 * We do not want to integrate dumping into libfirm, i.e., if the dumpers
521 * are off, we want to have as few interferences as possible. Therefore the
522 * initialization is performed lazily and not called from within init_firm.
524 * Creates the link attribute map. */
525 static void init_irdump(void)
527 /* We need a new, empty map. */
528 if (irdump_link_map) pmap_destroy(irdump_link_map);
529 irdump_link_map = pmap_create();
530 if (!dump_file_filter_id)
531 dump_file_filter_id = new_id_from_str("");
535 * Returns the private link field.
537 static void *ird_get_irn_link(const ir_node *n)
540 if (irdump_link_map == NULL)
543 if (pmap_contains(irdump_link_map, n))
544 res = pmap_get(irdump_link_map, n);
549 * Sets the private link field.
551 static void ird_set_irn_link(const ir_node *n, void *x)
553 if (irdump_link_map == NULL)
555 pmap_insert(irdump_link_map, n, x);
559 * Gets the private link field of an irg.
561 static void *ird_get_irg_link(const ir_graph *irg)
564 if (irdump_link_map == NULL)
567 if (pmap_contains(irdump_link_map, irg))
568 res = pmap_get(irdump_link_map, irg);
573 * Sets the private link field of an irg.
575 static void ird_set_irg_link(const ir_graph *irg, void *x)
577 if (irdump_link_map == NULL)
579 pmap_insert(irdump_link_map, irg, x);
583 * Walker, clears the private link field.
585 static void clear_link(ir_node *node, void *env)
588 ird_set_irn_link(node, NULL);
592 * If the entity has a ld_name, returns it if the dump_ld_name is set,
593 * else returns the name of the entity.
595 static const char *_get_ent_dump_name(const ir_entity *ent, int dump_ld_name)
598 return "<NULL entity>";
600 /* Don't use get_entity_ld_ident (ent) as it computes the mangled name! */
601 if (ent->ld_name != NULL)
602 return get_id_str(ent->ld_name);
604 return get_id_str(ent->name);
608 * If the entity has a ld_name, returns it if the option dump_ld_name is set,
609 * else returns the name of the entity.
611 const char *get_ent_dump_name(const ir_entity *ent)
613 return _get_ent_dump_name(ent, dump_ld_name);
616 /* Returns the name of an IRG. */
617 const char *get_irg_dump_name(const ir_graph *irg)
619 /* Don't use get_entity_ld_ident (ent) as it computes the mangled name! */
620 return _get_ent_dump_name(get_irg_entity(irg), 1);
624 * Returns non-zero if a node is in floating state.
626 static int node_floats(const ir_node *n)
628 return ((get_irn_pinned(n) == op_pin_state_floats) &&
629 (get_irg_pinned(current_ir_graph) == op_pin_state_floats));
633 * Walker that visits the anchors
635 static void ird_walk_graph(ir_graph *irg, irg_walk_func *pre, irg_walk_func *post, void *env)
637 if (dump_anchors || (dump_new_edges_flag && edges_activated(irg))) {
638 irg_walk_anchors(irg, pre, post, env);
640 irg_walk_graph(irg, pre, post, env);
645 * Walker, allocates an array for all blocks and puts it's nodes non-floating nodes into this array.
647 static void collect_node(ir_node *node, void *env)
652 || (get_op_flags(get_irn_op(node)) & irop_flag_dump_noblock)) {
653 ir_node ** arr = (ir_node **) ird_get_irg_link(get_irn_irg(node));
654 if (!arr) arr = NEW_ARR_F(ir_node *, 0);
655 ARR_APP1(ir_node *, arr, node);
656 ird_set_irg_link(get_irn_irg(node), arr); /* arr is an l-value, APP_ARR might change it! */
658 ir_node * block = get_nodes_block(node);
661 /* this node is in a Bad block, so we must place it into the graph's list */
662 ir_node ** arr = (ir_node **) ird_get_irg_link(get_irn_irg(node));
663 if (!arr) arr = NEW_ARR_F(ir_node *, 0);
664 ARR_APP1(ir_node *, arr, node);
665 ird_set_irg_link(get_irn_irg(node), arr); /* arr is an l-value, APP_ARR might change it! */
667 ird_set_irn_link(node, ird_get_irn_link(block));
668 ird_set_irn_link(block, node);
673 /** Construct lists to walk ir block-wise.
675 * Collects all blocks, nodes not op_pin_state_pinned,
676 * Bad, NoMem and Unknown into a flexible array in link field of
677 * irg they belong to. Sets the irg link field to NULL in all
678 * graphs not visited.
679 * Free the list with DEL_ARR_F().
681 static ir_node **construct_block_lists(ir_graph *irg)
684 #ifdef INTERPROCEDURAL_VIEW
685 int rem_view = get_interprocedural_view();
687 int walk_flag = ir_resources_reserved(irg) & IR_RESOURCE_IRN_VISITED;
688 ir_graph *rem = current_ir_graph;
690 current_ir_graph = irg;
693 ir_free_resources(irg, IR_RESOURCE_IRN_VISITED);
696 for (i = get_irp_n_irgs() - 1; i >= 0; --i)
697 ird_set_irg_link(get_irp_irg(i), NULL);
699 ird_walk_graph(current_ir_graph, clear_link, collect_node, current_ir_graph);
701 #ifdef INTERPROCEDURAL_VIEW
702 /* Collect also EndReg and EndExcept. We do not want to change the walker. */
703 set_interprocedural_view(0);
706 set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph)-1);
707 irg_walk(get_irg_end_reg(current_ir_graph), clear_link, collect_node, current_ir_graph);
708 set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph)-1);
709 irg_walk(get_irg_end_except(current_ir_graph), clear_link, collect_node, current_ir_graph);
711 #ifdef INTERPROCEDURAL_VIEW
712 set_interprocedural_view(rem_view);
716 ir_reserve_resources(irg, IR_RESOURCE_IRN_VISITED);
719 current_ir_graph = rem;
720 return ird_get_irg_link(irg);
723 typedef struct _list_tuple {
725 ir_extblk **extbb_list;
728 /** Construct lists to walk IR extended block-wise.
729 * Free the lists in the tuple with DEL_ARR_F().
730 * Sets the irg link field to NULL in all
731 * graphs not visited.
733 static list_tuple *construct_extblock_lists(ir_graph *irg)
735 ir_node **blk_list = construct_block_lists(irg);
737 ir_graph *rem = current_ir_graph;
738 list_tuple *lists = XMALLOC(list_tuple);
740 current_ir_graph = irg;
742 lists->blk_list = NEW_ARR_F(ir_node *, 0);
743 lists->extbb_list = NEW_ARR_F(ir_extblk *, 0);
745 inc_irg_block_visited(irg);
746 for (i = ARR_LEN(blk_list) - 1; i >= 0; --i) {
749 if (is_Block(blk_list[i])) {
750 ext = get_Block_extbb(blk_list[i]);
752 if (extbb_not_visited(ext)) {
753 ARR_APP1(ir_extblk *, lists->extbb_list, ext);
754 mark_extbb_visited(ext);
757 ARR_APP1(ir_node *, lists->blk_list, blk_list[i]);
761 current_ir_graph = rem;
762 ird_set_irg_link(irg, lists);
766 /*-----------------------------------------------------------------*/
767 /* Routines to dump information about a single ir node. */
768 /*-----------------------------------------------------------------*/
771 * dump the name of a node n to the File F.
773 int dump_node_opcode(FILE *F, ir_node *n)
776 const ir_op_ops *ops = get_op_ops(get_irn_op(n));
778 /* call the dump_node operation if available */
780 return ops->dump_node(n, F, dump_node_opcode_txt);
782 /* implementation for default nodes */
783 switch (get_irn_opcode(n)) {
785 switch (get_SymConst_kind(n)) {
786 case symconst_addr_ent:
787 fprintf(F, "SymC &%s", get_entity_name(get_SymConst_entity(n)));
789 case symconst_ofs_ent:
790 fprintf(F, "SymC %s offset", get_entity_name(get_SymConst_entity(n)));
792 case symconst_type_tag:
793 ir_fprintf(F, "SymC %+F tag", get_SymConst_type(n));
795 case symconst_type_size:
796 ir_fprintf(F, "SymC %+F size", get_SymConst_type(n));
798 case symconst_type_align:
799 ir_fprintf(F, "SymC %+F align", get_SymConst_type(n));
801 case symconst_enum_const:
802 fprintf(F, "SymC %s enum", get_enumeration_const_name(get_SymConst_enum(n)));
807 #ifdef INTERPROCEDURAL_VIEW
809 if (!get_interprocedural_view())
817 ir_node *pred = get_Proj_pred(n);
819 if (get_irn_opcode(pred) == iro_Cond
820 && get_Proj_proj(n) == get_Cond_default_proj(pred)
821 && get_irn_mode(get_Cond_selector(pred)) != mode_b)
822 fprintf(F, "defProj");
827 #ifdef INTERPROCEDURAL_VIEW
832 if (get_interprocedural_view()) {
833 fprintf(F, "%s %s", get_irn_opname(n), get_ent_dump_name(get_irg_entity(get_irn_irg(n))));
839 case iro_CallBegin: {
840 ir_node *addr = get_CallBegin_ptr(n);
841 ir_entity *ent = NULL;
843 ent = get_Sel_entity(addr);
844 else if (is_Global(addr))
845 ent = get_Global_entity(addr);
846 fprintf(F, "%s", get_irn_opname(n));
847 if (ent) fprintf(F, " %s", get_entity_name(ent));
851 if (get_Load_align(n) == align_non_aligned)
853 fprintf(F, "%s[%s]", get_irn_opname(n), get_mode_name_ex(get_Load_mode(n), &bad));
856 if (get_Store_align(n) == align_non_aligned)
858 fprintf(F, "%s", get_irn_opname(n));
861 if (is_Block_dead(n))
863 if (n == get_irg_start_block(get_irn_irg(n)))
865 if (n == get_irg_end_block(get_irn_irg(n)))
867 fprintf(F, "%s%s", get_irn_opname(n),
868 dump_block_marker ? (get_Block_mark(n) ? "*" : "") : "");
871 if (get_Conv_strict(n))
872 fprintf(F, "strict");
873 fprintf(F, "%s", get_irn_opname(n));
876 fprintf(F, "%s", get_irn_opname(n));
877 if (get_Div_no_remainder(n))
879 fprintf(F, "[%s]", get_mode_name_ex(get_Div_resmode(n), &bad));
882 fprintf(F, "%s[%s]", get_irn_opname(n), get_mode_name_ex(get_Mod_resmode(n), &bad));
885 fprintf(F, "%s[%s]", get_irn_opname(n), get_mode_name_ex(get_DivMod_resmode(n), &bad));
888 fprintf(F, "%s[%s]", get_irn_opname(n), get_builtin_kind_name(get_Builtin_kind(n)));
893 fprintf(F, "%s", get_irn_opname(n));
900 * Dump the mode of a node n to a file F.
901 * Ignore modes that are "always known".
903 static int dump_node_mode(FILE *F, ir_node *n)
906 const ir_op_ops *ops = get_op_ops(get_irn_op(n));
910 /* call the dump_node operation if available */
912 return ops->dump_node(n, F, dump_node_mode_txt);
914 /* default implementation */
915 iro = get_irn_opcode(n);
927 mode = get_irn_mode(n);
929 if (mode != NULL && mode != mode_BB && mode != mode_ANY && mode != mode_BAD &&
930 (mode != mode_T || iro == iro_Proj))
931 fprintf(F, "%s", get_mode_name_ex(mode, &bad));
937 * Dump the type of a node n to a file F if it's known.
939 static int dump_node_typeinfo(FILE *F, ir_node *n)
943 if (opt_dump_analysed_type_info) {
944 if (get_irg_typeinfo_state(current_ir_graph) == ir_typeinfo_consistent ||
945 get_irg_typeinfo_state(current_ir_graph) == ir_typeinfo_inconsistent) {
946 ir_type *tp = get_irn_typeinfo_type(n);
947 if (tp != firm_none_type) {
948 ir_fprintf(F, "[%+F]", tp);
957 typedef struct _pns_lookup {
958 long nr; /**< the proj number */
959 const char *name; /**< the name of the Proj */
962 typedef struct _proj_lookup {
963 ir_opcode code; /**< the opcode of the Proj predecessor */
964 unsigned num_data; /**< number of data entries */
965 const pns_lookup_t *data; /**< the data */
968 #define ARR_SIZE(a) (sizeof(a)/sizeof(a[0]))
970 /** the lookup table for Proj(Start) names */
971 static const pns_lookup_t start_lut[] = {
972 #define X(a) { pn_Start_##a, #a }
980 /** the lookup table for Proj(Cond) names */
981 static const pns_lookup_t cond_lut[] = {
982 #define X(a) { pn_Cond_##a, #a }
988 /** the lookup table for Proj(Call) names */
989 static const pns_lookup_t call_lut[] = {
990 #define X(a) { pn_Call_##a, #a }
999 /** the lookup table for Proj(Quot) names */
1000 static const pns_lookup_t quot_lut[] = {
1001 #define X(a) { pn_Quot_##a, #a }
1009 /** the lookup table for Proj(DivMod) names */
1010 static const pns_lookup_t divmod_lut[] = {
1011 #define X(a) { pn_DivMod_##a, #a }
1020 /** the lookup table for Proj(Div) names */
1021 static const pns_lookup_t div_lut[] = {
1022 #define X(a) { pn_Div_##a, #a }
1030 /** the lookup table for Proj(Mod) names */
1031 static const pns_lookup_t mod_lut[] = {
1032 #define X(a) { pn_Mod_##a, #a }
1040 /** the lookup table for Proj(Load) names */
1041 static const pns_lookup_t load_lut[] = {
1042 #define X(a) { pn_Load_##a, #a }
1050 /** the lookup table for Proj(Store) names */
1051 static const pns_lookup_t store_lut[] = {
1052 #define X(a) { pn_Store_##a, #a }
1059 /** the lookup table for Proj(Alloc) names */
1060 static const pns_lookup_t alloc_lut[] = {
1061 #define X(a) { pn_Alloc_##a, #a }
1069 /** the lookup table for Proj(CopyB) names */
1070 static const pns_lookup_t copyb_lut[] = {
1071 #define X(a) { pn_CopyB_##a, #a }
1078 /** the lookup table for Proj(InstOf) names */
1079 static const pns_lookup_t instof_lut[] = {
1080 #define X(a) { pn_InstOf_##a, #a }
1088 /** the lookup table for Proj(Raise) names */
1089 static const pns_lookup_t raise_lut[] = {
1090 #define X(a) { pn_Raise_##a, #a }
1096 /** the lookup table for Proj(Bound) names */
1097 static const pns_lookup_t bound_lut[] = {
1098 #define X(a) { pn_Bound_##a, #a }
1106 /** the Proj lookup table */
1107 static const proj_lookup_t proj_lut[] = {
1108 #define E(a) ARR_SIZE(a), a
1109 { iro_Start, E(start_lut) },
1110 { iro_Cond, E(cond_lut) },
1111 { iro_Call, E(call_lut) },
1112 { iro_Quot, E(quot_lut) },
1113 { iro_DivMod, E(divmod_lut) },
1114 { iro_Div, E(div_lut) },
1115 { iro_Mod, E(mod_lut) },
1116 { iro_Load, E(load_lut) },
1117 { iro_Store, E(store_lut) },
1118 { iro_Alloc, E(alloc_lut) },
1119 { iro_CopyB, E(copyb_lut) },
1120 { iro_InstOf, E(instof_lut) },
1121 { iro_Raise, E(raise_lut) },
1122 { iro_Bound, E(bound_lut) }
1127 * Dump additional node attributes of some nodes to a file F.
1129 static int dump_node_nodeattr(FILE *F, ir_node *n)
1135 const ir_op_ops *ops = get_op_ops(get_irn_op(n));
1137 /* call the dump_node operation if available */
1139 return ops->dump_node(n, F, dump_node_nodeattr_txt);
1141 switch (get_irn_opcode(n)) {
1143 ir_fprintf(F, "%T ", get_Const_tarval(n));
1147 pred = get_Proj_pred(n);
1148 proj_nr = get_Proj_proj(n);
1149 #ifdef INTERPROCEDURAL_VIEW
1152 code = get_irn_opcode(pred);
1154 if (code == iro_Cmp)
1155 fprintf(F, "%s ", get_pnc_string(get_Proj_proj(n)));
1156 else if (code == iro_Proj && get_irn_opcode(get_Proj_pred(pred)) == iro_Start)
1157 fprintf(F, "Arg %ld ", proj_nr);
1158 else if (code == iro_Cond && get_irn_mode(get_Cond_selector(pred)) != mode_b)
1159 fprintf(F, "%ld ", proj_nr);
1161 unsigned i, j, f = 0;
1163 for (i = 0; i < ARR_SIZE(proj_lut); ++i) {
1164 if (code == proj_lut[i].code) {
1165 for (j = 0; j < proj_lut[i].num_data; ++j) {
1166 if (proj_nr == proj_lut[i].data[j].nr) {
1167 fprintf(F, "%s ", proj_lut[i].data[j].name);
1176 fprintf(F, "%ld ", proj_nr);
1177 if (code == iro_Cond && get_Cond_jmp_pred(pred) != COND_JMP_PRED_NONE) {
1178 if (proj_nr == pn_Cond_false && get_Cond_jmp_pred(pred) == COND_JMP_PRED_FALSE)
1179 fprintf(F, "PRED ");
1180 if (proj_nr == pn_Cond_true && get_Cond_jmp_pred(pred) == COND_JMP_PRED_TRUE)
1181 fprintf(F, "PRED ");
1186 proj_nr = get_Filter_proj(n);
1187 #ifdef INTERPROCEDURAL_VIEW
1188 if (! get_interprocedural_view()) {
1190 pred = get_Filter_pred(n);
1194 fprintf(F, "%ld ", proj_nr);
1197 fprintf(F, "%s ", get_ent_dump_name(get_Sel_entity(n)));
1200 ir_fprintf(F, "(%+F)", get_Cast_type(n));
1203 fprintf(F, "%s ", get_pnc_string(get_Confirm_cmp(n)));
1206 ir_fprintf(F, "(%+F)", get_CopyB_type(n));
1217 #include "execution_frequency.h"
1219 static void dump_node_ana_vals(FILE *F, ir_node *n)
1224 #ifdef INTERPROCEDURAL_VIEW
1225 fprintf(F, " %lf*(%2.0lf + %2.0lf) = %2.0lf ",
1226 get_irn_exec_freq(n),
1227 get_irg_method_execution_frequency(get_irn_irg(n)),
1228 pow(5, get_irg_recursion_depth(get_irn_irg(n))),
1229 get_irn_exec_freq(n) * (get_irg_method_execution_frequency(get_irn_irg(n)) + pow(5, get_irg_recursion_depth(get_irn_irg(n))))
1235 /* Dumps a node label without the enclosing ". */
1236 int dump_node_label(FILE *F, ir_node *n)
1240 bad |= dump_node_opcode(F, n);
1242 bad |= dump_node_mode(F, n);
1244 bad |= dump_node_typeinfo(F, n);
1245 bad |= dump_node_nodeattr(F, n);
1246 if (dump_node_idx_labels) {
1247 fprintf(F, "%ld:%d", get_irn_node_nr(n), get_irn_idx(n));
1249 fprintf(F, "%ld", get_irn_node_nr(n));
1255 /* Dumps the vrp information of a node to a file */
1256 int dump_vrp_info(FILE *F, ir_node *n)
1258 vrp_attr *vrp = vrp_get_info(n);
1263 fprintf(F, "range_type: %d\n", vrp->range_type);
1264 if (vrp->range_type == VRP_RANGE || vrp->range_type ==
1266 ir_fprintf(F, "range_bottom: %F\n",vrp->range_bottom);
1267 ir_fprintf(F, "range_top: %F\n", vrp->range_top);
1269 ir_fprintf(F, "bits_set: %T\n", vrp->bits_set);
1270 ir_fprintf(F, "bits_not_set: %T\n", vrp->bits_not_set);
1276 * Dumps the attributes of a node n into the file F.
1277 * Currently this is only the color of a node.
1279 static void dump_node_vcgattr(FILE *F, ir_node *node, ir_node *local, int bad)
1285 print_vcg_color(F, ird_color_error);
1289 if (dump_node_vcgattr_hook)
1290 if (dump_node_vcgattr_hook(F, node, local))
1293 n = local ? local : node;
1295 if (overrule_nodecolor != ird_color_default_node) {
1296 print_vcg_color(F, overrule_nodecolor);
1300 mode = get_irn_mode(n);
1301 if (mode == mode_M) {
1302 print_vcg_color(F, ird_color_memory);
1305 if (mode == mode_X) {
1306 print_vcg_color(F, ird_color_controlflow);
1310 switch (get_irn_opcode(n)) {
1315 print_vcg_color(F, ird_color_anchor);
1318 print_vcg_color(F, ird_color_error);
1321 if (is_Block_dead(n))
1322 print_vcg_color(F, ird_color_dead_block_background);
1324 print_vcg_color(F, ird_color_block_background);
1327 print_vcg_color(F, ird_color_phi);
1330 print_vcg_color(F, ird_color_memory);
1334 print_vcg_color(F, ird_color_const);
1337 print_vcg_color(F, ird_color_proj);
1340 ir_op *op = get_irn_op(node);
1342 if (is_op_constlike(op)) {
1343 print_vcg_color(F, ird_color_const);
1344 } else if (is_op_uses_memory(op)) {
1345 print_vcg_color(F, ird_color_uses_memory);
1346 } else if (is_op_cfopcode(op) || is_op_forking(op)) {
1347 print_vcg_color(F, ird_color_controlflow);
1349 PRINT_DEFAULT_NODE_ATTR;
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 ir_fprintf(F, " label: \"%s %+F\" info1: \"", get_type_tpop_name(tp), tp);
2065 dump_type_to_file(F, tp, dump_verbosity_max);
2067 print_type_dbg_info(F, get_type_dbg_info(tp));
2068 print_typespecific_vcgattr(F, tp);
2075 static void dump_entity_node(FILE *F, ir_entity *ent)
2077 fprintf(F, "node: {title: \"");
2078 PRINT_ENTID(ent); fprintf(F, "\"");
2079 fprintf(F, DEFAULT_TYPE_ATTRIBUTE);
2080 fprintf(F, "label: ");
2081 fprintf(F, "\"%s\" ", get_ent_dump_name(ent));
2083 print_vcg_color(F, ird_color_entity);
2084 fprintf(F, "\n info1: \"");
2086 dump_entity_to_file(F, ent, dump_verbosity_entattrs | dump_verbosity_entconsts);
2089 print_dbg_info(F, get_entity_dbg_info(ent));
2093 static void dump_enum_item(FILE *F, ir_type *tp, int pos)
2096 ir_enum_const *ec = get_enumeration_const(tp, pos);
2097 ident *id = get_enumeration_const_nameid(ec);
2098 tarval *tv = get_enumeration_value(ec);
2101 tarval_snprintf(buf, sizeof(buf), tv);
2103 strncpy(buf, "<not set>", sizeof(buf));
2104 fprintf(F, "node: {title: \"");
2105 PRINT_ITEMID(tp, pos); fprintf(F, "\"");
2106 fprintf(F, DEFAULT_ENUM_ITEM_ATTRIBUTE);
2107 fprintf(F, "label: ");
2108 fprintf(F, "\"enum item %s\" " ENUM_ITEM_NODE_ATTR, get_id_str(id));
2109 fprintf(F, "\n info1: \"value: %s\"}\n", buf);
2113 * Dumps a new style initializer.
2115 static void dump_entity_initializer(FILE *F, const ir_entity *ent)
2122 /** Dumps a type or entity and it's edges. */
2123 static void dump_type_info(type_or_ent tore, void *env)
2126 int i = 0; /* to shutup gcc */
2128 /* dump this type or entity */
2130 switch (get_kind(tore.ent)) {
2132 ir_entity *ent = tore.ent;
2135 dump_entity_node(F, ent);
2137 /* skip this to reduce graph. Member edge of type is parallel to this edge. *
2138 fprintf(F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
2139 ENT_OWN_EDGE_ATTR "}\n", ent, get_entity_owner(ent));*/
2140 print_ent_type_edge(F,ent, get_entity_type(ent), ENT_TYPE_EDGE_ATTR);
2141 if (is_Class_type(get_entity_owner(ent))) {
2142 for (i = get_entity_n_overwrites(ent) - 1; i >= 0; --i)
2143 print_ent_ent_edge(F,ent, get_entity_overwrites(ent, i), 0, -1, ENT_OVERWRITES_EDGE_ATTR);
2145 /* attached subgraphs */
2146 if (const_entities) {
2147 if (ent->initializer != NULL) {
2148 /* new style initializers */
2149 dump_entity_initializer(F, ent);
2150 } else if (entity_has_compound_ent_values(ent)) {
2151 /* old style compound entity values */
2152 for (i = get_compound_ent_n_values(ent) - 1; i >= 0; --i) {
2153 value = get_compound_ent_value(ent, i);
2155 print_ent_node_edge(F, ent, value, ENT_VALUE_EDGE_ATTR, i);
2156 dump_const_expression(F, value);
2157 print_ent_ent_edge(F, ent, get_compound_ent_value_member(ent, i), 0, -1, ENT_CORR_EDGE_ATTR, i);
2159 fprintf(F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
2160 ENT_CORR_EDGE_ATTR "}\n", GET_ENTID(ent),
2161 get_compound_ent_value_member(ent, i), i);
2170 ir_type *tp = tore.typ;
2171 dump_type_node(F, tp);
2172 /* and now the edges */
2173 switch (get_type_tpop_code(tp)) {
2175 for (i = get_class_n_supertypes(tp) - 1; i >= 0; --i)
2176 print_type_type_edge(F, tp, get_class_supertype(tp, i), TYPE_SUPER_EDGE_ATTR);
2177 for (i = get_class_n_members(tp) - 1; i >= 0; --i)
2178 print_type_ent_edge(F, tp, get_class_member(tp, i), TYPE_MEMBER_EDGE_ATTR);
2181 for (i = get_struct_n_members(tp) - 1; i >= 0; --i)
2182 print_type_ent_edge(F, tp, get_struct_member(tp, i), TYPE_MEMBER_EDGE_ATTR);
2185 for (i = get_method_n_params(tp) - 1; i >= 0; --i)
2186 print_type_type_edge(F, tp, get_method_param_type(tp, i), METH_PAR_EDGE_ATTR,i);
2187 for (i = get_method_n_ress(tp) - 1; i >= 0; --i)
2188 print_type_type_edge(F, tp, get_method_res_type(tp, i), METH_RES_EDGE_ATTR,i);
2191 for (i = get_union_n_members(tp) - 1; i >= 0; --i)
2192 print_type_ent_edge(F, tp, get_union_member(tp, i), UNION_EDGE_ATTR);
2195 print_type_type_edge(F, tp, get_array_element_type(tp), ARR_ELT_TYPE_EDGE_ATTR);
2196 print_type_ent_edge(F, tp, get_array_element_entity(tp), ARR_ENT_EDGE_ATTR);
2197 for (i = get_array_n_dimensions(tp) - 1; i >= 0; --i) {
2198 ir_node *upper = get_array_upper_bound(tp, i);
2199 ir_node *lower = get_array_lower_bound(tp, i);
2200 print_node_type_edge(F, upper, tp, "label: \"upper %d\"", get_array_order(tp, i));
2201 print_node_type_edge(F, lower, tp, "label: \"lower %d\"", get_array_order(tp, i));
2202 dump_const_expression(F, upper);
2203 dump_const_expression(F, lower);
2206 case tpo_enumeration:
2207 for (i = get_enumeration_n_enums(tp) - 1; i >= 0; --i) {
2208 dump_enum_item(F, tp, i);
2209 print_enum_item_edge(F, tp, i, "label: \"item %d\"", i);
2213 print_type_type_edge(F, tp, get_pointer_points_to_type(tp), PTR_PTS_TO_EDGE_ATTR);
2220 break; /* case k_type */
2223 printf(" *** irdump, dump_type_info(l.%i), faulty type.\n", __LINE__);
2224 } /* switch kind_or_entity */
2227 typedef struct _h_env {
2232 /** For dumping class hierarchies.
2233 * Dumps a class type node and a superclass edge.
2234 * If env->dump_ent dumps entities of classes and overwrites edges.
2236 static void dump_class_hierarchy_node(type_or_ent tore, void *ctx)
2240 int i = 0; /* to shutup gcc */
2242 /* dump this type or entity */
2243 switch (get_kind(tore.ent)) {
2245 ir_entity *ent = tore.ent;
2246 if (get_entity_owner(ent) == get_glob_type()) break;
2247 if (!is_Method_type(get_entity_type(ent)))
2249 if (env->dump_ent && is_Class_type(get_entity_owner(ent))) {
2251 dump_entity_node(F, ent);
2253 print_type_ent_edge(F, get_entity_owner(ent), ent, TYPE_MEMBER_EDGE_ATTR);
2254 for (i = get_entity_n_overwrites(ent) - 1; i >= 0; --i)
2255 print_ent_ent_edge(F, get_entity_overwrites(ent, i), ent, 0, -1, ENT_OVERWRITES_EDGE_ATTR);
2260 ir_type *tp = tore.typ;
2261 if (tp == get_glob_type())
2263 switch (get_type_tpop_code(tp)) {
2265 dump_type_node(F, tp);
2266 /* and now the edges */
2267 for (i = get_class_n_supertypes(tp) - 1; i >= 0; --i) {
2268 print_type_type_edge(F,tp,get_class_supertype(tp, i),TYPE_SUPER_EDGE_ATTR);
2273 break; /* case k_type */
2276 printf(" *** irdump, dump_class_hierarchy_node(l.%i), faulty type.\n", __LINE__);
2277 } /* switch kind_or_entity */
2280 /*******************************************************************/
2281 /* dump analysis information that is expressed in graph terms. */
2282 /*******************************************************************/
2284 /* dump out edges */
2285 static void dump_out_edge(ir_node *n, void *env)
2289 for (i = get_irn_n_outs(n) - 1; i >= 0; --i) {
2290 ir_node *succ = get_irn_out(n, i);
2292 print_node_edge_kind(F, succ);
2293 fprintf(F, "{sourcename: \"");
2295 fprintf(F, "\" targetname: \"");
2297 fprintf(F, "\" color: red linestyle: dashed");
2302 static inline void dump_loop_label(FILE *F, ir_loop *loop)
2304 fprintf(F, "loop %d, %d sons, %d nodes",
2305 get_loop_depth(loop), get_loop_n_sons(loop), get_loop_n_nodes(loop));
2308 static inline void dump_loop_info(FILE *F, ir_loop *loop)
2310 fprintf(F, " info1: \"");
2311 fprintf(F, " loop nr: %d", get_loop_loop_nr(loop));
2312 #ifdef DEBUG_libfirm /* GL @@@ debug analyses */
2313 fprintf(F, "\n The loop was analyzed %d times.", PTR_TO_INT(get_loop_link(loop)));
2318 static inline void dump_loop_node(FILE *F, ir_loop *loop)
2320 fprintf(F, "node: {title: \"");
2322 fprintf(F, "\" label: \"");
2323 dump_loop_label(F, loop);
2325 dump_loop_info(F, loop);
2329 static inline void dump_loop_node_edge(FILE *F, ir_loop *loop, int i)
2332 fprintf(F, "edge: {sourcename: \"");
2334 fprintf(F, "\" targetname: \"");
2335 PRINT_NODEID(get_loop_node(loop, i));
2336 fprintf(F, "\" color: green");
2340 static inline void dump_loop_son_edge(FILE *F, ir_loop *loop, int i)
2343 fprintf(F, "edge: {sourcename: \"");
2345 fprintf(F, "\" targetname: \"");
2346 PRINT_LOOPID(get_loop_son(loop, i));
2347 fprintf(F, "\" color: darkgreen label: \"%d\"}\n",
2348 get_loop_element_pos(loop, get_loop_son(loop, i)));
2351 static void dump_loops(FILE *F, ir_loop *loop)
2354 /* dump this loop node */
2355 dump_loop_node(F, loop);
2357 /* dump edges to nodes in loop -- only if it is a real loop */
2358 if (get_loop_depth(loop) != 0) {
2359 for (i = get_loop_n_nodes(loop) - 1; i >= 0; --i) {
2360 dump_loop_node_edge(F, loop, i);
2363 for (i = get_loop_n_sons(loop) - 1; i >= 0; --i) {
2364 dump_loops(F, get_loop_son(loop, i));
2365 dump_loop_son_edge(F, loop, i);
2369 static inline void dump_loop_nodes_into_graph(FILE *F, ir_graph *irg)
2371 ir_loop *loop = get_irg_loop(irg);
2374 ir_graph *rem = current_ir_graph;
2375 current_ir_graph = irg;
2377 dump_loops(F, loop);
2379 current_ir_graph = rem;
2385 * dumps the VCG header
2387 void dump_vcg_header(FILE *F, const char *name, const char *layout, const char *orientation)
2394 label = edge_label ? "yes" : "no";
2395 if (! layout) layout = "Compilergraph";
2396 if (!orientation) orientation = "bottom_to_top";
2400 "graph: { title: \"ir graph of %s\"\n"
2401 "display_edge_labels: %s\n"
2402 "layoutalgorithm: mindepth //$ \"%s\"\n"
2403 "manhattan_edges: yes\n"
2404 "port_sharing: no\n"
2406 "classname 1: \"intrablock Data\"\n"
2407 "classname 2: \"Block\"\n"
2408 "classname 3: \"Entity type\"\n"
2409 "classname 4: \"Entity owner\"\n"
2410 "classname 5: \"Method Param\"\n"
2411 "classname 6: \"Method Res\"\n"
2412 "classname 7: \"Super\"\n"
2413 "classname 8: \"Union\"\n"
2414 "classname 9: \"Points-to\"\n"
2415 "classname 10: \"Array Element Type\"\n"
2416 "classname 11: \"Overwrites\"\n"
2417 "classname 12: \"Member\"\n"
2418 "classname 13: \"Control Flow\"\n"
2419 "classname 14: \"intrablock Memory\"\n"
2420 "classname 15: \"Dominators\"\n"
2421 "classname 16: \"interblock Data\"\n"
2422 "classname 17: \"interblock Memory\"\n"
2423 "classname 18: \"Exception Control Flow for Interval Analysis\"\n"
2424 "classname 19: \"Postdominators\"\n"
2425 "classname 20: \"Keep Alive\"\n"
2426 "classname 21: \"Out Edges\"\n"
2427 "classname 22: \"Macro Block Edges\"\n"
2428 //"classname 23: \"NoInput Nodes\"\n"
2429 "infoname 1: \"Attribute\"\n"
2430 "infoname 2: \"Verification errors\"\n"
2431 "infoname 3: \"Debug info\"\n",
2432 name, label, layout, orientation);
2434 for (i = 0; i < ird_color_count; ++i) {
2435 if (color_rgb[i] != NULL) {
2436 fprintf(F, "colorentry %s: %s\n", color_names[i], color_rgb[i]);
2439 fprintf(F, "\n"); /* a separator */
2445 * @param irg The graph to be dumped
2446 * @param suffix1 first filename suffix
2447 * @param suffix2 second filename suffix
2449 FILE *vcg_open(const ir_graph *irg, const char *suffix1, const char *suffix2)
2452 const char *nm = get_irg_dump_name(irg);
2453 int len = strlen(nm), i, j;
2454 char *fname; /* filename to put the vcg information in */
2456 if (!suffix1) suffix1 = "";
2457 if (!suffix2) suffix2 = "";
2459 /* open file for vcg graph */
2460 fname = XMALLOCN(char, len * 2 + strlen(suffix1) + strlen(suffix2) + 5);
2462 /* strncpy (fname, nm, len); */ /* copy the filename */
2464 for (i = 0; i < len; ++i) { /* replace '/' in the name: escape by @. */
2466 fname[j] = '@'; j++; fname[j] = '1'; j++;
2467 } else if (nm[i] == '@') {
2468 fname[j] = '@'; j++; fname[j] = '2'; j++;
2470 fname[j] = nm[i]; j++;
2474 strcat(fname, suffix1); /* append file suffix */
2475 strcat(fname, suffix2); /* append file suffix */
2476 strcat(fname, ".vcg"); /* append the .vcg suffix */
2478 /* vcg really expect only a <CR> at end of line, so
2479 * the "b"inary mode is what you mean (and even needed for Win32)
2481 F = fopen(fname, "wb"); /* open file for writing */
2493 * @param name prefix file name
2494 * @param suffix filename suffix
2496 FILE *vcg_open_name(const char *name, const char *suffix)
2499 char *fname; /* filename to put the vcg information in */
2500 int i, j, len = strlen(name);
2502 if (!suffix) suffix = "";
2504 /** open file for vcg graph */
2505 fname = XMALLOCN(char, len * 2 + 5 + strlen(suffix));
2506 /* strcpy (fname, name);*/ /* copy the filename */
2508 for (i = 0; i < len; ++i) { /* replace '/' in the name: escape by @. */
2509 if (name[i] == '/') {
2510 fname[j] = '@'; j++; fname[j] = '1'; j++;
2511 } else if (name[i] == '@') {
2512 fname[j] = '@'; j++; fname[j] = '2'; j++;
2514 fname[j] = name[i]; j++;
2518 strcat(fname, suffix);
2519 strcat(fname, ".vcg"); /* append the .vcg suffix */
2521 /* vcg really expect only a <CR> at end of line, so
2522 * the "b"inary mode is what you mean (and even needed for Win32)
2524 F = fopen(fname, "wb"); /* open file for writing */
2534 * Dumps the vcg file footer
2536 void dump_vcg_footer(FILE *F)
2541 /************************************************************************/
2542 /************************************************************************/
2543 /* Routines that dump all or parts of the firm representation to a file */
2544 /************************************************************************/
2545 /************************************************************************/
2547 /************************************************************************/
2548 /* Dump ir graphs, different formats and additional information. */
2549 /************************************************************************/
2551 typedef void (*do_dump_graph_func) (ir_graph *irg, FILE *out);
2553 static void do_dump(ir_graph *irg, const char *suffix, const char *suffix_ip,
2554 const char *suffix_nonip, do_dump_graph_func dump_func)
2558 const char *suffix1;
2560 if (!is_filtered_dump_name(get_entity_ident(get_irg_entity(irg))))
2563 rem = current_ir_graph;
2564 current_ir_graph = irg;
2566 #ifdef INTERPROCEDURAL_VIEW
2567 if (get_interprocedural_view())
2568 suffix1 = suffix_ip;
2571 suffix1 = suffix_nonip;
2572 current_ir_graph = rem;
2574 out = vcg_open(irg, suffix, suffix1);
2576 dump_func(irg, out);
2581 void dump_ir_graph_file(ir_graph *irg, FILE *out)
2583 if (dump_backedge_information_flag
2584 && get_irg_loopinfo_state(irg) != loopinfo_consistent) {
2585 construct_backedges(irg);
2588 dump_vcg_header(out, get_irg_dump_name(irg), NULL, NULL);
2590 /* call the dump graph hook */
2591 if (dump_ir_graph_hook) {
2592 if (dump_ir_graph_hook(out, irg)) {
2597 /* walk over the graph */
2598 /* dump_whole_node must be called in post visiting predecessors */
2599 ird_walk_graph(irg, NULL, dump_whole_node, out);
2601 /* dump the out edges in a separate walk */
2602 if ((dump_out_edge_flag) && (get_irg_outs_state(irg) != outs_none)) {
2603 irg_out_walk(get_irg_start(irg), dump_out_edge, NULL, out);
2606 dump_vcg_footer(out);
2609 /** Routine to dump a graph, blocks as conventional nodes. */
2610 void dump_ir_graph(ir_graph *irg, const char *suffix )
2612 do_dump(irg, suffix, "-pure-ip", "-pure", dump_ir_graph_file);
2615 void dump_ir_block_graph_file(ir_graph *irg, FILE *out)
2619 dump_vcg_header(out, get_irg_dump_name(irg), NULL, NULL);
2621 construct_block_lists(irg);
2624 * If we are in the interprocedural view, we dump not
2625 * only the requested irg but also all irgs that can be reached
2628 for (i = get_irp_n_irgs() - 1; i >= 0; --i) {
2629 ir_graph *g = get_irp_irg(i);
2630 ir_node **arr = ird_get_irg_link(g);
2632 dump_graph_from_list(out, g);
2637 dump_vcg_footer(out);
2640 /* Dump a firm graph without explicit block nodes. */
2641 void dump_ir_block_graph(ir_graph *irg, const char *suffix)
2643 do_dump(irg, suffix, "-ip", "", dump_ir_block_graph_file);
2646 void dump_ir_extblock_graph_file(ir_graph *irg, FILE *F)
2649 ir_entity *ent = get_irg_entity(irg);
2651 if (get_irg_extblk_state(irg) != extblk_valid)
2654 dump_vcg_header(F, get_irg_dump_name(irg), NULL, NULL);
2656 construct_extblock_lists(irg);
2658 fprintf(F, "graph: { title: \"");
2660 fprintf(F, "\" label: \"%s\" status:clustered color: white \n",
2661 get_ent_dump_name(ent));
2663 dump_graph_info(F, irg);
2664 print_dbg_info(F, get_entity_dbg_info(ent));
2666 for (i = get_irp_n_irgs() - 1; i >= 0; --i) {
2667 ir_graph *irg = get_irp_irg(i);
2668 list_tuple *lists = ird_get_irg_link(irg);
2671 /* dump the extended blocks first */
2672 if (ARR_LEN(lists->extbb_list)) {
2673 ird_set_irg_link(irg, lists->extbb_list);
2674 dump_extblock_graph(F, irg);
2677 /* we may have blocks without extended blocks, bad for instance */
2678 if (ARR_LEN(lists->blk_list)) {
2679 ird_set_irg_link(irg, lists->blk_list);
2680 dump_block_graph(F, irg);
2683 DEL_ARR_F(lists->extbb_list);
2684 DEL_ARR_F(lists->blk_list);
2689 /* Close the vcg information for the irg */
2690 fprintf(F, "}\n\n");
2696 /* Dump a firm graph without explicit block nodes but grouped in extended blocks. */
2697 void dump_ir_extblock_graph(ir_graph *irg, const char *suffix)
2699 do_dump(irg, suffix, "-ip", "", dump_ir_extblock_graph_file);
2702 void dump_ir_graph_w_types_file(ir_graph *irg, FILE *out)
2704 ir_graph *rem = current_ir_graph;
2705 int rem_dump_const_local;
2707 rem = current_ir_graph;
2708 current_ir_graph = irg;
2709 rem_dump_const_local = dump_const_local;
2710 /* dumping types does not work with local nodes */
2711 dump_const_local = 0;
2713 dump_vcg_header(out, get_irg_dump_name(irg), NULL, NULL);
2715 /* dump common ir graph */
2716 irg_walk(get_irg_end(irg), NULL, dump_whole_node, out);
2717 /* dump type info */
2718 type_walk_irg(irg, dump_type_info, NULL, out);
2719 inc_irg_visited(get_const_code_irg());
2720 /* dump edges from graph to type info */
2721 irg_walk(get_irg_end(irg), dump_node2type_edges, NULL, out);
2723 dump_vcg_footer(out);
2724 dump_const_local = rem_dump_const_local;
2725 current_ir_graph = rem;
2728 /* dumps a graph with type information */
2729 void dump_ir_graph_w_types(ir_graph *irg, const char *suffix)
2731 do_dump(irg, suffix, "-pure-wtypes-ip", "-pure-wtypes",
2732 dump_ir_graph_w_types_file);
2735 void dump_ir_block_graph_w_types_file(ir_graph *irg, FILE *out)
2738 int rem_dump_const_local;
2739 ir_graph *rem = current_ir_graph;
2741 rem_dump_const_local = dump_const_local;
2742 /* dumping types does not work with local nodes */
2743 dump_const_local = 0;
2745 dump_vcg_header(out, get_irg_dump_name(irg), NULL, NULL);
2747 /* dump common blocked ir graph */
2748 construct_block_lists(irg);
2750 for (i = get_irp_n_irgs() - 1; i >= 0; --i) {
2751 ir_node **arr = ird_get_irg_link(get_irp_irg(i));
2753 dump_graph_from_list(out, get_irp_irg(i));
2758 /* dump type info */
2759 current_ir_graph = irg;
2760 type_walk_irg(irg, dump_type_info, NULL, out);
2761 inc_irg_visited(get_const_code_irg());
2763 /* dump edges from graph to type info */
2764 irg_walk(get_irg_end(irg), dump_node2type_edges, NULL, out);
2766 dump_vcg_footer(out);
2767 dump_const_local = rem_dump_const_local;
2768 current_ir_graph = rem;
2771 void dump_ir_block_graph_w_types(ir_graph *irg, const char *suffix)
2773 do_dump(irg, suffix, "-wtypes-ip", "-wtypes",
2774 dump_ir_block_graph_w_types_file);
2777 /*---------------------------------------------------------------------*/
2778 /* The following routines dump a control flow graph. */
2779 /*---------------------------------------------------------------------*/
2781 static void dump_block_to_cfg(ir_node *block, void *env)
2787 if (is_Block(block)) {
2788 /* This is a block. Dump a node for the block. */
2789 fprintf(F, "node: {title: \""); PRINT_NODEID(block);
2790 fprintf(F, "\" label: \"");
2791 if (block == get_irg_start_block(get_irn_irg(block)))
2792 fprintf(F, "Start ");
2793 if (block == get_irg_end_block(get_irn_irg(block)))
2796 fprintf(F, "%s ", get_op_name(get_irn_op(block)));
2797 PRINT_NODEID(block);
2799 fprintf(F, "info1:\"");
2801 /* the generic version. */
2802 dump_irnode_to_file(F, block);
2804 /* Check whether we have bad predecessors to color the block. */
2805 for (i = get_Block_n_cfgpreds(block) - 1; i >= 0; --i)
2806 if ((fl = is_Bad(get_Block_cfgpred(block, i))))
2809 fprintf(F, "\""); /* closing quote of info */
2811 if ((block == get_irg_start_block(get_irn_irg(block))) ||
2812 (block == get_irg_end_block(get_irn_irg(block))) )
2813 fprintf(F, " color:blue ");
2815 fprintf(F, " color:yellow ");
2818 /* Dump the edges */
2819 for (i = get_Block_n_cfgpreds(block) - 1; i >= 0; --i)
2820 if (!is_Bad(skip_Proj(get_Block_cfgpred(block, i)))) {
2821 pred = get_nodes_block(skip_Proj(get_Block_cfgpred(block, i)));
2822 fprintf(F, "edge: { sourcename: \"");
2823 PRINT_NODEID(block);
2824 fprintf(F, "\" targetname: \"");
2826 fprintf(F, "\"}\n");
2829 /* Dump dominator/postdominator edge */
2830 if (dump_dominator_information_flag) {
2831 if (get_irg_dom_state(current_ir_graph) == dom_consistent && get_Block_idom(block)) {
2832 pred = get_Block_idom(block);
2833 fprintf(F, "edge: { sourcename: \"");
2834 PRINT_NODEID(block);
2835 fprintf(F, "\" targetname: \"");
2837 fprintf(F, "\" " DOMINATOR_EDGE_ATTR "}\n");
2839 if (get_irg_postdom_state(current_ir_graph) == dom_consistent && get_Block_ipostdom(block)) {
2840 pred = get_Block_ipostdom(block);
2841 fprintf(F, "edge: { sourcename: \"");
2842 PRINT_NODEID(block);
2843 fprintf(F, "\" targetname: \"");
2845 fprintf(F, "\" " POSTDOMINATOR_EDGE_ATTR "}\n");
2851 void dump_cfg(ir_graph *irg, const char *suffix)
2854 /* if a filter is set, dump only the irg's that match the filter */
2855 if (!is_filtered_dump_name(get_entity_ident(get_irg_entity(irg))))
2858 f = vcg_open(irg, suffix, "-cfg");
2860 ir_graph *rem = current_ir_graph;
2861 #ifdef INTERPROCEDURAL_VIEW
2862 int ipv = get_interprocedural_view();
2865 current_ir_graph = irg;
2866 dump_vcg_header(f, get_irg_dump_name(irg), NULL, NULL);
2868 #ifdef INTERPROCEDURAL_VIEW
2870 printf("Warning: dumping cfg not in interprocedural view!\n");
2871 set_interprocedural_view(0);
2875 /* walk over the blocks in the graph */
2876 irg_block_walk(get_irg_end(irg), dump_block_to_cfg, NULL, f);
2877 dump_node(f, get_irg_bad(irg));
2879 #ifdef INTERPROCEDURAL_VIEW
2880 set_interprocedural_view(ipv);
2884 current_ir_graph = rem;
2889 static void descend_and_dump(FILE *F, ir_node *n, int depth, pset *mark_set)
2891 if (pset_find_ptr(mark_set, n))
2894 pset_insert_ptr(mark_set, n);
2897 int i, start = is_Block(n) ? 0 : -1;
2898 dump_whole_node(n, F);
2899 for (i = start; i < get_irn_arity(n); ++i)
2900 descend_and_dump(F, get_irn_n(n, i), depth-1, mark_set);
2903 /* Don't dump edges to nodes further out. These might be edges to
2904 nodes we already dumped, if there is a shorter path to these. */
2908 static int subgraph_counter = 0;
2909 void dump_subgraph(ir_node *root, int depth, const char *suffix)
2914 sprintf(buf, "-subg_%03d", subgraph_counter++);
2915 F = vcg_open(get_irn_irg(root), suffix, buf);
2917 pset *mark_set = pset_new_ptr(1);
2918 dump_vcg_header(F, get_irg_dump_name(get_irn_irg(root)), NULL, NULL);
2919 descend_and_dump(F, root, depth, mark_set);
2926 void dump_callgraph(const char *suffix)
2928 FILE *F = vcg_open_name("Callgraph", suffix);
2931 int i, rem = edge_label;
2934 dump_vcg_header(F, "Callgraph", "Hierarchiv", NULL);
2936 for (i = get_irp_n_irgs() - 1; i >= 0; --i) {
2937 ir_graph *irg = get_irp_irg(i);
2938 ir_entity *ent = get_irg_entity(irg);
2940 int n_callees = get_irg_n_callees(irg);
2942 dump_entity_node(F, ent);
2943 for (j = 0; j < n_callees; ++j) {
2944 ir_entity *c = get_irg_entity(get_irg_callee(irg, j));
2945 //if (id_is_prefix(prefix, get_entity_ld_ident(c))) continue;
2946 int be = is_irg_callee_backedge(irg, j);
2949 "label:\"recursion %d\"" :
2950 "label:\"calls %d\"";
2951 print_ent_ent_edge(F, ent, c, be, ird_color_entity, attr, get_irg_callee_loop_depth(irg, j));
2962 /* Dump all irgs in interprocedural view to a single file. */
2963 void dump_all_cg_block_graph(const char *suffix)
2965 FILE *f = vcg_open_name("All_graphs", suffix);
2969 int rem_view = get_interprocedural_view();
2971 set_interprocedural_view(1);
2972 dump_vcg_header(f, "All_graphs", NULL);
2974 /* collect nodes in all irgs reachable in call graph*/
2975 for (i = get_irp_n_irgs() - 1; i >= 0; --i)
2976 ird_set_irg_link(get_irp_irg(i), NULL);
2978 cg_walk(clear_link, collect_node, NULL);
2980 /* dump all graphs */
2981 for (i = get_irp_n_irgs() - 1; i >= 0; --i) {
2982 current_ir_graph = get_irp_irg(i);
2983 assert(ird_get_irg_link(current_ir_graph));
2984 dump_graph_from_list(f, current_ir_graph);
2985 DEL_ARR_F(ird_get_irg_link(current_ir_graph));
2990 set_interprocedural_view(rem_view);
2995 /*---------------------------------------------------------------------*/
2996 /* the following routines dumps type information without any ir nodes. */
2997 /*---------------------------------------------------------------------*/
2999 void dump_type_graph(ir_graph *irg, const char *suffix)
3003 /* if a filter is set, dump only the irg's that match the filter */
3004 if (!is_filtered_dump_name(get_entity_ident(get_irg_entity(irg)))) return;
3006 f = vcg_open(irg, suffix, "-type");
3008 ir_graph *rem = current_ir_graph;
3009 current_ir_graph = irg;
3011 dump_vcg_header(f, get_irg_dump_name(irg), "Hierarchic", NULL);
3013 /* walk over the blocks in the graph */
3014 type_walk_irg(irg, dump_type_info, NULL, f);
3015 /* The walker for the const code can be called several times for the
3016 same (sub) expression. So that no nodes are dumped several times
3017 we decrease the visited flag of the corresponding graph after each
3018 walk. So now increase it finally. */
3019 inc_irg_visited(get_const_code_irg());
3023 current_ir_graph = rem;
3027 void dump_all_types(const char *suffix)
3029 FILE *f = vcg_open_name("All_types", suffix);
3031 dump_vcg_header(f, "All_types", "Hierarchic", NULL);
3032 type_walk(dump_type_info, NULL, f);
3033 inc_irg_visited(get_const_code_irg());
3040 void dump_class_hierarchy(int entities, const char *suffix)
3042 FILE *f = vcg_open_name("class_hierarchy", suffix);
3047 env.dump_ent = entities;
3048 dump_vcg_header(f, "class_hierarchy", "Hierarchic", NULL);
3049 type_walk(dump_class_hierarchy_node, NULL, &env);
3056 /*---------------------------------------------------------------------*/
3057 /* dumps all graphs with the graph-dumper passed. Possible dumpers: */
3059 /* dump_ir_block_graph */
3061 /* dump_type_graph */
3062 /* dump_ir_graph_w_types */
3063 /*---------------------------------------------------------------------*/
3065 void dump_all_ir_graphs(dump_graph_func *dmp_grph, const char *suffix)
3068 for (i = get_irp_n_irgs() - 1; i >= 0; --i)
3069 dmp_grph(get_irp_irg(i), suffix);
3073 ir_prog_pass_t pass;
3074 dump_graph_func *dump_graph;
3079 * Wrapper around dump_all_ir_graphs().
3081 static int dump_all_ir_graphs_wrapper(ir_prog *irp, void *context)
3083 struct pass_t *pass = context;
3086 dump_all_ir_graphs(pass->dump_graph, pass->suffix);
3090 ir_prog_pass_t *dump_all_ir_graph_pass(const char *name,
3091 dump_graph_func *dump_graph,
3094 size_t len = strlen(suffix);
3095 struct pass_t *pass = xmalloc(sizeof(*pass) + len);
3096 ir_prog_pass_t *res = def_prog_pass_constructor(
3097 &pass->pass, name ? name : "dump_all_graphs", dump_all_ir_graphs_wrapper);
3099 /* this pass does not change anything, so neither dump nor verify is needed. */
3100 res->dump_irprog = ir_prog_no_dump;
3101 res->verify_irprog = ir_prog_no_verify;
3103 pass->dump_graph = dump_graph;
3104 strcpy(pass->suffix, suffix);
3109 /*--------------------------------------------------------------------------------*
3110 * Dumps a stand alone loop graph with firm nodes which belong to one loop node *
3111 * packed together in one subgraph/box *
3112 *--------------------------------------------------------------------------------*/
3114 static void dump_loops_standalone(FILE *F, ir_loop *loop)
3116 int i = 0, loop_node_started = 0, son_number = 0, first = 0;
3118 ir_loop *son = NULL;
3120 /* Dump a new loop node. */
3121 dump_loop_node(F, loop);
3123 /* Dump the loop elements. */
3124 for (i = 0; i < get_loop_n_elements(loop); i++) {
3125 le = get_loop_element(loop, i);
3127 if (get_kind(son) == k_ir_loop) {
3129 /* We are a loop son -> Recurse */
3131 if (loop_node_started) { /* Close the "firm-nodes" node first if we started one. */
3132 fprintf(F, "\" }\n");
3133 fprintf(F, "edge: {sourcename: \"");
3135 fprintf(F, "\" targetname: \"");
3137 fprintf(F, "-%d-nodes\" label:\"%d...%d\"}\n", first, first, i-1);
3138 loop_node_started = 0;
3140 dump_loop_son_edge(F, loop, son_number++);
3141 dump_loops_standalone(F, son);
3142 } else if (get_kind(son) == k_ir_node) {
3143 /* We are a loop node -> Collect firm nodes */
3145 ir_node *n = le.node;
3148 if (!loop_node_started) {
3149 /* Start a new node which contains all firm nodes of the current loop */
3150 fprintf(F, "node: { title: \"");
3152 fprintf(F, "-%d-nodes\" color: lightyellow label: \"", i);
3153 loop_node_started = 1;
3158 bad |= dump_node_label(F, n);
3159 /* Causes indeterministic output: if (is_Block(n)) fprintf(F, "\t ->%d", (int)get_irn_link(n)); */
3160 if (has_backedges(n)) fprintf(F, "\t loop head!");
3161 } else { /* for callgraph loop tree */
3163 assert(get_kind(son) == k_ir_graph);
3165 /* We are a loop node -> Collect firm graphs */
3167 if (!loop_node_started) {
3168 /* Start a new node which contains all firm nodes of the current loop */
3169 fprintf(F, "node: { title: \"");
3171 fprintf(F, "-%d-nodes\" color: lightyellow label: \"", i);
3172 loop_node_started = 1;
3176 fprintf(F, " %s", get_irg_dump_name(n));
3177 /* fprintf(F, " %s (depth %d)", get_irg_dump_name(n), n->callgraph_weighted_loop_depth); */
3181 if (loop_node_started) {
3182 fprintf(F, "\" }\n");
3183 fprintf(F, "edge: {sourcename: \"");
3185 fprintf(F, "\" targetname: \"");
3187 fprintf(F, "-%d-nodes\" label:\"%d...%d\"}\n", first, first, i-1);
3188 loop_node_started = 0;
3192 void dump_loop_tree(ir_graph *irg, const char *suffix)
3196 /* if a filter is set, dump only the irg's that match the filter */
3197 if (!is_filtered_dump_name(get_entity_ident(get_irg_entity(irg))))
3200 f = vcg_open(irg, suffix, "-looptree");
3202 ir_graph *rem = current_ir_graph;
3203 int el_rem = edge_label;
3205 current_ir_graph = irg;
3208 dump_vcg_header(f, get_irg_dump_name(irg), "Tree", "top_to_bottom");
3210 if (get_irg_loop(irg))
3211 dump_loops_standalone(f, get_irg_loop(irg));
3216 edge_label = el_rem;
3217 current_ir_graph = rem;
3221 void dump_callgraph_loop_tree(const char *suffix)
3224 F = vcg_open_name("Callgraph_looptree", suffix);
3225 dump_vcg_header(F, "callgraph looptree", "Tree", "top_to_bottom");
3226 dump_loops_standalone(F, irp->outermost_cg_loop);
3232 /*----------------------------------------------------------------------------*/
3233 /* Dumps the firm nodes in the loop tree to a graph along with the loop nodes.*/
3234 /*----------------------------------------------------------------------------*/
3236 static void collect_nodeloop(FILE *F, ir_loop *loop, eset *loopnodes)
3238 int i, son_number = 0, node_number = 0;
3240 if (dump_loop_information_flag) dump_loop_node(F, loop);
3242 for (i = 0; i < get_loop_n_elements(loop); i++) {
3243 loop_element le = get_loop_element(loop, i);
3244 if (*(le.kind) == k_ir_loop) {
3245 if (dump_loop_information_flag) dump_loop_son_edge(F, loop, son_number++);
3247 collect_nodeloop(F, le.son, loopnodes);
3249 if (dump_loop_information_flag) dump_loop_node_edge(F, loop, node_number++);
3250 eset_insert(loopnodes, le.node);
3255 static void collect_nodeloop_external_nodes(ir_loop *loop, eset *loopnodes,
3260 for (i = 0; i < get_loop_n_elements(loop); i++) {
3261 loop_element le = get_loop_element(loop, i);
3262 if (*(le.kind) == k_ir_loop) {
3264 collect_nodeloop_external_nodes(le.son, loopnodes, extnodes);
3266 if (is_Block(le.node)) start = 0; else start = -1;
3267 for (j = start; j < get_irn_arity(le.node); j++) {
3268 ir_node *pred = get_irn_n(le.node, j);
3269 if (!eset_contains(loopnodes, pred)) {
3270 eset_insert(extnodes, pred);
3271 if (!is_Block(pred)) {
3272 pred = get_nodes_block(pred);
3273 if (!eset_contains(loopnodes, pred)) eset_insert(extnodes, pred);
3281 void dump_loop(ir_loop *l, const char *suffix)
3286 snprintf(name, sizeof(name), "loop_%d", get_loop_loop_nr(l));
3287 F = vcg_open_name(name, suffix);
3289 eset *loopnodes = eset_create();
3290 eset *extnodes = eset_create();
3293 dump_vcg_header(F, name, NULL, NULL);
3295 /* collect all nodes to dump */
3296 collect_nodeloop(F, l, loopnodes);
3297 collect_nodeloop_external_nodes(l, loopnodes, extnodes);
3299 /* build block lists */
3300 for (n = eset_first(loopnodes); n != NULL; n = eset_next(loopnodes))
3301 set_irn_link(n, NULL);
3302 for (n = eset_first(extnodes); n != NULL; n = eset_next(extnodes))
3303 set_irn_link(n, NULL);
3304 for (n = eset_first(loopnodes); n != NULL; n = eset_next(loopnodes)) {
3306 b = get_nodes_block(n);
3307 set_irn_link(n, get_irn_link(b));
3311 for (n = eset_first(extnodes); n != NULL; n = eset_next(extnodes)) {
3313 b = get_nodes_block(n);
3314 set_irn_link(n, get_irn_link(b));
3319 for (b = eset_first(loopnodes); b != NULL; b = eset_next(loopnodes)) {
3321 fprintf(F, "graph: { title: \"");
3323 fprintf(F, "\" label: \"");
3324 dump_node_opcode(F, b);
3325 fprintf(F, " %ld:%d", get_irn_node_nr(b), get_irn_idx(b));
3326 fprintf(F, "\" status:clustered color:yellow\n");
3328 /* dump the blocks edges */
3329 dump_ir_data_edges(F, b);
3331 /* dump the nodes that go into the block */
3332 for (n = get_irn_link(b); n; n = get_irn_link(n)) {
3333 if (eset_contains(extnodes, n))
3334 overrule_nodecolor = ird_color_block_inout;
3336 overrule_nodecolor = ird_color_default_node;
3337 if (!eset_contains(extnodes, n)) dump_ir_data_edges(F, n);
3340 /* Close the vcg information for the block */
3342 dump_const_node_local(F, b);
3346 for (b = eset_first(extnodes); b != NULL; b = eset_next(extnodes)) {
3348 fprintf(F, "graph: { title: \"");
3350 fprintf(F, "\" label: \"");
3351 dump_node_opcode(F, b);
3352 fprintf(F, " %ld:%d", get_irn_node_nr(b), get_irn_idx(b));
3353 fprintf(F, "\" status:clustered color:lightblue\n");
3355 /* dump the nodes that go into the block */
3356 for (n = get_irn_link(b); n; n = get_irn_link(n)) {
3357 if (!eset_contains(loopnodes, n))
3358 overrule_nodecolor = ird_color_block_inout;
3360 overrule_nodecolor = ird_color_default_node;
3361 if (eset_contains(loopnodes, n)) dump_ir_data_edges(F, n);
3364 /* Close the vcg information for the block */
3366 dump_const_node_local(F, b);
3370 eset_destroy(loopnodes);
3371 eset_destroy(extnodes);