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 ir_node *pred = get_Proj_pred(n);
697 if (get_irn_opcode(pred) == iro_Cond
698 && get_Proj_proj(n) == get_Cond_default_proj(pred)
699 && get_irn_mode(get_Cond_selector(pred)) != mode_b)
700 fprintf(F, "defProj");
706 if (get_Load_unaligned(n) == align_non_aligned)
708 fprintf(F, "%s[%s]", get_irn_opname(n), get_mode_name_ex(get_Load_mode(n), NULL));
711 if (get_Store_unaligned(n) == align_non_aligned)
713 fprintf(F, "%s", get_irn_opname(n));
716 if (n == get_irg_start_block(get_irn_irg(n)))
718 if (n == get_irg_end_block(get_irn_irg(n)))
720 fprintf(F, "%s%s", get_irn_opname(n),
721 (flags & ir_dump_flag_show_marks) ? (get_Block_mark(n) ? "*" : "") : "");
724 if (get_Conv_strict(n))
725 fprintf(F, "strict");
726 fprintf(F, "%s", get_irn_opname(n));
729 fprintf(F, "%s", get_irn_opname(n));
730 if (get_Div_no_remainder(n))
732 fprintf(F, "[%s]", get_mode_name_ex(get_Div_resmode(n), NULL));
735 fprintf(F, "%s[%s]", get_irn_opname(n), get_mode_name_ex(get_Mod_resmode(n), NULL));
738 fprintf(F, "%s[%s]", get_irn_opname(n), get_builtin_kind_name(get_Builtin_kind(n)));
743 fprintf(F, "%s", get_irn_opname(n));
748 * Dump the mode of a node n to a file F.
749 * Ignore modes that are "always known".
751 static void dump_node_mode(FILE *F, ir_node *n)
753 const ir_op_ops *ops = get_op_ops(get_irn_op(n));
757 /* call the dump_node operation if available */
758 if (ops->dump_node) {
759 ops->dump_node(F, n, dump_node_mode_txt);
763 /* default implementation */
764 iro = get_irn_opcode(n);
776 mode = get_irn_mode(n);
778 if (mode != NULL && mode != mode_BB && mode != mode_ANY && mode != mode_BAD &&
779 (mode != mode_T || iro == iro_Proj))
780 fprintf(F, "%s", get_mode_name_ex(mode, NULL));
785 * Dump the type of a node n to a file F if it's known.
787 static int dump_node_typeinfo(FILE *F, ir_node *n)
791 if (ir_get_dump_flags() & ir_dump_flag_analysed_types) {
792 if (get_irg_typeinfo_state(current_ir_graph) == ir_typeinfo_consistent ||
793 get_irg_typeinfo_state(current_ir_graph) == ir_typeinfo_inconsistent) {
794 ir_type *tp = get_irn_typeinfo_type(n);
795 if (tp != firm_none_type) {
796 ir_fprintf(F, "[%+F]", tp);
806 * Dump additional node attributes of some nodes to a file F.
808 static void dump_node_nodeattr(FILE *F, ir_node *n)
813 const ir_op_ops *ops = get_op_ops(get_irn_op(n));
815 /* call the dump_node operation if available */
816 if (ops->dump_node) {
817 ops->dump_node(F, n, dump_node_nodeattr_txt);
821 switch (get_irn_opcode(n)) {
823 ir_fprintf(F, "%T ", get_Const_tarval(n));
827 pred = get_Proj_pred(n);
828 proj_nr = get_Proj_proj(n);
829 code = get_irn_opcode(pred);
831 if (code == iro_Proj && get_irn_opcode(get_Proj_pred(pred)) == iro_Start)
832 fprintf(F, "Arg %ld ", proj_nr);
833 else if (code == iro_Cond && get_irn_mode(get_Cond_selector(pred)) != mode_b)
834 fprintf(F, "%ld ", proj_nr);
836 unsigned i, j, f = 0;
838 for (i = 0; i < ARRAY_SIZE(proj_lut); ++i) {
839 if (code == proj_lut[i].code) {
840 for (j = 0; j < proj_lut[i].num_data; ++j) {
841 if (proj_nr == proj_lut[i].data[j].nr) {
842 fprintf(F, "%s ", proj_lut[i].data[j].name);
851 fprintf(F, "%ld ", proj_nr);
852 if (code == iro_Cond && get_Cond_jmp_pred(pred) != COND_JMP_PRED_NONE) {
853 if (proj_nr == pn_Cond_false && get_Cond_jmp_pred(pred) == COND_JMP_PRED_FALSE)
855 if (proj_nr == pn_Cond_true && get_Cond_jmp_pred(pred) == COND_JMP_PRED_TRUE)
861 fprintf(F, "%s ", get_ent_dump_name(get_Sel_entity(n)));
864 ir_fprintf(F, "(%+F)", get_Cast_type(n));
867 fprintf(F, "%s ", get_relation_string(get_Cmp_relation(n)));
870 fprintf(F, "%s ", get_relation_string(get_Confirm_relation(n)));
873 ir_fprintf(F, "(%+F)", get_CopyB_type(n));
881 static void dump_node_ana_vals(FILE *F, ir_node *n)
888 void dump_node_label(FILE *F, ir_node *n)
890 dump_node_opcode(F, n);
892 dump_node_mode(F, n);
894 dump_node_typeinfo(F, n);
895 dump_node_nodeattr(F, n);
896 if (flags & ir_dump_flag_number_label) {
897 fprintf(F, "%ld", get_irn_node_nr(n));
899 if (flags & ir_dump_flag_idx_label) {
900 fprintf(F, ":%u", get_irn_idx(n));
905 * Dumps the attributes of a node n into the file F.
906 * Currently this is only the color of a node.
908 static void dump_node_vcgattr(FILE *F, ir_node *node, ir_node *local, int bad)
914 print_vcg_color(F, ird_color_error);
918 if (dump_node_vcgattr_hook != NULL) {
919 dump_node_vcgattr_hook(F, node, local);
923 n = local ? local : node;
925 if (overrule_nodecolor != ird_color_default_node) {
926 print_vcg_color(F, overrule_nodecolor);
930 mode = get_irn_mode(n);
931 if (mode == mode_M) {
932 print_vcg_color(F, ird_color_memory);
935 if (mode == mode_X) {
936 print_vcg_color(F, ird_color_controlflow);
940 switch (get_irn_opcode(n)) {
943 print_vcg_color(F, ird_color_anchor);
946 print_vcg_color(F, ird_color_error);
949 print_vcg_color(F, ird_color_block_background);
952 print_vcg_color(F, ird_color_phi);
955 print_vcg_color(F, ird_color_memory);
959 print_vcg_color(F, ird_color_const);
962 print_vcg_color(F, ird_color_proj);
965 ir_op *op = get_irn_op(node);
967 if (is_op_constlike(op)) {
968 print_vcg_color(F, ird_color_const);
969 } else if (is_op_uses_memory(op)) {
970 print_vcg_color(F, ird_color_uses_memory);
971 } else if (is_op_cfopcode(op) || is_op_forking(op)) {
972 print_vcg_color(F, ird_color_controlflow);
978 void *dump_add_node_info_callback(dump_node_info_cb_t *cb, void *data)
980 hook_entry_t *info = XMALLOCZ(hook_entry_t);
982 info->hook._hook_node_info = cb;
983 info->context = data;
984 register_hook(hook_node_info, info);
989 void dump_remove_node_info_callback(void *handle)
991 hook_entry_t *info = (hook_entry_t*)handle;
992 unregister_hook(hook_node_info, info);
997 * Dump the node information of a node n to a file F.
999 static void dump_node_info(FILE *F, ir_node *n)
1001 const ir_op_ops *ops = get_op_ops(get_irn_op(n));
1003 fprintf(F, " info1: \"");
1004 dump_irnode_to_file(F, n);
1005 /* call the dump_node operation if available */
1007 ops->dump_node(F, n, dump_node_info_txt);
1009 /* allow additional info to be added */
1010 hook_node_info(F, n);
1014 static int is_constlike_node(const ir_node *node)
1016 const ir_op *op = get_irn_op(node);
1017 return is_op_constlike(op);
1021 /** outputs the predecessors of n, that are constants, local. I.e.,
1022 generates a copy of the constant predecessors for each node called with. */
1023 static void dump_const_node_local(FILE *F, ir_node *n)
1026 if (!get_opt_dump_const_local()) return;
1028 /* Use visited flag to avoid outputting nodes twice.
1029 initialize it first. */
1030 for (i = 0; i < get_irn_arity(n); i++) {
1031 ir_node *con = get_irn_n(n, i);
1032 if (is_constlike_node(con)) {
1033 set_irn_visited(con, get_irg_visited(current_ir_graph) - 1);
1037 for (i = 0; i < get_irn_arity(n); i++) {
1038 ir_node *con = get_irn_n(n, i);
1039 if (is_constlike_node(con) && !irn_visited_else_mark(con)) {
1040 /* Generate a new name for the node by appending the names of
1042 fprintf(F, "node: {title: "); PRINT_CONSTID(n, con);
1043 fprintf(F, " label: \"");
1044 dump_node_label(F, con);
1046 dump_node_info(F, con);
1047 dump_node_vcgattr(F, n, con, 0);
1053 /** If the block of an edge is a const_like node, dump it local with an edge */
1054 static void dump_const_block_local(FILE *F, ir_node *n)
1058 if (!get_opt_dump_const_local()) return;
1060 blk = get_nodes_block(n);
1061 if (is_constlike_node(blk)) {
1062 /* Generate a new name for the node by appending the names of
1064 fprintf(F, "node: {title: \""); PRINT_CONSTBLKID(n, blk);
1065 fprintf(F, "\" label: \"");
1066 dump_node_label(F, blk);
1068 dump_node_info(F, blk);
1069 dump_node_vcgattr(F, n, blk, 0);
1072 fprintf(F, "edge: { sourcename: \"");
1074 fprintf(F, "\" targetname: \""); PRINT_CONSTBLKID(n,blk);
1076 if (dump_edge_vcgattr_hook) {
1078 if (dump_edge_vcgattr_hook(F, n, -1)) {
1082 fprintf(F, " " BLOCK_EDGE_ATTR "}\n");
1087 fprintf(F, "\" " BLOCK_EDGE_ATTR "}\n");
1092 * prints the error message of a node to a file F as info2.
1094 static void print_node_error(FILE *F, const char *err_msg)
1099 fprintf(F, " info2: \"%s\"", err_msg);
1103 * prints debug messages of a node to file F as info3.
1105 static void print_dbg_info(FILE *F, dbg_info *dbg)
1109 ir_dbg_info_snprint(buf, sizeof(buf), dbg);
1111 fprintf(F, " info3: \"%s\"\n", buf);
1115 static void print_type_dbg_info(FILE *F, type_dbg_info *dbg)
1125 static void dump_node(FILE *F, ir_node *n)
1130 if (get_opt_dump_const_local() && is_constlike_node(n))
1133 /* dump this node */
1134 fputs("node: {title: \"", F);
1138 fputs(" label: \"", F);
1139 bad = ! irn_verify_irg_dump(n, current_ir_graph, &p);
1140 dump_node_label(F, n);
1141 dump_node_ana_vals(F, n);
1142 //dump_node_ana_info(F, n);
1145 if (get_op_flags(get_irn_op(n)) & irop_flag_dump_noinput) {
1146 //fputs(" node_class:23", F);
1149 dump_node_info(F, n);
1150 print_node_error(F, p);
1151 print_dbg_info(F, get_irn_dbg_info(n));
1152 dump_node_vcgattr(F, n, NULL, bad);
1154 dump_const_node_local(F, n);
1156 if (dump_node_edge_hook)
1157 dump_node_edge_hook(F, n);
1160 /** dump the edge to the block this node belongs to */
1161 static void dump_ir_block_edge(FILE *F, ir_node *n)
1163 if (get_opt_dump_const_local() && is_constlike_node(n)) return;
1165 ir_node *block = get_nodes_block(n);
1167 if (get_opt_dump_const_local() && is_constlike_node(block)) {
1168 dump_const_block_local(F, n);
1170 fprintf(F, "edge: { sourcename: \"");
1172 fprintf(F, "\" targetname: ");
1173 fprintf(F, "\""); PRINT_NODEID(block); fprintf(F, "\"");
1175 if (dump_edge_vcgattr_hook) {
1177 if (dump_edge_vcgattr_hook(F, n, -1)) {
1181 fprintf(F, " " BLOCK_EDGE_ATTR "}\n");
1186 fprintf(F, " " BLOCK_EDGE_ATTR "}\n");
1191 static void print_data_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_DATA_EDGE_ATTR);
1200 fprintf(F, INTER_DATA_EDGE_ATTR);
1203 static void print_mem_edge_vcgattr(FILE *F, ir_node *from, int to)
1206 * do not use get_nodes_block() here, will fail
1207 * if the irg is not pinned.
1209 if (get_irn_n(from, -1) == get_irn_n(get_irn_n(from, to), -1))
1210 fprintf(F, INTRA_MEM_EDGE_ATTR);
1212 fprintf(F, INTER_MEM_EDGE_ATTR);
1215 /** Print the vcg attributes for the edge from node "from" to its "to"th input */
1216 static void print_edge_vcgattr(FILE *F, ir_node *from, int to)
1220 if (dump_edge_vcgattr_hook)
1221 if (dump_edge_vcgattr_hook(F, from, to))
1224 if ((flags & ir_dump_flag_back_edges) && is_backedge(from, to))
1225 fprintf(F, BACK_EDGE_ATTR);
1227 switch (get_irn_opcode(from)) {
1229 fprintf(F, CF_EDGE_ATTR);
1231 case iro_Start: break;
1234 if (get_irn_mode(get_End_keepalive(from, to)) == mode_BB)
1235 fprintf(F, KEEP_ALIVE_CF_EDGE_ATTR);
1237 fprintf(F, KEEP_ALIVE_DF_EDGE_ATTR);
1241 if (is_Proj(from)) {
1242 if (get_irn_mode(from) == mode_M)
1243 print_mem_edge_vcgattr(F, from, to);
1244 else if (get_irn_mode(from) == mode_X)
1245 fprintf(F, CF_EDGE_ATTR);
1247 print_data_edge_vcgattr(F, from, to);
1249 else if (get_irn_mode(get_irn_n(from, to)) == mode_M)
1250 print_mem_edge_vcgattr(F, from, to);
1251 else if (get_irn_mode(get_irn_n(from, to)) == mode_X)
1252 fprintf(F, CF_EDGE_ATTR);
1254 print_data_edge_vcgattr(F, from, to);
1258 /** dump edges to our inputs */
1259 static void dump_ir_data_edges(FILE *F, ir_node *n)
1263 if (!(flags & ir_dump_flag_keepalive_edges) && is_End(n)) {
1264 /* the End node has only keep-alive edges */
1268 /* dump the dependency edges. */
1269 num = get_irn_deps(n);
1270 for (i = 0; i < num; ++i) {
1271 ir_node *dep = get_irn_dep(n, i);
1274 print_node_edge_kind(F, n);
1275 fprintf(F, "{sourcename: \"");
1277 fprintf(F, "\" targetname: ");
1278 if ((get_opt_dump_const_local()) && is_constlike_node(dep)) {
1279 PRINT_CONSTID(n, dep);
1285 fprintf(F, " label: \"%d\" ", i);
1286 fprintf(F, " color: darkgreen}\n");
1290 num = get_irn_arity(n);
1291 for (i = 0; i < num; i++) {
1292 ir_node *pred = get_irn_n(n, i);
1295 if ((flags & ir_dump_flag_back_edges) && is_backedge(n, i)) {
1296 fprintf(F, "backedge: {sourcename: \"");
1298 print_node_edge_kind(F, n);
1299 fprintf(F, "{sourcename: \"");
1302 fprintf(F, "\" targetname: ");
1303 if ((get_opt_dump_const_local()) && is_constlike_node(pred)) {
1304 PRINT_CONSTID(n, pred);
1306 fprintf(F, "\""); PRINT_NODEID(pred); fprintf(F, "\"");
1308 fprintf(F, " label: \"%d\" ", i);
1309 print_edge_vcgattr(F, n, i);
1317 static void dump_ir_edges(ir_node *node, void *env)
1320 FILE *F = (FILE*)env;
1321 const ir_edge_t *edge;
1323 foreach_out_edge(node, edge) {
1324 ir_node *succ = get_edge_src_irn(edge);
1326 print_node_edge_kind(F, succ);
1327 fprintf(F, "{sourcename: \"");
1329 fprintf(F, "\" targetname: \"");
1333 fprintf(F, " label: \"%d\" ", i);
1334 fprintf(F, OUT_EDGE_ATTR);
1341 /** Dumps a node and its edges but not the block edge */
1342 static void dump_node_wo_blockedge(ir_node *n, void *env)
1344 FILE *F = (FILE*)env;
1346 dump_ir_data_edges(F, n);
1349 /** Dumps a node and its edges. */
1350 static void dump_node_with_edges(ir_node *n, void *env)
1352 FILE *F = (FILE*)env;
1353 dump_node_wo_blockedge(n, env);
1354 if (!node_floats(n))
1355 dump_ir_block_edge(F, n);
1358 /** Dumps a const-like node. */
1359 static void dump_const_node(ir_node *n, void *env)
1361 if (is_Block(n)) return;
1362 dump_node_wo_blockedge(n, env);
1365 /***********************************************************************/
1366 /* the following routines dump the nodes/irgs bracketed to graphs. */
1367 /***********************************************************************/
1369 /** Dumps a constant expression as entity initializer, array bound ... */
1370 static void dump_const_expression(FILE *F, ir_node *value)
1372 ir_graph *rem = current_ir_graph;
1373 ir_dump_flags_t old_flags = ir_get_dump_flags();
1374 ir_remove_dump_flags(ir_dump_flag_consts_local);
1376 current_ir_graph = get_const_code_irg();
1377 irg_walk(value, dump_const_node, NULL, F);
1378 /* Decrease visited flag so that we walk with the same flag for the next
1379 expression. This guarantees that we don't dump the same node twice,
1380 as for const expressions cse is performed to save memory. */
1381 set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph) -1);
1383 ir_set_dump_flags(old_flags);
1384 current_ir_graph = rem;
1387 /** Dump a block as graph containing its nodes.
1389 * Expects to find nodes belonging to the block as list in its
1391 * Dumps the edges of all nodes including itself. */
1392 static void dump_whole_block(FILE *F, ir_node *block)
1395 ird_color_t color = ird_color_block_background;
1397 assert(is_Block(block));
1399 fprintf(F, "graph: { title: \"");
1400 PRINT_NODEID(block);
1401 fprintf(F, "\" label: \"");
1402 dump_node_label(F, block);
1404 /* colorize blocks */
1405 if (! get_Block_matured(block))
1406 color = ird_color_block_background;
1408 fprintf(F, "\" status:clustered ");
1409 print_vcg_color(F, color);
1412 /* yComp can show attributes for blocks, XVCG parses but ignores them */
1413 dump_node_info(F, block);
1414 print_dbg_info(F, get_irn_dbg_info(block));
1416 /* dump the blocks edges */
1417 dump_ir_data_edges(F, block);
1419 if (dump_block_edge_hook)
1420 dump_block_edge_hook(F, block);
1422 /* dump the nodes that go into the block */
1423 for (node = (ir_node*)ird_get_irn_link(block); node; node = (ir_node*)ird_get_irn_link(node)) {
1425 dump_ir_data_edges(F, node);
1428 /* Close the vcg information for the block */
1430 dump_const_node_local(F, block);
1434 /** dumps a graph block-wise. Expects all blockless nodes in arr in irgs link.
1435 * The outermost nodes: blocks and nodes not op_pin_state_pinned, Bad, Unknown. */
1436 static void dump_block_graph(FILE *F, ir_graph *irg)
1439 ir_graph *rem = current_ir_graph;
1440 ir_node **arr = (ir_node**)ird_get_irg_link(irg);
1441 current_ir_graph = irg;
1443 for (i = 0, n = ARR_LEN(arr); i < n; ++i) {
1444 ir_node *node = arr[i];
1445 if (is_Block(node)) {
1446 /* Dumps the block and all the nodes in the block, which are to
1447 be found in Block->link. */
1448 dump_whole_block(F, node);
1450 /* Nodes that are not in a Block. */
1452 if (!node_floats(node) && is_Bad(get_nodes_block(node))) {
1453 dump_const_block_local(F, node);
1455 dump_ir_data_edges(F, node);
1457 if ((flags & ir_dump_flag_iredges) && edges_activated(irg))
1458 dump_ir_edges(node, F);
1461 if ((flags & ir_dump_flag_loops)
1462 && is_irg_state(irg, IR_GRAPH_STATE_CONSISTENT_LOOPINFO))
1463 dump_loop_nodes_into_graph(F, irg);
1465 current_ir_graph = rem;
1469 * Dump the info for an irg.
1470 * Parsed by XVCG but not shown. use yComp.
1472 static void dump_graph_info(FILE *F, ir_graph *irg)
1474 fprintf(F, "info1: \"");
1475 dump_entity_to_file(F, get_irg_entity(irg));
1478 /* dump graph state */
1479 fprintf(F, "state:");
1480 if (is_irg_state(irg, IR_GRAPH_STATE_ARCH_DEP))
1481 fprintf(F, " arch_dep");
1482 if (is_irg_state(irg, IR_GRAPH_STATE_MODEB_LOWERED))
1483 fprintf(F, " modeb_lowered");
1484 if (is_irg_state(irg, IR_GRAPH_STATE_NORMALISATION2))
1485 fprintf(F, " normalisation2");
1486 if (is_irg_state(irg, IR_GRAPH_STATE_IMPLICIT_BITFIELD_MASKING))
1487 fprintf(F, " implicit_bitfield_masking");
1488 if (is_irg_state(irg, IR_GRAPH_STATE_OPTIMIZE_UNREACHABLE_CODE))
1489 fprintf(F, " optimize_unreachable_code");
1490 if (is_irg_state(irg, IR_GRAPH_STATE_NO_CRITICAL_EDGES))
1491 fprintf(F, " no_critical_edges");
1492 if (is_irg_state(irg, IR_GRAPH_STATE_NO_BADS))
1493 fprintf(F, " no_bads");
1494 if (is_irg_state(irg, IR_GRAPH_STATE_NO_UNREACHABLE_CODE))
1495 fprintf(F, " no_unreachable_code");
1496 if (is_irg_state(irg, IR_GRAPH_STATE_ONE_RETURN))
1497 fprintf(F, " one_return");
1498 if (is_irg_state(irg, IR_GRAPH_STATE_CONSISTENT_DOMINANCE))
1499 fprintf(F, " consistent_dominance");
1500 if (is_irg_state(irg, IR_GRAPH_STATE_CONSISTENT_POSTDOMINANCE))
1501 fprintf(F, " consistent_postdominance");
1502 if (is_irg_state(irg, IR_GRAPH_STATE_CONSISTENT_OUT_EDGES))
1503 fprintf(F, " consistent_out_edges");
1504 if (is_irg_state(irg, IR_GRAPH_STATE_CONSISTENT_OUTS))
1505 fprintf(F, " consistent_outs");
1506 if (is_irg_state(irg, IR_GRAPH_STATE_CONSISTENT_LOOPINFO))
1507 fprintf(F, " consistent_loopinfo");
1508 if (is_irg_state(irg, IR_GRAPH_STATE_CONSISTENT_ENTITY_USAGE))
1509 fprintf(F, " consistent_entity_usage");
1510 if (is_irg_state(irg, IR_GRAPH_STATE_VALID_EXTENDED_BLOCKS))
1511 fprintf(F, " valid_exended_blocks");
1515 /** Dumps an irg as a graph clustered by block nodes.
1516 * If interprocedural view edges can point to nodes out of this graph.
1518 static void dump_graph_from_list(FILE *F, ir_graph *irg)
1520 ir_entity *ent = get_irg_entity(irg);
1522 fprintf(F, "graph: { title: \"");
1524 fprintf(F, "\" label: \"%s\" status:clustered color:%s \n",
1525 get_ent_dump_name(ent), color_names[ird_color_prog_background]);
1527 dump_graph_info(F, irg);
1528 print_dbg_info(F, get_entity_dbg_info(ent));
1530 dump_block_graph(F, irg);
1532 /* Close the vcg information for the irg */
1533 fprintf(F, "}\n\n");
1536 /*******************************************************************/
1537 /* Basic type and entity nodes and edges. */
1538 /*******************************************************************/
1540 /** dumps the edges between nodes and their type or entity attributes. */
1541 static void dump_node2type_edges(ir_node *n, void *env)
1543 FILE *F = (FILE*)env;
1546 switch (get_irn_opcode(n)) {
1548 /* @@@ some consts have an entity */
1551 if (SYMCONST_HAS_TYPE(get_SymConst_kind(n)))
1552 print_node_type_edge(F,n,get_SymConst_type(n),NODE2TYPE_EDGE_ATTR);
1555 print_node_ent_edge(F,n,get_Sel_entity(n),NODE2TYPE_EDGE_ATTR);
1558 print_node_type_edge(F,n,get_Call_type(n),NODE2TYPE_EDGE_ATTR);
1561 print_node_type_edge(F,n,get_Alloc_type(n),NODE2TYPE_EDGE_ATTR);
1564 print_node_type_edge(F,n,get_Free_type(n),NODE2TYPE_EDGE_ATTR);
1567 print_node_type_edge(F,n,get_Cast_type(n),NODE2TYPE_EDGE_ATTR);
1575 static int print_type_info(FILE *F, ir_type *tp)
1579 if (get_type_state(tp) == layout_undefined) {
1580 fprintf(F, "state: layout_undefined\n");
1582 fprintf(F, "state: layout_fixed,\n");
1584 if (get_type_mode(tp))
1585 fprintf(F, "mode: %s,\n", get_mode_name_ex(get_type_mode(tp), &bad));
1586 fprintf(F, "size: %db,\n", get_type_size_bits(tp));
1591 static void print_typespecific_info(FILE *F, ir_type *tp)
1593 switch (get_type_tpop_code(tp)) {
1595 fprintf(F, "peculiarity: %s\n", get_peculiarity_string(get_class_peculiarity(tp)));
1600 fprintf(F, "variadicity: %s\n", get_variadicity_name(get_method_variadicity(tp)));
1601 fprintf(F, "params: %d\n", get_method_n_params(tp));
1602 fprintf(F, "results: %d\n", get_method_n_ress(tp));
1608 case tpo_enumeration:
1620 static void print_typespecific_vcgattr(FILE *F, ir_type *tp)
1622 switch (get_type_tpop_code(tp)) {
1624 fprintf(F, " " TYPE_CLASS_NODE_ATTR);
1627 fprintf(F, " " TYPE_METH_NODE_ATTR);
1635 case tpo_enumeration:
1646 void dump_type_node(FILE *F, ir_type *tp)
1648 fprintf(F, "node: {title: ");
1650 fprintf(F, " label: \"");
1651 if (tp->dbi != NULL) {
1653 ir_print_type(buf, sizeof(buf), tp);
1654 fprintf(F, "%s '%s'", get_type_tpop_name(tp), buf);
1656 ir_fprintf(F, "%+F", tp);
1658 fputs("\" info1: \"", F);
1659 dump_type_to_file(F, tp);
1661 print_type_dbg_info(F, get_type_dbg_info(tp));
1662 print_typespecific_vcgattr(F, tp);
1666 static void dump_entity_node(FILE *F, ir_entity *ent)
1668 fprintf(F, "node: {title: \"");
1669 PRINT_ENTID(ent); fprintf(F, "\"");
1670 fprintf(F, " label: ");
1671 fprintf(F, "\"%s\" ", get_ent_dump_name(ent));
1673 print_vcg_color(F, ird_color_entity);
1674 fprintf(F, "\n info1: \"");
1676 dump_entity_to_file(F, ent);
1679 print_dbg_info(F, get_entity_dbg_info(ent));
1683 static void dump_enum_item(FILE *F, ir_type *tp, size_t pos)
1686 ir_enum_const *ec = get_enumeration_const(tp, pos);
1687 ident *id = get_enumeration_const_nameid(ec);
1688 ir_tarval *tv = get_enumeration_value(ec);
1691 tarval_snprintf(buf, sizeof(buf), tv);
1693 strncpy(buf, "<not set>", sizeof(buf));
1694 fprintf(F, "node: {title: \"");
1695 PRINT_ITEMID(tp, pos); fprintf(F, "\"");
1696 fprintf(F, " label: ");
1697 fprintf(F, "\"enum item %s\" " ENUM_ITEM_NODE_ATTR, get_id_str(id));
1698 fprintf(F, "\n info1: \"value: %s\"}\n", buf);
1702 * Dumps a new style initializer.
1704 static void dump_entity_initializer(FILE *F, const ir_entity *ent)
1712 * type-walker: Dumps a type or entity and its edges.
1714 static void dump_type_info(type_or_ent tore, void *env)
1716 FILE *F = (FILE*)env;
1717 size_t i = 0; /* to shutup gcc */
1719 /* dump this type or entity */
1721 switch (get_kind(tore.ent)) {
1723 ir_entity *ent = tore.ent;
1726 dump_entity_node(F, ent);
1728 /* skip this to reduce graph. Member edge of type is parallel to this edge. *
1729 fprintf(F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
1730 ENT_OWN_EDGE_ATTR "}\n", ent, get_entity_owner(ent));*/
1731 print_ent_type_edge(F,ent, get_entity_type(ent), ENT_TYPE_EDGE_ATTR);
1732 if (is_Class_type(get_entity_owner(ent))) {
1733 for (i = get_entity_n_overwrites(ent); i > 0;)
1734 print_ent_ent_edge(F, ent, get_entity_overwrites(ent, --i), 0, ird_color_none, ENT_OVERWRITES_EDGE_ATTR);
1736 /* attached subgraphs */
1737 if (! (flags & ir_dump_flag_no_entity_values)) {
1738 if (ent->initializer != NULL) {
1739 /* new style initializers */
1740 dump_entity_initializer(F, ent);
1741 } else if (entity_has_compound_ent_values(ent)) {
1742 /* old style compound entity values */
1743 for (i = get_compound_ent_n_values(ent); i > 0;) {
1744 value = get_compound_ent_value(ent, --i);
1746 print_ent_node_edge(F, ent, value, ENT_VALUE_EDGE_ATTR, i);
1747 dump_const_expression(F, value);
1748 print_ent_ent_edge(F, ent, get_compound_ent_value_member(ent, i), 0, ird_color_none, ENT_CORR_EDGE_ATTR, i);
1750 fprintf(F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
1751 ENT_CORR_EDGE_ATTR "}\n", GET_ENTID(ent),
1752 get_compound_ent_value_member(ent, i), i);
1761 ir_type *tp = tore.typ;
1762 dump_type_node(F, tp);
1763 /* and now the edges */
1764 switch (get_type_tpop_code(tp)) {
1766 for (i = get_class_n_supertypes(tp); i > 0;) {
1768 print_type_type_edge(F, tp, get_class_supertype(tp, i), TYPE_SUPER_EDGE_ATTR);
1770 for (i = get_class_n_members(tp); i > 0;) {
1772 print_type_ent_edge(F, tp, get_class_member(tp, i), TYPE_MEMBER_EDGE_ATTR);
1776 for (i = get_struct_n_members(tp); i > 0;) {
1778 print_type_ent_edge(F, tp, get_struct_member(tp, i), TYPE_MEMBER_EDGE_ATTR);
1782 for (i = get_method_n_params(tp); i > 0;) {
1784 print_type_type_edge(F, tp, get_method_param_type(tp, i), METH_PAR_EDGE_ATTR,i);
1786 for (i = get_method_n_ress(tp); i > 0;) {
1788 print_type_type_edge(F, tp, get_method_res_type(tp, i), METH_RES_EDGE_ATTR,i);
1792 for (i = get_union_n_members(tp); i > 0;) {
1794 print_type_ent_edge(F, tp, get_union_member(tp, i), UNION_EDGE_ATTR);
1798 print_type_type_edge(F, tp, get_array_element_type(tp), ARR_ELT_TYPE_EDGE_ATTR);
1799 print_type_ent_edge(F, tp, get_array_element_entity(tp), ARR_ENT_EDGE_ATTR);
1800 for (i = get_array_n_dimensions(tp); i > 0;) {
1801 ir_node *upper, *lower;
1804 upper = get_array_upper_bound(tp, i);
1805 lower = get_array_lower_bound(tp, i);
1806 print_node_type_edge(F, upper, tp, "label: \"upper %zu\"", get_array_order(tp, i));
1807 print_node_type_edge(F, lower, tp, "label: \"lower %zu\"", get_array_order(tp, i));
1808 dump_const_expression(F, upper);
1809 dump_const_expression(F, lower);
1812 case tpo_enumeration:
1813 for (i = get_enumeration_n_enums(tp); i > 0;) {
1815 dump_enum_item(F, tp, i);
1816 print_enum_item_edge(F, tp, i, "label: \"item %zu\"", i);
1820 print_type_type_edge(F, tp, get_pointer_points_to_type(tp), PTR_PTS_TO_EDGE_ATTR);
1827 break; /* case k_type */
1830 printf(" *** irdump, dump_type_info(l.%i), faulty type.\n", __LINE__);
1834 /** For dumping class hierarchies.
1835 * Dumps a class type node and a superclass edge.
1837 static void dump_class_hierarchy_node(type_or_ent tore, void *ctx)
1839 FILE *F = (FILE*)ctx;
1840 size_t i = 0; /* to shutup gcc */
1842 /* dump this type or entity */
1843 switch (get_kind(tore.ent)) {
1845 ir_entity *ent = tore.ent;
1846 if (get_entity_owner(ent) == get_glob_type()) break;
1847 if (!is_Method_type(get_entity_type(ent)))
1849 if (flags & ir_dump_flag_entities_in_hierarchy
1850 && is_Class_type(get_entity_owner(ent))) {
1852 dump_entity_node(F, ent);
1854 print_type_ent_edge(F, get_entity_owner(ent), ent, TYPE_MEMBER_EDGE_ATTR);
1855 for (i = get_entity_n_overwrites(ent); i > 0;) {
1857 print_ent_ent_edge(F, get_entity_overwrites(ent, i), ent, 0, ird_color_none, ENT_OVERWRITES_EDGE_ATTR);
1863 ir_type *tp = tore.typ;
1864 if (tp == get_glob_type())
1866 switch (get_type_tpop_code(tp)) {
1868 dump_type_node(F, tp);
1869 /* and now the edges */
1870 for (i = get_class_n_supertypes(tp); i > 0;) {
1872 print_type_type_edge(F,tp,get_class_supertype(tp, i),TYPE_SUPER_EDGE_ATTR);
1877 break; /* case k_type */
1880 printf(" *** irdump, dump_class_hierarchy_node(l.%i), faulty type.\n", __LINE__);
1884 /*******************************************************************/
1885 /* dump analysis information that is expressed in graph terms. */
1886 /*******************************************************************/
1888 /* dump out edges */
1889 static void dump_out_edge(ir_node *n, void *env)
1891 FILE *F = (FILE*)env;
1893 for (i = get_irn_n_outs(n) - 1; i >= 0; --i) {
1894 ir_node *succ = get_irn_out(n, i);
1896 print_node_edge_kind(F, succ);
1897 fprintf(F, "{sourcename: \"");
1899 fprintf(F, "\" targetname: \"");
1901 fprintf(F, "\" color: red linestyle: dashed");
1906 static void dump_loop_label(FILE *F, ir_loop *loop)
1908 fprintf(F, "loop %u, %lu sons, %lu nodes",
1909 get_loop_depth(loop), (unsigned long) get_loop_n_sons(loop),
1910 (unsigned long) get_loop_n_nodes(loop));
1913 static void dump_loop_info(FILE *F, ir_loop *loop)
1915 fprintf(F, " info1: \"");
1916 fprintf(F, " loop nr: %ld", get_loop_loop_nr(loop));
1917 #ifdef DEBUG_libfirm /* GL @@@ debug analyses */
1918 fprintf(F, "\n The loop was analyzed %ld times.", (long int) PTR_TO_INT(get_loop_link(loop)));
1923 static void dump_loop_node(FILE *F, ir_loop *loop)
1925 fprintf(F, "node: {title: \"");
1927 fprintf(F, "\" label: \"");
1928 dump_loop_label(F, loop);
1930 dump_loop_info(F, loop);
1934 static void dump_loop_node_edge(FILE *F, ir_loop *loop, size_t i)
1937 fprintf(F, "edge: {sourcename: \"");
1939 fprintf(F, "\" targetname: \"");
1940 PRINT_NODEID(get_loop_node(loop, i));
1941 fprintf(F, "\" color: green");
1945 static void dump_loop_son_edge(FILE *F, ir_loop *loop, size_t i)
1948 fprintf(F, "edge: {sourcename: \"");
1950 fprintf(F, "\" targetname: \"");
1951 PRINT_LOOPID(get_loop_son(loop, i));
1952 ir_fprintf(F, "\" color: darkgreen label: \"%zu\"}\n",
1953 get_loop_element_pos(loop, get_loop_son(loop, i)));
1956 static void dump_loops(FILE *F, ir_loop *loop)
1959 /* dump this loop node */
1960 dump_loop_node(F, loop);
1962 /* dump edges to nodes in loop -- only if it is a real loop */
1963 if (get_loop_depth(loop) != 0) {
1964 for (i = get_loop_n_nodes(loop); i > 0;) {
1966 dump_loop_node_edge(F, loop, i);
1969 for (i = get_loop_n_sons(loop); i > 0;) {
1971 dump_loops(F, get_loop_son(loop, i));
1972 dump_loop_son_edge(F, loop, i);
1976 static void dump_loop_nodes_into_graph(FILE *F, ir_graph *irg)
1978 ir_loop *loop = get_irg_loop(irg);
1981 ir_graph *rem = current_ir_graph;
1982 current_ir_graph = irg;
1984 dump_loops(F, loop);
1986 current_ir_graph = rem;
1992 * dumps the VCG header
1994 void dump_vcg_header(FILE *F, const char *name, const char *layout, const char *orientation)
1998 = (flags & ir_dump_flag_disable_edge_labels) ? "no" : "yes";
2002 if (! layout) layout = "Compilergraph";
2003 if (!orientation) orientation = "bottom_to_top";
2007 "graph: { title: \"ir graph of %s\"\n"
2008 "display_edge_labels: %s\n"
2009 "layoutalgorithm: mindepth //$ \"%s\"\n"
2010 "manhattan_edges: yes\n"
2011 "port_sharing: no\n"
2013 "classname 1: \"intrablock Data\"\n"
2014 "classname 2: \"Block\"\n"
2015 "classname 3: \"Entity type\"\n"
2016 "classname 4: \"Entity owner\"\n"
2017 "classname 5: \"Method Param\"\n"
2018 "classname 6: \"Method Res\"\n"
2019 "classname 7: \"Super\"\n"
2020 "classname 8: \"Union\"\n"
2021 "classname 9: \"Points-to\"\n"
2022 "classname 10: \"Array Element Type\"\n"
2023 "classname 11: \"Overwrites\"\n"
2024 "classname 12: \"Member\"\n"
2025 "classname 13: \"Control Flow\"\n"
2026 "classname 14: \"intrablock Memory\"\n"
2027 "classname 15: \"Dominators\"\n"
2028 "classname 16: \"interblock Data\"\n"
2029 "classname 17: \"interblock Memory\"\n"
2030 "classname 18: \"Exception Control Flow for Interval Analysis\"\n"
2031 "classname 19: \"Postdominators\"\n"
2032 "classname 20: \"Keep Alive\"\n"
2033 "classname 21: \"Out Edges\"\n"
2034 "classname 22: \"Macro Block Edges\"\n"
2035 //"classname 23: \"NoInput Nodes\"\n"
2036 "infoname 1: \"Attribute\"\n"
2037 "infoname 2: \"Verification errors\"\n"
2038 "infoname 3: \"Debug info\"\n",
2039 name, label, layout, orientation);
2041 for (i = 0; i < ird_color_count; ++i) {
2042 if (color_rgb[i] != NULL) {
2043 fprintf(F, "colorentry %s: %s\n", color_names[i], color_rgb[i]);
2050 * Dumps the vcg file footer
2052 void dump_vcg_footer(FILE *F)
2059 static void dump_blocks_as_subgraphs(FILE *out, ir_graph *irg)
2063 construct_block_lists(irg);
2066 * If we are in the interprocedural view, we dump not
2067 * only the requested irg but also all irgs that can be reached
2070 for (i = get_irp_n_irgs(); i > 0;) {
2071 ir_graph *other_irg = get_irp_irg(--i);
2072 ir_node **arr = (ir_node**)ird_get_irg_link(other_irg);
2076 dump_graph_from_list(out, other_irg);
2081 /** dumps a graph extended block-wise. Expects all blockless nodes in arr in irgs link.
2082 * The outermost nodes: blocks and nodes not op_pin_state_pinned, Bad, Unknown. */
2083 static void dump_extblock_graph(FILE *F, ir_graph *irg)
2086 ir_graph *rem = current_ir_graph;
2087 ir_extblk **arr = (ir_extblk**)ird_get_irg_link(irg);
2088 current_ir_graph = irg;
2090 for (i = 0, arr_len = ARR_LEN(arr); i < arr_len; ++i) {
2091 ir_extblk *extbb = arr[i];
2092 ir_node *leader = get_extbb_leader(extbb);
2095 fprintf(F, "graph: { title: \"");
2096 PRINT_EXTBBID(leader);
2097 fprintf(F, "\" label: \"ExtBB %ld\" status:clustered color:lightgreen\n",
2098 get_irn_node_nr(leader));
2100 for (j = 0, n_blks = ARR_LEN(extbb->blks); j < n_blks; ++j) {
2101 ir_node *node = extbb->blks[j];
2102 if (is_Block(node)) {
2103 /* Dumps the block and all the nodes in the block, which are to
2104 be found in Block->link. */
2105 dump_whole_block(F, node);
2107 /* Nodes that are not in a Block. */
2109 if (is_Bad(get_nodes_block(node)) && !node_floats(node)) {
2110 dump_const_block_local(F, node);
2112 dump_ir_data_edges(F, node);
2118 if ((flags & ir_dump_flag_loops)
2119 && (is_irg_state(irg, IR_GRAPH_STATE_CONSISTENT_LOOPINFO)))
2120 dump_loop_nodes_into_graph(F, irg);
2122 current_ir_graph = rem;
2126 static void dump_blocks_extbb_grouped(FILE *F, ir_graph *irg)
2129 ir_entity *ent = get_irg_entity(irg);
2131 if (!is_irg_state(irg, IR_GRAPH_STATE_VALID_EXTENDED_BLOCKS))
2134 construct_extblock_lists(irg);
2136 fprintf(F, "graph: { title: \"");
2138 fprintf(F, "\" label: \"%s\" status:clustered color: white \n",
2139 get_ent_dump_name(ent));
2141 dump_graph_info(F, irg);
2142 print_dbg_info(F, get_entity_dbg_info(ent));
2144 for (i = get_irp_n_irgs(); i > 0;) {
2145 ir_graph *other_irg = get_irp_irg(--i);
2146 list_tuple *lists = (list_tuple*)ird_get_irg_link(other_irg);
2149 /* dump the extended blocks first */
2150 if (ARR_LEN(lists->extbb_list)) {
2151 ird_set_irg_link(other_irg, lists->extbb_list);
2152 dump_extblock_graph(F, other_irg);
2155 /* we may have blocks without extended blocks, bad for instance */
2156 if (ARR_LEN(lists->blk_list)) {
2157 ird_set_irg_link(other_irg, lists->blk_list);
2158 dump_block_graph(F, other_irg);
2161 DEL_ARR_F(lists->extbb_list);
2162 DEL_ARR_F(lists->blk_list);
2167 /* Close the vcg information for the irg */
2168 fprintf(F, "}\n\n");
2173 void dump_ir_graph_file(FILE *out, ir_graph *irg)
2175 dump_vcg_header(out, get_irg_dump_name(irg), NULL, NULL);
2178 if (flags & ir_dump_flag_blocks_as_subgraphs) {
2179 if (flags & ir_dump_flag_group_extbb) {
2180 dump_blocks_extbb_grouped(out, irg);
2182 dump_blocks_as_subgraphs(out, irg);
2185 /* dump_node_with_edges must be called in post visiting predecessors */
2186 ird_walk_graph(irg, NULL, dump_node_with_edges, out);
2189 /* dump type info */
2190 if (flags & ir_dump_flag_with_typegraph) {
2191 ir_graph *rem = current_ir_graph;
2192 current_ir_graph = irg;
2194 type_walk_irg(irg, dump_type_info, NULL, out);
2195 inc_irg_visited(get_const_code_irg());
2196 /* dump edges from graph to type info */
2197 irg_walk(get_irg_end(irg), dump_node2type_edges, NULL, out);
2199 current_ir_graph = rem;
2202 /* dump iredges out edges */
2203 if ((flags & ir_dump_flag_iredges) && edges_activated(current_ir_graph)) {
2204 irg_walk_edges(get_irg_start_block(irg), dump_ir_edges, NULL, out);
2207 /* dump the out edges in a separate walk */
2208 if ((flags & ir_dump_flag_out_edges)
2209 && (is_irg_state(irg, IR_GRAPH_STATE_CONSISTENT_OUTS))) {
2210 irg_out_walk(get_irg_start(irg), dump_out_edge, NULL, out);
2213 dump_vcg_footer(out);
2216 static void dump_block_to_cfg(ir_node *block, void *env)
2218 FILE *F = (FILE*)env;
2221 if (is_Bad(block) && get_irn_mode(block) == mode_X) {
2222 dump_node(F, block);
2225 if (is_Block(block)) {
2226 /* This is a block. Dump a node for the block. */
2227 fprintf(F, "node: {title: \""); PRINT_NODEID(block);
2228 fprintf(F, "\" label: \"");
2229 if (block == get_irg_start_block(get_irn_irg(block)))
2230 fprintf(F, "Start ");
2231 if (block == get_irg_end_block(get_irn_irg(block)))
2234 fprintf(F, "%s ", get_op_name(get_irn_op(block)));
2235 PRINT_NODEID(block);
2237 fprintf(F, "info1:\"");
2239 /* the generic version. */
2240 dump_irnode_to_file(F, block);
2242 fprintf(F, "\""); /* closing quote of info */
2244 if ((block == get_irg_start_block(get_irn_irg(block))) ||
2245 (block == get_irg_end_block(get_irn_irg(block))) )
2246 fprintf(F, " color:blue ");
2250 /* Dump the edges */
2251 for (i = get_Block_n_cfgpreds(block) - 1; i >= 0; --i) {
2252 ir_node *pred = get_Block_cfgpred(block, i);
2254 pred = get_nodes_block(pred);
2255 fprintf(F, "edge: { sourcename: \"");
2256 PRINT_NODEID(block);
2257 fprintf(F, "\" targetname: \"");
2259 fprintf(F, "\"}\n");
2262 /* Dump dominator/postdominator edge */
2263 if (ir_get_dump_flags() & ir_dump_flag_dominance) {
2264 if (is_irg_state(get_irn_irg(block), IR_GRAPH_STATE_CONSISTENT_DOMINANCE) && get_Block_idom(block)) {
2265 ir_node *pred = get_Block_idom(block);
2266 fprintf(F, "edge: { sourcename: \"");
2267 PRINT_NODEID(block);
2268 fprintf(F, "\" targetname: \"");
2270 fprintf(F, "\" " DOMINATOR_EDGE_ATTR "}\n");
2272 if (is_irg_state(get_irn_irg(block), IR_GRAPH_STATE_CONSISTENT_POSTDOMINANCE) && get_Block_ipostdom(block)) {
2273 ir_node *pred = get_Block_ipostdom(block);
2274 fprintf(F, "edge: { sourcename: \"");
2275 PRINT_NODEID(block);
2276 fprintf(F, "\" targetname: \"");
2278 fprintf(F, "\" " POSTDOMINATOR_EDGE_ATTR "}\n");
2284 void dump_cfg(FILE *F, ir_graph *irg)
2286 dump_vcg_header(F, get_irg_dump_name(irg), NULL, NULL);
2288 /* walk over the blocks in the graph */
2289 irg_walk_graph(irg, dump_block_to_cfg, NULL, F);
2294 void dump_callgraph(FILE *F)
2297 ir_dump_flags_t old_flags = ir_get_dump_flags();
2299 ir_remove_dump_flags(ir_dump_flag_disable_edge_labels);
2300 dump_vcg_header(F, "Callgraph", "Hierarchic", NULL);
2302 for (i = get_irp_n_irgs(); i > 0;) {
2303 ir_graph *irg = get_irp_irg(--i);
2304 ir_entity *ent = get_irg_entity(irg);
2305 size_t j, n_callees = get_irg_n_callees(irg);
2307 dump_entity_node(F, ent);
2308 for (j = 0; j < n_callees; ++j) {
2309 ir_entity *c = get_irg_entity(get_irg_callee(irg, j));
2310 int be = is_irg_callee_backedge(irg, j);
2311 const char *attr = be
2312 ? "label:\"recursion %zu\""
2313 : "label:\"calls %zu\"";
2314 print_ent_ent_edge(F, ent, c, be, ird_color_entity, attr,
2315 get_irg_callee_loop_depth(irg, j));
2319 ir_set_dump_flags(old_flags);
2323 void dump_typegraph(FILE *out)
2325 dump_vcg_header(out, "All_types", "Hierarchic", NULL);
2326 type_walk(dump_type_info, NULL, out);
2327 dump_vcg_footer(out);
2330 void dump_class_hierarchy(FILE *out)
2332 dump_vcg_header(out, "class_hierarchy", "Hierarchic", NULL);
2333 type_walk(dump_class_hierarchy_node, NULL, out);
2334 dump_vcg_footer(out);
2337 static void dump_loops_standalone(FILE *F, ir_loop *loop)
2340 bool loop_node_started = false;
2342 size_t son_number = 0;
2344 ir_loop *son = NULL;
2346 /* Dump a new loop node. */
2347 dump_loop_node(F, loop);
2349 /* Dump the loop elements. */
2350 for (i = 0; i < get_loop_n_elements(loop); i++) {
2351 le = get_loop_element(loop, i);
2353 if (get_kind(son) == k_ir_loop) {
2355 /* We are a loop son -> Recurse */
2357 if (loop_node_started) { /* Close the "firm-nodes" node first if we started one. */
2358 fprintf(F, "\" }\n");
2359 fprintf(F, "edge: {sourcename: \"");
2361 fprintf(F, "\" targetname: \"");
2363 fprintf(F, "-%lu-nodes\" label:\"%lu...%lu\"}\n",
2364 (unsigned long) first,
2365 (unsigned long) first,
2366 (unsigned long) i-1);
2367 loop_node_started = false;
2369 dump_loop_son_edge(F, loop, son_number++);
2370 dump_loops_standalone(F, son);
2371 } else if (get_kind(son) == k_ir_node) {
2372 /* We are a loop node -> Collect firm nodes */
2374 ir_node *n = le.node;
2375 if (!loop_node_started) {
2376 /* Start a new node which contains all firm nodes of the current loop */
2377 fprintf(F, "node: { title: \"");
2379 fprintf(F, "-%lu-nodes\" color: lightyellow label: \"",
2381 loop_node_started = true;
2386 dump_node_label(F, n);
2387 /* Causes indeterministic output: if (is_Block(n)) fprintf(F, "\t ->%d", (int)get_irn_link(n)); */
2388 if (has_backedges(n)) fprintf(F, "\t loop head!");
2389 } else { /* for callgraph loop tree */
2391 assert(get_kind(son) == k_ir_graph);
2393 /* We are a loop node -> Collect firm graphs */
2395 if (!loop_node_started) {
2396 /* Start a new node which contains all firm nodes of the current loop */
2397 fprintf(F, "node: { title: \"");
2399 fprintf(F, "-%lu-nodes\" color: lightyellow label: \"",
2401 loop_node_started = true;
2405 fprintf(F, " %s", get_irg_dump_name(n));
2406 /* fprintf(F, " %s (depth %d)", get_irg_dump_name(n), n->callgraph_weighted_loop_depth); */
2410 if (loop_node_started) {
2411 fprintf(F, "\" }\n");
2412 fprintf(F, "edge: {sourcename: \"");
2414 fprintf(F, "\" targetname: \"");
2416 fprintf(F, "-%lu-nodes\" label:\"%lu...%lu\"}\n",
2417 (unsigned long) first,
2418 (unsigned long) first,
2419 (unsigned long) i-1);
2420 loop_node_started = false;
2424 void dump_loop_tree(FILE *out, ir_graph *irg)
2426 ir_graph *rem = current_ir_graph;
2427 ir_dump_flags_t old_flags = ir_get_dump_flags();
2429 current_ir_graph = irg;
2430 ir_remove_dump_flags(ir_dump_flag_disable_edge_labels);
2432 dump_vcg_header(out, get_irg_dump_name(irg), "Tree", "top_to_bottom");
2434 if (get_irg_loop(irg))
2435 dump_loops_standalone(out, get_irg_loop(irg));
2437 dump_vcg_footer(out);
2439 ir_set_dump_flags(old_flags);
2440 current_ir_graph = rem;
2443 void dump_callgraph_loop_tree(FILE *out)
2445 dump_vcg_header(out, "callgraph looptree", "Tree", "top_to_bottom");
2446 dump_loops_standalone(out, irp->outermost_cg_loop);
2447 dump_vcg_footer(out);
2450 static void collect_nodeloop(FILE *F, ir_loop *loop, eset *loopnodes)
2454 int node_number = 0;
2456 if (flags & ir_dump_flag_loops)
2457 dump_loop_node(F, loop);
2459 for (i = 0; i < get_loop_n_elements(loop); i++) {
2460 loop_element le = get_loop_element(loop, i);
2461 if (*(le.kind) == k_ir_loop) {
2462 if (flags & ir_dump_flag_loops)
2463 dump_loop_son_edge(F, loop, son_number++);
2465 collect_nodeloop(F, le.son, loopnodes);
2467 if (flags & ir_dump_flag_loops)
2468 dump_loop_node_edge(F, loop, node_number++);
2469 eset_insert(loopnodes, le.node);
2474 static void collect_nodeloop_external_nodes(ir_loop *loop, eset *loopnodes,
2480 for (i = 0; i < get_loop_n_elements(loop); i++) {
2481 loop_element le = get_loop_element(loop, i);
2482 if (*(le.kind) == k_ir_loop) {
2484 collect_nodeloop_external_nodes(le.son, loopnodes, extnodes);
2486 if (is_Block(le.node)) start = 0; else start = -1;
2487 for (j = start; j < get_irn_arity(le.node); j++) {
2488 ir_node *pred = get_irn_n(le.node, j);
2489 if (!eset_contains(loopnodes, pred)) {
2490 eset_insert(extnodes, pred);
2491 if (!is_Block(pred)) {
2492 pred = get_nodes_block(pred);
2493 if (!eset_contains(loopnodes, pred)) eset_insert(extnodes, pred);
2501 void dump_loop(FILE *F, ir_loop *l)
2503 eset *loopnodes = eset_create();
2504 eset *extnodes = eset_create();
2508 snprintf(name, sizeof(name), "loop_%ld", get_loop_loop_nr(l));
2509 dump_vcg_header(F, name, NULL, NULL);
2511 /* collect all nodes to dump */
2512 collect_nodeloop(F, l, loopnodes);
2513 collect_nodeloop_external_nodes(l, loopnodes, extnodes);
2515 /* build block lists */
2516 eset_foreach(loopnodes, ir_node*, n) {
2517 set_irn_link(n, NULL);
2519 eset_foreach(extnodes, ir_node*, n) {
2520 set_irn_link(n, NULL);
2522 eset_foreach(loopnodes, ir_node*, n) {
2524 b = get_nodes_block(n);
2525 set_irn_link(n, get_irn_link(b));
2529 eset_foreach(extnodes, ir_node*, n) {
2531 b = get_nodes_block(n);
2532 set_irn_link(n, get_irn_link(b));
2537 eset_foreach(loopnodes, ir_node*, b) {
2539 fprintf(F, "graph: { title: \"");
2541 fprintf(F, "\" label: \"");
2542 dump_node_opcode(F, b);
2543 fprintf(F, " %ld:%u", get_irn_node_nr(b), get_irn_idx(b));
2544 fprintf(F, "\" status:clustered color:yellow\n");
2546 /* dump the blocks edges */
2547 dump_ir_data_edges(F, b);
2549 /* dump the nodes that go into the block */
2550 for (n = (ir_node*)get_irn_link(b); n; n = (ir_node*)get_irn_link(n)) {
2551 if (eset_contains(extnodes, n))
2552 overrule_nodecolor = ird_color_block_inout;
2554 overrule_nodecolor = ird_color_default_node;
2555 if (!eset_contains(extnodes, n)) dump_ir_data_edges(F, n);
2558 /* Close the vcg information for the block */
2560 dump_const_node_local(F, b);
2564 eset_foreach(extnodes, ir_node*, b) {
2566 fprintf(F, "graph: { title: \"");
2568 fprintf(F, "\" label: \"");
2569 dump_node_opcode(F, b);
2570 fprintf(F, " %ld:%u", get_irn_node_nr(b), get_irn_idx(b));
2571 fprintf(F, "\" status:clustered color:lightblue\n");
2573 /* dump the nodes that go into the block */
2574 for (n = (ir_node*)get_irn_link(b); n; n = (ir_node*)get_irn_link(n)) {
2575 if (!eset_contains(loopnodes, n))
2576 overrule_nodecolor = ird_color_block_inout;
2578 overrule_nodecolor = ird_color_default_node;
2579 if (eset_contains(loopnodes, n)) dump_ir_data_edges(F, n);
2582 /* Close the vcg information for the block */
2584 dump_const_node_local(F, b);
2588 eset_destroy(loopnodes);
2589 eset_destroy(extnodes);
2594 static bool obstack_init;
2595 static struct obstack obst;
2596 static char *dump_path;
2598 void ir_set_dump_path(const char *path)
2601 dump_path = xstrdup(path);
2604 static void add_string_escaped(const char *string)
2607 for (p = string; *p != '\0'; ++p) {
2610 obstack_1grow(&obst, '@');
2611 obstack_1grow(&obst, '1');
2612 } else if (c == '@') {
2613 obstack_1grow(&obst, '@');
2614 obstack_1grow(&obst, '2');
2616 obstack_1grow(&obst, c);
2621 static void add_dump_path(void)
2623 if (!obstack_init) {
2624 obstack_init(&obst);
2625 obstack_init = true;
2628 if (dump_path != NULL) {
2629 size_t len = strlen(dump_path);
2630 obstack_grow(&obst, dump_path, len);
2631 if (len > 0 && dump_path[len-1] != '/')
2632 obstack_1grow(&obst, '/');
2636 void dump_ir_graph_ext(ir_graph_dump_func func, ir_graph *graph,
2639 const char *dump_name = get_irg_dump_name(graph);
2643 if (!ir_should_dump(dump_name))
2648 add_string_escaped(dump_name);
2649 obstack_printf(&obst, "-%02u", graph->dump_nr++);
2651 if (suffix != NULL) {
2652 if (suffix[0] != '.')
2653 obstack_1grow(&obst, '-');
2654 add_string_escaped(suffix);
2656 obstack_1grow(&obst, '\0');
2658 file_name = (char*)obstack_finish(&obst);
2659 /* xvcg expects only <CR> so we need "b"inary mode (for win32) */
2660 out = fopen(file_name, "wb");
2661 obstack_free(&obst, file_name);
2664 fprintf(stderr, "Couldn't open '%s': %s\n", file_name, strerror(errno));
2672 void dump_ir_prog_ext(ir_prog_dump_func func, const char *suffix)
2679 obstack_printf(&obst, "%02u", irp->dump_nr++);
2680 if (suffix != NULL) {
2681 if (suffix[0] != '.')
2682 obstack_1grow(&obst, '-');
2683 add_string_escaped(suffix);
2685 obstack_1grow(&obst, '\0');
2687 file_name = (char*)obstack_finish(&obst);
2688 out = fopen(file_name, "wb");
2689 obstack_free(&obst, file_name);
2692 fprintf(stderr, "Couldn't open '%s': %s\n", file_name, strerror(errno));
2699 void dump_ir_graph(ir_graph *graph, const char *suffix)
2703 snprintf(buf, sizeof(buf), "%s.vcg", suffix);
2704 dump_ir_graph_ext(dump_ir_graph_file, graph, buf);
2707 void dump_all_ir_graphs(const char *suffix)
2709 size_t i, n_irgs = get_irp_n_irgs();
2711 for (i = 0; i < n_irgs; ++i) {
2712 ir_graph *irg = get_irp_irg(i);
2713 dump_ir_graph(irg, suffix);
2717 typedef struct pass_t {
2718 ir_prog_pass_t pass;
2723 * Wrapper around dump_all_ir_graphs().
2725 static int dump_all_ir_graphs_wrapper(ir_prog *irp, void *context)
2727 pass_t *pass = (pass_t*)context;
2730 dump_all_ir_graphs(pass->suffix);
2734 ir_prog_pass_t *dump_all_ir_graph_pass(const char *name, const char *suffix)
2736 size_t len = strlen(suffix) + 1;
2737 pass_t *pass = XMALLOCF(pass_t, suffix, len);
2738 ir_prog_pass_t *res = def_prog_pass_constructor(
2739 &pass->pass, name ? name : "dump_all_graphs", dump_all_ir_graphs_wrapper);
2741 /* this pass does not change anything, so neither dump nor verify is needed. */
2742 res->dump_irprog = ir_prog_no_dump;
2743 res->verify_irprog = ir_prog_no_verify;
2745 memcpy(pass->suffix, suffix, len);