2 * Copyright (C) 1995-2011 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,
37 #include "irgraph_t.h"
51 #include "callgraph.h"
52 #include "irextbb_t.h"
54 #include "dbginfo_t.h"
68 typedef struct pns_lookup {
69 long nr; /**< the proj number */
70 const char *name; /**< the name of the Proj */
73 typedef struct proj_lookup {
74 unsigned code; /**< the opcode of the Proj predecessor */
75 unsigned num_data; /**< number of data entries */
76 const pns_lookup_t *data; /**< the data */
79 #include "gen_irdump.c.inl"
81 /** Dump only irgs with names that start with this prefix. */
82 static ident *dump_file_filter_id = NULL;
84 static ir_dump_flags_t flags =
85 ir_dump_flag_blocks_as_subgraphs |
86 ir_dump_flag_keepalive_edges |
87 ir_dump_flag_ld_names |
88 ir_dump_flag_back_edges |
89 ir_dump_flag_consts_local |
90 ir_dump_flag_analysed_types |
91 ir_dump_flag_entities_in_hierarchy |
92 ir_dump_flag_number_label;
94 static ird_color_t overrule_nodecolor = ird_color_default_node;
96 /** The vcg node attribute hook. */
97 static dump_node_vcgattr_func dump_node_vcgattr_hook = NULL;
98 /** The vcg edge attribute hook. */
99 static dump_edge_vcgattr_func dump_edge_vcgattr_hook = NULL;
100 /** The vcg dump block edge hook */
101 static dump_node_edge_func dump_block_edge_hook = NULL;
102 /** The vcg dump node edge hook. */
103 static dump_node_edge_func dump_node_edge_hook = NULL;
105 void set_dump_node_edge_hook(dump_node_edge_func func)
107 dump_node_edge_hook = func;
110 dump_node_edge_func get_dump_node_edge_hook(void)
112 return dump_node_edge_hook;
115 void set_dump_block_edge_hook(dump_node_edge_func func)
117 dump_block_edge_hook = func;
120 dump_node_edge_func get_dump_block_edge_hook(void)
122 return dump_node_edge_hook;
125 void set_dump_node_vcgattr_hook(dump_node_vcgattr_func hook)
127 dump_node_vcgattr_hook = hook;
130 void set_dump_edge_vcgattr_hook(dump_edge_vcgattr_func hook)
132 dump_edge_vcgattr_hook = hook;
135 void ir_set_dump_flags(ir_dump_flags_t new_flags)
140 void ir_add_dump_flags(ir_dump_flags_t new_flags)
145 void ir_remove_dump_flags(ir_dump_flags_t to_remove)
150 ir_dump_flags_t ir_get_dump_flags(void)
155 /** Returns 0 if dump_out_edge_flag or dump_loop_information_flag
156 * are set, else returns dump_const_local_flag.
158 static bool get_opt_dump_const_local(void)
160 return (flags & ir_dump_flag_out_edges)
161 || (flags & ir_dump_flag_loops)
162 || (flags & ir_dump_flag_consts_local)
163 || (flags & ir_dump_flag_iredges);
166 static char *dump_filter;
168 void ir_set_dump_filter(const char *new_filter)
171 dump_filter = xstrdup(new_filter);
174 const char *ir_get_dump_filter(void)
179 int ir_should_dump(const char *name)
183 if (dump_filter == NULL || dump_filter[0] == '\0')
186 for (n = name, f = dump_filter; *f != '\0' && *n != '\0';
194 /* -------------- some extended helper functions ----------------- */
196 const char *get_mode_name_ex(const ir_mode *mode, int *bad)
199 return get_mode_name(mode);
205 #define CUSTOM_COLOR_BASE 100
206 static const char *color_names[ird_color_count];
207 static const char *color_rgb[ird_color_count];
208 static struct obstack color_obst;
210 /** define a custom color. */
211 static void custom_color(int num, const char *rgb_def)
213 assert(num < ird_color_count);
214 obstack_printf(&color_obst, "%d", CUSTOM_COLOR_BASE + num);
215 obstack_1grow(&color_obst, '\0');
217 color_rgb[num] = rgb_def;
218 color_names[num] = (const char*)obstack_finish(&color_obst);
221 /** Define a named color. */
222 static void named_color(int num, const char *name)
224 assert(num < ird_color_count);
225 color_rgb[num] = NULL;
226 color_names[num] = name;
229 /** Initializes the used colors. */
230 static void init_colors(void)
232 static int initialized = 0;
236 obstack_init(&color_obst);
238 custom_color(ird_color_prog_background, "204 204 204");
239 custom_color(ird_color_block_background, "255 255 0");
240 custom_color(ird_color_dead_block_background, "190 150 150");
241 named_color(ird_color_block_inout, "lightblue");
242 named_color(ird_color_default_node, "white");
243 custom_color(ird_color_memory, "153 153 255");
244 custom_color(ird_color_controlflow, "255 153 153");
245 custom_color(ird_color_const, "204 255 255");
246 custom_color(ird_color_proj, "255 255 153");
247 custom_color(ird_color_uses_memory, "153 153 255");
248 custom_color(ird_color_phi, "105 255 105");
249 custom_color(ird_color_anchor, "100 100 255");
250 named_color(ird_color_error, "red");
251 custom_color(ird_color_entity, "204 204 255");
257 * Prints the VCG color to a file.
259 static void print_vcg_color(FILE *out, ird_color_t color)
261 assert(color < ird_color_count);
262 fprintf(out, "color:%s", color_names[color]);
266 * Prints the edge kind of a given IR node.
268 * Projs should be dumped near their predecessor, so they get "nearedge".
270 static void print_node_edge_kind(FILE *out, ir_node *node)
273 fprintf(out, "nearedge: ");
275 fprintf(out, "edge: ");
280 * Prints the edge from a type S to a type T with additional info fmt, ...
283 static void print_type_type_edge(FILE *F, const ir_type *S, const ir_type *T, const char *fmt, ...)
288 fprintf(F, "edge: { sourcename: "); PRINT_TYPEID(S);
289 fprintf(F, " targetname: "); PRINT_TYPEID(T);
290 ir_vfprintf(F, fmt, ap);
296 * Prints the edge from a type tp to an entity ent with additional info fmt, ...
299 static void print_type_ent_edge(FILE *F, const ir_type *tp, const ir_entity *ent, const char *fmt, ...)
304 fprintf(F, "edge: { sourcename: "); PRINT_TYPEID(tp);
305 fprintf(F, " targetname: \""); PRINT_ENTID(ent); fprintf(F, "\"");
306 ir_vfprintf(F, fmt, ap);
312 * Prints the edge from an entity ent1 to an entity ent2 with additional info fmt, ...
315 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, ...)
321 fprintf(F, "backedge: { sourcename: \"");
323 fprintf(F, "edge: { sourcename: \"");
325 fprintf(F, "\" targetname: \""); PRINT_ENTID(ent2); fprintf(F, "\"");
326 ir_vfprintf(F, fmt, ap);
328 if (color != ird_color_none)
329 print_vcg_color(F, color);
335 * Prints the edge from an entity ent to a type tp with additional info fmt, ...
338 static void print_ent_type_edge(FILE *F, const ir_entity *ent, const ir_type *tp, const char *fmt, ...)
343 fprintf(F, "edge: { sourcename: \""); PRINT_ENTID(ent);
344 fprintf(F, "\" targetname: "); PRINT_TYPEID(tp);
345 ir_vfprintf(F, fmt, ap);
351 * Prints the edge from a node irn to a type tp with additional info fmt, ...
354 static void print_node_type_edge(FILE *F, const ir_node *irn, ir_type *tp, const char *fmt, ...)
359 fprintf(F, "edge: { sourcename: \""); PRINT_NODEID(irn);
360 fprintf(F, "\" targetname: "); PRINT_TYPEID(tp);
361 ir_vfprintf(F, fmt, ap);
367 * Prints the edge from a node irn to an entity ent with additional info fmt, ...
370 static void print_node_ent_edge(FILE *F, const ir_node *irn, const ir_entity *ent, const char *fmt, ...)
375 fprintf(F, "edge: { sourcename: \""); PRINT_NODEID(irn);
376 fprintf(F, "\" targetname: \""); PRINT_ENTID(ent);
378 ir_vfprintf(F, fmt, ap);
384 * Prints the edge from an entity ent to a node irn with additional info fmt, ...
387 static void print_ent_node_edge(FILE *F, const ir_entity *ent, const ir_node *irn, const char *fmt, ...)
392 fprintf(F, "edge: { sourcename: \""); PRINT_ENTID(ent);
393 fprintf(F, "\" targetname: \""); PRINT_NODEID(irn); fprintf(F, "\"");
394 ir_vfprintf(F, fmt, ap);
400 * Prints the edge from a type tp to an enumeration item item with additional info fmt, ...
403 static void print_enum_item_edge(FILE *F, const ir_type *tp, size_t item, const char *fmt, ...)
408 fprintf(F, "edge: { sourcename: "); PRINT_TYPEID(tp);
409 fprintf(F, " targetname: \""); PRINT_ITEMID(tp, item); fprintf(F, "\" ");
410 ir_vfprintf(F, fmt, ap);
415 /*-----------------------------------------------------------------*/
416 /* global and ahead declarations */
417 /*-----------------------------------------------------------------*/
419 static void dump_loop_nodes_into_graph(FILE *F, ir_graph *irg);
421 /*-----------------------------------------------------------------*/
422 /* Helper functions. */
423 /*-----------------------------------------------------------------*/
426 * This map is used as a private link attr to be able to call dumper
427 * anywhere without destroying link fields.
429 static pmap *irdump_link_map = NULL;
431 /** NOT A STANDARD LIBFIRM INIT METHOD
433 * We do not want to integrate dumping into libfirm, i.e., if the dumpers
434 * are off, we want to have as few interferences as possible. Therefore the
435 * initialization is performed lazily and not called from within init_firm.
437 * Creates the link attribute map. */
438 static void init_irdump(void)
440 /* We need a new, empty map. */
441 if (irdump_link_map) pmap_destroy(irdump_link_map);
442 irdump_link_map = pmap_create();
443 if (!dump_file_filter_id)
444 dump_file_filter_id = new_id_from_str("");
448 * Returns the private link field.
450 static void *ird_get_irn_link(const ir_node *n)
453 if (irdump_link_map == NULL)
456 if (pmap_contains(irdump_link_map, n))
457 res = pmap_get(irdump_link_map, n);
462 * Sets the private link field.
464 static void ird_set_irn_link(const ir_node *n, void *x)
466 if (irdump_link_map == NULL)
468 pmap_insert(irdump_link_map, n, x);
472 * Gets the private link field of an irg.
474 static void *ird_get_irg_link(const ir_graph *irg)
477 if (irdump_link_map == NULL)
480 if (pmap_contains(irdump_link_map, irg))
481 res = pmap_get(irdump_link_map, irg);
486 * Sets the private link field of an irg.
488 static void ird_set_irg_link(const ir_graph *irg, void *x)
490 if (irdump_link_map == NULL)
492 pmap_insert(irdump_link_map, irg, x);
496 * Walker, clears the private link field.
498 static void clear_link(ir_node *node, void *env)
501 ird_set_irn_link(node, NULL);
505 * If the entity has a ld_name, returns it if the dump_ld_name is set,
506 * else returns the name of the entity.
508 static const char *_get_ent_dump_name(const ir_entity *ent, bool dump_ld_name)
511 return "<NULL entity>";
513 /* Don't use get_entity_ld_ident (ent) as it computes the mangled name! */
514 if (ent->ld_name != NULL)
515 return get_id_str(ent->ld_name);
517 return get_id_str(ent->name);
520 const char *get_ent_dump_name(const ir_entity *ent)
522 return _get_ent_dump_name(ent, flags & ir_dump_flag_ld_names);
525 const char *get_irg_dump_name(const ir_graph *irg)
527 /* Don't use get_entity_ld_ident (ent) as it computes the mangled name! */
528 return _get_ent_dump_name(get_irg_entity(irg), true);
532 * Returns non-zero if a node is in floating state.
534 static int node_floats(const ir_node *n)
536 return ((get_irn_pinned(n) == op_pin_state_floats) &&
537 (get_irg_pinned(current_ir_graph) == op_pin_state_floats));
541 * Walker that visits the anchors
543 static void ird_walk_graph(ir_graph *irg, irg_walk_func *pre, irg_walk_func *post, void *env)
545 if ((flags & ir_dump_flag_all_anchors)
546 || ((flags & ir_dump_flag_iredges) && edges_activated(irg))) {
547 irg_walk_anchors(irg, pre, post, env);
549 irg_walk_graph(irg, pre, post, env);
554 * Walker, allocates an array for all blocks and puts their non-floating
555 * nodes into this array.
557 static void collect_node(ir_node *node, void *env)
562 || (get_op_flags(get_irn_op(node)) & irop_flag_dump_noblock)) {
563 ir_node ** arr = (ir_node **) ird_get_irg_link(get_irn_irg(node));
564 if (!arr) arr = NEW_ARR_F(ir_node *, 0);
565 ARR_APP1(ir_node *, arr, node);
566 ird_set_irg_link(get_irn_irg(node), arr); /* arr is an l-value, APP_ARR might change it! */
568 ir_node * block = get_nodes_block(node);
571 /* this node is in a Bad block, so we must place it into the graph's list */
572 ir_node ** arr = (ir_node **) ird_get_irg_link(get_irn_irg(node));
573 if (!arr) arr = NEW_ARR_F(ir_node *, 0);
574 ARR_APP1(ir_node *, arr, node);
575 ird_set_irg_link(get_irn_irg(node), arr); /* arr is an l-value, APP_ARR might change it! */
577 ird_set_irn_link(node, ird_get_irn_link(block));
578 ird_set_irn_link(block, node);
583 /** Construct lists to walk ir block-wise.
585 * Collects all blocks, nodes not op_pin_state_pinned,
586 * Bad, NoMem and Unknown into a flexible array in link field of
587 * irg they belong to. Sets the irg link field to NULL in all
588 * graphs not visited.
589 * Free the list with DEL_ARR_F().
591 static ir_node **construct_block_lists(ir_graph *irg)
594 int walk_flag = ir_resources_reserved(irg) & IR_RESOURCE_IRN_VISITED;
595 ir_graph *rem = current_ir_graph;
597 current_ir_graph = irg;
600 ir_free_resources(irg, IR_RESOURCE_IRN_VISITED);
603 for (i = get_irp_n_irgs(); i > 0;)
604 ird_set_irg_link(get_irp_irg(--i), NULL);
606 ird_walk_graph(current_ir_graph, clear_link, collect_node, current_ir_graph);
609 ir_reserve_resources(irg, IR_RESOURCE_IRN_VISITED);
612 current_ir_graph = rem;
613 return (ir_node**)ird_get_irg_link(irg);
616 typedef struct list_tuple {
618 ir_extblk **extbb_list;
621 /** Construct lists to walk IR extended block-wise.
622 * Free the lists in the tuple with DEL_ARR_F(). Sets the irg link field to
623 * NULL in all graphs not visited.
625 static list_tuple *construct_extblock_lists(ir_graph *irg)
627 ir_node **blk_list = construct_block_lists(irg);
629 ir_graph *rem = current_ir_graph;
630 list_tuple *lists = XMALLOC(list_tuple);
632 current_ir_graph = irg;
634 lists->blk_list = NEW_ARR_F(ir_node *, 0);
635 lists->extbb_list = NEW_ARR_F(ir_extblk *, 0);
637 inc_irg_block_visited(irg);
638 for (i = 0, n = ARR_LEN(blk_list); i < n; ++i) {
641 if (is_Block(blk_list[i])) {
642 ext = get_Block_extbb(blk_list[i]);
644 if (extbb_not_visited(ext)) {
645 ARR_APP1(ir_extblk *, lists->extbb_list, ext);
646 mark_extbb_visited(ext);
649 ARR_APP1(ir_node *, lists->blk_list, blk_list[i]);
653 current_ir_graph = rem;
654 ird_set_irg_link(irg, lists);
658 void dump_node_opcode(FILE *F, ir_node *n)
660 const ir_op_ops *ops = get_op_ops(get_irn_op(n));
662 /* call the dump_node operation if available */
663 if (ops->dump_node) {
664 ops->dump_node(F, n, dump_node_opcode_txt);
668 /* implementation for default nodes */
669 switch (get_irn_opcode(n)) {
671 switch (get_SymConst_kind(n)) {
672 case symconst_addr_ent:
673 fprintf(F, "SymC &%s", get_entity_name(get_SymConst_entity(n)));
675 case symconst_ofs_ent:
676 fprintf(F, "SymC %s offset", get_entity_name(get_SymConst_entity(n)));
678 case symconst_type_tag:
679 ir_fprintf(F, "SymC %+F tag", get_SymConst_type(n));
681 case symconst_type_size:
682 ir_fprintf(F, "SymC %+F size", get_SymConst_type(n));
684 case symconst_type_align:
685 ir_fprintf(F, "SymC %+F align", get_SymConst_type(n));
687 case symconst_enum_const:
688 fprintf(F, "SymC %s enum", get_enumeration_const_name(get_SymConst_enum(n)));
694 if (get_Load_unaligned(n) == align_non_aligned)
696 fprintf(F, "%s[%s]", get_irn_opname(n), get_mode_name_ex(get_Load_mode(n), NULL));
699 if (get_Store_unaligned(n) == align_non_aligned)
701 fprintf(F, "%s", get_irn_opname(n));
704 if (n == get_irg_start_block(get_irn_irg(n)))
706 if (n == get_irg_end_block(get_irn_irg(n)))
708 fprintf(F, "%s%s", get_irn_opname(n),
709 (flags & ir_dump_flag_show_marks) ? (get_Block_mark(n) ? "*" : "") : "");
712 if (get_Conv_strict(n))
713 fprintf(F, "strict");
714 fprintf(F, "%s", get_irn_opname(n));
717 fprintf(F, "%s", get_irn_opname(n));
718 if (get_Div_no_remainder(n))
720 fprintf(F, "[%s]", get_mode_name_ex(get_Div_resmode(n), NULL));
723 fprintf(F, "%s[%s]", get_irn_opname(n), get_mode_name_ex(get_Mod_resmode(n), NULL));
726 fprintf(F, "%s[%s]", get_irn_opname(n), get_builtin_kind_name(get_Builtin_kind(n)));
730 fprintf(F, "%s", get_irn_opname(n));
735 * Dump the mode of a node n to a file F.
736 * Ignore modes that are "always known".
738 static void dump_node_mode(FILE *F, ir_node *n)
740 const ir_op_ops *ops = get_op_ops(get_irn_op(n));
744 /* call the dump_node operation if available */
745 if (ops->dump_node) {
746 ops->dump_node(F, n, dump_node_mode_txt);
750 /* default implementation */
751 iro = get_irn_opcode(n);
763 mode = get_irn_mode(n);
765 if (mode != NULL && mode != mode_BB && mode != mode_ANY && mode != mode_BAD &&
766 (mode != mode_T || iro == iro_Proj))
767 fprintf(F, "%s", get_mode_name_ex(mode, NULL));
772 * Dump the type of a node n to a file F if it's known.
774 static int dump_node_typeinfo(FILE *F, ir_node *n)
778 if (ir_get_dump_flags() & ir_dump_flag_analysed_types) {
779 if (get_irg_typeinfo_state(current_ir_graph) == ir_typeinfo_consistent ||
780 get_irg_typeinfo_state(current_ir_graph) == ir_typeinfo_inconsistent) {
781 ir_type *tp = get_irn_typeinfo_type(n);
782 if (tp != firm_none_type) {
783 ir_fprintf(F, "[%+F]", tp);
793 * Dump additional node attributes of some nodes to a file F.
795 static void dump_node_nodeattr(FILE *F, ir_node *n)
800 const ir_op_ops *ops = get_op_ops(get_irn_op(n));
802 /* call the dump_node operation if available */
803 if (ops->dump_node) {
804 ops->dump_node(F, n, dump_node_nodeattr_txt);
808 switch (get_irn_opcode(n)) {
810 ir_fprintf(F, "%T ", get_Const_tarval(n));
814 pred = get_Proj_pred(n);
815 proj_nr = get_Proj_proj(n);
816 code = get_irn_opcode(pred);
818 if (code == iro_Proj && get_irn_opcode(get_Proj_pred(pred)) == iro_Start)
819 fprintf(F, "Arg %ld ", proj_nr);
820 else if (code == iro_Cond && get_irn_mode(get_Cond_selector(pred)) != mode_b)
821 fprintf(F, "%ld ", proj_nr);
823 unsigned i, j, f = 0;
825 for (i = 0; i < ARRAY_SIZE(proj_lut); ++i) {
826 if (code == proj_lut[i].code) {
827 for (j = 0; j < proj_lut[i].num_data; ++j) {
828 if (proj_nr == proj_lut[i].data[j].nr) {
829 fprintf(F, "%s ", proj_lut[i].data[j].name);
838 fprintf(F, "%ld ", proj_nr);
839 if (code == iro_Cond && get_Cond_jmp_pred(pred) != COND_JMP_PRED_NONE) {
840 if (proj_nr == pn_Cond_false && get_Cond_jmp_pred(pred) == COND_JMP_PRED_FALSE)
842 if (proj_nr == pn_Cond_true && get_Cond_jmp_pred(pred) == COND_JMP_PRED_TRUE)
848 fprintf(F, "%s ", get_ent_dump_name(get_Sel_entity(n)));
851 ir_fprintf(F, "(%+F)", get_Cast_type(n));
854 fprintf(F, "%s ", get_relation_string(get_Cmp_relation(n)));
857 fprintf(F, "%s ", get_relation_string(get_Confirm_relation(n)));
860 ir_fprintf(F, "(%+F)", get_CopyB_type(n));
868 static void dump_node_ana_vals(FILE *F, ir_node *n)
875 void dump_node_label(FILE *F, ir_node *n)
877 dump_node_opcode(F, n);
879 dump_node_mode(F, n);
881 dump_node_typeinfo(F, n);
882 dump_node_nodeattr(F, n);
883 if (flags & ir_dump_flag_number_label) {
884 fprintf(F, "%ld", get_irn_node_nr(n));
886 if (flags & ir_dump_flag_idx_label) {
887 fprintf(F, ":%u", get_irn_idx(n));
892 * Dumps the attributes of a node n into the file F.
893 * Currently this is only the color of a node.
895 static void dump_node_vcgattr(FILE *F, ir_node *node, ir_node *local, int bad)
901 print_vcg_color(F, ird_color_error);
905 if (dump_node_vcgattr_hook != NULL) {
906 dump_node_vcgattr_hook(F, node, local);
910 n = local ? local : node;
912 if (overrule_nodecolor != ird_color_default_node) {
913 print_vcg_color(F, overrule_nodecolor);
917 mode = get_irn_mode(n);
918 if (mode == mode_M) {
919 print_vcg_color(F, ird_color_memory);
922 if (mode == mode_X) {
923 print_vcg_color(F, ird_color_controlflow);
927 switch (get_irn_opcode(n)) {
930 print_vcg_color(F, ird_color_anchor);
933 print_vcg_color(F, ird_color_error);
936 print_vcg_color(F, ird_color_block_background);
939 print_vcg_color(F, ird_color_phi);
942 print_vcg_color(F, ird_color_memory);
946 print_vcg_color(F, ird_color_const);
949 print_vcg_color(F, ird_color_proj);
952 ir_op *op = get_irn_op(node);
954 if (is_op_constlike(op)) {
955 print_vcg_color(F, ird_color_const);
956 } else if (is_op_uses_memory(op)) {
957 print_vcg_color(F, ird_color_uses_memory);
958 } else if (is_op_cfopcode(op) || is_op_forking(op)) {
959 print_vcg_color(F, ird_color_controlflow);
965 void *dump_add_node_info_callback(dump_node_info_cb_t *cb, void *data)
967 hook_entry_t *info = XMALLOCZ(hook_entry_t);
969 info->hook._hook_node_info = cb;
970 info->context = data;
971 register_hook(hook_node_info, info);
976 void dump_remove_node_info_callback(void *handle)
978 hook_entry_t *info = (hook_entry_t*)handle;
979 unregister_hook(hook_node_info, info);
984 * Dump the node information of a node n to a file F.
986 static void dump_node_info(FILE *F, ir_node *n)
988 const ir_op_ops *ops = get_op_ops(get_irn_op(n));
990 fprintf(F, " info1: \"");
991 dump_irnode_to_file(F, n);
992 /* call the dump_node operation if available */
994 ops->dump_node(F, n, dump_node_info_txt);
996 /* allow additional info to be added */
997 hook_node_info(F, n);
1001 static int is_constlike_node(const ir_node *node)
1003 const ir_op *op = get_irn_op(node);
1004 return is_op_constlike(op);
1008 /** outputs the predecessors of n, that are constants, local. I.e.,
1009 generates a copy of the constant predecessors for each node called with. */
1010 static void dump_const_node_local(FILE *F, ir_node *n)
1013 if (!get_opt_dump_const_local()) return;
1015 /* Use visited flag to avoid outputting nodes twice.
1016 initialize it first. */
1017 for (i = 0; i < get_irn_arity(n); i++) {
1018 ir_node *con = get_irn_n(n, i);
1019 if (is_constlike_node(con)) {
1020 set_irn_visited(con, get_irg_visited(current_ir_graph) - 1);
1024 for (i = 0; i < get_irn_arity(n); i++) {
1025 ir_node *con = get_irn_n(n, i);
1026 if (is_constlike_node(con) && !irn_visited_else_mark(con)) {
1027 /* Generate a new name for the node by appending the names of
1029 fprintf(F, "node: {title: "); PRINT_CONSTID(n, con);
1030 fprintf(F, " label: \"");
1031 dump_node_label(F, con);
1033 dump_node_info(F, con);
1034 dump_node_vcgattr(F, n, con, 0);
1040 /** If the block of an edge is a const_like node, dump it local with an edge */
1041 static void dump_const_block_local(FILE *F, ir_node *n)
1045 if (!get_opt_dump_const_local()) return;
1047 blk = get_nodes_block(n);
1048 if (is_constlike_node(blk)) {
1049 /* Generate a new name for the node by appending the names of
1051 fprintf(F, "node: {title: \""); PRINT_CONSTBLKID(n, blk);
1052 fprintf(F, "\" label: \"");
1053 dump_node_label(F, blk);
1055 dump_node_info(F, blk);
1056 dump_node_vcgattr(F, n, blk, 0);
1059 fprintf(F, "edge: { sourcename: \"");
1061 fprintf(F, "\" targetname: \""); PRINT_CONSTBLKID(n,blk);
1063 if (dump_edge_vcgattr_hook) {
1065 if (dump_edge_vcgattr_hook(F, n, -1)) {
1069 fprintf(F, " " BLOCK_EDGE_ATTR "}\n");
1074 fprintf(F, "\" " BLOCK_EDGE_ATTR "}\n");
1079 * prints the error message of a node to a file F as info2.
1081 static void print_node_error(FILE *F, const char *err_msg)
1086 fprintf(F, " info2: \"%s\"", err_msg);
1090 * prints debug messages of a node to file F as info3.
1092 static void print_dbg_info(FILE *F, dbg_info *dbg)
1096 ir_dbg_info_snprint(buf, sizeof(buf), dbg);
1098 fprintf(F, " info3: \"%s\"\n", buf);
1102 static void print_type_dbg_info(FILE *F, type_dbg_info *dbg)
1112 static void dump_node(FILE *F, ir_node *n)
1117 if (get_opt_dump_const_local() && is_constlike_node(n))
1120 /* dump this node */
1121 fputs("node: {title: \"", F);
1125 fputs(" label: \"", F);
1126 bad = ! irn_verify_irg_dump(n, current_ir_graph, &p);
1127 dump_node_label(F, n);
1128 dump_node_ana_vals(F, n);
1129 //dump_node_ana_info(F, n);
1132 if (get_op_flags(get_irn_op(n)) & irop_flag_dump_noinput) {
1133 //fputs(" node_class:23", F);
1136 dump_node_info(F, n);
1137 print_node_error(F, p);
1138 print_dbg_info(F, get_irn_dbg_info(n));
1139 dump_node_vcgattr(F, n, NULL, bad);
1141 dump_const_node_local(F, n);
1143 if (dump_node_edge_hook)
1144 dump_node_edge_hook(F, n);
1147 /** dump the edge to the block this node belongs to */
1148 static void dump_ir_block_edge(FILE *F, ir_node *n)
1150 if (get_opt_dump_const_local() && is_constlike_node(n)) return;
1152 ir_node *block = get_nodes_block(n);
1154 if (get_opt_dump_const_local() && is_constlike_node(block)) {
1155 dump_const_block_local(F, n);
1157 fprintf(F, "edge: { sourcename: \"");
1159 fprintf(F, "\" targetname: ");
1160 fprintf(F, "\""); PRINT_NODEID(block); fprintf(F, "\"");
1162 if (dump_edge_vcgattr_hook) {
1164 if (dump_edge_vcgattr_hook(F, n, -1)) {
1168 fprintf(F, " " BLOCK_EDGE_ATTR "}\n");
1173 fprintf(F, " " BLOCK_EDGE_ATTR "}\n");
1178 static void print_data_edge_vcgattr(FILE *F, ir_node *from, int to)
1181 * do not use get_nodes_block() here, will fail
1182 * if the irg is not pinned.
1184 if (get_irn_n(from, -1) == get_irn_n(get_irn_n(from, to), -1))
1185 fprintf(F, INTRA_DATA_EDGE_ATTR);
1187 fprintf(F, INTER_DATA_EDGE_ATTR);
1190 static void print_mem_edge_vcgattr(FILE *F, ir_node *from, int to)
1193 * do not use get_nodes_block() here, will fail
1194 * if the irg is not pinned.
1196 if (get_irn_n(from, -1) == get_irn_n(get_irn_n(from, to), -1))
1197 fprintf(F, INTRA_MEM_EDGE_ATTR);
1199 fprintf(F, INTER_MEM_EDGE_ATTR);
1202 /** Print the vcg attributes for the edge from node "from" to its "to"th input */
1203 static void print_edge_vcgattr(FILE *F, ir_node *from, int to)
1207 if (dump_edge_vcgattr_hook)
1208 if (dump_edge_vcgattr_hook(F, from, to))
1211 if ((flags & ir_dump_flag_back_edges) && is_backedge(from, to))
1212 fprintf(F, BACK_EDGE_ATTR);
1214 switch (get_irn_opcode(from)) {
1216 fprintf(F, CF_EDGE_ATTR);
1218 case iro_Start: break;
1221 if (get_irn_mode(get_End_keepalive(from, to)) == mode_BB)
1222 fprintf(F, KEEP_ALIVE_CF_EDGE_ATTR);
1224 fprintf(F, KEEP_ALIVE_DF_EDGE_ATTR);
1228 if (is_Proj(from)) {
1229 if (get_irn_mode(from) == mode_M)
1230 print_mem_edge_vcgattr(F, from, to);
1231 else if (get_irn_mode(from) == mode_X)
1232 fprintf(F, CF_EDGE_ATTR);
1234 print_data_edge_vcgattr(F, from, to);
1236 else if (get_irn_mode(get_irn_n(from, to)) == mode_M)
1237 print_mem_edge_vcgattr(F, from, to);
1238 else if (get_irn_mode(get_irn_n(from, to)) == mode_X)
1239 fprintf(F, CF_EDGE_ATTR);
1241 print_data_edge_vcgattr(F, from, to);
1245 /** dump edges to our inputs */
1246 static void dump_ir_data_edges(FILE *F, ir_node *n)
1250 if (!(flags & ir_dump_flag_keepalive_edges) && is_End(n)) {
1251 /* the End node has only keep-alive edges */
1255 /* dump the dependency edges. */
1256 num = get_irn_deps(n);
1257 for (i = 0; i < num; ++i) {
1258 ir_node *dep = get_irn_dep(n, i);
1261 print_node_edge_kind(F, n);
1262 fprintf(F, "{sourcename: \"");
1264 fprintf(F, "\" targetname: ");
1265 if ((get_opt_dump_const_local()) && is_constlike_node(dep)) {
1266 PRINT_CONSTID(n, dep);
1272 fprintf(F, " label: \"%d\" ", i);
1273 fprintf(F, " color: darkgreen}\n");
1277 num = get_irn_arity(n);
1278 for (i = 0; i < num; i++) {
1279 ir_node *pred = get_irn_n(n, i);
1282 if ((flags & ir_dump_flag_back_edges) && is_backedge(n, i)) {
1283 fprintf(F, "backedge: {sourcename: \"");
1285 print_node_edge_kind(F, n);
1286 fprintf(F, "{sourcename: \"");
1289 fprintf(F, "\" targetname: ");
1290 if ((get_opt_dump_const_local()) && is_constlike_node(pred)) {
1291 PRINT_CONSTID(n, pred);
1293 fprintf(F, "\""); PRINT_NODEID(pred); fprintf(F, "\"");
1295 fprintf(F, " label: \"%d\" ", i);
1296 print_edge_vcgattr(F, n, i);
1304 static void dump_ir_edges(ir_node *node, void *env)
1307 FILE *F = (FILE*)env;
1308 const ir_edge_t *edge;
1310 foreach_out_edge(node, edge) {
1311 ir_node *succ = get_edge_src_irn(edge);
1313 print_node_edge_kind(F, succ);
1314 fprintf(F, "{sourcename: \"");
1316 fprintf(F, "\" targetname: \"");
1320 fprintf(F, " label: \"%d\" ", i);
1321 fprintf(F, OUT_EDGE_ATTR);
1328 /** Dumps a node and its edges but not the block edge */
1329 static void dump_node_wo_blockedge(ir_node *n, void *env)
1331 FILE *F = (FILE*)env;
1333 dump_ir_data_edges(F, n);
1336 /** Dumps a node and its edges. */
1337 static void dump_node_with_edges(ir_node *n, void *env)
1339 FILE *F = (FILE*)env;
1340 dump_node_wo_blockedge(n, env);
1341 if (!node_floats(n))
1342 dump_ir_block_edge(F, n);
1345 /** Dumps a const-like node. */
1346 static void dump_const_node(ir_node *n, void *env)
1348 if (is_Block(n)) return;
1349 dump_node_wo_blockedge(n, env);
1352 /***********************************************************************/
1353 /* the following routines dump the nodes/irgs bracketed to graphs. */
1354 /***********************************************************************/
1356 /** Dumps a constant expression as entity initializer, array bound ... */
1357 static void dump_const_expression(FILE *F, ir_node *value)
1359 ir_graph *rem = current_ir_graph;
1360 ir_dump_flags_t old_flags = ir_get_dump_flags();
1361 ir_remove_dump_flags(ir_dump_flag_consts_local);
1363 current_ir_graph = get_const_code_irg();
1364 irg_walk(value, dump_const_node, NULL, F);
1365 /* Decrease visited flag so that we walk with the same flag for the next
1366 expression. This guarantees that we don't dump the same node twice,
1367 as for const expressions cse is performed to save memory. */
1368 set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph) -1);
1370 ir_set_dump_flags(old_flags);
1371 current_ir_graph = rem;
1374 /** Dump a block as graph containing its nodes.
1376 * Expects to find nodes belonging to the block as list in its
1378 * Dumps the edges of all nodes including itself. */
1379 static void dump_whole_block(FILE *F, ir_node *block)
1382 ird_color_t color = ird_color_block_background;
1384 assert(is_Block(block));
1386 fprintf(F, "graph: { title: \"");
1387 PRINT_NODEID(block);
1388 fprintf(F, "\" label: \"");
1389 dump_node_label(F, block);
1391 /* colorize blocks */
1392 if (! get_Block_matured(block))
1393 color = ird_color_block_background;
1395 fprintf(F, "\" status:clustered ");
1396 print_vcg_color(F, color);
1399 /* yComp can show attributes for blocks, XVCG parses but ignores them */
1400 dump_node_info(F, block);
1401 print_dbg_info(F, get_irn_dbg_info(block));
1403 /* dump the blocks edges */
1404 dump_ir_data_edges(F, block);
1406 if (dump_block_edge_hook)
1407 dump_block_edge_hook(F, block);
1409 /* dump the nodes that go into the block */
1410 for (node = (ir_node*)ird_get_irn_link(block); node; node = (ir_node*)ird_get_irn_link(node)) {
1412 dump_ir_data_edges(F, node);
1415 /* Close the vcg information for the block */
1417 dump_const_node_local(F, block);
1421 /** dumps a graph block-wise. Expects all blockless nodes in arr in irgs link.
1422 * The outermost nodes: blocks and nodes not op_pin_state_pinned, Bad, Unknown. */
1423 static void dump_block_graph(FILE *F, ir_graph *irg)
1426 ir_graph *rem = current_ir_graph;
1427 ir_node **arr = (ir_node**)ird_get_irg_link(irg);
1428 current_ir_graph = irg;
1430 for (i = 0, n = ARR_LEN(arr); i < n; ++i) {
1431 ir_node *node = arr[i];
1432 if (is_Block(node)) {
1433 /* Dumps the block and all the nodes in the block, which are to
1434 be found in Block->link. */
1435 dump_whole_block(F, node);
1437 /* Nodes that are not in a Block. */
1439 if (!node_floats(node) && is_Bad(get_nodes_block(node))) {
1440 dump_const_block_local(F, node);
1442 dump_ir_data_edges(F, node);
1444 if ((flags & ir_dump_flag_iredges) && edges_activated(irg))
1445 dump_ir_edges(node, F);
1448 if ((flags & ir_dump_flag_loops)
1449 && is_irg_state(irg, IR_GRAPH_STATE_CONSISTENT_LOOPINFO))
1450 dump_loop_nodes_into_graph(F, irg);
1452 current_ir_graph = rem;
1456 * Dump the info for an irg.
1457 * Parsed by XVCG but not shown. use yComp.
1459 static void dump_graph_info(FILE *F, ir_graph *irg)
1461 fprintf(F, "info1: \"");
1462 dump_entity_to_file(F, get_irg_entity(irg));
1465 /* dump graph state */
1466 fprintf(F, "state:");
1467 if (is_irg_state(irg, IR_GRAPH_STATE_ARCH_DEP))
1468 fprintf(F, " arch_dep");
1469 if (is_irg_state(irg, IR_GRAPH_STATE_MODEB_LOWERED))
1470 fprintf(F, " modeb_lowered");
1471 if (is_irg_state(irg, IR_GRAPH_STATE_NORMALISATION2))
1472 fprintf(F, " normalisation2");
1473 if (is_irg_state(irg, IR_GRAPH_STATE_IMPLICIT_BITFIELD_MASKING))
1474 fprintf(F, " implicit_bitfield_masking");
1475 if (is_irg_state(irg, IR_GRAPH_STATE_OPTIMIZE_UNREACHABLE_CODE))
1476 fprintf(F, " optimize_unreachable_code");
1477 if (is_irg_state(irg, IR_GRAPH_STATE_NO_CRITICAL_EDGES))
1478 fprintf(F, " no_critical_edges");
1479 if (is_irg_state(irg, IR_GRAPH_STATE_NO_BADS))
1480 fprintf(F, " no_bads");
1481 if (is_irg_state(irg, IR_GRAPH_STATE_NO_UNREACHABLE_CODE))
1482 fprintf(F, " no_unreachable_code");
1483 if (is_irg_state(irg, IR_GRAPH_STATE_ONE_RETURN))
1484 fprintf(F, " one_return");
1485 if (is_irg_state(irg, IR_GRAPH_STATE_CONSISTENT_DOMINANCE))
1486 fprintf(F, " consistent_dominance");
1487 if (is_irg_state(irg, IR_GRAPH_STATE_CONSISTENT_POSTDOMINANCE))
1488 fprintf(F, " consistent_postdominance");
1489 if (is_irg_state(irg, IR_GRAPH_STATE_CONSISTENT_OUT_EDGES))
1490 fprintf(F, " consistent_out_edges");
1491 if (is_irg_state(irg, IR_GRAPH_STATE_CONSISTENT_OUTS))
1492 fprintf(F, " consistent_outs");
1493 if (is_irg_state(irg, IR_GRAPH_STATE_CONSISTENT_LOOPINFO))
1494 fprintf(F, " consistent_loopinfo");
1495 if (is_irg_state(irg, IR_GRAPH_STATE_CONSISTENT_ENTITY_USAGE))
1496 fprintf(F, " consistent_entity_usage");
1497 if (is_irg_state(irg, IR_GRAPH_STATE_VALID_EXTENDED_BLOCKS))
1498 fprintf(F, " valid_exended_blocks");
1502 /** Dumps an irg as a graph clustered by block nodes.
1503 * If interprocedural view edges can point to nodes out of this graph.
1505 static void dump_graph_from_list(FILE *F, ir_graph *irg)
1507 ir_entity *ent = get_irg_entity(irg);
1509 fprintf(F, "graph: { title: \"");
1511 fprintf(F, "\" label: \"%s\" status:clustered color:%s \n",
1512 get_ent_dump_name(ent), color_names[ird_color_prog_background]);
1514 dump_graph_info(F, irg);
1515 print_dbg_info(F, get_entity_dbg_info(ent));
1517 dump_block_graph(F, irg);
1519 /* Close the vcg information for the irg */
1520 fprintf(F, "}\n\n");
1523 /*******************************************************************/
1524 /* Basic type and entity nodes and edges. */
1525 /*******************************************************************/
1527 /** dumps the edges between nodes and their type or entity attributes. */
1528 static void dump_node2type_edges(ir_node *n, void *env)
1530 FILE *F = (FILE*)env;
1533 switch (get_irn_opcode(n)) {
1535 /* @@@ some consts have an entity */
1538 if (SYMCONST_HAS_TYPE(get_SymConst_kind(n)))
1539 print_node_type_edge(F,n,get_SymConst_type(n),NODE2TYPE_EDGE_ATTR);
1542 print_node_ent_edge(F,n,get_Sel_entity(n),NODE2TYPE_EDGE_ATTR);
1545 print_node_type_edge(F,n,get_Call_type(n),NODE2TYPE_EDGE_ATTR);
1548 print_node_type_edge(F,n,get_Alloc_type(n),NODE2TYPE_EDGE_ATTR);
1551 print_node_type_edge(F,n,get_Free_type(n),NODE2TYPE_EDGE_ATTR);
1554 print_node_type_edge(F,n,get_Cast_type(n),NODE2TYPE_EDGE_ATTR);
1562 static int print_type_info(FILE *F, ir_type *tp)
1566 if (get_type_state(tp) == layout_undefined) {
1567 fprintf(F, "state: layout_undefined\n");
1569 fprintf(F, "state: layout_fixed,\n");
1571 if (get_type_mode(tp))
1572 fprintf(F, "mode: %s,\n", get_mode_name_ex(get_type_mode(tp), &bad));
1573 fprintf(F, "size: %db,\n", get_type_size_bits(tp));
1578 static void print_typespecific_info(FILE *F, ir_type *tp)
1580 switch (get_type_tpop_code(tp)) {
1582 fprintf(F, "peculiarity: %s\n", get_peculiarity_string(get_class_peculiarity(tp)));
1587 fprintf(F, "variadicity: %s\n", get_variadicity_name(get_method_variadicity(tp)));
1588 fprintf(F, "params: %d\n", get_method_n_params(tp));
1589 fprintf(F, "results: %d\n", get_method_n_ress(tp));
1595 case tpo_enumeration:
1607 static void print_typespecific_vcgattr(FILE *F, ir_type *tp)
1609 switch (get_type_tpop_code(tp)) {
1611 fprintf(F, " " TYPE_CLASS_NODE_ATTR);
1614 fprintf(F, " " TYPE_METH_NODE_ATTR);
1622 case tpo_enumeration:
1633 void dump_type_node(FILE *F, ir_type *tp)
1635 fprintf(F, "node: {title: ");
1637 fprintf(F, " label: \"");
1638 if (tp->dbi != NULL) {
1640 ir_print_type(buf, sizeof(buf), tp);
1641 fprintf(F, "%s '%s'", get_type_tpop_name(tp), buf);
1643 ir_fprintf(F, "%+F", tp);
1645 fputs("\" info1: \"", F);
1646 dump_type_to_file(F, tp);
1648 print_type_dbg_info(F, get_type_dbg_info(tp));
1649 print_typespecific_vcgattr(F, tp);
1653 static void dump_entity_node(FILE *F, ir_entity *ent)
1655 fprintf(F, "node: {title: \"");
1656 PRINT_ENTID(ent); fprintf(F, "\"");
1657 fprintf(F, " label: ");
1658 fprintf(F, "\"%s\" ", get_ent_dump_name(ent));
1660 print_vcg_color(F, ird_color_entity);
1661 fprintf(F, "\n info1: \"");
1663 dump_entity_to_file(F, ent);
1666 print_dbg_info(F, get_entity_dbg_info(ent));
1670 static void dump_enum_item(FILE *F, ir_type *tp, size_t pos)
1673 ir_enum_const *ec = get_enumeration_const(tp, pos);
1674 ident *id = get_enumeration_const_nameid(ec);
1675 ir_tarval *tv = get_enumeration_value(ec);
1678 tarval_snprintf(buf, sizeof(buf), tv);
1680 strncpy(buf, "<not set>", sizeof(buf));
1681 fprintf(F, "node: {title: \"");
1682 PRINT_ITEMID(tp, pos); fprintf(F, "\"");
1683 fprintf(F, " label: ");
1684 fprintf(F, "\"enum item %s\" " ENUM_ITEM_NODE_ATTR, get_id_str(id));
1685 fprintf(F, "\n info1: \"value: %s\"}\n", buf);
1689 * Dumps a new style initializer.
1691 static void dump_entity_initializer(FILE *F, const ir_entity *ent)
1699 * type-walker: Dumps a type or entity and its edges.
1701 static void dump_type_info(type_or_ent tore, void *env)
1703 FILE *F = (FILE*)env;
1704 size_t i = 0; /* to shutup gcc */
1706 /* dump this type or entity */
1708 switch (get_kind(tore.ent)) {
1710 ir_entity *ent = tore.ent;
1713 dump_entity_node(F, ent);
1715 /* skip this to reduce graph. Member edge of type is parallel to this edge. *
1716 fprintf(F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
1717 ENT_OWN_EDGE_ATTR "}\n", ent, get_entity_owner(ent));*/
1718 print_ent_type_edge(F,ent, get_entity_type(ent), ENT_TYPE_EDGE_ATTR);
1719 if (is_Class_type(get_entity_owner(ent))) {
1720 for (i = get_entity_n_overwrites(ent); i > 0;)
1721 print_ent_ent_edge(F, ent, get_entity_overwrites(ent, --i), 0, ird_color_none, ENT_OVERWRITES_EDGE_ATTR);
1723 /* attached subgraphs */
1724 if (! (flags & ir_dump_flag_no_entity_values)) {
1725 if (ent->initializer != NULL) {
1726 /* new style initializers */
1727 dump_entity_initializer(F, ent);
1728 } else if (entity_has_compound_ent_values(ent)) {
1729 /* old style compound entity values */
1730 for (i = get_compound_ent_n_values(ent); i > 0;) {
1731 value = get_compound_ent_value(ent, --i);
1733 print_ent_node_edge(F, ent, value, ENT_VALUE_EDGE_ATTR, i);
1734 dump_const_expression(F, value);
1735 print_ent_ent_edge(F, ent, get_compound_ent_value_member(ent, i), 0, ird_color_none, ENT_CORR_EDGE_ATTR, i);
1737 fprintf(F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
1738 ENT_CORR_EDGE_ATTR "}\n", GET_ENTID(ent),
1739 get_compound_ent_value_member(ent, i), i);
1748 ir_type *tp = tore.typ;
1749 dump_type_node(F, tp);
1750 /* and now the edges */
1751 switch (get_type_tpop_code(tp)) {
1753 for (i = get_class_n_supertypes(tp); i > 0;) {
1755 print_type_type_edge(F, tp, get_class_supertype(tp, i), TYPE_SUPER_EDGE_ATTR);
1757 for (i = get_class_n_members(tp); i > 0;) {
1759 print_type_ent_edge(F, tp, get_class_member(tp, i), TYPE_MEMBER_EDGE_ATTR);
1763 for (i = get_struct_n_members(tp); i > 0;) {
1765 print_type_ent_edge(F, tp, get_struct_member(tp, i), TYPE_MEMBER_EDGE_ATTR);
1769 for (i = get_method_n_params(tp); i > 0;) {
1771 print_type_type_edge(F, tp, get_method_param_type(tp, i), METH_PAR_EDGE_ATTR,i);
1773 for (i = get_method_n_ress(tp); i > 0;) {
1775 print_type_type_edge(F, tp, get_method_res_type(tp, i), METH_RES_EDGE_ATTR,i);
1779 for (i = get_union_n_members(tp); i > 0;) {
1781 print_type_ent_edge(F, tp, get_union_member(tp, i), UNION_EDGE_ATTR);
1785 print_type_type_edge(F, tp, get_array_element_type(tp), ARR_ELT_TYPE_EDGE_ATTR);
1786 print_type_ent_edge(F, tp, get_array_element_entity(tp), ARR_ENT_EDGE_ATTR);
1787 for (i = get_array_n_dimensions(tp); i > 0;) {
1788 ir_node *upper, *lower;
1791 upper = get_array_upper_bound(tp, i);
1792 lower = get_array_lower_bound(tp, i);
1793 print_node_type_edge(F, upper, tp, "label: \"upper %zu\"", get_array_order(tp, i));
1794 print_node_type_edge(F, lower, tp, "label: \"lower %zu\"", get_array_order(tp, i));
1795 dump_const_expression(F, upper);
1796 dump_const_expression(F, lower);
1799 case tpo_enumeration:
1800 for (i = get_enumeration_n_enums(tp); i > 0;) {
1802 dump_enum_item(F, tp, i);
1803 print_enum_item_edge(F, tp, i, "label: \"item %zu\"", i);
1807 print_type_type_edge(F, tp, get_pointer_points_to_type(tp), PTR_PTS_TO_EDGE_ATTR);
1814 break; /* case k_type */
1817 printf(" *** irdump, dump_type_info(l.%i), faulty type.\n", __LINE__);
1821 /** For dumping class hierarchies.
1822 * Dumps a class type node and a superclass edge.
1824 static void dump_class_hierarchy_node(type_or_ent tore, void *ctx)
1826 FILE *F = (FILE*)ctx;
1827 size_t i = 0; /* to shutup gcc */
1829 /* dump this type or entity */
1830 switch (get_kind(tore.ent)) {
1832 ir_entity *ent = tore.ent;
1833 if (get_entity_owner(ent) == get_glob_type()) break;
1834 if (!is_Method_type(get_entity_type(ent)))
1836 if (flags & ir_dump_flag_entities_in_hierarchy
1837 && is_Class_type(get_entity_owner(ent))) {
1839 dump_entity_node(F, ent);
1841 print_type_ent_edge(F, get_entity_owner(ent), ent, TYPE_MEMBER_EDGE_ATTR);
1842 for (i = get_entity_n_overwrites(ent); i > 0;) {
1844 print_ent_ent_edge(F, get_entity_overwrites(ent, i), ent, 0, ird_color_none, ENT_OVERWRITES_EDGE_ATTR);
1850 ir_type *tp = tore.typ;
1851 if (tp == get_glob_type())
1853 switch (get_type_tpop_code(tp)) {
1855 dump_type_node(F, tp);
1856 /* and now the edges */
1857 for (i = get_class_n_supertypes(tp); i > 0;) {
1859 print_type_type_edge(F,tp,get_class_supertype(tp, i),TYPE_SUPER_EDGE_ATTR);
1864 break; /* case k_type */
1867 printf(" *** irdump, dump_class_hierarchy_node(l.%i), faulty type.\n", __LINE__);
1871 /*******************************************************************/
1872 /* dump analysis information that is expressed in graph terms. */
1873 /*******************************************************************/
1875 /* dump out edges */
1876 static void dump_out_edge(ir_node *n, void *env)
1878 FILE *F = (FILE*)env;
1880 for (i = get_irn_n_outs(n) - 1; i >= 0; --i) {
1881 ir_node *succ = get_irn_out(n, i);
1883 print_node_edge_kind(F, succ);
1884 fprintf(F, "{sourcename: \"");
1886 fprintf(F, "\" targetname: \"");
1888 fprintf(F, "\" color: red linestyle: dashed");
1893 static void dump_loop_label(FILE *F, const ir_loop *loop)
1895 fprintf(F, "loop %u", get_loop_depth(loop));
1898 static void dump_loop_info(FILE *F, const ir_loop *loop)
1900 fprintf(F, " info1: \"");
1901 fprintf(F, " loop nr: %ld", get_loop_loop_nr(loop));
1902 #ifdef DEBUG_libfirm /* GL @@@ debug analyses */
1903 fprintf(F, "\n The loop was analyzed %ld times.", (long int) PTR_TO_INT(get_loop_link(loop)));
1908 static void dump_loop_node(FILE *F, const ir_loop *loop)
1910 fprintf(F, "node: {title: \"");
1912 fprintf(F, "\" label: \"");
1913 dump_loop_label(F, loop);
1915 dump_loop_info(F, loop);
1919 static void dump_loop_node_edge(FILE *F, const ir_loop *loop, size_t i)
1922 fprintf(F, "edge: {sourcename: \"");
1924 fprintf(F, "\" targetname: \"");
1925 PRINT_NODEID(get_loop_element(loop, i).node);
1926 fprintf(F, "\" color: green");
1930 static void dump_loop_son_edge(FILE *F, const ir_loop *loop, size_t i)
1933 fprintf(F, "edge: {sourcename: \"");
1935 fprintf(F, "\" targetname: \"");
1936 PRINT_LOOPID(get_loop_element(loop, i).son);
1937 ir_fprintf(F, "\" color: darkgreen label: \"%zu\"}\n", i);
1940 static void dump_loops(FILE *F, const ir_loop *loop)
1943 size_t n_elements = get_loop_n_elements(loop);
1944 /* dump this loop node */
1945 dump_loop_node(F, loop);
1947 /* dump edges to nodes in loop -- only if it is a real loop */
1948 if (get_loop_depth(loop) != 0) {
1949 for (i = n_elements; i > 0;) {
1950 loop_element element;
1952 element = get_loop_element(loop, i);
1953 if (*element.kind != k_ir_node)
1955 dump_loop_node_edge(F, loop, i);
1958 for (i = n_elements; i > 0;) {
1959 loop_element element;
1961 element = get_loop_element(loop, i);
1962 if (*element.kind != k_ir_loop)
1964 dump_loops(F, element.son);
1965 dump_loop_son_edge(F, loop, i);
1969 static void dump_loop_nodes_into_graph(FILE *F, ir_graph *irg)
1971 ir_loop *loop = get_irg_loop(irg);
1974 ir_graph *rem = current_ir_graph;
1975 current_ir_graph = irg;
1977 dump_loops(F, loop);
1979 current_ir_graph = rem;
1985 * dumps the VCG header
1987 void dump_vcg_header(FILE *F, const char *name, const char *layout, const char *orientation)
1991 = (flags & ir_dump_flag_disable_edge_labels) ? "no" : "yes";
1995 if (! layout) layout = "Compilergraph";
1996 if (!orientation) orientation = "bottom_to_top";
2000 "graph: { title: \"ir graph of %s\"\n"
2001 "display_edge_labels: %s\n"
2002 "layoutalgorithm: mindepth //$ \"%s\"\n"
2003 "manhattan_edges: yes\n"
2004 "port_sharing: no\n"
2006 "classname 1: \"intrablock Data\"\n"
2007 "classname 2: \"Block\"\n"
2008 "classname 3: \"Entity type\"\n"
2009 "classname 4: \"Entity owner\"\n"
2010 "classname 5: \"Method Param\"\n"
2011 "classname 6: \"Method Res\"\n"
2012 "classname 7: \"Super\"\n"
2013 "classname 8: \"Union\"\n"
2014 "classname 9: \"Points-to\"\n"
2015 "classname 10: \"Array Element Type\"\n"
2016 "classname 11: \"Overwrites\"\n"
2017 "classname 12: \"Member\"\n"
2018 "classname 13: \"Control Flow\"\n"
2019 "classname 14: \"intrablock Memory\"\n"
2020 "classname 15: \"Dominators\"\n"
2021 "classname 16: \"interblock Data\"\n"
2022 "classname 17: \"interblock Memory\"\n"
2023 "classname 18: \"Exception Control Flow for Interval Analysis\"\n"
2024 "classname 19: \"Postdominators\"\n"
2025 "classname 20: \"Keep Alive\"\n"
2026 "classname 21: \"Out Edges\"\n"
2027 "classname 22: \"Macro Block Edges\"\n"
2028 //"classname 23: \"NoInput Nodes\"\n"
2029 "infoname 1: \"Attribute\"\n"
2030 "infoname 2: \"Verification errors\"\n"
2031 "infoname 3: \"Debug info\"\n",
2032 name, label, layout, orientation);
2034 for (i = 0; i < ird_color_count; ++i) {
2035 if (color_rgb[i] != NULL) {
2036 fprintf(F, "colorentry %s: %s\n", color_names[i], color_rgb[i]);
2043 * Dumps the vcg file footer
2045 void dump_vcg_footer(FILE *F)
2052 static void dump_blocks_as_subgraphs(FILE *out, ir_graph *irg)
2056 construct_block_lists(irg);
2059 * If we are in the interprocedural view, we dump not
2060 * only the requested irg but also all irgs that can be reached
2063 for (i = get_irp_n_irgs(); i > 0;) {
2064 ir_graph *other_irg = get_irp_irg(--i);
2065 ir_node **arr = (ir_node**)ird_get_irg_link(other_irg);
2069 dump_graph_from_list(out, other_irg);
2074 /** dumps a graph extended block-wise. Expects all blockless nodes in arr in irgs link.
2075 * The outermost nodes: blocks and nodes not op_pin_state_pinned, Bad, Unknown. */
2076 static void dump_extblock_graph(FILE *F, ir_graph *irg)
2079 ir_graph *rem = current_ir_graph;
2080 ir_extblk **arr = (ir_extblk**)ird_get_irg_link(irg);
2081 current_ir_graph = irg;
2083 for (i = 0, arr_len = ARR_LEN(arr); i < arr_len; ++i) {
2084 ir_extblk *extbb = arr[i];
2085 ir_node *leader = get_extbb_leader(extbb);
2088 fprintf(F, "graph: { title: \"");
2089 PRINT_EXTBBID(leader);
2090 fprintf(F, "\" label: \"ExtBB %ld\" status:clustered color:lightgreen\n",
2091 get_irn_node_nr(leader));
2093 for (j = 0, n_blks = ARR_LEN(extbb->blks); j < n_blks; ++j) {
2094 ir_node *node = extbb->blks[j];
2095 if (is_Block(node)) {
2096 /* Dumps the block and all the nodes in the block, which are to
2097 be found in Block->link. */
2098 dump_whole_block(F, node);
2100 /* Nodes that are not in a Block. */
2102 if (is_Bad(get_nodes_block(node)) && !node_floats(node)) {
2103 dump_const_block_local(F, node);
2105 dump_ir_data_edges(F, node);
2111 if ((flags & ir_dump_flag_loops)
2112 && (is_irg_state(irg, IR_GRAPH_STATE_CONSISTENT_LOOPINFO)))
2113 dump_loop_nodes_into_graph(F, irg);
2115 current_ir_graph = rem;
2119 static void dump_blocks_extbb_grouped(FILE *F, ir_graph *irg)
2122 ir_entity *ent = get_irg_entity(irg);
2124 if (!is_irg_state(irg, IR_GRAPH_STATE_VALID_EXTENDED_BLOCKS))
2127 construct_extblock_lists(irg);
2129 fprintf(F, "graph: { title: \"");
2131 fprintf(F, "\" label: \"%s\" status:clustered color: white \n",
2132 get_ent_dump_name(ent));
2134 dump_graph_info(F, irg);
2135 print_dbg_info(F, get_entity_dbg_info(ent));
2137 for (i = get_irp_n_irgs(); i > 0;) {
2138 ir_graph *other_irg = get_irp_irg(--i);
2139 list_tuple *lists = (list_tuple*)ird_get_irg_link(other_irg);
2142 /* dump the extended blocks first */
2143 if (ARR_LEN(lists->extbb_list)) {
2144 ird_set_irg_link(other_irg, lists->extbb_list);
2145 dump_extblock_graph(F, other_irg);
2148 /* we may have blocks without extended blocks, bad for instance */
2149 if (ARR_LEN(lists->blk_list)) {
2150 ird_set_irg_link(other_irg, lists->blk_list);
2151 dump_block_graph(F, other_irg);
2154 DEL_ARR_F(lists->extbb_list);
2155 DEL_ARR_F(lists->blk_list);
2160 /* Close the vcg information for the irg */
2161 fprintf(F, "}\n\n");
2166 void dump_ir_graph_file(FILE *out, ir_graph *irg)
2168 dump_vcg_header(out, get_irg_dump_name(irg), NULL, NULL);
2171 if (flags & ir_dump_flag_blocks_as_subgraphs) {
2172 if (flags & ir_dump_flag_group_extbb) {
2173 dump_blocks_extbb_grouped(out, irg);
2175 dump_blocks_as_subgraphs(out, irg);
2178 /* dump_node_with_edges must be called in post visiting predecessors */
2179 ird_walk_graph(irg, NULL, dump_node_with_edges, out);
2182 /* dump type info */
2183 if (flags & ir_dump_flag_with_typegraph) {
2184 ir_graph *rem = current_ir_graph;
2185 current_ir_graph = irg;
2187 type_walk_irg(irg, dump_type_info, NULL, out);
2188 inc_irg_visited(get_const_code_irg());
2189 /* dump edges from graph to type info */
2190 irg_walk(get_irg_end(irg), dump_node2type_edges, NULL, out);
2192 current_ir_graph = rem;
2195 /* dump iredges out edges */
2196 if ((flags & ir_dump_flag_iredges) && edges_activated(current_ir_graph)) {
2197 irg_walk_edges(get_irg_start_block(irg), dump_ir_edges, NULL, out);
2200 /* dump the out edges in a separate walk */
2201 if ((flags & ir_dump_flag_out_edges)
2202 && (is_irg_state(irg, IR_GRAPH_STATE_CONSISTENT_OUTS))) {
2203 irg_out_walk(get_irg_start(irg), dump_out_edge, NULL, out);
2206 dump_vcg_footer(out);
2209 static void dump_block_to_cfg(ir_node *block, void *env)
2211 FILE *F = (FILE*)env;
2214 if (is_Bad(block) && get_irn_mode(block) == mode_X) {
2215 dump_node(F, block);
2218 if (is_Block(block)) {
2219 /* This is a block. Dump a node for the block. */
2220 fprintf(F, "node: {title: \""); PRINT_NODEID(block);
2221 fprintf(F, "\" label: \"");
2222 if (block == get_irg_start_block(get_irn_irg(block)))
2223 fprintf(F, "Start ");
2224 if (block == get_irg_end_block(get_irn_irg(block)))
2227 fprintf(F, "%s ", get_op_name(get_irn_op(block)));
2228 PRINT_NODEID(block);
2230 fprintf(F, "info1:\"");
2232 /* the generic version. */
2233 dump_irnode_to_file(F, block);
2235 fprintf(F, "\""); /* closing quote of info */
2237 if ((block == get_irg_start_block(get_irn_irg(block))) ||
2238 (block == get_irg_end_block(get_irn_irg(block))) )
2239 fprintf(F, " color:blue ");
2243 /* Dump the edges */
2244 for (i = get_Block_n_cfgpreds(block) - 1; i >= 0; --i) {
2245 ir_node *pred = get_Block_cfgpred(block, i);
2247 pred = get_nodes_block(pred);
2248 fprintf(F, "edge: { sourcename: \"");
2249 PRINT_NODEID(block);
2250 fprintf(F, "\" targetname: \"");
2252 fprintf(F, "\"}\n");
2255 /* Dump dominator/postdominator edge */
2256 if (ir_get_dump_flags() & ir_dump_flag_dominance) {
2257 if (is_irg_state(get_irn_irg(block), IR_GRAPH_STATE_CONSISTENT_DOMINANCE) && get_Block_idom(block)) {
2258 ir_node *pred = get_Block_idom(block);
2259 fprintf(F, "edge: { sourcename: \"");
2260 PRINT_NODEID(block);
2261 fprintf(F, "\" targetname: \"");
2263 fprintf(F, "\" " DOMINATOR_EDGE_ATTR "}\n");
2265 if (is_irg_state(get_irn_irg(block), IR_GRAPH_STATE_CONSISTENT_POSTDOMINANCE) && get_Block_ipostdom(block)) {
2266 ir_node *pred = get_Block_ipostdom(block);
2267 fprintf(F, "edge: { sourcename: \"");
2268 PRINT_NODEID(block);
2269 fprintf(F, "\" targetname: \"");
2271 fprintf(F, "\" " POSTDOMINATOR_EDGE_ATTR "}\n");
2277 void dump_cfg(FILE *F, ir_graph *irg)
2279 dump_vcg_header(F, get_irg_dump_name(irg), NULL, NULL);
2281 /* walk over the blocks in the graph */
2282 irg_walk_graph(irg, dump_block_to_cfg, NULL, F);
2287 void dump_callgraph(FILE *F)
2290 ir_dump_flags_t old_flags = ir_get_dump_flags();
2292 ir_remove_dump_flags(ir_dump_flag_disable_edge_labels);
2293 dump_vcg_header(F, "Callgraph", "Hierarchic", NULL);
2295 for (i = get_irp_n_irgs(); i > 0;) {
2296 ir_graph *irg = get_irp_irg(--i);
2297 ir_entity *ent = get_irg_entity(irg);
2298 size_t j, n_callees = get_irg_n_callees(irg);
2300 dump_entity_node(F, ent);
2301 for (j = 0; j < n_callees; ++j) {
2302 ir_entity *c = get_irg_entity(get_irg_callee(irg, j));
2303 int be = is_irg_callee_backedge(irg, j);
2304 const char *attr = be
2305 ? "label:\"recursion %zu\""
2306 : "label:\"calls %zu\"";
2307 print_ent_ent_edge(F, ent, c, be, ird_color_entity, attr,
2308 get_irg_callee_loop_depth(irg, j));
2312 ir_set_dump_flags(old_flags);
2316 void dump_typegraph(FILE *out)
2318 dump_vcg_header(out, "All_types", "Hierarchic", NULL);
2319 type_walk(dump_type_info, NULL, out);
2320 dump_vcg_footer(out);
2323 void dump_class_hierarchy(FILE *out)
2325 dump_vcg_header(out, "class_hierarchy", "Hierarchic", NULL);
2326 type_walk(dump_class_hierarchy_node, NULL, out);
2327 dump_vcg_footer(out);
2330 static void dump_loops_standalone(FILE *F, ir_loop *loop)
2333 bool loop_node_started = false;
2335 size_t son_number = 0;
2337 ir_loop *son = NULL;
2339 /* Dump a new loop node. */
2340 dump_loop_node(F, loop);
2342 /* Dump the loop elements. */
2343 for (i = 0; i < get_loop_n_elements(loop); i++) {
2344 le = get_loop_element(loop, i);
2346 if (get_kind(son) == k_ir_loop) {
2348 /* We are a loop son -> Recurse */
2350 if (loop_node_started) { /* Close the "firm-nodes" node first if we started one. */
2351 fprintf(F, "\" }\n");
2352 fprintf(F, "edge: {sourcename: \"");
2354 fprintf(F, "\" targetname: \"");
2356 fprintf(F, "-%lu-nodes\" label:\"%lu...%lu\"}\n",
2357 (unsigned long) first,
2358 (unsigned long) first,
2359 (unsigned long) i-1);
2360 loop_node_started = false;
2362 dump_loop_son_edge(F, loop, son_number++);
2363 dump_loops_standalone(F, son);
2364 } else if (get_kind(son) == k_ir_node) {
2365 /* We are a loop node -> Collect firm nodes */
2367 ir_node *n = le.node;
2368 if (!loop_node_started) {
2369 /* Start a new node which contains all firm nodes of the current loop */
2370 fprintf(F, "node: { title: \"");
2372 fprintf(F, "-%lu-nodes\" color: lightyellow label: \"",
2374 loop_node_started = true;
2379 dump_node_label(F, n);
2380 /* Causes indeterministic output: if (is_Block(n)) fprintf(F, "\t ->%d", (int)get_irn_link(n)); */
2381 if (has_backedges(n)) fprintf(F, "\t loop head!");
2382 } else { /* for callgraph loop tree */
2384 assert(get_kind(son) == k_ir_graph);
2386 /* We are a loop node -> Collect firm graphs */
2388 if (!loop_node_started) {
2389 /* Start a new node which contains all firm nodes of the current loop */
2390 fprintf(F, "node: { title: \"");
2392 fprintf(F, "-%lu-nodes\" color: lightyellow label: \"",
2394 loop_node_started = true;
2398 fprintf(F, " %s", get_irg_dump_name(n));
2399 /* fprintf(F, " %s (depth %d)", get_irg_dump_name(n), n->callgraph_weighted_loop_depth); */
2403 if (loop_node_started) {
2404 fprintf(F, "\" }\n");
2405 fprintf(F, "edge: {sourcename: \"");
2407 fprintf(F, "\" targetname: \"");
2409 fprintf(F, "-%lu-nodes\" label:\"%lu...%lu\"}\n",
2410 (unsigned long) first,
2411 (unsigned long) first,
2412 (unsigned long) i-1);
2413 loop_node_started = false;
2417 void dump_loop_tree(FILE *out, ir_graph *irg)
2419 ir_graph *rem = current_ir_graph;
2420 ir_dump_flags_t old_flags = ir_get_dump_flags();
2422 current_ir_graph = irg;
2423 ir_remove_dump_flags(ir_dump_flag_disable_edge_labels);
2425 dump_vcg_header(out, get_irg_dump_name(irg), "Tree", "top_to_bottom");
2427 if (get_irg_loop(irg))
2428 dump_loops_standalone(out, get_irg_loop(irg));
2430 dump_vcg_footer(out);
2432 ir_set_dump_flags(old_flags);
2433 current_ir_graph = rem;
2436 void dump_callgraph_loop_tree(FILE *out)
2438 dump_vcg_header(out, "callgraph looptree", "Tree", "top_to_bottom");
2439 dump_loops_standalone(out, irp->outermost_cg_loop);
2440 dump_vcg_footer(out);
2443 static void collect_nodeloop(FILE *F, ir_loop *loop, eset *loopnodes)
2447 int node_number = 0;
2449 if (flags & ir_dump_flag_loops)
2450 dump_loop_node(F, loop);
2452 for (i = 0; i < get_loop_n_elements(loop); i++) {
2453 loop_element le = get_loop_element(loop, i);
2454 if (*(le.kind) == k_ir_loop) {
2455 if (flags & ir_dump_flag_loops)
2456 dump_loop_son_edge(F, loop, son_number++);
2458 collect_nodeloop(F, le.son, loopnodes);
2460 if (flags & ir_dump_flag_loops)
2461 dump_loop_node_edge(F, loop, node_number++);
2462 eset_insert(loopnodes, le.node);
2467 static void collect_nodeloop_external_nodes(ir_loop *loop, eset *loopnodes,
2473 for (i = 0; i < get_loop_n_elements(loop); i++) {
2474 loop_element le = get_loop_element(loop, i);
2475 if (*(le.kind) == k_ir_loop) {
2477 collect_nodeloop_external_nodes(le.son, loopnodes, extnodes);
2479 if (is_Block(le.node)) start = 0; else start = -1;
2480 for (j = start; j < get_irn_arity(le.node); j++) {
2481 ir_node *pred = get_irn_n(le.node, j);
2482 if (!eset_contains(loopnodes, pred)) {
2483 eset_insert(extnodes, pred);
2484 if (!is_Block(pred)) {
2485 pred = get_nodes_block(pred);
2486 if (!eset_contains(loopnodes, pred)) eset_insert(extnodes, pred);
2494 void dump_loop(FILE *F, ir_loop *l)
2496 eset *loopnodes = eset_create();
2497 eset *extnodes = eset_create();
2501 snprintf(name, sizeof(name), "loop_%ld", get_loop_loop_nr(l));
2502 dump_vcg_header(F, name, NULL, NULL);
2504 /* collect all nodes to dump */
2505 collect_nodeloop(F, l, loopnodes);
2506 collect_nodeloop_external_nodes(l, loopnodes, extnodes);
2508 /* build block lists */
2509 eset_foreach(loopnodes, ir_node*, n) {
2510 set_irn_link(n, NULL);
2512 eset_foreach(extnodes, ir_node*, n) {
2513 set_irn_link(n, NULL);
2515 eset_foreach(loopnodes, ir_node*, n) {
2517 b = get_nodes_block(n);
2518 set_irn_link(n, get_irn_link(b));
2522 eset_foreach(extnodes, ir_node*, n) {
2524 b = get_nodes_block(n);
2525 set_irn_link(n, get_irn_link(b));
2530 eset_foreach(loopnodes, ir_node*, b) {
2532 fprintf(F, "graph: { title: \"");
2534 fprintf(F, "\" label: \"");
2535 dump_node_opcode(F, b);
2536 fprintf(F, " %ld:%u", get_irn_node_nr(b), get_irn_idx(b));
2537 fprintf(F, "\" status:clustered color:yellow\n");
2539 /* dump the blocks edges */
2540 dump_ir_data_edges(F, b);
2542 /* dump the nodes that go into the block */
2543 for (n = (ir_node*)get_irn_link(b); n; n = (ir_node*)get_irn_link(n)) {
2544 if (eset_contains(extnodes, n))
2545 overrule_nodecolor = ird_color_block_inout;
2547 overrule_nodecolor = ird_color_default_node;
2548 if (!eset_contains(extnodes, n)) dump_ir_data_edges(F, n);
2551 /* Close the vcg information for the block */
2553 dump_const_node_local(F, b);
2557 eset_foreach(extnodes, ir_node*, b) {
2559 fprintf(F, "graph: { title: \"");
2561 fprintf(F, "\" label: \"");
2562 dump_node_opcode(F, b);
2563 fprintf(F, " %ld:%u", get_irn_node_nr(b), get_irn_idx(b));
2564 fprintf(F, "\" status:clustered color:lightblue\n");
2566 /* dump the nodes that go into the block */
2567 for (n = (ir_node*)get_irn_link(b); n; n = (ir_node*)get_irn_link(n)) {
2568 if (!eset_contains(loopnodes, n))
2569 overrule_nodecolor = ird_color_block_inout;
2571 overrule_nodecolor = ird_color_default_node;
2572 if (eset_contains(loopnodes, n)) dump_ir_data_edges(F, n);
2575 /* Close the vcg information for the block */
2577 dump_const_node_local(F, b);
2581 eset_destroy(loopnodes);
2582 eset_destroy(extnodes);
2587 static bool obstack_init;
2588 static struct obstack obst;
2589 static char *dump_path;
2591 void ir_set_dump_path(const char *path)
2594 dump_path = xstrdup(path);
2597 static void add_string_escaped(const char *string)
2600 for (p = string; *p != '\0'; ++p) {
2603 obstack_1grow(&obst, '@');
2604 obstack_1grow(&obst, '1');
2605 } else if (c == '@') {
2606 obstack_1grow(&obst, '@');
2607 obstack_1grow(&obst, '2');
2609 obstack_1grow(&obst, c);
2614 static void add_dump_path(void)
2616 if (!obstack_init) {
2617 obstack_init(&obst);
2618 obstack_init = true;
2621 if (dump_path != NULL) {
2622 size_t len = strlen(dump_path);
2623 obstack_grow(&obst, dump_path, len);
2624 if (len > 0 && dump_path[len-1] != '/')
2625 obstack_1grow(&obst, '/');
2629 void dump_ir_graph_ext(ir_graph_dump_func func, ir_graph *graph,
2632 const char *dump_name = get_irg_dump_name(graph);
2636 if (!ir_should_dump(dump_name))
2641 add_string_escaped(dump_name);
2642 obstack_printf(&obst, "-%02u", graph->dump_nr++);
2644 if (suffix != NULL) {
2645 if (suffix[0] != '.')
2646 obstack_1grow(&obst, '-');
2647 add_string_escaped(suffix);
2649 obstack_1grow(&obst, '\0');
2651 file_name = (char*)obstack_finish(&obst);
2652 /* xvcg expects only <CR> so we need "b"inary mode (for win32) */
2653 out = fopen(file_name, "wb");
2654 obstack_free(&obst, file_name);
2657 fprintf(stderr, "Couldn't open '%s': %s\n", file_name, strerror(errno));
2665 void dump_ir_prog_ext(ir_prog_dump_func func, const char *suffix)
2672 obstack_printf(&obst, "%02u", irp->dump_nr++);
2673 if (suffix != NULL) {
2674 if (suffix[0] != '.')
2675 obstack_1grow(&obst, '-');
2676 add_string_escaped(suffix);
2678 obstack_1grow(&obst, '\0');
2680 file_name = (char*)obstack_finish(&obst);
2681 out = fopen(file_name, "wb");
2682 obstack_free(&obst, file_name);
2685 fprintf(stderr, "Couldn't open '%s': %s\n", file_name, strerror(errno));
2692 void dump_ir_graph(ir_graph *graph, const char *suffix)
2696 snprintf(buf, sizeof(buf), "%s.vcg", suffix);
2697 dump_ir_graph_ext(dump_ir_graph_file, graph, buf);
2700 void dump_all_ir_graphs(const char *suffix)
2702 size_t i, n_irgs = get_irp_n_irgs();
2704 for (i = 0; i < n_irgs; ++i) {
2705 ir_graph *irg = get_irp_irg(i);
2706 dump_ir_graph(irg, suffix);
2710 typedef struct pass_t {
2711 ir_prog_pass_t pass;
2716 * Wrapper around dump_all_ir_graphs().
2718 static int dump_all_ir_graphs_wrapper(ir_prog *irp, void *context)
2720 pass_t *pass = (pass_t*)context;
2723 dump_all_ir_graphs(pass->suffix);
2727 ir_prog_pass_t *dump_all_ir_graph_pass(const char *name, const char *suffix)
2729 size_t len = strlen(suffix) + 1;
2730 pass_t *pass = XMALLOCF(pass_t, suffix, len);
2731 ir_prog_pass_t *res = def_prog_pass_constructor(
2732 &pass->pass, name ? name : "dump_all_graphs", dump_all_ir_graphs_wrapper);
2734 /* this pass does not change anything, so neither dump nor verify is needed. */
2735 res->dump_irprog = ir_prog_no_dump;
2736 res->verify_irprog = ir_prog_no_verify;
2738 memcpy(pass->suffix, suffix, len);