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,
38 #include "irgraph_t.h"
52 #include "callgraph.h"
53 #include "irextbb_t.h"
55 #include "dbginfo_t.h"
69 typedef struct pns_lookup {
70 long nr; /**< the proj number */
71 const char *name; /**< the name of the Proj */
74 typedef struct proj_lookup {
75 unsigned code; /**< the opcode of the Proj predecessor */
76 unsigned num_data; /**< number of data entries */
77 const pns_lookup_t *data; /**< the data */
80 #include "gen_irdump.c.inl"
82 /** Dump only irgs with names that start with this prefix. */
83 static ident *dump_file_filter_id = NULL;
85 static ir_dump_flags_t flags =
86 ir_dump_flag_blocks_as_subgraphs |
87 ir_dump_flag_keepalive_edges |
88 ir_dump_flag_ld_names |
89 ir_dump_flag_back_edges |
90 ir_dump_flag_consts_local |
91 ir_dump_flag_analysed_types |
92 ir_dump_flag_entities_in_hierarchy |
93 ir_dump_flag_number_label;
95 static ird_color_t overrule_nodecolor = ird_color_default_node;
97 /** The vcg node attribute hook. */
98 static dump_node_vcgattr_func dump_node_vcgattr_hook = NULL;
99 /** The vcg edge attribute hook. */
100 static dump_edge_vcgattr_func dump_edge_vcgattr_hook = NULL;
101 /** The vcg dump block edge hook */
102 static dump_node_edge_func dump_block_edge_hook = NULL;
103 /** The vcg dump node edge hook. */
104 static dump_node_edge_func dump_node_edge_hook = NULL;
106 void set_dump_node_edge_hook(dump_node_edge_func func)
108 dump_node_edge_hook = func;
111 dump_node_edge_func get_dump_node_edge_hook(void)
113 return dump_node_edge_hook;
116 void set_dump_block_edge_hook(dump_node_edge_func func)
118 dump_block_edge_hook = func;
121 dump_node_edge_func get_dump_block_edge_hook(void)
123 return dump_node_edge_hook;
126 void set_dump_node_vcgattr_hook(dump_node_vcgattr_func hook)
128 dump_node_vcgattr_hook = hook;
131 void set_dump_edge_vcgattr_hook(dump_edge_vcgattr_func hook)
133 dump_edge_vcgattr_hook = hook;
136 void ir_set_dump_flags(ir_dump_flags_t new_flags)
141 void ir_add_dump_flags(ir_dump_flags_t new_flags)
146 void ir_remove_dump_flags(ir_dump_flags_t to_remove)
151 ir_dump_flags_t ir_get_dump_flags(void)
156 /** Returns 0 if dump_out_edge_flag or dump_loop_information_flag
157 * are set, else returns dump_const_local_flag.
159 static bool get_opt_dump_const_local(void)
161 return (flags & ir_dump_flag_out_edges)
162 || (flags & ir_dump_flag_loops)
163 || (flags & ir_dump_flag_consts_local)
164 || (flags & ir_dump_flag_iredges);
167 static char *dump_filter;
169 void ir_set_dump_filter(const char *new_filter)
172 dump_filter = xstrdup(new_filter);
175 const char *ir_get_dump_filter(void)
180 int ir_should_dump(const char *name)
184 if (dump_filter == NULL || dump_filter[0] == '\0')
187 for (n = name, f = dump_filter; *f != '\0' && *n != '\0';
195 /* -------------- some extended helper functions ----------------- */
197 const char *get_mode_name_ex(const ir_mode *mode, int *bad)
200 return get_mode_name(mode);
206 #define CUSTOM_COLOR_BASE 100
207 static const char *color_names[ird_color_count];
208 static const char *color_rgb[ird_color_count];
209 static struct obstack color_obst;
211 /** define a custom color. */
212 static void custom_color(int num, const char *rgb_def)
214 assert(num < ird_color_count);
215 obstack_printf(&color_obst, "%d", CUSTOM_COLOR_BASE + num);
216 obstack_1grow(&color_obst, '\0');
218 color_rgb[num] = rgb_def;
219 color_names[num] = (const char*)obstack_finish(&color_obst);
222 /** Define a named color. */
223 static void named_color(int num, const char *name)
225 assert(num < ird_color_count);
226 color_rgb[num] = NULL;
227 color_names[num] = name;
230 /** Initializes the used colors. */
231 static void init_colors(void)
233 static int initialized = 0;
237 obstack_init(&color_obst);
239 custom_color(ird_color_prog_background, "204 204 204");
240 custom_color(ird_color_block_background, "255 255 0");
241 custom_color(ird_color_dead_block_background, "190 150 150");
242 named_color(ird_color_block_inout, "lightblue");
243 named_color(ird_color_default_node, "white");
244 custom_color(ird_color_memory, "153 153 255");
245 custom_color(ird_color_controlflow, "255 153 153");
246 custom_color(ird_color_const, "204 255 255");
247 custom_color(ird_color_proj, "255 255 153");
248 custom_color(ird_color_uses_memory, "153 153 255");
249 custom_color(ird_color_phi, "105 255 105");
250 custom_color(ird_color_anchor, "100 100 255");
251 named_color(ird_color_error, "red");
252 custom_color(ird_color_entity, "204 204 255");
258 * Prints the VCG color to a file.
260 static void print_vcg_color(FILE *out, ird_color_t color)
262 assert(color < ird_color_count);
263 fprintf(out, "color:%s", color_names[color]);
267 * Prints the edge kind of a given IR node.
269 * Projs should be dumped near their predecessor, so they get "nearedge".
271 static void print_node_edge_kind(FILE *out, ir_node *node)
274 fprintf(out, "nearedge: ");
276 fprintf(out, "edge: ");
281 * Prints the edge from a type S to a type T with additional info fmt, ...
284 static void print_type_type_edge(FILE *F, const ir_type *S, const ir_type *T, const char *fmt, ...)
289 fprintf(F, "edge: { sourcename: "); PRINT_TYPEID(S);
290 fprintf(F, " targetname: "); PRINT_TYPEID(T);
291 ir_vfprintf(F, fmt, ap);
297 * Prints the edge from a type tp to an entity ent with additional info fmt, ...
300 static void print_type_ent_edge(FILE *F, const ir_type *tp, const ir_entity *ent, const char *fmt, ...)
305 fprintf(F, "edge: { sourcename: "); PRINT_TYPEID(tp);
306 fprintf(F, " targetname: \""); PRINT_ENTID(ent); fprintf(F, "\"");
307 ir_vfprintf(F, fmt, ap);
313 * Prints the edge from an entity ent1 to an entity ent2 with additional info fmt, ...
316 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, ...)
322 fprintf(F, "backedge: { sourcename: \"");
324 fprintf(F, "edge: { sourcename: \"");
326 fprintf(F, "\" targetname: \""); PRINT_ENTID(ent2); fprintf(F, "\"");
327 ir_vfprintf(F, fmt, ap);
329 if (color != ird_color_none)
330 print_vcg_color(F, color);
336 * Prints the edge from an entity ent to a type tp with additional info fmt, ...
339 static void print_ent_type_edge(FILE *F, const ir_entity *ent, const ir_type *tp, const char *fmt, ...)
344 fprintf(F, "edge: { sourcename: \""); PRINT_ENTID(ent);
345 fprintf(F, "\" targetname: "); PRINT_TYPEID(tp);
346 ir_vfprintf(F, fmt, ap);
352 * Prints the edge from a node irn to a type tp with additional info fmt, ...
355 static void print_node_type_edge(FILE *F, const ir_node *irn, ir_type *tp, const char *fmt, ...)
360 fprintf(F, "edge: { sourcename: \""); PRINT_NODEID(irn);
361 fprintf(F, "\" targetname: "); PRINT_TYPEID(tp);
362 ir_vfprintf(F, fmt, ap);
368 * Prints the edge from a node irn to an entity ent with additional info fmt, ...
371 static void print_node_ent_edge(FILE *F, const ir_node *irn, const ir_entity *ent, const char *fmt, ...)
376 fprintf(F, "edge: { sourcename: \""); PRINT_NODEID(irn);
377 fprintf(F, "\" targetname: \""); PRINT_ENTID(ent);
379 ir_vfprintf(F, fmt, ap);
385 * Prints the edge from an entity ent to a node irn with additional info fmt, ...
388 static void print_ent_node_edge(FILE *F, const ir_entity *ent, const ir_node *irn, const char *fmt, ...)
393 fprintf(F, "edge: { sourcename: \""); PRINT_ENTID(ent);
394 fprintf(F, "\" targetname: \""); PRINT_NODEID(irn); fprintf(F, "\"");
395 ir_vfprintf(F, fmt, ap);
401 * Prints the edge from a type tp to an enumeration item item with additional info fmt, ...
404 static void print_enum_item_edge(FILE *F, const ir_type *tp, size_t item, const char *fmt, ...)
409 fprintf(F, "edge: { sourcename: "); PRINT_TYPEID(tp);
410 fprintf(F, " targetname: \""); PRINT_ITEMID(tp, item); fprintf(F, "\" ");
411 ir_vfprintf(F, fmt, ap);
416 /*-----------------------------------------------------------------*/
417 /* global and ahead declarations */
418 /*-----------------------------------------------------------------*/
420 static void dump_loop_nodes_into_graph(FILE *F, ir_graph *irg);
422 /*-----------------------------------------------------------------*/
423 /* Helper functions. */
424 /*-----------------------------------------------------------------*/
427 * This map is used as a private link attr to be able to call dumper
428 * anywhere without destroying link fields.
430 static pmap *irdump_link_map = NULL;
432 /** NOT A STANDARD LIBFIRM INIT METHOD
434 * We do not want to integrate dumping into libfirm, i.e., if the dumpers
435 * are off, we want to have as few interferences as possible. Therefore the
436 * initialization is performed lazily and not called from within init_firm.
438 * Creates the link attribute map. */
439 static void init_irdump(void)
441 /* We need a new, empty map. */
442 if (irdump_link_map) pmap_destroy(irdump_link_map);
443 irdump_link_map = pmap_create();
444 if (!dump_file_filter_id)
445 dump_file_filter_id = new_id_from_str("");
449 * Returns the private link field.
451 static void *ird_get_irn_link(const ir_node *n)
454 if (irdump_link_map == NULL)
457 if (pmap_contains(irdump_link_map, n))
458 res = pmap_get(irdump_link_map, n);
463 * Sets the private link field.
465 static void ird_set_irn_link(const ir_node *n, void *x)
467 if (irdump_link_map == NULL)
469 pmap_insert(irdump_link_map, n, x);
473 * Gets the private link field of an irg.
475 static void *ird_get_irg_link(const ir_graph *irg)
478 if (irdump_link_map == NULL)
481 if (pmap_contains(irdump_link_map, irg))
482 res = pmap_get(irdump_link_map, irg);
487 * Sets the private link field of an irg.
489 static void ird_set_irg_link(const ir_graph *irg, void *x)
491 if (irdump_link_map == NULL)
493 pmap_insert(irdump_link_map, irg, x);
497 * Walker, clears the private link field.
499 static void clear_link(ir_node *node, void *env)
502 ird_set_irn_link(node, NULL);
506 * If the entity has a ld_name, returns it if the dump_ld_name is set,
507 * else returns the name of the entity.
509 static const char *_get_ent_dump_name(const ir_entity *ent, bool dump_ld_name)
512 return "<NULL entity>";
514 /* Don't use get_entity_ld_ident (ent) as it computes the mangled name! */
515 if (ent->ld_name != NULL)
516 return get_id_str(ent->ld_name);
518 return get_id_str(ent->name);
521 const char *get_ent_dump_name(const ir_entity *ent)
523 return _get_ent_dump_name(ent, flags & ir_dump_flag_ld_names);
526 const char *get_irg_dump_name(const ir_graph *irg)
528 /* Don't use get_entity_ld_ident (ent) as it computes the mangled name! */
529 return _get_ent_dump_name(get_irg_entity(irg), true);
533 * Returns non-zero if a node is in floating state.
535 static int node_floats(const ir_node *n)
537 return ((get_irn_pinned(n) == op_pin_state_floats) &&
538 (get_irg_pinned(current_ir_graph) == op_pin_state_floats));
542 * Walker that visits the anchors
544 static void ird_walk_graph(ir_graph *irg, irg_walk_func *pre, irg_walk_func *post, void *env)
546 if ((flags & ir_dump_flag_all_anchors)
547 || ((flags & ir_dump_flag_iredges) && edges_activated(irg))) {
548 irg_walk_anchors(irg, pre, post, env);
550 irg_walk_graph(irg, pre, post, env);
555 * Walker, allocates an array for all blocks and puts their non-floating
556 * nodes into this array.
558 static void collect_node(ir_node *node, void *env)
563 || (get_op_flags(get_irn_op(node)) & irop_flag_dump_noblock)) {
564 ir_node ** arr = (ir_node **) ird_get_irg_link(get_irn_irg(node));
565 if (!arr) arr = NEW_ARR_F(ir_node *, 0);
566 ARR_APP1(ir_node *, arr, node);
567 ird_set_irg_link(get_irn_irg(node), arr); /* arr is an l-value, APP_ARR might change it! */
569 ir_node * block = get_nodes_block(node);
572 /* this node is in a Bad block, so we must place it into the graph's list */
573 ir_node ** arr = (ir_node **) ird_get_irg_link(get_irn_irg(node));
574 if (!arr) arr = NEW_ARR_F(ir_node *, 0);
575 ARR_APP1(ir_node *, arr, node);
576 ird_set_irg_link(get_irn_irg(node), arr); /* arr is an l-value, APP_ARR might change it! */
578 ird_set_irn_link(node, ird_get_irn_link(block));
579 ird_set_irn_link(block, node);
584 /** Construct lists to walk ir block-wise.
586 * Collects all blocks, nodes not op_pin_state_pinned,
587 * Bad, NoMem and Unknown into a flexible array in link field of
588 * irg they belong to. Sets the irg link field to NULL in all
589 * graphs not visited.
590 * Free the list with DEL_ARR_F().
592 static ir_node **construct_block_lists(ir_graph *irg)
595 int walk_flag = ir_resources_reserved(irg) & IR_RESOURCE_IRN_VISITED;
596 ir_graph *rem = current_ir_graph;
598 current_ir_graph = irg;
601 ir_free_resources(irg, IR_RESOURCE_IRN_VISITED);
604 for (i = get_irp_n_irgs(); i > 0;)
605 ird_set_irg_link(get_irp_irg(--i), NULL);
607 ird_walk_graph(current_ir_graph, clear_link, collect_node, current_ir_graph);
610 ir_reserve_resources(irg, IR_RESOURCE_IRN_VISITED);
613 current_ir_graph = rem;
614 return (ir_node**)ird_get_irg_link(irg);
617 typedef struct list_tuple {
619 ir_extblk **extbb_list;
622 /** Construct lists to walk IR extended block-wise.
623 * Free the lists in the tuple with DEL_ARR_F(). Sets the irg link field to
624 * NULL in all graphs not visited.
626 static list_tuple *construct_extblock_lists(ir_graph *irg)
628 ir_node **blk_list = construct_block_lists(irg);
630 ir_graph *rem = current_ir_graph;
631 list_tuple *lists = XMALLOC(list_tuple);
633 current_ir_graph = irg;
635 lists->blk_list = NEW_ARR_F(ir_node *, 0);
636 lists->extbb_list = NEW_ARR_F(ir_extblk *, 0);
638 inc_irg_block_visited(irg);
639 for (i = 0, n = ARR_LEN(blk_list); i < n; ++i) {
642 if (is_Block(blk_list[i])) {
643 ext = get_Block_extbb(blk_list[i]);
645 if (extbb_not_visited(ext)) {
646 ARR_APP1(ir_extblk *, lists->extbb_list, ext);
647 mark_extbb_visited(ext);
650 ARR_APP1(ir_node *, lists->blk_list, blk_list[i]);
654 current_ir_graph = rem;
655 ird_set_irg_link(irg, lists);
659 void dump_node_opcode(FILE *F, ir_node *n)
661 const ir_op_ops *ops = get_op_ops(get_irn_op(n));
663 /* call the dump_node operation if available */
664 if (ops->dump_node) {
665 ops->dump_node(F, n, dump_node_opcode_txt);
669 /* implementation for default nodes */
670 switch (get_irn_opcode(n)) {
672 switch (get_SymConst_kind(n)) {
673 case symconst_addr_ent:
674 fprintf(F, "SymC &%s", get_entity_name(get_SymConst_entity(n)));
676 case symconst_ofs_ent:
677 fprintf(F, "SymC %s offset", get_entity_name(get_SymConst_entity(n)));
679 case symconst_type_tag:
680 ir_fprintf(F, "SymC %+F tag", get_SymConst_type(n));
682 case symconst_type_size:
683 ir_fprintf(F, "SymC %+F size", get_SymConst_type(n));
685 case symconst_type_align:
686 ir_fprintf(F, "SymC %+F align", get_SymConst_type(n));
688 case symconst_enum_const:
689 fprintf(F, "SymC %s enum", get_enumeration_const_name(get_SymConst_enum(n)));
695 if (get_Load_unaligned(n) == align_non_aligned)
697 fprintf(F, "%s[%s]", get_irn_opname(n), get_mode_name_ex(get_Load_mode(n), NULL));
700 if (get_Store_unaligned(n) == align_non_aligned)
702 fprintf(F, "%s", get_irn_opname(n));
705 if (n == get_irg_start_block(get_irn_irg(n)))
707 if (n == get_irg_end_block(get_irn_irg(n)))
709 fprintf(F, "%s%s", get_irn_opname(n),
710 (flags & ir_dump_flag_show_marks) ? (get_Block_mark(n) ? "*" : "") : "");
713 if (get_Conv_strict(n))
714 fprintf(F, "strict");
715 fprintf(F, "%s", get_irn_opname(n));
718 fprintf(F, "%s", get_irn_opname(n));
719 if (get_Div_no_remainder(n))
721 fprintf(F, "[%s]", get_mode_name_ex(get_Div_resmode(n), NULL));
724 fprintf(F, "%s[%s]", get_irn_opname(n), get_mode_name_ex(get_Mod_resmode(n), NULL));
727 fprintf(F, "%s[%s]", get_irn_opname(n), get_builtin_kind_name(get_Builtin_kind(n)));
731 fprintf(F, "%s", get_irn_opname(n));
736 * Dump the mode of a node n to a file F.
737 * Ignore modes that are "always known".
739 static void dump_node_mode(FILE *F, ir_node *n)
741 const ir_op_ops *ops = get_op_ops(get_irn_op(n));
745 /* call the dump_node operation if available */
746 if (ops->dump_node) {
747 ops->dump_node(F, n, dump_node_mode_txt);
751 /* default implementation */
752 iro = get_irn_opcode(n);
764 mode = get_irn_mode(n);
766 if (mode != NULL && mode != mode_BB && mode != mode_ANY && mode != mode_BAD &&
767 (mode != mode_T || iro == iro_Proj))
768 fprintf(F, "%s", get_mode_name_ex(mode, NULL));
773 * Dump the type of a node n to a file F if it's known.
775 static int dump_node_typeinfo(FILE *F, ir_node *n)
779 if (ir_get_dump_flags() & ir_dump_flag_analysed_types) {
780 if (get_irg_typeinfo_state(current_ir_graph) == ir_typeinfo_consistent ||
781 get_irg_typeinfo_state(current_ir_graph) == ir_typeinfo_inconsistent) {
782 ir_type *tp = get_irn_typeinfo_type(n);
783 if (tp != firm_none_type) {
784 ir_fprintf(F, "[%+F]", tp);
794 * Dump additional node attributes of some nodes to a file F.
796 static void dump_node_nodeattr(FILE *F, ir_node *n)
801 const ir_op_ops *ops = get_op_ops(get_irn_op(n));
803 /* call the dump_node operation if available */
804 if (ops->dump_node) {
805 ops->dump_node(F, n, dump_node_nodeattr_txt);
809 switch (get_irn_opcode(n)) {
811 ir_fprintf(F, "%T ", get_Const_tarval(n));
815 pred = get_Proj_pred(n);
816 proj_nr = get_Proj_proj(n);
817 code = get_irn_opcode(pred);
819 if (code == iro_Proj && get_irn_opcode(get_Proj_pred(pred)) == iro_Start)
820 fprintf(F, "Arg %ld ", proj_nr);
821 else if (code == iro_Cond && get_irn_mode(get_Cond_selector(pred)) != mode_b)
822 fprintf(F, "%ld ", proj_nr);
824 unsigned i, j, f = 0;
826 for (i = 0; i < ARRAY_SIZE(proj_lut); ++i) {
827 if (code == proj_lut[i].code) {
828 for (j = 0; j < proj_lut[i].num_data; ++j) {
829 if (proj_nr == proj_lut[i].data[j].nr) {
830 fprintf(F, "%s ", proj_lut[i].data[j].name);
839 fprintf(F, "%ld ", proj_nr);
840 if (code == iro_Cond && get_Cond_jmp_pred(pred) != COND_JMP_PRED_NONE) {
841 if (proj_nr == pn_Cond_false && get_Cond_jmp_pred(pred) == COND_JMP_PRED_FALSE)
843 if (proj_nr == pn_Cond_true && get_Cond_jmp_pred(pred) == COND_JMP_PRED_TRUE)
849 fprintf(F, "%s ", get_ent_dump_name(get_Sel_entity(n)));
852 ir_fprintf(F, "(%+F)", get_Cast_type(n));
855 fprintf(F, "%s ", get_relation_string(get_Cmp_relation(n)));
858 fprintf(F, "%s ", get_relation_string(get_Confirm_relation(n)));
861 ir_fprintf(F, "(%+F)", get_CopyB_type(n));
869 static void dump_node_ana_vals(FILE *F, ir_node *n)
876 void dump_node_label(FILE *F, ir_node *n)
878 dump_node_opcode(F, n);
880 dump_node_mode(F, n);
882 dump_node_typeinfo(F, n);
883 dump_node_nodeattr(F, n);
884 if (flags & ir_dump_flag_number_label) {
885 fprintf(F, "%ld", get_irn_node_nr(n));
887 if (flags & ir_dump_flag_idx_label) {
888 fprintf(F, ":%u", get_irn_idx(n));
893 * Dumps the attributes of a node n into the file F.
894 * Currently this is only the color of a node.
896 static void dump_node_vcgattr(FILE *F, ir_node *node, ir_node *local, int bad)
902 print_vcg_color(F, ird_color_error);
906 if (dump_node_vcgattr_hook != NULL) {
907 dump_node_vcgattr_hook(F, node, local);
911 n = local ? local : node;
913 if (overrule_nodecolor != ird_color_default_node) {
914 print_vcg_color(F, overrule_nodecolor);
918 mode = get_irn_mode(n);
919 if (mode == mode_M) {
920 print_vcg_color(F, ird_color_memory);
923 if (mode == mode_X) {
924 print_vcg_color(F, ird_color_controlflow);
928 switch (get_irn_opcode(n)) {
931 print_vcg_color(F, ird_color_anchor);
934 print_vcg_color(F, ird_color_error);
937 print_vcg_color(F, ird_color_block_background);
940 print_vcg_color(F, ird_color_phi);
943 print_vcg_color(F, ird_color_memory);
947 print_vcg_color(F, ird_color_const);
950 print_vcg_color(F, ird_color_proj);
953 ir_op *op = get_irn_op(node);
955 if (is_op_constlike(op)) {
956 print_vcg_color(F, ird_color_const);
957 } else if (is_op_uses_memory(op)) {
958 print_vcg_color(F, ird_color_uses_memory);
959 } else if (is_op_cfopcode(op) || is_op_forking(op)) {
960 print_vcg_color(F, ird_color_controlflow);
966 void *dump_add_node_info_callback(dump_node_info_cb_t *cb, void *data)
968 hook_entry_t *info = XMALLOCZ(hook_entry_t);
970 info->hook._hook_node_info = cb;
971 info->context = data;
972 register_hook(hook_node_info, info);
977 void dump_remove_node_info_callback(void *handle)
979 hook_entry_t *info = (hook_entry_t*)handle;
980 unregister_hook(hook_node_info, info);
985 * Dump the node information of a node n to a file F.
987 static void dump_node_info(FILE *F, ir_node *n)
989 const ir_op_ops *ops = get_op_ops(get_irn_op(n));
991 fprintf(F, " info1: \"");
992 dump_irnode_to_file(F, n);
993 /* call the dump_node operation if available */
995 ops->dump_node(F, n, dump_node_info_txt);
997 /* allow additional info to be added */
998 hook_node_info(F, n);
1002 static int is_constlike_node(const ir_node *node)
1004 const ir_op *op = get_irn_op(node);
1005 return is_op_constlike(op);
1009 /** outputs the predecessors of n, that are constants, local. I.e.,
1010 generates a copy of the constant predecessors for each node called with. */
1011 static void dump_const_node_local(FILE *F, ir_node *n)
1014 if (!get_opt_dump_const_local()) return;
1016 /* Use visited flag to avoid outputting nodes twice.
1017 initialize it first. */
1018 for (i = 0; i < get_irn_arity(n); i++) {
1019 ir_node *con = get_irn_n(n, i);
1020 if (is_constlike_node(con)) {
1021 set_irn_visited(con, get_irg_visited(current_ir_graph) - 1);
1025 for (i = 0; i < get_irn_arity(n); i++) {
1026 ir_node *con = get_irn_n(n, i);
1027 if (is_constlike_node(con) && !irn_visited_else_mark(con)) {
1028 /* Generate a new name for the node by appending the names of
1030 fprintf(F, "node: {title: "); PRINT_CONSTID(n, con);
1031 fprintf(F, " label: \"");
1032 dump_node_label(F, con);
1034 dump_node_info(F, con);
1035 dump_node_vcgattr(F, n, con, 0);
1041 /** If the block of an edge is a const_like node, dump it local with an edge */
1042 static void dump_const_block_local(FILE *F, ir_node *n)
1046 if (!get_opt_dump_const_local()) return;
1048 blk = get_nodes_block(n);
1049 if (is_constlike_node(blk)) {
1050 /* Generate a new name for the node by appending the names of
1052 fprintf(F, "node: {title: \""); PRINT_CONSTBLKID(n, blk);
1053 fprintf(F, "\" label: \"");
1054 dump_node_label(F, blk);
1056 dump_node_info(F, blk);
1057 dump_node_vcgattr(F, n, blk, 0);
1060 fprintf(F, "edge: { sourcename: \"");
1062 fprintf(F, "\" targetname: \""); PRINT_CONSTBLKID(n,blk);
1064 if (dump_edge_vcgattr_hook) {
1066 if (dump_edge_vcgattr_hook(F, n, -1)) {
1070 fprintf(F, " " BLOCK_EDGE_ATTR "}\n");
1075 fprintf(F, "\" " BLOCK_EDGE_ATTR "}\n");
1080 * prints the error message of a node to a file F as info2.
1082 static void print_node_error(FILE *F, const char *err_msg)
1087 fprintf(F, " info2: \"%s\"", err_msg);
1091 * prints debug messages of a node to file F as info3.
1093 static void print_dbg_info(FILE *F, dbg_info *dbg)
1097 ir_dbg_info_snprint(buf, sizeof(buf), dbg);
1099 fprintf(F, " info3: \"%s\"\n", buf);
1103 static void print_type_dbg_info(FILE *F, type_dbg_info *dbg)
1113 static void dump_node(FILE *F, ir_node *n)
1118 if (get_opt_dump_const_local() && is_constlike_node(n))
1121 /* dump this node */
1122 fputs("node: {title: \"", F);
1126 fputs(" label: \"", F);
1127 bad = ! irn_verify_irg_dump(n, current_ir_graph, &p);
1128 dump_node_label(F, n);
1129 dump_node_ana_vals(F, n);
1130 //dump_node_ana_info(F, n);
1133 if (get_op_flags(get_irn_op(n)) & irop_flag_dump_noinput) {
1134 //fputs(" node_class:23", F);
1137 dump_node_info(F, n);
1138 print_node_error(F, p);
1139 print_dbg_info(F, get_irn_dbg_info(n));
1140 dump_node_vcgattr(F, n, NULL, bad);
1142 dump_const_node_local(F, n);
1144 if (dump_node_edge_hook)
1145 dump_node_edge_hook(F, n);
1148 /** dump the edge to the block this node belongs to */
1149 static void dump_ir_block_edge(FILE *F, ir_node *n)
1151 if (get_opt_dump_const_local() && is_constlike_node(n)) return;
1153 ir_node *block = get_nodes_block(n);
1155 if (get_opt_dump_const_local() && is_constlike_node(block)) {
1156 dump_const_block_local(F, n);
1158 fprintf(F, "edge: { sourcename: \"");
1160 fprintf(F, "\" targetname: ");
1161 fprintf(F, "\""); PRINT_NODEID(block); fprintf(F, "\"");
1163 if (dump_edge_vcgattr_hook) {
1165 if (dump_edge_vcgattr_hook(F, n, -1)) {
1169 fprintf(F, " " BLOCK_EDGE_ATTR "}\n");
1174 fprintf(F, " " BLOCK_EDGE_ATTR "}\n");
1179 static void print_data_edge_vcgattr(FILE *F, ir_node *from, int to)
1182 * do not use get_nodes_block() here, will fail
1183 * if the irg is not pinned.
1185 if (get_irn_n(from, -1) == get_irn_n(get_irn_n(from, to), -1))
1186 fprintf(F, INTRA_DATA_EDGE_ATTR);
1188 fprintf(F, INTER_DATA_EDGE_ATTR);
1191 static void print_mem_edge_vcgattr(FILE *F, ir_node *from, int to)
1194 * do not use get_nodes_block() here, will fail
1195 * if the irg is not pinned.
1197 if (get_irn_n(from, -1) == get_irn_n(get_irn_n(from, to), -1))
1198 fprintf(F, INTRA_MEM_EDGE_ATTR);
1200 fprintf(F, INTER_MEM_EDGE_ATTR);
1203 /** Print the vcg attributes for the edge from node "from" to its "to"th input */
1204 static void print_edge_vcgattr(FILE *F, ir_node *from, int to)
1208 if (dump_edge_vcgattr_hook)
1209 if (dump_edge_vcgattr_hook(F, from, to))
1212 if ((flags & ir_dump_flag_back_edges) && is_backedge(from, to))
1213 fprintf(F, BACK_EDGE_ATTR);
1215 switch (get_irn_opcode(from)) {
1217 fprintf(F, CF_EDGE_ATTR);
1219 case iro_Start: break;
1222 if (get_irn_mode(get_End_keepalive(from, to)) == mode_BB)
1223 fprintf(F, KEEP_ALIVE_CF_EDGE_ATTR);
1225 fprintf(F, KEEP_ALIVE_DF_EDGE_ATTR);
1229 if (is_Proj(from)) {
1230 if (get_irn_mode(from) == mode_M)
1231 print_mem_edge_vcgattr(F, from, to);
1232 else if (get_irn_mode(from) == mode_X)
1233 fprintf(F, CF_EDGE_ATTR);
1235 print_data_edge_vcgattr(F, from, to);
1237 else if (get_irn_mode(get_irn_n(from, to)) == mode_M)
1238 print_mem_edge_vcgattr(F, from, to);
1239 else if (get_irn_mode(get_irn_n(from, to)) == mode_X)
1240 fprintf(F, CF_EDGE_ATTR);
1242 print_data_edge_vcgattr(F, from, to);
1246 /** dump edges to our inputs */
1247 static void dump_ir_data_edges(FILE *F, ir_node *n)
1251 if (!(flags & ir_dump_flag_keepalive_edges) && is_End(n)) {
1252 /* the End node has only keep-alive edges */
1256 /* dump the dependency edges. */
1257 num = get_irn_deps(n);
1258 for (i = 0; i < num; ++i) {
1259 ir_node *dep = get_irn_dep(n, i);
1262 print_node_edge_kind(F, n);
1263 fprintf(F, "{sourcename: \"");
1265 fprintf(F, "\" targetname: ");
1266 if ((get_opt_dump_const_local()) && is_constlike_node(dep)) {
1267 PRINT_CONSTID(n, dep);
1273 fprintf(F, " label: \"%d\" ", i);
1274 fprintf(F, " color: darkgreen}\n");
1278 num = get_irn_arity(n);
1279 for (i = 0; i < num; i++) {
1280 ir_node *pred = get_irn_n(n, i);
1283 if ((flags & ir_dump_flag_back_edges) && is_backedge(n, i)) {
1284 fprintf(F, "backedge: {sourcename: \"");
1286 print_node_edge_kind(F, n);
1287 fprintf(F, "{sourcename: \"");
1290 fprintf(F, "\" targetname: ");
1291 if ((get_opt_dump_const_local()) && is_constlike_node(pred)) {
1292 PRINT_CONSTID(n, pred);
1294 fprintf(F, "\""); PRINT_NODEID(pred); fprintf(F, "\"");
1296 fprintf(F, " label: \"%d\" ", i);
1297 print_edge_vcgattr(F, n, i);
1305 static void dump_ir_edges(ir_node *node, void *env)
1308 FILE *F = (FILE*)env;
1309 const ir_edge_t *edge;
1311 foreach_out_edge(node, edge) {
1312 ir_node *succ = get_edge_src_irn(edge);
1314 print_node_edge_kind(F, succ);
1315 fprintf(F, "{sourcename: \"");
1317 fprintf(F, "\" targetname: \"");
1321 fprintf(F, " label: \"%d\" ", i);
1322 fprintf(F, OUT_EDGE_ATTR);
1329 /** Dumps a node and its edges but not the block edge */
1330 static void dump_node_wo_blockedge(ir_node *n, void *env)
1332 FILE *F = (FILE*)env;
1334 dump_ir_data_edges(F, n);
1337 /** Dumps a node and its edges. */
1338 static void dump_node_with_edges(ir_node *n, void *env)
1340 FILE *F = (FILE*)env;
1341 dump_node_wo_blockedge(n, env);
1342 if (!node_floats(n))
1343 dump_ir_block_edge(F, n);
1346 /** Dumps a const-like node. */
1347 static void dump_const_node(ir_node *n, void *env)
1349 if (is_Block(n)) return;
1350 dump_node_wo_blockedge(n, env);
1353 /***********************************************************************/
1354 /* the following routines dump the nodes/irgs bracketed to graphs. */
1355 /***********************************************************************/
1357 /** Dumps a constant expression as entity initializer, array bound ... */
1358 static void dump_const_expression(FILE *F, ir_node *value)
1360 ir_graph *rem = current_ir_graph;
1361 ir_dump_flags_t old_flags = ir_get_dump_flags();
1362 ir_remove_dump_flags(ir_dump_flag_consts_local);
1364 current_ir_graph = get_const_code_irg();
1365 irg_walk(value, dump_const_node, NULL, F);
1366 /* Decrease visited flag so that we walk with the same flag for the next
1367 expression. This guarantees that we don't dump the same node twice,
1368 as for const expressions cse is performed to save memory. */
1369 set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph) -1);
1371 ir_set_dump_flags(old_flags);
1372 current_ir_graph = rem;
1375 /** Dump a block as graph containing its nodes.
1377 * Expects to find nodes belonging to the block as list in its
1379 * Dumps the edges of all nodes including itself. */
1380 static void dump_whole_block(FILE *F, ir_node *block)
1383 ird_color_t color = ird_color_block_background;
1385 assert(is_Block(block));
1387 fprintf(F, "graph: { title: \"");
1388 PRINT_NODEID(block);
1389 fprintf(F, "\" label: \"");
1390 dump_node_label(F, block);
1392 /* colorize blocks */
1393 if (! get_Block_matured(block))
1394 color = ird_color_block_background;
1396 fprintf(F, "\" status:clustered ");
1397 print_vcg_color(F, color);
1400 /* yComp can show attributes for blocks, XVCG parses but ignores them */
1401 dump_node_info(F, block);
1402 print_dbg_info(F, get_irn_dbg_info(block));
1404 /* dump the blocks edges */
1405 dump_ir_data_edges(F, block);
1407 if (dump_block_edge_hook)
1408 dump_block_edge_hook(F, block);
1410 /* dump the nodes that go into the block */
1411 for (node = (ir_node*)ird_get_irn_link(block); node; node = (ir_node*)ird_get_irn_link(node)) {
1413 dump_ir_data_edges(F, node);
1416 /* Close the vcg information for the block */
1418 dump_const_node_local(F, block);
1422 /** dumps a graph block-wise. Expects all blockless nodes in arr in irgs link.
1423 * The outermost nodes: blocks and nodes not op_pin_state_pinned, Bad, Unknown. */
1424 static void dump_block_graph(FILE *F, ir_graph *irg)
1427 ir_graph *rem = current_ir_graph;
1428 ir_node **arr = (ir_node**)ird_get_irg_link(irg);
1429 current_ir_graph = irg;
1431 for (i = 0, n = ARR_LEN(arr); i < n; ++i) {
1432 ir_node *node = arr[i];
1433 if (is_Block(node)) {
1434 /* Dumps the block and all the nodes in the block, which are to
1435 be found in Block->link. */
1436 dump_whole_block(F, node);
1438 /* Nodes that are not in a Block. */
1440 if (!node_floats(node) && is_Bad(get_nodes_block(node))) {
1441 dump_const_block_local(F, node);
1443 dump_ir_data_edges(F, node);
1445 if ((flags & ir_dump_flag_iredges) && edges_activated(irg))
1446 dump_ir_edges(node, F);
1449 if ((flags & ir_dump_flag_loops)
1450 && is_irg_state(irg, IR_GRAPH_STATE_CONSISTENT_LOOPINFO))
1451 dump_loop_nodes_into_graph(F, irg);
1453 current_ir_graph = rem;
1457 * Dump the info for an irg.
1458 * Parsed by XVCG but not shown. use yComp.
1460 static void dump_graph_info(FILE *F, ir_graph *irg)
1462 fprintf(F, "info1: \"");
1463 dump_entity_to_file(F, get_irg_entity(irg));
1466 /* dump graph state */
1467 fprintf(F, "state:");
1468 if (is_irg_state(irg, IR_GRAPH_STATE_ARCH_DEP))
1469 fprintf(F, " arch_dep");
1470 if (is_irg_state(irg, IR_GRAPH_STATE_MODEB_LOWERED))
1471 fprintf(F, " modeb_lowered");
1472 if (is_irg_state(irg, IR_GRAPH_STATE_NORMALISATION2))
1473 fprintf(F, " normalisation2");
1474 if (is_irg_state(irg, IR_GRAPH_STATE_IMPLICIT_BITFIELD_MASKING))
1475 fprintf(F, " implicit_bitfield_masking");
1476 if (is_irg_state(irg, IR_GRAPH_STATE_OPTIMIZE_UNREACHABLE_CODE))
1477 fprintf(F, " optimize_unreachable_code");
1478 if (is_irg_state(irg, IR_GRAPH_STATE_NO_CRITICAL_EDGES))
1479 fprintf(F, " no_critical_edges");
1480 if (is_irg_state(irg, IR_GRAPH_STATE_NO_BADS))
1481 fprintf(F, " no_bads");
1482 if (is_irg_state(irg, IR_GRAPH_STATE_NO_UNREACHABLE_CODE))
1483 fprintf(F, " no_unreachable_code");
1484 if (is_irg_state(irg, IR_GRAPH_STATE_ONE_RETURN))
1485 fprintf(F, " one_return");
1486 if (is_irg_state(irg, IR_GRAPH_STATE_CONSISTENT_DOMINANCE))
1487 fprintf(F, " consistent_dominance");
1488 if (is_irg_state(irg, IR_GRAPH_STATE_CONSISTENT_POSTDOMINANCE))
1489 fprintf(F, " consistent_postdominance");
1490 if (is_irg_state(irg, IR_GRAPH_STATE_CONSISTENT_OUT_EDGES))
1491 fprintf(F, " consistent_out_edges");
1492 if (is_irg_state(irg, IR_GRAPH_STATE_CONSISTENT_OUTS))
1493 fprintf(F, " consistent_outs");
1494 if (is_irg_state(irg, IR_GRAPH_STATE_CONSISTENT_LOOPINFO))
1495 fprintf(F, " consistent_loopinfo");
1496 if (is_irg_state(irg, IR_GRAPH_STATE_CONSISTENT_ENTITY_USAGE))
1497 fprintf(F, " consistent_entity_usage");
1498 if (is_irg_state(irg, IR_GRAPH_STATE_VALID_EXTENDED_BLOCKS))
1499 fprintf(F, " valid_exended_blocks");
1503 /** Dumps an irg as a graph clustered by block nodes.
1504 * If interprocedural view edges can point to nodes out of this graph.
1506 static void dump_graph_from_list(FILE *F, ir_graph *irg)
1508 ir_entity *ent = get_irg_entity(irg);
1510 fprintf(F, "graph: { title: \"");
1512 fprintf(F, "\" label: \"%s\" status:clustered color:%s \n",
1513 get_ent_dump_name(ent), color_names[ird_color_prog_background]);
1515 dump_graph_info(F, irg);
1516 print_dbg_info(F, get_entity_dbg_info(ent));
1518 dump_block_graph(F, irg);
1520 /* Close the vcg information for the irg */
1521 fprintf(F, "}\n\n");
1524 /*******************************************************************/
1525 /* Basic type and entity nodes and edges. */
1526 /*******************************************************************/
1528 /** dumps the edges between nodes and their type or entity attributes. */
1529 static void dump_node2type_edges(ir_node *n, void *env)
1531 FILE *F = (FILE*)env;
1534 switch (get_irn_opcode(n)) {
1536 /* @@@ some consts have an entity */
1539 if (SYMCONST_HAS_TYPE(get_SymConst_kind(n)))
1540 print_node_type_edge(F,n,get_SymConst_type(n),NODE2TYPE_EDGE_ATTR);
1543 print_node_ent_edge(F,n,get_Sel_entity(n),NODE2TYPE_EDGE_ATTR);
1546 print_node_type_edge(F,n,get_Call_type(n),NODE2TYPE_EDGE_ATTR);
1549 print_node_type_edge(F,n,get_Alloc_type(n),NODE2TYPE_EDGE_ATTR);
1552 print_node_type_edge(F,n,get_Free_type(n),NODE2TYPE_EDGE_ATTR);
1555 print_node_type_edge(F,n,get_Cast_type(n),NODE2TYPE_EDGE_ATTR);
1563 static int print_type_info(FILE *F, ir_type *tp)
1567 if (get_type_state(tp) == layout_undefined) {
1568 fprintf(F, "state: layout_undefined\n");
1570 fprintf(F, "state: layout_fixed,\n");
1572 if (get_type_mode(tp))
1573 fprintf(F, "mode: %s,\n", get_mode_name_ex(get_type_mode(tp), &bad));
1574 fprintf(F, "size: %db,\n", get_type_size_bits(tp));
1579 static void print_typespecific_info(FILE *F, ir_type *tp)
1581 switch (get_type_tpop_code(tp)) {
1583 fprintf(F, "peculiarity: %s\n", get_peculiarity_string(get_class_peculiarity(tp)));
1588 fprintf(F, "variadicity: %s\n", get_variadicity_name(get_method_variadicity(tp)));
1589 fprintf(F, "params: %d\n", get_method_n_params(tp));
1590 fprintf(F, "results: %d\n", get_method_n_ress(tp));
1596 case tpo_enumeration:
1608 static void print_typespecific_vcgattr(FILE *F, ir_type *tp)
1610 switch (get_type_tpop_code(tp)) {
1612 fprintf(F, " " TYPE_CLASS_NODE_ATTR);
1615 fprintf(F, " " TYPE_METH_NODE_ATTR);
1623 case tpo_enumeration:
1634 void dump_type_node(FILE *F, ir_type *tp)
1636 fprintf(F, "node: {title: ");
1638 fprintf(F, " label: \"");
1639 if (tp->dbi != NULL) {
1641 ir_print_type(buf, sizeof(buf), tp);
1642 fprintf(F, "%s '%s'", get_type_tpop_name(tp), buf);
1644 ir_fprintf(F, "%+F", tp);
1646 fputs("\" info1: \"", F);
1647 dump_type_to_file(F, tp);
1649 print_type_dbg_info(F, get_type_dbg_info(tp));
1650 print_typespecific_vcgattr(F, tp);
1654 static void dump_entity_node(FILE *F, ir_entity *ent)
1656 fprintf(F, "node: {title: \"");
1657 PRINT_ENTID(ent); fprintf(F, "\"");
1658 fprintf(F, " label: ");
1659 fprintf(F, "\"%s\" ", get_ent_dump_name(ent));
1661 print_vcg_color(F, ird_color_entity);
1662 fprintf(F, "\n info1: \"");
1664 dump_entity_to_file(F, ent);
1667 print_dbg_info(F, get_entity_dbg_info(ent));
1671 static void dump_enum_item(FILE *F, ir_type *tp, size_t pos)
1674 ir_enum_const *ec = get_enumeration_const(tp, pos);
1675 ident *id = get_enumeration_const_nameid(ec);
1676 ir_tarval *tv = get_enumeration_value(ec);
1679 tarval_snprintf(buf, sizeof(buf), tv);
1681 strncpy(buf, "<not set>", sizeof(buf));
1682 fprintf(F, "node: {title: \"");
1683 PRINT_ITEMID(tp, pos); fprintf(F, "\"");
1684 fprintf(F, " label: ");
1685 fprintf(F, "\"enum item %s\" " ENUM_ITEM_NODE_ATTR, get_id_str(id));
1686 fprintf(F, "\n info1: \"value: %s\"}\n", buf);
1690 * Dumps a new style initializer.
1692 static void dump_entity_initializer(FILE *F, const ir_entity *ent)
1700 * type-walker: Dumps a type or entity and its edges.
1702 static void dump_type_info(type_or_ent tore, void *env)
1704 FILE *F = (FILE*)env;
1705 size_t i = 0; /* to shutup gcc */
1707 /* dump this type or entity */
1709 switch (get_kind(tore.ent)) {
1711 ir_entity *ent = tore.ent;
1714 dump_entity_node(F, ent);
1716 /* skip this to reduce graph. Member edge of type is parallel to this edge. *
1717 fprintf(F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
1718 ENT_OWN_EDGE_ATTR "}\n", ent, get_entity_owner(ent));*/
1719 print_ent_type_edge(F,ent, get_entity_type(ent), ENT_TYPE_EDGE_ATTR);
1720 if (is_Class_type(get_entity_owner(ent))) {
1721 for (i = get_entity_n_overwrites(ent); i > 0;)
1722 print_ent_ent_edge(F, ent, get_entity_overwrites(ent, --i), 0, ird_color_none, ENT_OVERWRITES_EDGE_ATTR);
1724 /* attached subgraphs */
1725 if (! (flags & ir_dump_flag_no_entity_values)) {
1726 if (ent->initializer != NULL) {
1727 /* new style initializers */
1728 dump_entity_initializer(F, ent);
1729 } else if (entity_has_compound_ent_values(ent)) {
1730 /* old style compound entity values */
1731 for (i = get_compound_ent_n_values(ent); i > 0;) {
1732 value = get_compound_ent_value(ent, --i);
1734 print_ent_node_edge(F, ent, value, ENT_VALUE_EDGE_ATTR, i);
1735 dump_const_expression(F, value);
1736 print_ent_ent_edge(F, ent, get_compound_ent_value_member(ent, i), 0, ird_color_none, ENT_CORR_EDGE_ATTR, i);
1738 fprintf(F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
1739 ENT_CORR_EDGE_ATTR "}\n", GET_ENTID(ent),
1740 get_compound_ent_value_member(ent, i), i);
1749 ir_type *tp = tore.typ;
1750 dump_type_node(F, tp);
1751 /* and now the edges */
1752 switch (get_type_tpop_code(tp)) {
1754 for (i = get_class_n_supertypes(tp); i > 0;) {
1756 print_type_type_edge(F, tp, get_class_supertype(tp, i), TYPE_SUPER_EDGE_ATTR);
1758 for (i = get_class_n_members(tp); i > 0;) {
1760 print_type_ent_edge(F, tp, get_class_member(tp, i), TYPE_MEMBER_EDGE_ATTR);
1764 for (i = get_struct_n_members(tp); i > 0;) {
1766 print_type_ent_edge(F, tp, get_struct_member(tp, i), TYPE_MEMBER_EDGE_ATTR);
1770 for (i = get_method_n_params(tp); i > 0;) {
1772 print_type_type_edge(F, tp, get_method_param_type(tp, i), METH_PAR_EDGE_ATTR,i);
1774 for (i = get_method_n_ress(tp); i > 0;) {
1776 print_type_type_edge(F, tp, get_method_res_type(tp, i), METH_RES_EDGE_ATTR,i);
1780 for (i = get_union_n_members(tp); i > 0;) {
1782 print_type_ent_edge(F, tp, get_union_member(tp, i), UNION_EDGE_ATTR);
1786 print_type_type_edge(F, tp, get_array_element_type(tp), ARR_ELT_TYPE_EDGE_ATTR);
1787 print_type_ent_edge(F, tp, get_array_element_entity(tp), ARR_ENT_EDGE_ATTR);
1788 for (i = get_array_n_dimensions(tp); i > 0;) {
1789 ir_node *upper, *lower;
1792 upper = get_array_upper_bound(tp, i);
1793 lower = get_array_lower_bound(tp, i);
1794 print_node_type_edge(F, upper, tp, "label: \"upper %zu\"", get_array_order(tp, i));
1795 print_node_type_edge(F, lower, tp, "label: \"lower %zu\"", get_array_order(tp, i));
1796 dump_const_expression(F, upper);
1797 dump_const_expression(F, lower);
1800 case tpo_enumeration:
1801 for (i = get_enumeration_n_enums(tp); i > 0;) {
1803 dump_enum_item(F, tp, i);
1804 print_enum_item_edge(F, tp, i, "label: \"item %zu\"", i);
1808 print_type_type_edge(F, tp, get_pointer_points_to_type(tp), PTR_PTS_TO_EDGE_ATTR);
1815 break; /* case k_type */
1818 printf(" *** irdump, dump_type_info(l.%i), faulty type.\n", __LINE__);
1822 /** For dumping class hierarchies.
1823 * Dumps a class type node and a superclass edge.
1825 static void dump_class_hierarchy_node(type_or_ent tore, void *ctx)
1827 FILE *F = (FILE*)ctx;
1828 size_t i = 0; /* to shutup gcc */
1830 /* dump this type or entity */
1831 switch (get_kind(tore.ent)) {
1833 ir_entity *ent = tore.ent;
1834 if (get_entity_owner(ent) == get_glob_type()) break;
1835 if (!is_Method_type(get_entity_type(ent)))
1837 if (flags & ir_dump_flag_entities_in_hierarchy
1838 && is_Class_type(get_entity_owner(ent))) {
1840 dump_entity_node(F, ent);
1842 print_type_ent_edge(F, get_entity_owner(ent), ent, TYPE_MEMBER_EDGE_ATTR);
1843 for (i = get_entity_n_overwrites(ent); i > 0;) {
1845 print_ent_ent_edge(F, get_entity_overwrites(ent, i), ent, 0, ird_color_none, ENT_OVERWRITES_EDGE_ATTR);
1851 ir_type *tp = tore.typ;
1852 if (tp == get_glob_type())
1854 switch (get_type_tpop_code(tp)) {
1856 dump_type_node(F, tp);
1857 /* and now the edges */
1858 for (i = get_class_n_supertypes(tp); i > 0;) {
1860 print_type_type_edge(F,tp,get_class_supertype(tp, i),TYPE_SUPER_EDGE_ATTR);
1865 break; /* case k_type */
1868 printf(" *** irdump, dump_class_hierarchy_node(l.%i), faulty type.\n", __LINE__);
1872 /*******************************************************************/
1873 /* dump analysis information that is expressed in graph terms. */
1874 /*******************************************************************/
1876 /* dump out edges */
1877 static void dump_out_edge(ir_node *n, void *env)
1879 FILE *F = (FILE*)env;
1881 for (i = get_irn_n_outs(n) - 1; i >= 0; --i) {
1882 ir_node *succ = get_irn_out(n, i);
1884 print_node_edge_kind(F, succ);
1885 fprintf(F, "{sourcename: \"");
1887 fprintf(F, "\" targetname: \"");
1889 fprintf(F, "\" color: red linestyle: dashed");
1894 static void dump_loop_label(FILE *F, ir_loop *loop)
1896 fprintf(F, "loop %u, %lu sons, %lu nodes",
1897 get_loop_depth(loop), (unsigned long) get_loop_n_sons(loop),
1898 (unsigned long) get_loop_n_nodes(loop));
1901 static void dump_loop_info(FILE *F, ir_loop *loop)
1903 fprintf(F, " info1: \"");
1904 fprintf(F, " loop nr: %ld", get_loop_loop_nr(loop));
1905 #ifdef DEBUG_libfirm /* GL @@@ debug analyses */
1906 fprintf(F, "\n The loop was analyzed %ld times.", (long int) PTR_TO_INT(get_loop_link(loop)));
1911 static void dump_loop_node(FILE *F, ir_loop *loop)
1913 fprintf(F, "node: {title: \"");
1915 fprintf(F, "\" label: \"");
1916 dump_loop_label(F, loop);
1918 dump_loop_info(F, loop);
1922 static void dump_loop_node_edge(FILE *F, ir_loop *loop, size_t i)
1925 fprintf(F, "edge: {sourcename: \"");
1927 fprintf(F, "\" targetname: \"");
1928 PRINT_NODEID(get_loop_node(loop, i));
1929 fprintf(F, "\" color: green");
1933 static void dump_loop_son_edge(FILE *F, ir_loop *loop, size_t i)
1936 fprintf(F, "edge: {sourcename: \"");
1938 fprintf(F, "\" targetname: \"");
1939 PRINT_LOOPID(get_loop_son(loop, i));
1940 ir_fprintf(F, "\" color: darkgreen label: \"%zu\"}\n",
1941 get_loop_element_pos(loop, get_loop_son(loop, i)));
1944 static void dump_loops(FILE *F, ir_loop *loop)
1947 /* dump this loop node */
1948 dump_loop_node(F, loop);
1950 /* dump edges to nodes in loop -- only if it is a real loop */
1951 if (get_loop_depth(loop) != 0) {
1952 for (i = get_loop_n_nodes(loop); i > 0;) {
1954 dump_loop_node_edge(F, loop, i);
1957 for (i = get_loop_n_sons(loop); i > 0;) {
1959 dump_loops(F, get_loop_son(loop, i));
1960 dump_loop_son_edge(F, loop, i);
1964 static void dump_loop_nodes_into_graph(FILE *F, ir_graph *irg)
1966 ir_loop *loop = get_irg_loop(irg);
1969 ir_graph *rem = current_ir_graph;
1970 current_ir_graph = irg;
1972 dump_loops(F, loop);
1974 current_ir_graph = rem;
1980 * dumps the VCG header
1982 void dump_vcg_header(FILE *F, const char *name, const char *layout, const char *orientation)
1986 = (flags & ir_dump_flag_disable_edge_labels) ? "no" : "yes";
1990 if (! layout) layout = "Compilergraph";
1991 if (!orientation) orientation = "bottom_to_top";
1995 "graph: { title: \"ir graph of %s\"\n"
1996 "display_edge_labels: %s\n"
1997 "layoutalgorithm: mindepth //$ \"%s\"\n"
1998 "manhattan_edges: yes\n"
1999 "port_sharing: no\n"
2001 "classname 1: \"intrablock Data\"\n"
2002 "classname 2: \"Block\"\n"
2003 "classname 3: \"Entity type\"\n"
2004 "classname 4: \"Entity owner\"\n"
2005 "classname 5: \"Method Param\"\n"
2006 "classname 6: \"Method Res\"\n"
2007 "classname 7: \"Super\"\n"
2008 "classname 8: \"Union\"\n"
2009 "classname 9: \"Points-to\"\n"
2010 "classname 10: \"Array Element Type\"\n"
2011 "classname 11: \"Overwrites\"\n"
2012 "classname 12: \"Member\"\n"
2013 "classname 13: \"Control Flow\"\n"
2014 "classname 14: \"intrablock Memory\"\n"
2015 "classname 15: \"Dominators\"\n"
2016 "classname 16: \"interblock Data\"\n"
2017 "classname 17: \"interblock Memory\"\n"
2018 "classname 18: \"Exception Control Flow for Interval Analysis\"\n"
2019 "classname 19: \"Postdominators\"\n"
2020 "classname 20: \"Keep Alive\"\n"
2021 "classname 21: \"Out Edges\"\n"
2022 "classname 22: \"Macro Block Edges\"\n"
2023 //"classname 23: \"NoInput Nodes\"\n"
2024 "infoname 1: \"Attribute\"\n"
2025 "infoname 2: \"Verification errors\"\n"
2026 "infoname 3: \"Debug info\"\n",
2027 name, label, layout, orientation);
2029 for (i = 0; i < ird_color_count; ++i) {
2030 if (color_rgb[i] != NULL) {
2031 fprintf(F, "colorentry %s: %s\n", color_names[i], color_rgb[i]);
2038 * Dumps the vcg file footer
2040 void dump_vcg_footer(FILE *F)
2047 static void dump_blocks_as_subgraphs(FILE *out, ir_graph *irg)
2051 construct_block_lists(irg);
2054 * If we are in the interprocedural view, we dump not
2055 * only the requested irg but also all irgs that can be reached
2058 for (i = get_irp_n_irgs(); i > 0;) {
2059 ir_graph *other_irg = get_irp_irg(--i);
2060 ir_node **arr = (ir_node**)ird_get_irg_link(other_irg);
2064 dump_graph_from_list(out, other_irg);
2069 /** dumps a graph extended block-wise. Expects all blockless nodes in arr in irgs link.
2070 * The outermost nodes: blocks and nodes not op_pin_state_pinned, Bad, Unknown. */
2071 static void dump_extblock_graph(FILE *F, ir_graph *irg)
2074 ir_graph *rem = current_ir_graph;
2075 ir_extblk **arr = (ir_extblk**)ird_get_irg_link(irg);
2076 current_ir_graph = irg;
2078 for (i = 0, arr_len = ARR_LEN(arr); i < arr_len; ++i) {
2079 ir_extblk *extbb = arr[i];
2080 ir_node *leader = get_extbb_leader(extbb);
2083 fprintf(F, "graph: { title: \"");
2084 PRINT_EXTBBID(leader);
2085 fprintf(F, "\" label: \"ExtBB %ld\" status:clustered color:lightgreen\n",
2086 get_irn_node_nr(leader));
2088 for (j = 0, n_blks = ARR_LEN(extbb->blks); j < n_blks; ++j) {
2089 ir_node *node = extbb->blks[j];
2090 if (is_Block(node)) {
2091 /* Dumps the block and all the nodes in the block, which are to
2092 be found in Block->link. */
2093 dump_whole_block(F, node);
2095 /* Nodes that are not in a Block. */
2097 if (is_Bad(get_nodes_block(node)) && !node_floats(node)) {
2098 dump_const_block_local(F, node);
2100 dump_ir_data_edges(F, node);
2106 if ((flags & ir_dump_flag_loops)
2107 && (is_irg_state(irg, IR_GRAPH_STATE_CONSISTENT_LOOPINFO)))
2108 dump_loop_nodes_into_graph(F, irg);
2110 current_ir_graph = rem;
2114 static void dump_blocks_extbb_grouped(FILE *F, ir_graph *irg)
2117 ir_entity *ent = get_irg_entity(irg);
2119 if (!is_irg_state(irg, IR_GRAPH_STATE_VALID_EXTENDED_BLOCKS))
2122 construct_extblock_lists(irg);
2124 fprintf(F, "graph: { title: \"");
2126 fprintf(F, "\" label: \"%s\" status:clustered color: white \n",
2127 get_ent_dump_name(ent));
2129 dump_graph_info(F, irg);
2130 print_dbg_info(F, get_entity_dbg_info(ent));
2132 for (i = get_irp_n_irgs(); i > 0;) {
2133 ir_graph *other_irg = get_irp_irg(--i);
2134 list_tuple *lists = (list_tuple*)ird_get_irg_link(other_irg);
2137 /* dump the extended blocks first */
2138 if (ARR_LEN(lists->extbb_list)) {
2139 ird_set_irg_link(other_irg, lists->extbb_list);
2140 dump_extblock_graph(F, other_irg);
2143 /* we may have blocks without extended blocks, bad for instance */
2144 if (ARR_LEN(lists->blk_list)) {
2145 ird_set_irg_link(other_irg, lists->blk_list);
2146 dump_block_graph(F, other_irg);
2149 DEL_ARR_F(lists->extbb_list);
2150 DEL_ARR_F(lists->blk_list);
2155 /* Close the vcg information for the irg */
2156 fprintf(F, "}\n\n");
2161 void dump_ir_graph_file(FILE *out, ir_graph *irg)
2163 dump_vcg_header(out, get_irg_dump_name(irg), NULL, NULL);
2166 if (flags & ir_dump_flag_blocks_as_subgraphs) {
2167 if (flags & ir_dump_flag_group_extbb) {
2168 dump_blocks_extbb_grouped(out, irg);
2170 dump_blocks_as_subgraphs(out, irg);
2173 /* dump_node_with_edges must be called in post visiting predecessors */
2174 ird_walk_graph(irg, NULL, dump_node_with_edges, out);
2177 /* dump type info */
2178 if (flags & ir_dump_flag_with_typegraph) {
2179 ir_graph *rem = current_ir_graph;
2180 current_ir_graph = irg;
2182 type_walk_irg(irg, dump_type_info, NULL, out);
2183 inc_irg_visited(get_const_code_irg());
2184 /* dump edges from graph to type info */
2185 irg_walk(get_irg_end(irg), dump_node2type_edges, NULL, out);
2187 current_ir_graph = rem;
2190 /* dump iredges out edges */
2191 if ((flags & ir_dump_flag_iredges) && edges_activated(current_ir_graph)) {
2192 irg_walk_edges(get_irg_start_block(irg), dump_ir_edges, NULL, out);
2195 /* dump the out edges in a separate walk */
2196 if ((flags & ir_dump_flag_out_edges)
2197 && (is_irg_state(irg, IR_GRAPH_STATE_CONSISTENT_OUTS))) {
2198 irg_out_walk(get_irg_start(irg), dump_out_edge, NULL, out);
2201 dump_vcg_footer(out);
2204 static void dump_block_to_cfg(ir_node *block, void *env)
2206 FILE *F = (FILE*)env;
2209 if (is_Bad(block) && get_irn_mode(block) == mode_X) {
2210 dump_node(F, block);
2213 if (is_Block(block)) {
2214 /* This is a block. Dump a node for the block. */
2215 fprintf(F, "node: {title: \""); PRINT_NODEID(block);
2216 fprintf(F, "\" label: \"");
2217 if (block == get_irg_start_block(get_irn_irg(block)))
2218 fprintf(F, "Start ");
2219 if (block == get_irg_end_block(get_irn_irg(block)))
2222 fprintf(F, "%s ", get_op_name(get_irn_op(block)));
2223 PRINT_NODEID(block);
2225 fprintf(F, "info1:\"");
2227 /* the generic version. */
2228 dump_irnode_to_file(F, block);
2230 fprintf(F, "\""); /* closing quote of info */
2232 if ((block == get_irg_start_block(get_irn_irg(block))) ||
2233 (block == get_irg_end_block(get_irn_irg(block))) )
2234 fprintf(F, " color:blue ");
2238 /* Dump the edges */
2239 for (i = get_Block_n_cfgpreds(block) - 1; i >= 0; --i) {
2240 ir_node *pred = get_Block_cfgpred(block, i);
2242 pred = get_nodes_block(pred);
2243 fprintf(F, "edge: { sourcename: \"");
2244 PRINT_NODEID(block);
2245 fprintf(F, "\" targetname: \"");
2247 fprintf(F, "\"}\n");
2250 /* Dump dominator/postdominator edge */
2251 if (ir_get_dump_flags() & ir_dump_flag_dominance) {
2252 if (is_irg_state(get_irn_irg(block), IR_GRAPH_STATE_CONSISTENT_DOMINANCE) && get_Block_idom(block)) {
2253 ir_node *pred = get_Block_idom(block);
2254 fprintf(F, "edge: { sourcename: \"");
2255 PRINT_NODEID(block);
2256 fprintf(F, "\" targetname: \"");
2258 fprintf(F, "\" " DOMINATOR_EDGE_ATTR "}\n");
2260 if (is_irg_state(get_irn_irg(block), IR_GRAPH_STATE_CONSISTENT_POSTDOMINANCE) && get_Block_ipostdom(block)) {
2261 ir_node *pred = get_Block_ipostdom(block);
2262 fprintf(F, "edge: { sourcename: \"");
2263 PRINT_NODEID(block);
2264 fprintf(F, "\" targetname: \"");
2266 fprintf(F, "\" " POSTDOMINATOR_EDGE_ATTR "}\n");
2272 void dump_cfg(FILE *F, ir_graph *irg)
2274 dump_vcg_header(F, get_irg_dump_name(irg), NULL, NULL);
2276 /* walk over the blocks in the graph */
2277 irg_walk_graph(irg, dump_block_to_cfg, NULL, F);
2282 void dump_callgraph(FILE *F)
2285 ir_dump_flags_t old_flags = ir_get_dump_flags();
2287 ir_remove_dump_flags(ir_dump_flag_disable_edge_labels);
2288 dump_vcg_header(F, "Callgraph", "Hierarchic", NULL);
2290 for (i = get_irp_n_irgs(); i > 0;) {
2291 ir_graph *irg = get_irp_irg(--i);
2292 ir_entity *ent = get_irg_entity(irg);
2293 size_t j, n_callees = get_irg_n_callees(irg);
2295 dump_entity_node(F, ent);
2296 for (j = 0; j < n_callees; ++j) {
2297 ir_entity *c = get_irg_entity(get_irg_callee(irg, j));
2298 int be = is_irg_callee_backedge(irg, j);
2299 const char *attr = be
2300 ? "label:\"recursion %zu\""
2301 : "label:\"calls %zu\"";
2302 print_ent_ent_edge(F, ent, c, be, ird_color_entity, attr,
2303 get_irg_callee_loop_depth(irg, j));
2307 ir_set_dump_flags(old_flags);
2311 void dump_typegraph(FILE *out)
2313 dump_vcg_header(out, "All_types", "Hierarchic", NULL);
2314 type_walk(dump_type_info, NULL, out);
2315 dump_vcg_footer(out);
2318 void dump_class_hierarchy(FILE *out)
2320 dump_vcg_header(out, "class_hierarchy", "Hierarchic", NULL);
2321 type_walk(dump_class_hierarchy_node, NULL, out);
2322 dump_vcg_footer(out);
2325 static void dump_loops_standalone(FILE *F, ir_loop *loop)
2328 bool loop_node_started = false;
2330 size_t son_number = 0;
2332 ir_loop *son = NULL;
2334 /* Dump a new loop node. */
2335 dump_loop_node(F, loop);
2337 /* Dump the loop elements. */
2338 for (i = 0; i < get_loop_n_elements(loop); i++) {
2339 le = get_loop_element(loop, i);
2341 if (get_kind(son) == k_ir_loop) {
2343 /* We are a loop son -> Recurse */
2345 if (loop_node_started) { /* Close the "firm-nodes" node first if we started one. */
2346 fprintf(F, "\" }\n");
2347 fprintf(F, "edge: {sourcename: \"");
2349 fprintf(F, "\" targetname: \"");
2351 fprintf(F, "-%lu-nodes\" label:\"%lu...%lu\"}\n",
2352 (unsigned long) first,
2353 (unsigned long) first,
2354 (unsigned long) i-1);
2355 loop_node_started = false;
2357 dump_loop_son_edge(F, loop, son_number++);
2358 dump_loops_standalone(F, son);
2359 } else if (get_kind(son) == k_ir_node) {
2360 /* We are a loop node -> Collect firm nodes */
2362 ir_node *n = le.node;
2363 if (!loop_node_started) {
2364 /* Start a new node which contains all firm nodes of the current loop */
2365 fprintf(F, "node: { title: \"");
2367 fprintf(F, "-%lu-nodes\" color: lightyellow label: \"",
2369 loop_node_started = true;
2374 dump_node_label(F, n);
2375 /* Causes indeterministic output: if (is_Block(n)) fprintf(F, "\t ->%d", (int)get_irn_link(n)); */
2376 if (has_backedges(n)) fprintf(F, "\t loop head!");
2377 } else { /* for callgraph loop tree */
2379 assert(get_kind(son) == k_ir_graph);
2381 /* We are a loop node -> Collect firm graphs */
2383 if (!loop_node_started) {
2384 /* Start a new node which contains all firm nodes of the current loop */
2385 fprintf(F, "node: { title: \"");
2387 fprintf(F, "-%lu-nodes\" color: lightyellow label: \"",
2389 loop_node_started = true;
2393 fprintf(F, " %s", get_irg_dump_name(n));
2394 /* fprintf(F, " %s (depth %d)", get_irg_dump_name(n), n->callgraph_weighted_loop_depth); */
2398 if (loop_node_started) {
2399 fprintf(F, "\" }\n");
2400 fprintf(F, "edge: {sourcename: \"");
2402 fprintf(F, "\" targetname: \"");
2404 fprintf(F, "-%lu-nodes\" label:\"%lu...%lu\"}\n",
2405 (unsigned long) first,
2406 (unsigned long) first,
2407 (unsigned long) i-1);
2408 loop_node_started = false;
2412 void dump_loop_tree(FILE *out, ir_graph *irg)
2414 ir_graph *rem = current_ir_graph;
2415 ir_dump_flags_t old_flags = ir_get_dump_flags();
2417 current_ir_graph = irg;
2418 ir_remove_dump_flags(ir_dump_flag_disable_edge_labels);
2420 dump_vcg_header(out, get_irg_dump_name(irg), "Tree", "top_to_bottom");
2422 if (get_irg_loop(irg))
2423 dump_loops_standalone(out, get_irg_loop(irg));
2425 dump_vcg_footer(out);
2427 ir_set_dump_flags(old_flags);
2428 current_ir_graph = rem;
2431 void dump_callgraph_loop_tree(FILE *out)
2433 dump_vcg_header(out, "callgraph looptree", "Tree", "top_to_bottom");
2434 dump_loops_standalone(out, irp->outermost_cg_loop);
2435 dump_vcg_footer(out);
2438 static void collect_nodeloop(FILE *F, ir_loop *loop, eset *loopnodes)
2442 int node_number = 0;
2444 if (flags & ir_dump_flag_loops)
2445 dump_loop_node(F, loop);
2447 for (i = 0; i < get_loop_n_elements(loop); i++) {
2448 loop_element le = get_loop_element(loop, i);
2449 if (*(le.kind) == k_ir_loop) {
2450 if (flags & ir_dump_flag_loops)
2451 dump_loop_son_edge(F, loop, son_number++);
2453 collect_nodeloop(F, le.son, loopnodes);
2455 if (flags & ir_dump_flag_loops)
2456 dump_loop_node_edge(F, loop, node_number++);
2457 eset_insert(loopnodes, le.node);
2462 static void collect_nodeloop_external_nodes(ir_loop *loop, eset *loopnodes,
2468 for (i = 0; i < get_loop_n_elements(loop); i++) {
2469 loop_element le = get_loop_element(loop, i);
2470 if (*(le.kind) == k_ir_loop) {
2472 collect_nodeloop_external_nodes(le.son, loopnodes, extnodes);
2474 if (is_Block(le.node)) start = 0; else start = -1;
2475 for (j = start; j < get_irn_arity(le.node); j++) {
2476 ir_node *pred = get_irn_n(le.node, j);
2477 if (!eset_contains(loopnodes, pred)) {
2478 eset_insert(extnodes, pred);
2479 if (!is_Block(pred)) {
2480 pred = get_nodes_block(pred);
2481 if (!eset_contains(loopnodes, pred)) eset_insert(extnodes, pred);
2489 void dump_loop(FILE *F, ir_loop *l)
2491 eset *loopnodes = eset_create();
2492 eset *extnodes = eset_create();
2496 snprintf(name, sizeof(name), "loop_%ld", get_loop_loop_nr(l));
2497 dump_vcg_header(F, name, NULL, NULL);
2499 /* collect all nodes to dump */
2500 collect_nodeloop(F, l, loopnodes);
2501 collect_nodeloop_external_nodes(l, loopnodes, extnodes);
2503 /* build block lists */
2504 eset_foreach(loopnodes, ir_node*, n) {
2505 set_irn_link(n, NULL);
2507 eset_foreach(extnodes, ir_node*, n) {
2508 set_irn_link(n, NULL);
2510 eset_foreach(loopnodes, ir_node*, n) {
2512 b = get_nodes_block(n);
2513 set_irn_link(n, get_irn_link(b));
2517 eset_foreach(extnodes, ir_node*, n) {
2519 b = get_nodes_block(n);
2520 set_irn_link(n, get_irn_link(b));
2525 eset_foreach(loopnodes, ir_node*, b) {
2527 fprintf(F, "graph: { title: \"");
2529 fprintf(F, "\" label: \"");
2530 dump_node_opcode(F, b);
2531 fprintf(F, " %ld:%u", get_irn_node_nr(b), get_irn_idx(b));
2532 fprintf(F, "\" status:clustered color:yellow\n");
2534 /* dump the blocks edges */
2535 dump_ir_data_edges(F, b);
2537 /* dump the nodes that go into the block */
2538 for (n = (ir_node*)get_irn_link(b); n; n = (ir_node*)get_irn_link(n)) {
2539 if (eset_contains(extnodes, n))
2540 overrule_nodecolor = ird_color_block_inout;
2542 overrule_nodecolor = ird_color_default_node;
2543 if (!eset_contains(extnodes, n)) dump_ir_data_edges(F, n);
2546 /* Close the vcg information for the block */
2548 dump_const_node_local(F, b);
2552 eset_foreach(extnodes, ir_node*, b) {
2554 fprintf(F, "graph: { title: \"");
2556 fprintf(F, "\" label: \"");
2557 dump_node_opcode(F, b);
2558 fprintf(F, " %ld:%u", get_irn_node_nr(b), get_irn_idx(b));
2559 fprintf(F, "\" status:clustered color:lightblue\n");
2561 /* dump the nodes that go into the block */
2562 for (n = (ir_node*)get_irn_link(b); n; n = (ir_node*)get_irn_link(n)) {
2563 if (!eset_contains(loopnodes, n))
2564 overrule_nodecolor = ird_color_block_inout;
2566 overrule_nodecolor = ird_color_default_node;
2567 if (eset_contains(loopnodes, n)) dump_ir_data_edges(F, n);
2570 /* Close the vcg information for the block */
2572 dump_const_node_local(F, b);
2576 eset_destroy(loopnodes);
2577 eset_destroy(extnodes);
2582 static bool obstack_init;
2583 static struct obstack obst;
2584 static char *dump_path;
2586 void ir_set_dump_path(const char *path)
2589 dump_path = xstrdup(path);
2592 static void add_string_escaped(const char *string)
2595 for (p = string; *p != '\0'; ++p) {
2598 obstack_1grow(&obst, '@');
2599 obstack_1grow(&obst, '1');
2600 } else if (c == '@') {
2601 obstack_1grow(&obst, '@');
2602 obstack_1grow(&obst, '2');
2604 obstack_1grow(&obst, c);
2609 static void add_dump_path(void)
2611 if (!obstack_init) {
2612 obstack_init(&obst);
2613 obstack_init = true;
2616 if (dump_path != NULL) {
2617 size_t len = strlen(dump_path);
2618 obstack_grow(&obst, dump_path, len);
2619 if (len > 0 && dump_path[len-1] != '/')
2620 obstack_1grow(&obst, '/');
2624 void dump_ir_graph_ext(ir_graph_dump_func func, ir_graph *graph,
2627 const char *dump_name = get_irg_dump_name(graph);
2631 if (!ir_should_dump(dump_name))
2636 add_string_escaped(dump_name);
2637 obstack_printf(&obst, "-%02u", graph->dump_nr++);
2639 if (suffix != NULL) {
2640 if (suffix[0] != '.')
2641 obstack_1grow(&obst, '-');
2642 add_string_escaped(suffix);
2644 obstack_1grow(&obst, '\0');
2646 file_name = (char*)obstack_finish(&obst);
2647 /* xvcg expects only <CR> so we need "b"inary mode (for win32) */
2648 out = fopen(file_name, "wb");
2649 obstack_free(&obst, file_name);
2652 fprintf(stderr, "Couldn't open '%s': %s\n", file_name, strerror(errno));
2660 void dump_ir_prog_ext(ir_prog_dump_func func, const char *suffix)
2667 obstack_printf(&obst, "%02u", irp->dump_nr++);
2668 if (suffix != NULL) {
2669 if (suffix[0] != '.')
2670 obstack_1grow(&obst, '-');
2671 add_string_escaped(suffix);
2673 obstack_1grow(&obst, '\0');
2675 file_name = (char*)obstack_finish(&obst);
2676 out = fopen(file_name, "wb");
2677 obstack_free(&obst, file_name);
2680 fprintf(stderr, "Couldn't open '%s': %s\n", file_name, strerror(errno));
2687 void dump_ir_graph(ir_graph *graph, const char *suffix)
2691 snprintf(buf, sizeof(buf), "%s.vcg", suffix);
2692 dump_ir_graph_ext(dump_ir_graph_file, graph, buf);
2695 void dump_all_ir_graphs(const char *suffix)
2697 size_t i, n_irgs = get_irp_n_irgs();
2699 for (i = 0; i < n_irgs; ++i) {
2700 ir_graph *irg = get_irp_irg(i);
2701 dump_ir_graph(irg, suffix);
2705 typedef struct pass_t {
2706 ir_prog_pass_t pass;
2711 * Wrapper around dump_all_ir_graphs().
2713 static int dump_all_ir_graphs_wrapper(ir_prog *irp, void *context)
2715 pass_t *pass = (pass_t*)context;
2718 dump_all_ir_graphs(pass->suffix);
2722 ir_prog_pass_t *dump_all_ir_graph_pass(const char *name, const char *suffix)
2724 size_t len = strlen(suffix) + 1;
2725 pass_t *pass = XMALLOCF(pass_t, suffix, len);
2726 ir_prog_pass_t *res = def_prog_pass_constructor(
2727 &pass->pass, name ? name : "dump_all_graphs", dump_all_ir_graphs_wrapper);
2729 /* this pass does not change anything, so neither dump nor verify is needed. */
2730 res->dump_irprog = ir_prog_no_dump;
2731 res->verify_irprog = ir_prog_no_verify;
2733 memcpy(pass->suffix, suffix, len);