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, const ir_loop *loop)
1896 fprintf(F, "loop %u", get_loop_depth(loop));
1899 static void dump_loop_info(FILE *F, const ir_loop *loop)
1901 fprintf(F, " info1: \"");
1902 fprintf(F, " loop nr: %ld", get_loop_loop_nr(loop));
1903 #ifdef DEBUG_libfirm /* GL @@@ debug analyses */
1904 fprintf(F, "\n The loop was analyzed %ld times.", (long int) PTR_TO_INT(get_loop_link(loop)));
1909 static void dump_loop_node(FILE *F, const ir_loop *loop)
1911 fprintf(F, "node: {title: \"");
1913 fprintf(F, "\" label: \"");
1914 dump_loop_label(F, loop);
1916 dump_loop_info(F, loop);
1920 static void dump_loop_node_edge(FILE *F, const ir_loop *loop, size_t i)
1923 fprintf(F, "edge: {sourcename: \"");
1925 fprintf(F, "\" targetname: \"");
1926 PRINT_NODEID(get_loop_element(loop, i).node);
1927 fprintf(F, "\" color: green");
1931 static void dump_loop_son_edge(FILE *F, const ir_loop *loop, size_t i)
1934 fprintf(F, "edge: {sourcename: \"");
1936 fprintf(F, "\" targetname: \"");
1937 PRINT_LOOPID(get_loop_element(loop, i).son);
1938 ir_fprintf(F, "\" color: darkgreen label: \"%zu\"}\n", i);
1941 static void dump_loops(FILE *F, const ir_loop *loop)
1944 size_t n_elements = get_loop_n_elements(loop);
1945 /* dump this loop node */
1946 dump_loop_node(F, loop);
1948 /* dump edges to nodes in loop -- only if it is a real loop */
1949 if (get_loop_depth(loop) != 0) {
1950 for (i = n_elements; i > 0;) {
1951 loop_element element;
1953 element = get_loop_element(loop, i);
1954 if (*element.kind != k_ir_node)
1956 dump_loop_node_edge(F, loop, i);
1959 for (i = n_elements; i > 0;) {
1960 loop_element element;
1962 element = get_loop_element(loop, i);
1963 if (*element.kind != k_ir_loop)
1965 dump_loops(F, element.son);
1966 dump_loop_son_edge(F, loop, i);
1970 static void dump_loop_nodes_into_graph(FILE *F, ir_graph *irg)
1972 ir_loop *loop = get_irg_loop(irg);
1975 ir_graph *rem = current_ir_graph;
1976 current_ir_graph = irg;
1978 dump_loops(F, loop);
1980 current_ir_graph = rem;
1986 * dumps the VCG header
1988 void dump_vcg_header(FILE *F, const char *name, const char *layout, const char *orientation)
1992 = (flags & ir_dump_flag_disable_edge_labels) ? "no" : "yes";
1996 if (! layout) layout = "Compilergraph";
1997 if (!orientation) orientation = "bottom_to_top";
2001 "graph: { title: \"ir graph of %s\"\n"
2002 "display_edge_labels: %s\n"
2003 "layoutalgorithm: mindepth //$ \"%s\"\n"
2004 "manhattan_edges: yes\n"
2005 "port_sharing: no\n"
2007 "classname 1: \"intrablock Data\"\n"
2008 "classname 2: \"Block\"\n"
2009 "classname 3: \"Entity type\"\n"
2010 "classname 4: \"Entity owner\"\n"
2011 "classname 5: \"Method Param\"\n"
2012 "classname 6: \"Method Res\"\n"
2013 "classname 7: \"Super\"\n"
2014 "classname 8: \"Union\"\n"
2015 "classname 9: \"Points-to\"\n"
2016 "classname 10: \"Array Element Type\"\n"
2017 "classname 11: \"Overwrites\"\n"
2018 "classname 12: \"Member\"\n"
2019 "classname 13: \"Control Flow\"\n"
2020 "classname 14: \"intrablock Memory\"\n"
2021 "classname 15: \"Dominators\"\n"
2022 "classname 16: \"interblock Data\"\n"
2023 "classname 17: \"interblock Memory\"\n"
2024 "classname 18: \"Exception Control Flow for Interval Analysis\"\n"
2025 "classname 19: \"Postdominators\"\n"
2026 "classname 20: \"Keep Alive\"\n"
2027 "classname 21: \"Out Edges\"\n"
2028 "classname 22: \"Macro Block Edges\"\n"
2029 //"classname 23: \"NoInput Nodes\"\n"
2030 "infoname 1: \"Attribute\"\n"
2031 "infoname 2: \"Verification errors\"\n"
2032 "infoname 3: \"Debug info\"\n",
2033 name, label, layout, orientation);
2035 for (i = 0; i < ird_color_count; ++i) {
2036 if (color_rgb[i] != NULL) {
2037 fprintf(F, "colorentry %s: %s\n", color_names[i], color_rgb[i]);
2044 * Dumps the vcg file footer
2046 void dump_vcg_footer(FILE *F)
2053 static void dump_blocks_as_subgraphs(FILE *out, ir_graph *irg)
2057 construct_block_lists(irg);
2060 * If we are in the interprocedural view, we dump not
2061 * only the requested irg but also all irgs that can be reached
2064 for (i = get_irp_n_irgs(); i > 0;) {
2065 ir_graph *other_irg = get_irp_irg(--i);
2066 ir_node **arr = (ir_node**)ird_get_irg_link(other_irg);
2070 dump_graph_from_list(out, other_irg);
2075 /** dumps a graph extended block-wise. Expects all blockless nodes in arr in irgs link.
2076 * The outermost nodes: blocks and nodes not op_pin_state_pinned, Bad, Unknown. */
2077 static void dump_extblock_graph(FILE *F, ir_graph *irg)
2080 ir_graph *rem = current_ir_graph;
2081 ir_extblk **arr = (ir_extblk**)ird_get_irg_link(irg);
2082 current_ir_graph = irg;
2084 for (i = 0, arr_len = ARR_LEN(arr); i < arr_len; ++i) {
2085 ir_extblk *extbb = arr[i];
2086 ir_node *leader = get_extbb_leader(extbb);
2089 fprintf(F, "graph: { title: \"");
2090 PRINT_EXTBBID(leader);
2091 fprintf(F, "\" label: \"ExtBB %ld\" status:clustered color:lightgreen\n",
2092 get_irn_node_nr(leader));
2094 for (j = 0, n_blks = ARR_LEN(extbb->blks); j < n_blks; ++j) {
2095 ir_node *node = extbb->blks[j];
2096 if (is_Block(node)) {
2097 /* Dumps the block and all the nodes in the block, which are to
2098 be found in Block->link. */
2099 dump_whole_block(F, node);
2101 /* Nodes that are not in a Block. */
2103 if (is_Bad(get_nodes_block(node)) && !node_floats(node)) {
2104 dump_const_block_local(F, node);
2106 dump_ir_data_edges(F, node);
2112 if ((flags & ir_dump_flag_loops)
2113 && (is_irg_state(irg, IR_GRAPH_STATE_CONSISTENT_LOOPINFO)))
2114 dump_loop_nodes_into_graph(F, irg);
2116 current_ir_graph = rem;
2120 static void dump_blocks_extbb_grouped(FILE *F, ir_graph *irg)
2123 ir_entity *ent = get_irg_entity(irg);
2125 if (!is_irg_state(irg, IR_GRAPH_STATE_VALID_EXTENDED_BLOCKS))
2128 construct_extblock_lists(irg);
2130 fprintf(F, "graph: { title: \"");
2132 fprintf(F, "\" label: \"%s\" status:clustered color: white \n",
2133 get_ent_dump_name(ent));
2135 dump_graph_info(F, irg);
2136 print_dbg_info(F, get_entity_dbg_info(ent));
2138 for (i = get_irp_n_irgs(); i > 0;) {
2139 ir_graph *other_irg = get_irp_irg(--i);
2140 list_tuple *lists = (list_tuple*)ird_get_irg_link(other_irg);
2143 /* dump the extended blocks first */
2144 if (ARR_LEN(lists->extbb_list)) {
2145 ird_set_irg_link(other_irg, lists->extbb_list);
2146 dump_extblock_graph(F, other_irg);
2149 /* we may have blocks without extended blocks, bad for instance */
2150 if (ARR_LEN(lists->blk_list)) {
2151 ird_set_irg_link(other_irg, lists->blk_list);
2152 dump_block_graph(F, other_irg);
2155 DEL_ARR_F(lists->extbb_list);
2156 DEL_ARR_F(lists->blk_list);
2161 /* Close the vcg information for the irg */
2162 fprintf(F, "}\n\n");
2167 void dump_ir_graph_file(FILE *out, ir_graph *irg)
2169 dump_vcg_header(out, get_irg_dump_name(irg), NULL, NULL);
2172 if (flags & ir_dump_flag_blocks_as_subgraphs) {
2173 if (flags & ir_dump_flag_group_extbb) {
2174 dump_blocks_extbb_grouped(out, irg);
2176 dump_blocks_as_subgraphs(out, irg);
2179 /* dump_node_with_edges must be called in post visiting predecessors */
2180 ird_walk_graph(irg, NULL, dump_node_with_edges, out);
2183 /* dump type info */
2184 if (flags & ir_dump_flag_with_typegraph) {
2185 ir_graph *rem = current_ir_graph;
2186 current_ir_graph = irg;
2188 type_walk_irg(irg, dump_type_info, NULL, out);
2189 inc_irg_visited(get_const_code_irg());
2190 /* dump edges from graph to type info */
2191 irg_walk(get_irg_end(irg), dump_node2type_edges, NULL, out);
2193 current_ir_graph = rem;
2196 /* dump iredges out edges */
2197 if ((flags & ir_dump_flag_iredges) && edges_activated(current_ir_graph)) {
2198 irg_walk_edges(get_irg_start_block(irg), dump_ir_edges, NULL, out);
2201 /* dump the out edges in a separate walk */
2202 if ((flags & ir_dump_flag_out_edges)
2203 && (is_irg_state(irg, IR_GRAPH_STATE_CONSISTENT_OUTS))) {
2204 irg_out_walk(get_irg_start(irg), dump_out_edge, NULL, out);
2207 dump_vcg_footer(out);
2210 static void dump_block_to_cfg(ir_node *block, void *env)
2212 FILE *F = (FILE*)env;
2215 if (is_Bad(block) && get_irn_mode(block) == mode_X) {
2216 dump_node(F, block);
2219 if (is_Block(block)) {
2220 /* This is a block. Dump a node for the block. */
2221 fprintf(F, "node: {title: \""); PRINT_NODEID(block);
2222 fprintf(F, "\" label: \"");
2223 if (block == get_irg_start_block(get_irn_irg(block)))
2224 fprintf(F, "Start ");
2225 if (block == get_irg_end_block(get_irn_irg(block)))
2228 fprintf(F, "%s ", get_op_name(get_irn_op(block)));
2229 PRINT_NODEID(block);
2231 fprintf(F, "info1:\"");
2233 /* the generic version. */
2234 dump_irnode_to_file(F, block);
2236 fprintf(F, "\""); /* closing quote of info */
2238 if ((block == get_irg_start_block(get_irn_irg(block))) ||
2239 (block == get_irg_end_block(get_irn_irg(block))) )
2240 fprintf(F, " color:blue ");
2244 /* Dump the edges */
2245 for (i = get_Block_n_cfgpreds(block) - 1; i >= 0; --i) {
2246 ir_node *pred = get_Block_cfgpred(block, i);
2248 pred = get_nodes_block(pred);
2249 fprintf(F, "edge: { sourcename: \"");
2250 PRINT_NODEID(block);
2251 fprintf(F, "\" targetname: \"");
2253 fprintf(F, "\"}\n");
2256 /* Dump dominator/postdominator edge */
2257 if (ir_get_dump_flags() & ir_dump_flag_dominance) {
2258 if (is_irg_state(get_irn_irg(block), IR_GRAPH_STATE_CONSISTENT_DOMINANCE) && get_Block_idom(block)) {
2259 ir_node *pred = get_Block_idom(block);
2260 fprintf(F, "edge: { sourcename: \"");
2261 PRINT_NODEID(block);
2262 fprintf(F, "\" targetname: \"");
2264 fprintf(F, "\" " DOMINATOR_EDGE_ATTR "}\n");
2266 if (is_irg_state(get_irn_irg(block), IR_GRAPH_STATE_CONSISTENT_POSTDOMINANCE) && get_Block_ipostdom(block)) {
2267 ir_node *pred = get_Block_ipostdom(block);
2268 fprintf(F, "edge: { sourcename: \"");
2269 PRINT_NODEID(block);
2270 fprintf(F, "\" targetname: \"");
2272 fprintf(F, "\" " POSTDOMINATOR_EDGE_ATTR "}\n");
2278 void dump_cfg(FILE *F, ir_graph *irg)
2280 dump_vcg_header(F, get_irg_dump_name(irg), NULL, NULL);
2282 /* walk over the blocks in the graph */
2283 irg_walk_graph(irg, dump_block_to_cfg, NULL, F);
2288 void dump_callgraph(FILE *F)
2291 ir_dump_flags_t old_flags = ir_get_dump_flags();
2293 ir_remove_dump_flags(ir_dump_flag_disable_edge_labels);
2294 dump_vcg_header(F, "Callgraph", "Hierarchic", NULL);
2296 for (i = get_irp_n_irgs(); i > 0;) {
2297 ir_graph *irg = get_irp_irg(--i);
2298 ir_entity *ent = get_irg_entity(irg);
2299 size_t j, n_callees = get_irg_n_callees(irg);
2301 dump_entity_node(F, ent);
2302 for (j = 0; j < n_callees; ++j) {
2303 ir_entity *c = get_irg_entity(get_irg_callee(irg, j));
2304 int be = is_irg_callee_backedge(irg, j);
2305 const char *attr = be
2306 ? "label:\"recursion %zu\""
2307 : "label:\"calls %zu\"";
2308 print_ent_ent_edge(F, ent, c, be, ird_color_entity, attr,
2309 get_irg_callee_loop_depth(irg, j));
2313 ir_set_dump_flags(old_flags);
2317 void dump_typegraph(FILE *out)
2319 dump_vcg_header(out, "All_types", "Hierarchic", NULL);
2320 type_walk(dump_type_info, NULL, out);
2321 dump_vcg_footer(out);
2324 void dump_class_hierarchy(FILE *out)
2326 dump_vcg_header(out, "class_hierarchy", "Hierarchic", NULL);
2327 type_walk(dump_class_hierarchy_node, NULL, out);
2328 dump_vcg_footer(out);
2331 static void dump_loops_standalone(FILE *F, ir_loop *loop)
2334 bool loop_node_started = false;
2336 size_t son_number = 0;
2338 ir_loop *son = NULL;
2340 /* Dump a new loop node. */
2341 dump_loop_node(F, loop);
2343 /* Dump the loop elements. */
2344 for (i = 0; i < get_loop_n_elements(loop); i++) {
2345 le = get_loop_element(loop, i);
2347 if (get_kind(son) == k_ir_loop) {
2349 /* We are a loop son -> Recurse */
2351 if (loop_node_started) { /* Close the "firm-nodes" node first if we started one. */
2352 fprintf(F, "\" }\n");
2353 fprintf(F, "edge: {sourcename: \"");
2355 fprintf(F, "\" targetname: \"");
2357 fprintf(F, "-%lu-nodes\" label:\"%lu...%lu\"}\n",
2358 (unsigned long) first,
2359 (unsigned long) first,
2360 (unsigned long) i-1);
2361 loop_node_started = false;
2363 dump_loop_son_edge(F, loop, son_number++);
2364 dump_loops_standalone(F, son);
2365 } else if (get_kind(son) == k_ir_node) {
2366 /* We are a loop node -> Collect firm nodes */
2368 ir_node *n = le.node;
2369 if (!loop_node_started) {
2370 /* Start a new node which contains all firm nodes of the current loop */
2371 fprintf(F, "node: { title: \"");
2373 fprintf(F, "-%lu-nodes\" color: lightyellow label: \"",
2375 loop_node_started = true;
2380 dump_node_label(F, n);
2381 /* Causes indeterministic output: if (is_Block(n)) fprintf(F, "\t ->%d", (int)get_irn_link(n)); */
2382 if (has_backedges(n)) fprintf(F, "\t loop head!");
2383 } else { /* for callgraph loop tree */
2385 assert(get_kind(son) == k_ir_graph);
2387 /* We are a loop node -> Collect firm graphs */
2389 if (!loop_node_started) {
2390 /* Start a new node which contains all firm nodes of the current loop */
2391 fprintf(F, "node: { title: \"");
2393 fprintf(F, "-%lu-nodes\" color: lightyellow label: \"",
2395 loop_node_started = true;
2399 fprintf(F, " %s", get_irg_dump_name(n));
2400 /* fprintf(F, " %s (depth %d)", get_irg_dump_name(n), n->callgraph_weighted_loop_depth); */
2404 if (loop_node_started) {
2405 fprintf(F, "\" }\n");
2406 fprintf(F, "edge: {sourcename: \"");
2408 fprintf(F, "\" targetname: \"");
2410 fprintf(F, "-%lu-nodes\" label:\"%lu...%lu\"}\n",
2411 (unsigned long) first,
2412 (unsigned long) first,
2413 (unsigned long) i-1);
2414 loop_node_started = false;
2418 void dump_loop_tree(FILE *out, ir_graph *irg)
2420 ir_graph *rem = current_ir_graph;
2421 ir_dump_flags_t old_flags = ir_get_dump_flags();
2423 current_ir_graph = irg;
2424 ir_remove_dump_flags(ir_dump_flag_disable_edge_labels);
2426 dump_vcg_header(out, get_irg_dump_name(irg), "Tree", "top_to_bottom");
2428 if (get_irg_loop(irg))
2429 dump_loops_standalone(out, get_irg_loop(irg));
2431 dump_vcg_footer(out);
2433 ir_set_dump_flags(old_flags);
2434 current_ir_graph = rem;
2437 void dump_callgraph_loop_tree(FILE *out)
2439 dump_vcg_header(out, "callgraph looptree", "Tree", "top_to_bottom");
2440 dump_loops_standalone(out, irp->outermost_cg_loop);
2441 dump_vcg_footer(out);
2444 static void collect_nodeloop(FILE *F, ir_loop *loop, eset *loopnodes)
2448 int node_number = 0;
2450 if (flags & ir_dump_flag_loops)
2451 dump_loop_node(F, loop);
2453 for (i = 0; i < get_loop_n_elements(loop); i++) {
2454 loop_element le = get_loop_element(loop, i);
2455 if (*(le.kind) == k_ir_loop) {
2456 if (flags & ir_dump_flag_loops)
2457 dump_loop_son_edge(F, loop, son_number++);
2459 collect_nodeloop(F, le.son, loopnodes);
2461 if (flags & ir_dump_flag_loops)
2462 dump_loop_node_edge(F, loop, node_number++);
2463 eset_insert(loopnodes, le.node);
2468 static void collect_nodeloop_external_nodes(ir_loop *loop, eset *loopnodes,
2474 for (i = 0; i < get_loop_n_elements(loop); i++) {
2475 loop_element le = get_loop_element(loop, i);
2476 if (*(le.kind) == k_ir_loop) {
2478 collect_nodeloop_external_nodes(le.son, loopnodes, extnodes);
2480 if (is_Block(le.node)) start = 0; else start = -1;
2481 for (j = start; j < get_irn_arity(le.node); j++) {
2482 ir_node *pred = get_irn_n(le.node, j);
2483 if (!eset_contains(loopnodes, pred)) {
2484 eset_insert(extnodes, pred);
2485 if (!is_Block(pred)) {
2486 pred = get_nodes_block(pred);
2487 if (!eset_contains(loopnodes, pred)) eset_insert(extnodes, pred);
2495 void dump_loop(FILE *F, ir_loop *l)
2497 eset *loopnodes = eset_create();
2498 eset *extnodes = eset_create();
2502 snprintf(name, sizeof(name), "loop_%ld", get_loop_loop_nr(l));
2503 dump_vcg_header(F, name, NULL, NULL);
2505 /* collect all nodes to dump */
2506 collect_nodeloop(F, l, loopnodes);
2507 collect_nodeloop_external_nodes(l, loopnodes, extnodes);
2509 /* build block lists */
2510 eset_foreach(loopnodes, ir_node*, n) {
2511 set_irn_link(n, NULL);
2513 eset_foreach(extnodes, ir_node*, n) {
2514 set_irn_link(n, NULL);
2516 eset_foreach(loopnodes, ir_node*, n) {
2518 b = get_nodes_block(n);
2519 set_irn_link(n, get_irn_link(b));
2523 eset_foreach(extnodes, ir_node*, n) {
2525 b = get_nodes_block(n);
2526 set_irn_link(n, get_irn_link(b));
2531 eset_foreach(loopnodes, ir_node*, b) {
2533 fprintf(F, "graph: { title: \"");
2535 fprintf(F, "\" label: \"");
2536 dump_node_opcode(F, b);
2537 fprintf(F, " %ld:%u", get_irn_node_nr(b), get_irn_idx(b));
2538 fprintf(F, "\" status:clustered color:yellow\n");
2540 /* dump the blocks edges */
2541 dump_ir_data_edges(F, b);
2543 /* dump the nodes that go into the block */
2544 for (n = (ir_node*)get_irn_link(b); n; n = (ir_node*)get_irn_link(n)) {
2545 if (eset_contains(extnodes, n))
2546 overrule_nodecolor = ird_color_block_inout;
2548 overrule_nodecolor = ird_color_default_node;
2549 if (!eset_contains(extnodes, n)) dump_ir_data_edges(F, n);
2552 /* Close the vcg information for the block */
2554 dump_const_node_local(F, b);
2558 eset_foreach(extnodes, ir_node*, b) {
2560 fprintf(F, "graph: { title: \"");
2562 fprintf(F, "\" label: \"");
2563 dump_node_opcode(F, b);
2564 fprintf(F, " %ld:%u", get_irn_node_nr(b), get_irn_idx(b));
2565 fprintf(F, "\" status:clustered color:lightblue\n");
2567 /* dump the nodes that go into the block */
2568 for (n = (ir_node*)get_irn_link(b); n; n = (ir_node*)get_irn_link(n)) {
2569 if (!eset_contains(loopnodes, n))
2570 overrule_nodecolor = ird_color_block_inout;
2572 overrule_nodecolor = ird_color_default_node;
2573 if (eset_contains(loopnodes, n)) dump_ir_data_edges(F, n);
2576 /* Close the vcg information for the block */
2578 dump_const_node_local(F, b);
2582 eset_destroy(loopnodes);
2583 eset_destroy(extnodes);
2588 static bool obstack_init;
2589 static struct obstack obst;
2590 static char *dump_path;
2592 void ir_set_dump_path(const char *path)
2595 dump_path = xstrdup(path);
2598 static void add_string_escaped(const char *string)
2601 for (p = string; *p != '\0'; ++p) {
2604 obstack_1grow(&obst, '@');
2605 obstack_1grow(&obst, '1');
2606 } else if (c == '@') {
2607 obstack_1grow(&obst, '@');
2608 obstack_1grow(&obst, '2');
2610 obstack_1grow(&obst, c);
2615 static void add_dump_path(void)
2617 if (!obstack_init) {
2618 obstack_init(&obst);
2619 obstack_init = true;
2622 if (dump_path != NULL) {
2623 size_t len = strlen(dump_path);
2624 obstack_grow(&obst, dump_path, len);
2625 if (len > 0 && dump_path[len-1] != '/')
2626 obstack_1grow(&obst, '/');
2630 void dump_ir_graph_ext(ir_graph_dump_func func, ir_graph *graph,
2633 const char *dump_name = get_irg_dump_name(graph);
2637 if (!ir_should_dump(dump_name))
2642 add_string_escaped(dump_name);
2643 obstack_printf(&obst, "-%02u", graph->dump_nr++);
2645 if (suffix != NULL) {
2646 if (suffix[0] != '.')
2647 obstack_1grow(&obst, '-');
2648 add_string_escaped(suffix);
2650 obstack_1grow(&obst, '\0');
2652 file_name = (char*)obstack_finish(&obst);
2653 /* xvcg expects only <CR> so we need "b"inary mode (for win32) */
2654 out = fopen(file_name, "wb");
2655 obstack_free(&obst, file_name);
2658 fprintf(stderr, "Couldn't open '%s': %s\n", file_name, strerror(errno));
2666 void dump_ir_prog_ext(ir_prog_dump_func func, const char *suffix)
2673 obstack_printf(&obst, "%02u", irp->dump_nr++);
2674 if (suffix != NULL) {
2675 if (suffix[0] != '.')
2676 obstack_1grow(&obst, '-');
2677 add_string_escaped(suffix);
2679 obstack_1grow(&obst, '\0');
2681 file_name = (char*)obstack_finish(&obst);
2682 out = fopen(file_name, "wb");
2683 obstack_free(&obst, file_name);
2686 fprintf(stderr, "Couldn't open '%s': %s\n", file_name, strerror(errno));
2693 void dump_ir_graph(ir_graph *graph, const char *suffix)
2697 snprintf(buf, sizeof(buf), "%s.vcg", suffix);
2698 dump_ir_graph_ext(dump_ir_graph_file, graph, buf);
2701 void dump_all_ir_graphs(const char *suffix)
2703 size_t i, n_irgs = get_irp_n_irgs();
2705 for (i = 0; i < n_irgs; ++i) {
2706 ir_graph *irg = get_irp_irg(i);
2707 dump_ir_graph(irg, suffix);
2711 typedef struct pass_t {
2712 ir_prog_pass_t pass;
2717 * Wrapper around dump_all_ir_graphs().
2719 static int dump_all_ir_graphs_wrapper(ir_prog *irp, void *context)
2721 pass_t *pass = (pass_t*)context;
2724 dump_all_ir_graphs(pass->suffix);
2728 ir_prog_pass_t *dump_all_ir_graph_pass(const char *name, const char *suffix)
2730 size_t len = strlen(suffix) + 1;
2731 pass_t *pass = XMALLOCF(pass_t, suffix, len);
2732 ir_prog_pass_t *res = def_prog_pass_constructor(
2733 &pass->pass, name ? name : "dump_all_graphs", dump_all_ir_graphs_wrapper);
2735 /* this pass does not change anything, so neither dump nor verify is needed. */
2736 res->dump_irprog = ir_prog_no_dump;
2737 res->verify_irprog = ir_prog_no_verify;
2739 memcpy(pass->suffix, suffix, len);